egg-max-vertices, egg-max-indices, max-collect-indices

This commit is contained in:
David Rose 2006-07-13 16:09:08 +00:00
parent ee6a0c7382
commit 233f3e080d
16 changed files with 353 additions and 162 deletions

View File

@ -979,80 +979,6 @@ get_connected_shading() {
}
}
////////////////////////////////////////////////////////////////////
// Function: EggGroupNode::rebuild_vertex_pool
// Access: Published
// Description: Copies vertices used by the primitives at this group
// node (and below, if recurse is true) into the
// indicated vertex pool, and updates the primitives to
// reference this pool. It is up to the caller to
// parent the new vertex pool somewhere appropriate in
// the egg hierarchy.
////////////////////////////////////////////////////////////////////
void EggGroupNode::
rebuild_vertex_pool(EggVertexPool *vertex_pool, bool recurse) {
Children::iterator ci;
for (ci = _children.begin(); ci != _children.end(); ++ci) {
EggNode *child = *ci;
if (child->is_of_type(EggCompositePrimitive::get_class_type())) {
typedef pvector< PT(EggVertex) > Vertices;
typedef pvector<EggAttributes> Attributes;
Vertices vertices;
Attributes attributes;
EggCompositePrimitive *prim = DCAST(EggCompositePrimitive, child);
EggPrimitive::const_iterator pi;
for (pi = prim->begin(); pi != prim->end(); ++pi) {
vertices.push_back(*pi);
}
int i;
int num_components = prim->get_num_components();
for (i = 0; i < num_components; i++) {
attributes.push_back(*prim->get_component(i));
}
prim->clear();
Vertices::const_iterator vi;
for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
EggVertex *vertex = (*vi);
EggVertex *new_vertex = vertex_pool->create_unique_vertex(*vertex);
new_vertex->copy_grefs_from(*vertex);
prim->add_vertex(new_vertex);
}
for (i = 0; i < num_components; i++) {
prim->set_component(i, &attributes[i]);
}
} else if (child->is_of_type(EggPrimitive::get_class_type())) {
typedef pvector< PT(EggVertex) > Vertices;
Vertices vertices;
EggPrimitive *prim = DCAST(EggPrimitive, child);
EggPrimitive::const_iterator pi;
for (pi = prim->begin(); pi != prim->end(); ++pi) {
vertices.push_back(*pi);
}
prim->clear();
Vertices::const_iterator vi;
for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
EggVertex *vertex = (*vi);
EggVertex *new_vertex = vertex_pool->create_unique_vertex(*vertex);
new_vertex->copy_grefs_from(*vertex);
prim->add_vertex(new_vertex);
}
} else if (child->is_of_type(EggGroupNode::get_class_type())) {
if (recurse) {
DCAST(EggGroupNode, child)->rebuild_vertex_pool(vertex_pool, recurse);
}
}
}
}
////////////////////////////////////////////////////////////////////
// Function: EggGroupNode::unify_attributes
// Access: Published
@ -1268,6 +1194,145 @@ has_normals() const {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: EggGroupNode::rebuild_vertex_pools
// Access: Published
// Description: Copies vertices used by the primitives at this group
// node (and below, if recurse is true) into one or more
// new vertex pools, and updates the primitives to
// reference these pools. It is up to the caller to
// parent the newly-created vertex pools somewhere
// appropriate in the egg hierarchy.
//
// No more than max_vertices will be placed into any one
// vertex pool. This is the sole criteria for splitting
// vertex pools.
////////////////////////////////////////////////////////////////////
void EggGroupNode::
rebuild_vertex_pools(EggVertexPools &vertex_pools, unsigned int max_vertices,
bool recurse) {
Children::iterator ci;
for (ci = _children.begin(); ci != _children.end(); ++ci) {
EggNode *child = *ci;
if (child->is_of_type(EggPrimitive::get_class_type())) {
typedef pvector< PT(EggVertex) > Vertices;
Vertices vertices;
EggPrimitive *prim = DCAST(EggPrimitive, child);
// Copy all of the vertices out.
EggPrimitive::const_iterator pi;
for (pi = prim->begin(); pi != prim->end(); ++pi) {
vertices.push_back(*pi);
}
if (prim->is_of_type(EggCompositePrimitive::get_class_type())) {
// A compositive primitive has the additional complication of
// dealing with its attributes.
typedef pvector<EggAttributes> Attributes;
Attributes attributes;
EggCompositePrimitive *cprim = DCAST(EggCompositePrimitive, prim);
int i;
int num_components = cprim->get_num_components();
for (i = 0; i < num_components; i++) {
attributes.push_back(*cprim->get_component(i));
}
cprim->clear();
for (i = 0; i < num_components; i++) {
cprim->set_component(i, &attributes[i]);
}
} else {
prim->clear();
}
// Now look for a new home for the vertices. First, see if any
// of the vertex pools we've already created already have a copy
// of each one of the vertices.
bool found_pool = false;
EggVertexPool *best_pool = NULL;
int best_new_vertices = 0;
Vertices new_vertices;
EggVertexPools::iterator vpi;
for (vpi = vertex_pools.begin();
vpi != vertex_pools.end() && !found_pool;
++vpi) {
EggVertexPool *vertex_pool = (*vpi);
int num_new_vertices = 0;
new_vertices.clear();
new_vertices.reserve(vertices.size());
Vertices::const_iterator vi;
for (vi = vertices.begin();
vi != vertices.end() && !found_pool;
++vi) {
EggVertex *vertex = (*vi);
EggVertex *new_vertex = vertex_pool->find_matching_vertex(*vertex);
new_vertices.push_back(new_vertex);
if (new_vertex == (EggVertex *)NULL) {
++num_new_vertices;
}
}
if (num_new_vertices == 0) {
// Great, we found a vertex pool that already shares all
// these vertices. No need to look any further.
found_pool = true;
} else if (vertex_pool->size() + num_new_vertices <= max_vertices) {
// We would have to add some vertices to this pool, so this
// vertex pool qualifies only if the number of vertices we
// have to add would still keep it within our limit.
if (best_pool == (EggVertexPool *)NULL ||
num_new_vertices < best_new_vertices) {
// This is currently our most favorable vertex pool.
best_pool = vertex_pool;
best_new_vertices = num_new_vertices;
}
}
}
if (!found_pool) {
if (best_pool == (EggVertexPool *)NULL) {
// There was no vertex pool that qualified. We will have to
// create a new vertex pool.
best_pool = new EggVertexPool("");
vertex_pools.push_back(best_pool);
}
new_vertices.clear();
new_vertices.reserve(vertices.size());
Vertices::const_iterator vi;
for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
EggVertex *vertex = (*vi);
EggVertex *new_vertex = best_pool->create_unique_vertex(*vertex);
new_vertex->copy_grefs_from(*vertex);
new_vertices.push_back(new_vertex);
}
}
Vertices::const_iterator vi;
nassertv(new_vertices.size() == vertices.size());
for (vi = new_vertices.begin(); vi != new_vertices.end(); ++vi) {
EggVertex *new_vertex = (*vi);
nassertv(new_vertex != (EggVertex *)NULL);
prim->add_vertex(new_vertex);
}
} else if (child->is_of_type(EggGroupNode::get_class_type())) {
if (recurse) {
DCAST(EggGroupNode, child)->rebuild_vertex_pools(vertex_pools, max_vertices, recurse);
}
}
}
}
////////////////////////////////////////////////////////////////////
// Function: EggGroupNode::update_under
// Access: Protected, Virtual

