mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00
egg-max-vertices, egg-max-indices, max-collect-indices
This commit is contained in:
parent
ee6a0c7382
commit
233f3e080d
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -467,6 +467,28 @@ create_unique_vertex(const EggVertex ©) {
|
||||
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 ©) {
|
||||
UniqueVertices::iterator uvi;
|
||||
uvi = _unique_vertices.find((EggVertex *)©);
|
||||
|
||||
if (uvi != _unique_vertices.end()) {
|
||||
// There was already such a vertex. Return it.
|
||||
return (*uvi);
|
||||
}
|
||||
|
||||
// No matching vertex.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggVertexPool::remove_vertex
|
||||
|
@ -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 ©);
|
||||
EggVertex *find_matching_vertex(const EggVertex ©);
|
||||
|
||||
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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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.
|
||||
//
|
||||
|
@ -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. "
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user