define NodePath::premunge_scene() and supporting implementation
This commit is contained in:
parent
872c141de0
commit
732bbafaa9
|
|
@ -170,8 +170,55 @@ munge_data_impl(const GeomVertexData *data) {
|
|||
// Description: Converts a Geom and/or its data as necessary.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool StandardMunger::
|
||||
munge_geom_impl(CPT(Geom) &geom, CPT(GeomVertexData) &vertex_data,
|
||||
Thread *current_thread) {
|
||||
munge_geom_impl(CPT(Geom) &geom, CPT(GeomVertexData) &vertex_data, Thread *) {
|
||||
int supported_geom_rendering = get_gsg()->get_supported_geom_rendering();
|
||||
|
||||
int unsupported_bits = geom->get_geom_rendering() & ~supported_geom_rendering;
|
||||
if (unsupported_bits != 0) {
|
||||
// Even beyond munging the vertex format, we have to convert the
|
||||
// Geom itself into a new primitive type the GSG can render
|
||||
// directly.
|
||||
if ((unsupported_bits & Geom::GR_composite_bits) != 0) {
|
||||
// This decomposes everything in the primitive, so that if (for
|
||||
// instance) the primitive contained both strips and fans, but
|
||||
// the GSG didn't support fans, it would decompose the strips
|
||||
// too. To handle this correctly, we'd need a separate
|
||||
// decompose_fans() and decompose_strips() call; but for now,
|
||||
// we'll just say it's good enough. In practice, we don't have
|
||||
// any GSG's that can support strips without also supporting
|
||||
// fans.
|
||||
geom = geom->decompose();
|
||||
|
||||
// Decomposing might produce an indexed Geom, so re-check the
|
||||
// unsupported bits.
|
||||
unsupported_bits = geom->get_geom_rendering() & ~supported_geom_rendering;
|
||||
}
|
||||
if ((unsupported_bits & Geom::GR_shade_model_bits) != 0) {
|
||||
// Rotate the vertices to account for different shade-model
|
||||
// expectations (e.g. SM_flat_last_vertex to
|
||||
// SM_flat_first_vertex)
|
||||
geom = geom->rotate();
|
||||
}
|
||||
if ((unsupported_bits & Geom::GR_indexed_bits) != 0) {
|
||||
// Convert indexed geometry to nonindexed geometry.
|
||||
PT(Geom) new_geom = geom->make_copy();
|
||||
new_geom->set_vertex_data(vertex_data);
|
||||
new_geom->make_nonindexed(false);
|
||||
geom = new_geom;
|
||||
vertex_data = new_geom->get_vertex_data();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StandardMunger::premunge_geom_impl
|
||||
// Access: Protected, Virtual
|
||||
// Description: Converts a Geom and/or its data as necessary.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool StandardMunger::
|
||||
premunge_geom_impl(CPT(Geom) &geom, CPT(GeomVertexData) &vertex_data) {
|
||||
int supported_geom_rendering = get_gsg()->get_supported_geom_rendering();
|
||||
|
||||
int unsupported_bits = geom->get_geom_rendering() & ~supported_geom_rendering;
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ protected:
|
|||
virtual int compare_to_impl(const GeomMunger *other) const;
|
||||
virtual bool munge_geom_impl(CPT(Geom) &geom, CPT(GeomVertexData) &data,
|
||||
Thread *current_thread);
|
||||
virtual bool premunge_geom_impl(CPT(Geom) &geom, CPT(GeomVertexData) &data);
|
||||
virtual int geom_compare_to_impl(const GeomMunger *other) const;
|
||||
virtual CPT(RenderState) munge_state_impl(const RenderState *state);
|
||||
|
||||
|
|
|
|||
|
|
@ -16,20 +16,3 @@
|
|||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLP(GeomMunger)::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CLP(GeomMunger)::
|
||||
CLP(GeomMunger)(GraphicsStateGuardian *gsg, const RenderState *state) :
|
||||
StandardMunger(gsg, state, 4, NT_uint8, C_color),
|
||||
_texture(state->get_texture()),
|
||||
_tex_gen(state->get_tex_gen())
|
||||
{
|
||||
// Set a callback to unregister ourselves when either the Texture or
|
||||
// the TexGen object gets deleted.
|
||||
_texture.set_callback(this);
|
||||
_tex_gen.set_callback(this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,31 @@
|
|||
GeomMunger *CLP(GeomMunger)::_deleted_chain = NULL;
|
||||
TypeHandle CLP(GeomMunger)::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLP(GeomMunger)::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CLP(GeomMunger)::
|
||||
CLP(GeomMunger)(GraphicsStateGuardian *gsg, const RenderState *state) :
|
||||
StandardMunger(gsg, state, 4, NT_uint8, C_color),
|
||||
_texture(state->get_texture()),
|
||||
_tex_gen(state->get_tex_gen())
|
||||
{
|
||||
// Set a callback to unregister ourselves when either the Texture or
|
||||
// the TexGen object gets deleted.
|
||||
_texture.set_callback(this);
|
||||
_tex_gen.set_callback(this);
|
||||
|
||||
_flags = 0;
|
||||
|
||||
if (CLP(interleaved_arrays)) {
|
||||
_flags |= F_interleaved_arrays;
|
||||
} else if (CLP(parallel_arrays)) {
|
||||
_flags |= F_parallel_arrays;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLP(GeomMunger)::Destructor
|
||||
// Access: Public, Virtual
|
||||
|
|
@ -113,22 +138,211 @@ munge_format_impl(const GeomVertexFormat *orig,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if (true) {
|
||||
CPT(GeomVertexFormat) format = GeomVertexFormat::register_format(new_format);
|
||||
|
||||
if ((_flags & F_parallel_arrays) != 0) {
|
||||
// Split out the interleaved array into n parallel arrays.
|
||||
CPT(GeomVertexFormat) format = new_format;
|
||||
new_format = new GeomVertexFormat;
|
||||
for (int i = 0; i < format->get_num_columns(); i++) {
|
||||
for (int i = 0; i < format->get_num_columns(); ++i) {
|
||||
const GeomVertexColumn *column = format->get_column(i);
|
||||
PT(GeomVertexArrayFormat) new_array_format = new GeomVertexArrayFormat;
|
||||
new_array_format->add_column(column->get_name(), column->get_num_components(),
|
||||
column->get_numeric_type());
|
||||
column->get_numeric_type(), column->get_contents());
|
||||
new_format->add_array(new_array_format);
|
||||
}
|
||||
}
|
||||
*/
|
||||
format = GeomVertexFormat::register_format(new_format);
|
||||
|
||||
} else if ((_flags & F_interleaved_arrays) != 0) {
|
||||
// Combine the primary data columns into a single array.
|
||||
new_format = new GeomVertexFormat(*format);
|
||||
PT(GeomVertexArrayFormat) new_array_format = new GeomVertexArrayFormat;
|
||||
|
||||
const GeomVertexColumn *column = format->get_vertex_column();
|
||||
if (column != (const GeomVertexColumn *)NULL) {
|
||||
new_array_format->add_column
|
||||
(column->get_name(), column->get_num_components(),
|
||||
column->get_numeric_type(), column->get_contents());
|
||||
new_format->remove_column(column->get_name());
|
||||
}
|
||||
|
||||
return GeomVertexFormat::register_format(new_format);
|
||||
column = format->get_normal_column();
|
||||
if (column != (const GeomVertexColumn *)NULL) {
|
||||
new_array_format->add_column
|
||||
(column->get_name(), column->get_num_components(),
|
||||
column->get_numeric_type(), column->get_contents());
|
||||
new_format->remove_column(column->get_name());
|
||||
}
|
||||
|
||||
column = format->get_color_column();
|
||||
if (column != (const GeomVertexColumn *)NULL) {
|
||||
new_array_format->add_column
|
||||
(column->get_name(), column->get_num_components(),
|
||||
column->get_numeric_type(), column->get_contents());
|
||||
new_format->remove_column(column->get_name());
|
||||
}
|
||||
|
||||
// Put only the used texture coordinates into the interleaved
|
||||
// array.
|
||||
if (_texture != (TextureAttrib *)NULL) {
|
||||
typedef pset<const InternalName *> UsedStages;
|
||||
UsedStages used_stages;
|
||||
|
||||
int num_stages = _texture->get_num_on_stages();
|
||||
for (int i = 0; i < num_stages; ++i) {
|
||||
TextureStage *stage = _texture->get_on_stage(i);
|
||||
if (_tex_gen == (TexGenAttrib *)NULL ||
|
||||
!_tex_gen->has_stage(stage)) {
|
||||
InternalName *name = stage->get_texcoord_name();
|
||||
if (used_stages.insert(name).second) {
|
||||
// This is the first time we've encountered this texcoord name.
|
||||
const GeomVertexColumn *texcoord_type = format->get_column(name);
|
||||
|
||||
if (texcoord_type != (const GeomVertexColumn *)NULL) {
|
||||
new_array_format->add_column
|
||||
(name, texcoord_type->get_num_values(), NT_float32, C_texcoord);
|
||||
} else {
|
||||
// We have to add something as a placeholder, even if the
|
||||
// texture coordinates aren't defined.
|
||||
new_array_format->add_column(name, 2, NT_float32, C_texcoord);
|
||||
}
|
||||
new_format->remove_column(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
new_format->insert_array(0, new_array_format);
|
||||
format = GeomVertexFormat::register_format(new_format);
|
||||
}
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLP(GeomMunger)::premunge_format_impl
|
||||
// Access: Protected, Virtual
|
||||
// Description: Given a source GeomVertexFormat, converts it if
|
||||
// necessary to the appropriate format for rendering.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(GeomVertexFormat) CLP(GeomMunger)::
|
||||
premunge_format_impl(const GeomVertexFormat *orig) {
|
||||
PT(GeomVertexFormat) new_format = new GeomVertexFormat(*orig);
|
||||
|
||||
const GeomVertexColumn *color_type = orig->get_color_column();
|
||||
if (color_type != (GeomVertexColumn *)NULL &&
|
||||
color_type->get_numeric_type() == NT_packed_dabc) {
|
||||
// We need to convert the color format; OpenGL doesn't support the
|
||||
// byte order of DirectX's packed ARGB format.
|
||||
int color_array = orig->get_array_with(InternalName::get_color());
|
||||
|
||||
PT(GeomVertexArrayFormat) new_array_format = new_format->modify_array(color_array);
|
||||
|
||||
// Replace the existing color format with the new format.
|
||||
new_array_format->add_column
|
||||
(InternalName::get_color(), 4, NT_uint8,
|
||||
C_color, color_type->get_start());
|
||||
}
|
||||
|
||||
CPT(GeomVertexFormat) format = GeomVertexFormat::register_format(new_format);
|
||||
|
||||
if ((_flags & F_parallel_arrays) != 0) {
|
||||
// Split out the interleaved array into n parallel arrays.
|
||||
new_format = new GeomVertexFormat;
|
||||
for (int i = 0; i < format->get_num_columns(); ++i) {
|
||||
const GeomVertexColumn *column = format->get_column(i);
|
||||
PT(GeomVertexArrayFormat) new_array_format = new GeomVertexArrayFormat;
|
||||
new_array_format->add_column(column->get_name(), column->get_num_components(),
|
||||
column->get_numeric_type(), column->get_contents());
|
||||
new_format->add_array(new_array_format);
|
||||
}
|
||||
format = GeomVertexFormat::register_format(new_format);
|
||||
|
||||
} else {
|
||||
// Combine the primary data columns into a single array. Unlike
|
||||
// the munge case, above, in the premunge case, we do this even if
|
||||
// F_interleaved_arrays is not set (unless F_parallel_arrays is
|
||||
// set), since the presumption is that you're more willing to pay
|
||||
// the overhead of doing this step at load time than you might be
|
||||
// at run time.
|
||||
new_format = new GeomVertexFormat(*format);
|
||||
PT(GeomVertexArrayFormat) new_array_format = new GeomVertexArrayFormat;
|
||||
|
||||
const GeomVertexColumn *column = format->get_vertex_column();
|
||||
if (column != (const GeomVertexColumn *)NULL) {
|
||||
new_array_format->add_column
|
||||
(column->get_name(), column->get_num_components(),
|
||||
column->get_numeric_type(), column->get_contents());
|
||||
new_format->remove_column(column->get_name());
|
||||
}
|
||||
|
||||
column = format->get_normal_column();
|
||||
if (column != (const GeomVertexColumn *)NULL) {
|
||||
new_array_format->add_column
|
||||
(column->get_name(), column->get_num_components(),
|
||||
column->get_numeric_type(), column->get_contents());
|
||||
new_format->remove_column(column->get_name());
|
||||
}
|
||||
|
||||
column = format->get_color_column();
|
||||
if (column != (const GeomVertexColumn *)NULL) {
|
||||
new_array_format->add_column
|
||||
(column->get_name(), column->get_num_components(),
|
||||
column->get_numeric_type(), column->get_contents());
|
||||
new_format->remove_column(column->get_name());
|
||||
}
|
||||
|
||||
// Put only the used texture coordinates into the interleaved
|
||||
// array. The others will be kept around, but in a parallel
|
||||
// array.
|
||||
if (_texture != (TextureAttrib *)NULL) {
|
||||
typedef pset<const InternalName *> UsedStages;
|
||||
UsedStages used_stages;
|
||||
|
||||
int num_stages = _texture->get_num_on_stages();
|
||||
for (int i = 0; i < num_stages; ++i) {
|
||||
TextureStage *stage = _texture->get_on_stage(i);
|
||||
if (_tex_gen == (TexGenAttrib *)NULL ||
|
||||
!_tex_gen->has_stage(stage)) {
|
||||
InternalName *name = stage->get_texcoord_name();
|
||||
if (used_stages.insert(name).second) {
|
||||
// This is the first time we've encountered this texcoord name.
|
||||
const GeomVertexColumn *texcoord_type = format->get_column(name);
|
||||
|
||||
if (texcoord_type != (const GeomVertexColumn *)NULL) {
|
||||
new_array_format->add_column
|
||||
(name, texcoord_type->get_num_values(), NT_float32, C_texcoord);
|
||||
} else {
|
||||
// We have to add something as a placeholder, even if the
|
||||
// texture coordinates aren't defined.
|
||||
new_array_format->add_column(name, 2, NT_float32, C_texcoord);
|
||||
}
|
||||
new_format->remove_column(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now go through the remaining arrays and make sure they are
|
||||
// tightly packed. If not, repack them.
|
||||
for (int i = 0; i < new_format->get_num_arrays(); ++i) {
|
||||
CPT(GeomVertexArrayFormat) orig_a = new_format->get_array(i);
|
||||
if (orig_a->count_unused_space() != 0) {
|
||||
PT(GeomVertexArrayFormat) new_a = new GeomVertexArrayFormat;
|
||||
for (int j = 0; j < orig_a->get_num_columns(); ++j) {
|
||||
const GeomVertexColumn *column = orig_a->get_column(j);
|
||||
new_a->add_column(column->get_name(), column->get_num_components(),
|
||||
column->get_numeric_type(), column->get_contents());
|
||||
}
|
||||
new_format->set_array(i, new_a);
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, insert the interleaved array first in the format.
|
||||
new_format->insert_array(0, new_array_format);
|
||||
format = GeomVertexFormat::register_format(new_format);
|
||||
}
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -148,6 +362,9 @@ compare_to_impl(const GeomMunger *other) const {
|
|||
if (_tex_gen != om->_tex_gen) {
|
||||
return _tex_gen < om->_tex_gen ? -1 : 1;
|
||||
}
|
||||
if (_flags != om->_flags) {
|
||||
return _flags < om->_flags ? -1 : 1;
|
||||
}
|
||||
|
||||
return StandardMunger::compare_to_impl(other);
|
||||
}
|
||||
|
|
@ -162,8 +379,16 @@ compare_to_impl(const GeomMunger *other) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int CLP(GeomMunger)::
|
||||
geom_compare_to_impl(const GeomMunger *other) const {
|
||||
// We don't consider _texture and _tex_gen for this purpose; they
|
||||
// affect only whether the GL display list should be regenerated or
|
||||
// not, and don't require reconverting the vertices.
|
||||
return StandardMunger::geom_compare_to_impl(other);
|
||||
const CLP(GeomMunger) *om = DCAST(CLP(GeomMunger), other);
|
||||
if (_texture != om->_texture) {
|
||||
return _texture < om->_texture ? -1 : 1;
|
||||
}
|
||||
if (_tex_gen != om->_tex_gen) {
|
||||
return _tex_gen < om->_tex_gen ? -1 : 1;
|
||||
}
|
||||
if (_flags != om->_flags) {
|
||||
return _flags < om->_flags ? -1 : 1;
|
||||
}
|
||||
|
||||
return StandardMunger::compare_to_impl(other);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ class CLP(GeomContext);
|
|||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_GL CLP(GeomMunger) : public StandardMunger, public WeakPointerCallback {
|
||||
public:
|
||||
INLINE CLP(GeomMunger)(GraphicsStateGuardian *gsg, const RenderState *state);
|
||||
CLP(GeomMunger)(GraphicsStateGuardian *gsg, const RenderState *state);
|
||||
virtual ~CLP(GeomMunger)();
|
||||
ALLOC_DELETED_CHAIN(CLP(GeomMunger));
|
||||
|
||||
|
|
@ -43,7 +43,9 @@ public:
|
|||
|
||||
protected:
|
||||
virtual CPT(GeomVertexFormat) munge_format_impl(const GeomVertexFormat *orig,
|
||||
const GeomVertexAnimationSpec &animation);
|
||||
const GeomVertexAnimationSpec &animation);
|
||||
virtual CPT(GeomVertexFormat) premunge_format_impl(const GeomVertexFormat *orig);
|
||||
|
||||
virtual int compare_to_impl(const GeomMunger *other) const;
|
||||
virtual int geom_compare_to_impl(const GeomMunger *other) const;
|
||||
|
||||
|
|
@ -54,6 +56,12 @@ private:
|
|||
typedef pset<CLP(GeomContext) *> GeomContexts;
|
||||
GeomContexts _geom_contexts;
|
||||
|
||||
enum Flags {
|
||||
F_interleaved_arrays = 0x0001,
|
||||
F_parallel_arrays = 0x0002,
|
||||
};
|
||||
int _flags;
|
||||
|
||||
static GeomMunger *_deleted_chain;
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -79,6 +79,23 @@ ConfigVariableBool CLP(compile_and_execute)
|
|||
"for the first time, by allowing the display list to be "
|
||||
"rendered at the same time it is being compiled."));
|
||||
|
||||
ConfigVariableBool CLP(interleaved_arrays)
|
||||
("gl-interleaved-arrays", false,
|
||||
PRC_DESC("Set this true to convert OpenGL geometry such that the "
|
||||
"primary data columns vertex, normal, color, and texcoord "
|
||||
"are interleaved into one array when possible, or false to "
|
||||
"render geometry as it appears in the GeomVertexData. See "
|
||||
"also gl-parallel-arrays."));
|
||||
|
||||
ConfigVariableBool CLP(parallel_arrays)
|
||||
("gl-parallel-arrays", false,
|
||||
PRC_DESC("Set this true to convert OpenGL geometry such that each "
|
||||
"data column is a separate array, or false to "
|
||||
"render geometry as it appears in the GeomVertexData. See "
|
||||
"also gl-interleaved-arrays."));
|
||||
|
||||
extern ConfigVariableBool CLP(parallel_arrays);
|
||||
|
||||
void CLP(init_classes)() {
|
||||
CLP(GeomContext)::init_type();
|
||||
CLP(GeomMunger)::init_type();
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ extern ConfigVariableBool CLP(force_mipmaps);
|
|||
extern ConfigVariableBool CLP(color_mask);
|
||||
extern ConfigVariableBool CLP(support_occlusion_query);
|
||||
extern ConfigVariableBool CLP(compile_and_execute);
|
||||
extern ConfigVariableBool CLP(interleaved_arrays);
|
||||
extern ConfigVariableBool CLP(parallel_arrays);
|
||||
|
||||
extern EXPCL_GL void CLP(init_classes)();
|
||||
|
||||
|
|
|
|||
|
|
@ -59,6 +59,19 @@ get_total_size() const {
|
|||
return _total_size;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomCacheManager::evict_old_entries
|
||||
// Access: Public
|
||||
// Description: Trims the cache size down to get_max_size() by
|
||||
// evicting old cache entries as needed. It is assumed
|
||||
// that you already hold the lock before calling this
|
||||
// method.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void GeomCacheManager::
|
||||
evict_old_entries() {
|
||||
evict_old_entries(get_max_size(), true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomCacheManager::flush_level
|
||||
// Access: Public, Static
|
||||
|
|
|
|||
|
|
@ -56,6 +56,17 @@ GeomCacheManager::
|
|||
nassertv(false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomCacheManager::flush
|
||||
// Access: Published
|
||||
// Description: Immediately empties all elements in the cache.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GeomCacheManager::
|
||||
flush() {
|
||||
MutexHolder holder(_lock);
|
||||
evict_old_entries(0, false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomCacheManager::get_global_ptr
|
||||
// Access: Published, Static
|
||||
|
|
@ -71,23 +82,22 @@ get_global_ptr() {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomCacheManager::evict_old_entries
|
||||
// Access: Private
|
||||
// Description: Trims the cache size down to get_max_size() by
|
||||
// Access: Public
|
||||
// Description: Trims the cache size down to the specified size by
|
||||
// evicting old cache entries as needed. It is assumed
|
||||
// that you already hold the lock before calling this
|
||||
// method.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GeomCacheManager::
|
||||
evict_old_entries() {
|
||||
evict_old_entries(int max_size, bool keep_current) {
|
||||
int current_frame = ClockObject::get_global_clock()->get_frame_count();
|
||||
int min_frames = geom_cache_min_frames;
|
||||
|
||||
int max_size = get_max_size();
|
||||
while (_total_size > max_size) {
|
||||
PT(GeomCacheEntry) entry = _list->_next;
|
||||
nassertv(entry != _list);
|
||||
|
||||
if (current_frame - entry->_last_frame_used < min_frames) {
|
||||
if (keep_current && current_frame - entry->_last_frame_used < min_frames) {
|
||||
// Never mind, this one is too new.
|
||||
if (gobj_cat.is_debug()) {
|
||||
gobj_cat.debug()
|
||||
|
|
|
|||
|
|
@ -55,10 +55,13 @@ PUBLISHED:
|
|||
|
||||
INLINE int get_total_size() const;
|
||||
|
||||
void flush();
|
||||
|
||||
static GeomCacheManager *get_global_ptr();
|
||||
|
||||
public:
|
||||
void evict_old_entries();
|
||||
INLINE void evict_old_entries();
|
||||
void evict_old_entries(int max_size, bool keep_current);
|
||||
INLINE static void flush_level();
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -106,6 +106,55 @@ munge_data(const GeomVertexData *data) const {
|
|||
return ((GeomMunger *)this)->munge_data_impl(data);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomMunger::premunge_format
|
||||
// Access: Public
|
||||
// Description: This is similar to munge_format(), but it is done at
|
||||
// load time, to optimize a model for eventual rendering
|
||||
// on a particular GSG. At this point, we do not
|
||||
// necessarily know the final render state that will be
|
||||
// applied, so we cannot make any destructive changes to
|
||||
// the geom, its data, or its format.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CPT(GeomVertexFormat) GeomMunger::
|
||||
premunge_format(const GeomVertexFormat *format) const {
|
||||
return ((GeomMunger *)this)->do_premunge_format(format);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomMunger::premunge_data
|
||||
// Access: Public
|
||||
// Description: This is similar to munge_data(), but it is done at
|
||||
// load time, to optimize a model for eventual rendering
|
||||
// on a particular GSG. At this point, we do not
|
||||
// necessarily know the final render state that will be
|
||||
// applied, so we cannot make any destructive changes to
|
||||
// the geom, its data, or its format.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CPT(GeomVertexData) GeomMunger::
|
||||
premunge_data(const GeomVertexData *data) const {
|
||||
return ((GeomMunger *)this)->premunge_data_impl(data);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomMunger::premunge_geom
|
||||
// Access: Public
|
||||
// Description: This is similar to munge_geom(), but it is done at
|
||||
// load time, to optimize a model for eventual rendering
|
||||
// on a particular GSG. At this point, we do not
|
||||
// necessarily know the final render state that will be
|
||||
// applied, so we cannot make any destructive changes to
|
||||
// the geom, its data, or its format.
|
||||
//
|
||||
// Unlike munge_geom(), this result is not cached, since
|
||||
// the assumption is that this operation is performed at
|
||||
// load time once for each model.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void GeomMunger::
|
||||
premunge_geom(CPT(Geom) &geom, CPT(GeomVertexData) &data) const {
|
||||
((GeomMunger *)this)->premunge_geom_impl(geom, data);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomMunger::compare_to
|
||||
// Access: Public
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ remove_data(const GeomVertexData *data) {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomMunger::munge_geom
|
||||
// Access: Published
|
||||
// Access: Public
|
||||
// Description: Applies the indicated munger to the geom and its
|
||||
// data, and returns a (possibly different) geom and
|
||||
// data, according to the munger's whim.
|
||||
|
|
@ -262,6 +262,82 @@ munge_geom_impl(CPT(Geom) &, CPT(GeomVertexData) &, Thread *) {
|
|||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomMunger::do_premunge_format
|
||||
// Access: Protected
|
||||
// Description: The protected implementation of premunge_format(). This
|
||||
// exists just to cast away the const pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(GeomVertexFormat) GeomMunger::
|
||||
do_premunge_format(const GeomVertexFormat *format) {
|
||||
nassertr(_is_registered, NULL);
|
||||
nassertr(format->is_registered(), NULL);
|
||||
|
||||
MutexHolder holder(_formats_lock);
|
||||
|
||||
Formats::iterator fi;
|
||||
fi = _premunge_formats.find(format);
|
||||
if (fi != _premunge_formats.end()) {
|
||||
// This format was previously munged, so the answer will be the
|
||||
// same.
|
||||
return (*fi).second;
|
||||
}
|
||||
|
||||
// We have to munge this format for the first time.
|
||||
CPT(GeomVertexFormat) derived_format = premunge_format_impl(format);
|
||||
nassertr(derived_format->is_registered(), NULL);
|
||||
|
||||
// Store the answer in the map, so we can quickly get it next time.
|
||||
bool inserted = _premunge_formats.insert(Formats::value_type(format, derived_format)).second;
|
||||
nassertr(inserted, NULL);
|
||||
|
||||
return derived_format;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomMunger::premunge_format_impl
|
||||
// Access: Protected, Virtual
|
||||
// Description: Given a source GeomVertexFormat, converts it if
|
||||
// necessary to the appropriate format for rendering.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(GeomVertexFormat) GeomMunger::
|
||||
premunge_format_impl(const GeomVertexFormat *orig) {
|
||||
return orig;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomMunger::premunge_data_impl
|
||||
// Access: Protected, Virtual
|
||||
// Description: Given a source GeomVertexData, converts it as
|
||||
// necessary for rendering.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(GeomVertexData) GeomMunger::
|
||||
premunge_data_impl(const GeomVertexData *data) {
|
||||
nassertr(_is_registered, NULL);
|
||||
|
||||
CPT(GeomVertexFormat) orig_format = data->get_format();
|
||||
CPT(GeomVertexFormat) new_format = premunge_format(orig_format);
|
||||
|
||||
if (new_format == orig_format) {
|
||||
// Trivial case.
|
||||
return data;
|
||||
}
|
||||
|
||||
return data->convert_to(new_format);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomMunger::premunge_geom_impl
|
||||
// Access: Protected, Virtual
|
||||
// Description: Converts a Geom and/or its data as necessary.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool GeomMunger::
|
||||
premunge_geom_impl(CPT(Geom) &, CPT(GeomVertexData) &) {
|
||||
// The default implementation does nothing (the work has already
|
||||
// been done in premunge_format_impl() and premunge_data_impl()).
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomMunger::compare_to_impl
|
||||
// Access: Protected, Virtual
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ public:
|
|||
INLINE static void unregister_mungers_for_gsg(GraphicsStateGuardianBase *gsg);
|
||||
|
||||
INLINE CPT(GeomVertexFormat) munge_format(const GeomVertexFormat *format,
|
||||
const GeomVertexAnimationSpec &animation) const;
|
||||
const GeomVertexAnimationSpec &animation) const;
|
||||
|
||||
INLINE CPT(GeomVertexData) munge_data(const GeomVertexData *data) const;
|
||||
void remove_data(const GeomVertexData *data);
|
||||
|
|
@ -79,6 +79,10 @@ public:
|
|||
void munge_geom(CPT(Geom) &geom, CPT(GeomVertexData) &data,
|
||||
Thread *current_thread);
|
||||
|
||||
INLINE CPT(GeomVertexFormat) premunge_format(const GeomVertexFormat *format) const;
|
||||
INLINE CPT(GeomVertexData) premunge_data(const GeomVertexData *data) const;
|
||||
INLINE void premunge_geom(CPT(Geom) &geom, CPT(GeomVertexData) &data) const;
|
||||
|
||||
public:
|
||||
INLINE int compare_to(const GeomMunger &other) const;
|
||||
INLINE int geom_compare_to(const GeomMunger &other) const;
|
||||
|
|
@ -87,13 +91,20 @@ protected:
|
|||
INLINE void unregister_myself();
|
||||
|
||||
CPT(GeomVertexFormat) do_munge_format(const GeomVertexFormat *format,
|
||||
const GeomVertexAnimationSpec &animation);
|
||||
const GeomVertexAnimationSpec &animation);
|
||||
|
||||
virtual CPT(GeomVertexFormat) munge_format_impl(const GeomVertexFormat *orig,
|
||||
const GeomVertexAnimationSpec &animation);
|
||||
const GeomVertexAnimationSpec &animation);
|
||||
virtual CPT(GeomVertexData) munge_data_impl(const GeomVertexData *data);
|
||||
virtual bool munge_geom_impl(CPT(Geom) &geom, CPT(GeomVertexData) &data,
|
||||
Thread *current_thread);
|
||||
|
||||
|
||||
CPT(GeomVertexFormat) do_premunge_format(const GeomVertexFormat *format);
|
||||
virtual CPT(GeomVertexFormat) premunge_format_impl(const GeomVertexFormat *orig);
|
||||
virtual CPT(GeomVertexData) premunge_data_impl(const GeomVertexData *data);
|
||||
virtual bool premunge_geom_impl(CPT(Geom) &geom, CPT(GeomVertexData) &data);
|
||||
|
||||
virtual int compare_to_impl(const GeomMunger *other) const;
|
||||
virtual int geom_compare_to_impl(const GeomMunger *other) const;
|
||||
|
||||
|
|
@ -116,6 +127,7 @@ private:
|
|||
typedef pmap<CPT(GeomVertexFormat), CPT(GeomVertexFormat) > Formats;
|
||||
typedef pmap<GeomVertexAnimationSpec, Formats> FormatsByAnimation;
|
||||
FormatsByAnimation _formats_by_animation;
|
||||
Formats _premunge_formats;
|
||||
|
||||
// This mutex protects the above.
|
||||
Mutex _formats_lock;
|
||||
|
|
|
|||
|
|
@ -221,7 +221,7 @@ add_column(InternalName *name, int num_components,
|
|||
}
|
||||
|
||||
return add_column(GeomVertexColumn(name, num_components,
|
||||
numeric_type, contents, start));
|
||||
numeric_type, contents, start));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -391,6 +391,35 @@ is_data_subset_of(const GeomVertexArrayFormat &other) const {
|
|||
return (i == _columns.size());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomVertexArrayFormat::count_unused_space
|
||||
// Access: Published
|
||||
// Description: Returns the number of bytes per row that are not
|
||||
// assigned to any column.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int GeomVertexArrayFormat::
|
||||
count_unused_space() const {
|
||||
consider_sort_columns();
|
||||
|
||||
int unused_space = 0;
|
||||
int last_pos = 0;
|
||||
|
||||
Columns::const_iterator ci;
|
||||
for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
|
||||
const GeomVertexColumn *column = (*ci);
|
||||
if (column->get_start() > last_pos) {
|
||||
unused_space += (column->get_start() - last_pos);
|
||||
}
|
||||
last_pos = column->get_start() + column->get_total_bytes();
|
||||
}
|
||||
|
||||
if (_stride > last_pos) {
|
||||
unused_space += (_stride - last_pos);
|
||||
}
|
||||
|
||||
return unused_space;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomVertexArrayFormat::output
|
||||
// Access: Published
|
||||
|
|
@ -399,11 +428,21 @@ is_data_subset_of(const GeomVertexArrayFormat &other) const {
|
|||
void GeomVertexArrayFormat::
|
||||
output(ostream &out) const {
|
||||
Columns::const_iterator ci;
|
||||
int last_pos = 0;
|
||||
out << "[";
|
||||
for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
|
||||
const GeomVertexColumn *column = (*ci);
|
||||
if (column->get_start() > last_pos) {
|
||||
out << " ..." << (column->get_start() - last_pos) << "...";
|
||||
}
|
||||
out << " " << *column;
|
||||
last_pos = column->get_start() + column->get_total_bytes();
|
||||
}
|
||||
|
||||
if (_stride > last_pos) {
|
||||
out << " ..." << (_stride - last_pos) << "...";
|
||||
}
|
||||
|
||||
out << " ]";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ PUBLISHED:
|
|||
INLINE bool has_column(const InternalName *name) const;
|
||||
|
||||
bool is_data_subset_of(const GeomVertexArrayFormat &other) const;
|
||||
int count_unused_space() const;
|
||||
|
||||
void output(ostream &out) const;
|
||||
void write(ostream &out, int indent_level = 0) const;
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "indent.h"
|
||||
#include "pset.h"
|
||||
#include "config_pgraph.h"
|
||||
#include "graphicsStateGuardianBase.h"
|
||||
|
||||
TypeHandle GeomNode::_type_handle;
|
||||
|
||||
|
|
@ -639,6 +640,35 @@ is_geom_node() const {
|
|||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomNode::do_premunge
|
||||
// Access: Public
|
||||
// Description: Uses the indicated GSG to premunge the Geoms in this
|
||||
// node to optimize them for eventual rendering. See
|
||||
// SceneGraphReducer::premunge().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GeomNode::
|
||||
do_premunge(GraphicsStateGuardianBase *gsg,
|
||||
const RenderState *node_state,
|
||||
GeomTransformer &transformer) {
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
|
||||
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
|
||||
CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
|
||||
|
||||
GeomList::iterator gi;
|
||||
PT(GeomList) geoms = cdata->modify_geoms();
|
||||
for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
|
||||
GeomEntry &entry = (*gi);
|
||||
CPT(RenderState) geom_state = node_state->compose(entry._state);
|
||||
CPT(Geom) geom = entry._geom.get_read_pointer();
|
||||
PT(GeomMunger) munger = gsg->get_geom_munger(geom_state, current_thread);
|
||||
entry._geom = transformer.premunge_geom(geom, munger);
|
||||
}
|
||||
}
|
||||
CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomNode::compute_internal_bounds
|
||||
// Access: Protected, Virtual
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@
|
|||
#include "pvector.h"
|
||||
#include "copyOnWritePointer.h"
|
||||
|
||||
class GraphicsStateGuardianBase;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : GeomNode
|
||||
// Description : A node that holds Geom objects, renderable pieces of
|
||||
|
|
@ -89,6 +91,10 @@ public:
|
|||
|
||||
virtual bool is_geom_node() const;
|
||||
|
||||
void do_premunge(GraphicsStateGuardianBase *gsg,
|
||||
const RenderState *node_state,
|
||||
GeomTransformer &transformer);
|
||||
|
||||
protected:
|
||||
virtual PT(BoundingVolume) compute_internal_bounds(int pipeline_stage, Thread *current_thread) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "pStatTimer.h"
|
||||
#include "vector_int.h"
|
||||
#include "userVertexTransform.h"
|
||||
#include "geomMunger.h"
|
||||
|
||||
static PStatCollector apply_vertex_collector("*:Flatten:apply:vertex");
|
||||
static PStatCollector apply_texcoord_collector("*:Flatten:apply:texcoord");
|
||||
|
|
@ -709,3 +710,30 @@ collect_vertex_data(GeomNode *node, int collect_bits) {
|
|||
|
||||
return num_created;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomTransformer::premunge_geom
|
||||
// Access: Public
|
||||
// Description: Uses the indicated munger to premunge the given Geom
|
||||
// to optimize it for eventual rendering. See
|
||||
// SceneGraphReducer::premunge().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PT(Geom) GeomTransformer::
|
||||
premunge_geom(const Geom *geom, GeomMunger *munger) {
|
||||
// This method had been originally provided to cache the result for
|
||||
// a particular geom/munger and vdata/munger combination, similar to
|
||||
// the way other GeomTransformer methods work. On reflection, this
|
||||
// additional caching is not necessary, since the GeomVertexFormat
|
||||
// does its own caching, and there's no danger of that cache filling
|
||||
// up during the span of one frame.
|
||||
|
||||
CPT(GeomVertexData) vdata = geom->get_vertex_data();
|
||||
vdata = munger->premunge_data(vdata);
|
||||
CPT(Geom) pgeom = geom;
|
||||
munger->premunge_geom(pgeom, vdata);
|
||||
|
||||
PT(Geom) geom_copy = geom->make_copy();
|
||||
geom_copy->set_vertex_data(vdata);
|
||||
|
||||
return geom_copy;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
class GeomNode;
|
||||
class RenderState;
|
||||
class InternalName;
|
||||
class GeomMunger;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : GeomTransformer
|
||||
|
|
@ -73,6 +74,8 @@ public:
|
|||
int collect_vertex_data(Geom *geom, int collect_bits);
|
||||
int collect_vertex_data(GeomNode *node, int collect_bits);
|
||||
|
||||
PT(Geom) premunge_geom(const Geom *geom, GeomMunger *munger);
|
||||
|
||||
private:
|
||||
int _max_collect_vertices;
|
||||
|
||||
|
|
|
|||
|
|
@ -5570,6 +5570,33 @@ verify_complete(Thread *current_thread) const {
|
|||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePath::premunge_scene
|
||||
// Access: Published
|
||||
// Description: Walks through the scene graph beginning at the bottom
|
||||
// node, and internally adjusts any GeomVertexFormats
|
||||
// for optimal rendering on the indicated GSG. If this
|
||||
// step is not done prior to rendering, the formats will
|
||||
// be optimized at render time instead, for a small
|
||||
// cost.
|
||||
//
|
||||
// It is not normally necessary to do this on a model
|
||||
// loaded directly from disk, since the loader will do
|
||||
// this by default.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NodePath::
|
||||
premunge_scene(GraphicsStateGuardianBase *gsg) {
|
||||
nassertv_always(!is_empty());
|
||||
|
||||
CPT(RenderState) state = RenderState::make_empty();
|
||||
if (has_parent()) {
|
||||
state = get_parent().get_net_state();
|
||||
}
|
||||
|
||||
SceneGraphReducer gr;
|
||||
gr.premunge(node(), gsg, state);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePath::prepare_scene
|
||||
// Access: Published
|
||||
|
|
|
|||
|
|
@ -793,6 +793,7 @@ PUBLISHED:
|
|||
// Miscellaneous
|
||||
bool verify_complete(Thread *current_thread = Thread::get_current_thread()) const;
|
||||
|
||||
void premunge_scene(GraphicsStateGuardianBase *gsg);
|
||||
void prepare_scene(GraphicsStateGuardianBase *gsg);
|
||||
|
||||
void show_bounds();
|
||||
|
|
|
|||
|
|
@ -911,6 +911,30 @@ clear_cache() {
|
|||
return orig_size - new_size;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RenderState::clear_munger_cache
|
||||
// Access: Published, Static
|
||||
// Description: Completely empties the cache of state + gsg ->
|
||||
// munger, for all states and all gsg's. Normally there
|
||||
// is no need to empty this cache.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void RenderState::
|
||||
clear_munger_cache() {
|
||||
ReMutexHolder holder(*_states_lock);
|
||||
|
||||
// First, we need to count the number of times each RenderState
|
||||
// object is recorded in the cache.
|
||||
typedef pmap<const RenderState *, int> StateCount;
|
||||
StateCount state_count;
|
||||
|
||||
States::iterator si;
|
||||
for (si = _states->begin(); si != _states->end(); ++si) {
|
||||
RenderState *state = (RenderState *)(*si);
|
||||
state->_mungers.clear();
|
||||
state->_last_mi = state->_mungers.end();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RenderState::list_cycles
|
||||
// Access: Published, Static
|
||||
|
|
|
|||
|
|
@ -128,6 +128,7 @@ PUBLISHED:
|
|||
static int get_num_states();
|
||||
static int get_num_unused_states();
|
||||
static int clear_cache();
|
||||
static void clear_munger_cache();
|
||||
static void list_cycles(ostream &out);
|
||||
static void list_states(ostream &out);
|
||||
static bool validate_states();
|
||||
|
|
|
|||
|
|
@ -159,3 +159,20 @@ unify(PandaNode *root) {
|
|||
PStatTimer timer(_unify_collector);
|
||||
r_unify(root);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SceneGraphReducer::premunge
|
||||
// Access: Published
|
||||
// Description: Walks the scene graph rooted at this node and below,
|
||||
// and uses the indicated GSG to premunge every Geom
|
||||
// found to optimize it for eventual rendering on the
|
||||
// indicated GSG.
|
||||
//
|
||||
// This operation will also apply to stashed children.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void SceneGraphReducer::
|
||||
premunge(PandaNode *root, GraphicsStateGuardianBase *gsg,
|
||||
const RenderState *initial_state) {
|
||||
PStatTimer timer(_premunge_collector);
|
||||
r_premunge(root, gsg, initial_state);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ PStatCollector SceneGraphReducer::_apply_collector("*:Flatten:apply");
|
|||
PStatCollector SceneGraphReducer::_collect_collector("*:Flatten:collect");
|
||||
PStatCollector SceneGraphReducer::_make_nonindexed_collector("*:Flatten:make nonindexed");
|
||||
PStatCollector SceneGraphReducer::_unify_collector("*:Flatten:unify");
|
||||
PStatCollector SceneGraphReducer::_premunge_collector("*:Premunge");
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SceneGraphReducer::flatten
|
||||
|
|
@ -738,3 +739,32 @@ r_unify(PandaNode *node) {
|
|||
r_unify(children.get_child(i));
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SceneGraphReducer::r_premunge
|
||||
// Access: Private
|
||||
// Description: The recursive implementation of premunge().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void SceneGraphReducer::
|
||||
r_premunge(PandaNode *node, GraphicsStateGuardianBase *gsg,
|
||||
const RenderState *state) {
|
||||
CPT(RenderState) next_state = state->compose(node->get_state());
|
||||
|
||||
if (node->is_geom_node()) {
|
||||
GeomNode *geom_node = DCAST(GeomNode, node);
|
||||
geom_node->do_premunge(gsg, next_state, _transformer);
|
||||
}
|
||||
|
||||
int i;
|
||||
PandaNode::Children children = node->get_children();
|
||||
int num_children = children.get_num_children();
|
||||
for (i = 0; i < num_children; ++i) {
|
||||
r_premunge(children.get_child(i), gsg, next_state);
|
||||
}
|
||||
|
||||
PandaNode::Stashed stashed = node->get_stashed();
|
||||
int num_stashed = stashed.get_num_stashed();
|
||||
for (i = 0; i < num_stashed; ++i) {
|
||||
r_premunge(stashed.get_stashed(i), gsg, next_state);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,6 +134,9 @@ PUBLISHED:
|
|||
INLINE int make_nonindexed(PandaNode *root, int nonindexed_bits = ~0);
|
||||
INLINE void unify(PandaNode *root);
|
||||
|
||||
INLINE void premunge(PandaNode *root, GraphicsStateGuardianBase *gsg,
|
||||
const RenderState *initial_state);
|
||||
|
||||
protected:
|
||||
void r_apply_attribs(PandaNode *node, const AccumulatedAttribs &attribs,
|
||||
int attrib_types, GeomTransformer &transformer);
|
||||
|
|
@ -164,6 +167,9 @@ protected:
|
|||
int r_make_nonindexed(PandaNode *node, int collect_bits);
|
||||
void r_unify(PandaNode *node);
|
||||
|
||||
void r_premunge(PandaNode *node, GraphicsStateGuardianBase *gsg,
|
||||
const RenderState *state);
|
||||
|
||||
private:
|
||||
float _combine_radius;
|
||||
GeomTransformer _transformer;
|
||||
|
|
@ -173,6 +179,7 @@ private:
|
|||
static PStatCollector _collect_collector;
|
||||
static PStatCollector _make_nonindexed_collector;
|
||||
static PStatCollector _unify_collector;
|
||||
static PStatCollector _premunge_collector;
|
||||
};
|
||||
|
||||
#include "sceneGraphReducer.I"
|
||||
|
|
|
|||
Loading…
Reference in New Issue