View File

@ -22,6 +22,7 @@
#include "pandabase.h"
#include "eggNode.h"
#include "eggVertexPool.h"
#include "coordinateSystem.h"
#include "typedObject.h"
@ -150,7 +151,6 @@ PUBLISHED:
int remove_invalid_primitives(bool recurse);
void clear_connected_shading();
void get_connected_shading();
void rebuild_vertex_pool(EggVertexPool *vertex_pool, bool recurse);
void unify_attributes(bool use_connected_shading, bool allow_per_primitive,
bool recurse);
void apply_last_attribute(bool recurse);
@ -160,6 +160,11 @@ PUBLISHED:
virtual bool joint_has_primitives() const;
virtual bool has_normals() const;
public:
void rebuild_vertex_pools(EggVertexPools &vertex_pools,
unsigned int max_vertices,
bool recurse);
protected:
virtual void update_under(int depth_offset);

View File

@ -467,6 +467,28 @@ create_unique_vertex(const EggVertex &copy) {
return add_vertex(new EggVertex(copy));
}
////////////////////////////////////////////////////////////////////
// Function: EggVertexPool::find_matching_vertex
// Access: Public
// Description: If the EggVertexPool already has a vertex matching
// the indicated vertex, returns it; otherwise, returns
// NULL. This is similar to create_unique_vertex()
// except that a new vertex is never created.
////////////////////////////////////////////////////////////////////
EggVertex *EggVertexPool::
find_matching_vertex(const EggVertex &copy) {
UniqueVertices::iterator uvi;
uvi = _unique_vertices.find((EggVertex *)&copy);
if (uvi != _unique_vertices.end()) {
// There was already such a vertex. Return it.
return (*uvi);
}
// No matching vertex.
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: EggVertexPool::remove_vertex

View File

@ -27,6 +27,7 @@
#include "pointerTo.h"
#include "pset.h"
#include "pvector.h"
#include "pmap.h"
#include "lmatrix.h"
#include "iterator_types.h"
@ -125,6 +126,7 @@ PUBLISHED:
// already one identical to the indicated vertex, or returns the
// existing one if there is.
EggVertex *create_unique_vertex(const EggVertex &copy);
EggVertex *find_matching_vertex(const EggVertex &copy);
void remove_vertex(EggVertex *vertex);
int remove_unused_vertices();
@ -165,6 +167,8 @@ private:
friend class EggVertex;
};
typedef pvector< PT(EggVertexPool) > EggVertexPools;
#include "eggVertexPool.I"
#endif

View File

@ -135,6 +135,16 @@ ConfigVariableEnum<EggRenderMode::AlphaMode> egg_alpha_mode
"transparent, because of a <RGBA> that involves a non-unity alpha, "
"or because of a four-channel texture."));
ConfigVariableInt egg_max_vertices
("egg-max-vertices", 65535,
PRC_DESC("Specifies the maximum number of vertices that will be "
"added to any one GeomVertexData by the egg loader."));
ConfigVariableInt egg_max_indices
("egg-max-indices", 65535,
PRC_DESC("Specifies the maximum number of vertex indices that will be "
"added to any one GeomPrimitive by the egg loader."));
ConfigureFn(config_egg2pg) {
init_libegg2pg();
}

View File

@ -51,6 +51,8 @@ extern EXPCL_PANDAEGG ConfigVariableBool egg_load_classic_nurbs_curves;
extern EXPCL_PANDAEGG ConfigVariableBool egg_accept_errors;
extern EXPCL_PANDAEGG ConfigVariableBool egg_suppress_hidden;
extern EXPCL_PANDAEGG ConfigVariableEnum<EggRenderMode::AlphaMode> egg_alpha_mode;
extern EXPCL_PANDAEGG ConfigVariableInt egg_max_vertices;
extern EXPCL_PANDAEGG ConfigVariableInt egg_max_indices;
extern EXPCL_PANDAEGG void init_libegg2pg();

View File

@ -322,11 +322,13 @@ make_polyset(EggBin *egg_bin, PandaNode *parent, const LMatrix4d *transform,
return;
}
// Generate an optimal vertex pool for the polygons within just the
// bin (which translates directly to an optimal GeomVertexData
// structure).
PT(EggVertexPool) vertex_pool = new EggVertexPool("bin");
egg_bin->rebuild_vertex_pool(vertex_pool, false);
// Generate an optimal vertex pool (or multiple vertex pools, if we
// have a lot of vertex) for the polygons within just the bin. Each
// EggVertexPool translates directly to an optimal GeomVertexData
// structure.
EggVertexPools vertex_pools;
egg_bin->rebuild_vertex_pools(vertex_pools, (unsigned int)egg_max_vertices,
false);
if (egg_mesh) {
// If we're using the mesher, mesh now.
@ -342,67 +344,87 @@ make_polyset(EggBin *egg_bin, PandaNode *parent, const LMatrix4d *transform,
// vertices, so we can copy them to the GeomVertexData.
egg_bin->apply_first_attribute(false);
egg_bin->post_apply_flat_attribute(false);
vertex_pool->remove_unused_vertices();
// vertex_pool->write(cerr, 0);
// egg_bin->write(cerr, 0);
// Now create a handful of GeomPrimitives corresponding to the
// various types of primitives we have.
Primitives primitives;
for (ci = egg_bin->begin(); ci != egg_bin->end(); ++ci) {
EggPrimitive *egg_prim;
DCAST_INTO_V(egg_prim, (*ci));
make_primitive(render_state, egg_prim, primitives);
}
PT(GeomNode) geom_node;
if (!primitives.empty()) {
LMatrix4d mat;
if (transform != NULL) {
mat = (*transform);
} else {
mat = egg_bin->get_vertex_to_node();
}
// Now iterate through each EggVertexPool. Normally, there's only
// one, but if we have a really big mesh, it might have been split
// into multiple vertex pools (to keep each one within the
// egg_max_vertices constraint).
EggVertexPools::iterator vpi;
for (vpi = vertex_pools.begin(); vpi != vertex_pools.end(); ++vpi) {
EggVertexPool *vertex_pool = (*vpi);
vertex_pool->remove_unused_vertices();
// vertex_pool->write(cerr, 0);
// Now convert the vertex pool to a GeomVertexData.
nassertv(vertex_pool != (EggVertexPool *)NULL);
PT(GeomVertexData) vertex_data =
make_vertex_data(render_state, vertex_pool, egg_bin, mat,
is_dynamic, character_maker);
nassertv(vertex_data != (GeomVertexData *)NULL);
// And create a Geom to hold the primitives.
PT(Geom) geom = new Geom(vertex_data);
// Add each new primitive to the Geom.
Primitives::const_iterator pi;
for (pi = primitives.begin(); pi != primitives.end(); ++pi) {
GeomPrimitive *primitive = (*pi).second;
geom->add_primitive(primitive);
}
// vertex_data->write(cerr);
// geom->write(cerr);
// render_state->_state->write(cerr, 0);
// Now, is our parent node a GeomNode, or just an ordinary
// PandaNode? If it's a GeomNode, we can add the new Geom directly
// to our parent; otherwise, we need to create a new node.
PT(GeomNode) geom_node;
if (parent->is_geom_node() && !render_state->_hidden) {
geom_node = DCAST(GeomNode, parent);
} else {
geom_node = new GeomNode(egg_bin->get_name());
if (render_state->_hidden) {
parent->add_stashed(geom_node);
} else {
parent->add_child(geom_node);
// Create a handful of GeomPrimitives corresponding to the various
// types of primitives that reference this vertex pool.
UniquePrimitives unique_primitives;
Primitives primitives;
for (ci = egg_bin->begin(); ci != egg_bin->end(); ++ci) {
EggPrimitive *egg_prim;
DCAST_INTO_V(egg_prim, (*ci));
if (egg_prim->get_pool() == vertex_pool) {
make_primitive(render_state, egg_prim, unique_primitives, primitives);
}
}
geom_node->add_geom(geom, render_state->_state);
if (egg_show_normals) {
if (!primitives.empty()) {
LMatrix4d mat;
if (transform != NULL) {
mat = (*transform);
} else {
mat = egg_bin->get_vertex_to_node();
}
// Now convert this vertex pool to a GeomVertexData.
PT(GeomVertexData) vertex_data =
make_vertex_data(render_state, vertex_pool, egg_bin, mat,
is_dynamic, character_maker);
nassertv(vertex_data != (GeomVertexData *)NULL);
// And create a Geom to hold the primitives.
PT(Geom) geom = new Geom(vertex_data);
// Add each new primitive to the Geom.
Primitives::const_iterator pi;
for (pi = primitives.begin(); pi != primitives.end(); ++pi) {
GeomPrimitive *primitive = (*pi);
geom->add_primitive(primitive);
}
// vertex_data->write(cerr);
// geom->write(cerr);
// render_state->_state->write(cerr, 0);
// Create a new GeomNode if we haven't already.
if (geom_node == (GeomNode *)NULL) {
// Now, is our parent node a GeomNode, or just an ordinary
// PandaNode? If it's a GeomNode, we can add the new Geom directly
// to our parent; otherwise, we need to create a new node.
if (parent->is_geom_node() && !render_state->_hidden) {
geom_node = DCAST(GeomNode, parent);
} else {
geom_node = new GeomNode(egg_bin->get_name());
if (render_state->_hidden) {
parent->add_stashed(geom_node);
} else {
parent->add_child(geom_node);
}
}
}
geom_node->add_geom(geom, render_state->_state);
}
}
if (geom_node != (GeomNode *)NULL && egg_show_normals) {
// Create some more geometry to visualize each normal.
for (vpi = vertex_pools.begin(); vpi != vertex_pools.end(); ++vpi) {
EggVertexPool *vertex_pool = (*vpi);
show_normals(vertex_pool, geom_node);
}
}
@ -2243,6 +2265,7 @@ record_morph(GeomVertexArrayFormat *array_format,
////////////////////////////////////////////////////////////////////
void EggLoader::
make_primitive(const EggRenderState *render_state, EggPrimitive *egg_prim,
EggLoader::UniquePrimitives &unique_primitives,
EggLoader::Primitives &primitives) {
PT(GeomPrimitive) primitive;
if (egg_prim->is_of_type(EggPolygon::get_class_type())) {
@ -2287,9 +2310,27 @@ make_primitive(const EggRenderState *render_state, EggPrimitive *egg_prim,
// Insert the primitive into the set, but if we already have a
// primitive of that type, reset the pointer to that one instead.
PrimitiveUnifier pu(primitive);
pair<Primitives::iterator, bool> result =
primitives.insert(Primitives::value_type(pu, primitive));
primitive = (*result.first).second;
pair<UniquePrimitives::iterator, bool> result =
unique_primitives.insert(UniquePrimitives::value_type(pu, primitive));
if (result.second) {
// This was the first primitive of this type. Store it.
primitives.push_back(primitive);
}
GeomPrimitive *orig_prim = (*result.first).second;
// Make sure we don't try to put more than egg_max_indices into any
// one GeomPrimitive.
if (orig_prim->get_num_vertices() + egg_prim->size() <= (unsigned int)egg_max_indices) {
primitive = orig_prim;
} else if (orig_prim != primitive) {
// If the old primitive is full, keep the new primitive from now
// on.
(*result.first).second = primitive;
primitives.push_back(primitive);
}
// Now add the vertices.
EggPrimitive::const_iterator vi;

View File

@ -109,7 +109,8 @@ private:
TypeHandle _type;
GeomPrimitive::ShadeModel _shade_model;
};
typedef pmap<PrimitiveUnifier, PT(GeomPrimitive) > Primitives;
typedef pmap<PrimitiveUnifier, PT(GeomPrimitive) > UniquePrimitives;
typedef pvector< PT(GeomPrimitive) > Primitives;
void show_normals(EggVertexPool *vertex_pool, GeomNode *geom_node);
@ -151,7 +152,9 @@ private:
InternalName *column_name, int num_components);
void make_primitive(const EggRenderState *render_state,
EggPrimitive *egg_prim, Primitives &primitives);
EggPrimitive *egg_prim,
UniquePrimitives &unique_primitives,
Primitives &primitives);
void set_portal_polygon(EggGroup *egg_group, PortalNode *pnode);
PT(EggPolygon) find_first_polygon(EggGroup *egg_group);

View File

@ -177,15 +177,19 @@ rotate() const {
// Function: Geom::unify
// Access: Published
// Description: Unifies all of the primitives contained within this
// Geom into a single primitive object. This may
// require decomposing the primitives if, for instance,
// the Geom contains both triangle strips and triangle
// fans.
// Geom into a single (or as few as possible, within the
// constraints of max_indices) primitive objects. This
// may require decomposing the primitives if, for
// instance, the Geom contains both triangle strips and
// triangle fans.
//
// max_indices represents the maximum number of indices
// that will be put in any one GeomPrimitive.
////////////////////////////////////////////////////////////////////
INLINE PT(Geom) Geom::
unify() const {
unify(int max_indices) const {
PT(Geom) new_geom = make_copy();
new_geom->unify_in_place();
new_geom->unify_in_place(max_indices);
return new_geom;
}

View File

@ -512,17 +512,21 @@ rotate_in_place() {
// Function: Geom::unify_in_place
// Access: Published
// Description: Unifies all of the primitives contained within this
// Geom into a single primitive object. This may
// require decomposing the primitives if, for instance,
// the Geom contains both triangle strips and triangle
// fans.
// Geom into a single (or as few as possible, within the
// constraints of max_indices) primitive objects. This
// may require decomposing the primitives if, for
// instance, the Geom contains both triangle strips and
// triangle fans.
//
// max_indices represents the maximum number of indices
// that will be put in any one GeomPrimitive.
//
// Don't call this in a downstream thread unless you
// don't mind it blowing away other changes you might
// have recently made in an upstream thread.
////////////////////////////////////////////////////////////////////
void Geom::
unify_in_place() {
unify_in_place(int max_indices) {
Thread *current_thread = Thread::get_current_thread();
if (get_num_primitives() <= 1) {
// If we don't have more than one primitive to start with, no need
@ -564,8 +568,7 @@ unify_in_place() {
}
}
// At the end of the day, we have just one primitive, which becomes
// the one primitive in our list of primitives.
// Now we have just one primitive.
nassertv(new_prim->check_valid(cdata->_data));
// The new primitive, naturally, inherits the Geom's overall shade
@ -573,7 +576,36 @@ unify_in_place() {
new_prim->set_shade_model(cdata->_shade_model);
cdata->_primitives.clear();
cdata->_primitives.push_back(new_prim);
// Should we split it up again to satisfy max_indices?
if (new_prim->get_num_vertices() > max_indices) {
// Copy new_prim into smaller prims, no one of which has more than
// max_indices vertices.
int i = 0;
while (i < new_prim->get_num_primitives()) {
PT(GeomPrimitive) smaller = new_prim->make_copy();
smaller->clear_vertices();
while (i < new_prim->get_num_primitives() &&
smaller->get_num_vertices() + new_prim->get_primitive_num_vertices(i) < max_indices) {
int start = new_prim->get_primitive_start(i);
int end = new_prim->get_primitive_end(i);
for (int n = start; n < end; ++n) {
smaller->add_vertex(new_prim->get_vertex(n));
}
smaller->close_primitive();
++i;
}
cdata->_primitives.push_back(smaller);
}
} else {
// The new_prim has few enough vertices; keep it.
cdata->_primitives.push_back(new_prim);
}
cdata->_modified = Geom::get_next_modified();
clear_cache_stage(current_thread);

View File

@ -93,11 +93,11 @@ PUBLISHED:
INLINE PT(Geom) decompose() const;
INLINE PT(Geom) rotate() const;
INLINE PT(Geom) unify() const;
INLINE PT(Geom) unify(int max_indices) const;
void decompose_in_place();
void rotate_in_place();
void unify_in_place();
void unify_in_place(int max_indices);
virtual bool copy_primitives_from(const Geom *other);

View File

@ -175,8 +175,8 @@ set_index_type(GeomPrimitive::NumericType index_type) {
// Access: Published
// Description: Adds the indicated vertex to the list of vertex
// indices used by the graphics primitive type. To
// define primitive, you must call add_vertex() for each
// vertex of the new primitve, and then call
// define a primitive, you must call add_vertex() for
// each vertex of the new primitive, and then call
// close_primitive() after you have specified the last
// vertex of each primitive.
//

View File

@ -188,7 +188,7 @@ ConfigVariableBool retransform_sprites
"necessary in order for fog to work correctly on the sprites."));
ConfigVariableInt max_collect_vertices
("max-collect-vertices", 1024,
("max-collect-vertices", 65535,
PRC_DESC("Specifies the maximum number of vertices that are allowed to be "
"accumulated into any one GeomVertexData structure as a result "
"of collecting objects together during a flatten operation. "
@ -198,7 +198,7 @@ ConfigVariableInt max_collect_vertices
"GeomVertexData structure."));
ConfigVariableInt max_collect_indices
("max-collect-indices", 1024,
("max-collect-indices", 65535,
PRC_DESC("Specifies the maximum number of vertex indices that are allowed "
"to be accumulated into any one GeomPrimitive as a result "
"of collecting objects together during a flatten operation. "

View File

@ -432,13 +432,16 @@ check_valid() const {
// triangle strips and triangle fans, being decomposed
// into triangles. See also Geom::unify().
//
// max_indices represents the maximum number of indices
// that will be put in any one GeomPrimitive.
//
// In order for this to be successful, the primitives
// must reference the same GeomVertexData, have the same
// fundamental primitive type, and have compatible shade
// models.
////////////////////////////////////////////////////////////////////
void GeomNode::
unify() {
unify(int max_indices) {
Thread *current_thread = Thread::get_current_thread();
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
@ -479,7 +482,7 @@ unify() {
// Finally, go back through and unify the resulting geom(s).
for (gi = new_geoms->begin(); gi != new_geoms->end(); ++gi) {
const GeomEntry &entry = (*gi);
entry._geom->unify_in_place();
entry._geom->unify_in_place(max_indices);
}
}
CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);

View File

@ -72,7 +72,7 @@ PUBLISHED:
INLINE void remove_all_geoms();
bool check_valid() const;
void unify();
void unify(int max_indices);
void write_geoms(ostream &out, int indent_level) const;
void write_verbose(ostream &out, int indent_level) const;

View File

@ -739,7 +739,7 @@ void SceneGraphReducer::
r_unify(PandaNode *node) {
if (node->is_geom_node()) {
GeomNode *geom_node = DCAST(GeomNode, node);
geom_node->unify();
geom_node->unify(max_collect_indices);
}
PandaNode::Children children = node->get_children();