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
|
// Function: EggGroupNode::unify_attributes
|
||||||
// Access: Published
|
// Access: Published
|
||||||
@ -1268,6 +1194,145 @@ has_normals() const {
|
|||||||
return false;
|
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
|
// Function: EggGroupNode::update_under
|
||||||
// Access: Protected, Virtual
|
// Access: Protected, Virtual
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "pandabase.h"
|
#include "pandabase.h"
|
||||||
|
|
||||||
#include "eggNode.h"
|
#include "eggNode.h"
|
||||||
|
#include "eggVertexPool.h"
|
||||||
|
|
||||||
#include "coordinateSystem.h"
|
#include "coordinateSystem.h"
|
||||||
#include "typedObject.h"
|
#include "typedObject.h"
|
||||||
@ -150,7 +151,6 @@ PUBLISHED:
|
|||||||
int remove_invalid_primitives(bool recurse);
|
int remove_invalid_primitives(bool recurse);
|
||||||
void clear_connected_shading();
|
void clear_connected_shading();
|
||||||
void get_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,
|
void unify_attributes(bool use_connected_shading, bool allow_per_primitive,
|
||||||
bool recurse);
|
bool recurse);
|
||||||
void apply_last_attribute(bool recurse);
|
void apply_last_attribute(bool recurse);
|
||||||
@ -160,6 +160,11 @@ PUBLISHED:
|
|||||||
virtual bool joint_has_primitives() const;
|
virtual bool joint_has_primitives() const;
|
||||||
virtual bool has_normals() const;
|
virtual bool has_normals() const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void rebuild_vertex_pools(EggVertexPools &vertex_pools,
|
||||||
|
unsigned int max_vertices,
|
||||||
|
bool recurse);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void update_under(int depth_offset);
|
virtual void update_under(int depth_offset);
|
||||||
|
|
||||||
|
@ -467,6 +467,28 @@ create_unique_vertex(const EggVertex ©) {
|
|||||||
return add_vertex(new 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 ©) {
|
||||||
|
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
|
// Function: EggVertexPool::remove_vertex
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include "pointerTo.h"
|
#include "pointerTo.h"
|
||||||
#include "pset.h"
|
#include "pset.h"
|
||||||
|
#include "pvector.h"
|
||||||
#include "pmap.h"
|
#include "pmap.h"
|
||||||
#include "lmatrix.h"
|
#include "lmatrix.h"
|
||||||
#include "iterator_types.h"
|
#include "iterator_types.h"
|
||||||
@ -125,6 +126,7 @@ PUBLISHED:
|
|||||||
// already one identical to the indicated vertex, or returns the
|
// already one identical to the indicated vertex, or returns the
|
||||||
// existing one if there is.
|
// existing one if there is.
|
||||||
EggVertex *create_unique_vertex(const EggVertex ©);
|
EggVertex *create_unique_vertex(const EggVertex ©);
|
||||||
|
EggVertex *find_matching_vertex(const EggVertex ©);
|
||||||
|
|
||||||
void remove_vertex(EggVertex *vertex);
|
void remove_vertex(EggVertex *vertex);
|
||||||
int remove_unused_vertices();
|
int remove_unused_vertices();
|
||||||
@ -165,6 +167,8 @@ private:
|
|||||||
friend class EggVertex;
|
friend class EggVertex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef pvector< PT(EggVertexPool) > EggVertexPools;
|
||||||
|
|
||||||
#include "eggVertexPool.I"
|
#include "eggVertexPool.I"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -135,6 +135,16 @@ ConfigVariableEnum<EggRenderMode::AlphaMode> egg_alpha_mode
|
|||||||
"transparent, because of a <RGBA> that involves a non-unity alpha, "
|
"transparent, because of a <RGBA> that involves a non-unity alpha, "
|
||||||
"or because of a four-channel texture."));
|
"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) {
|
ConfigureFn(config_egg2pg) {
|
||||||
init_libegg2pg();
|
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_accept_errors;
|
||||||
extern EXPCL_PANDAEGG ConfigVariableBool egg_suppress_hidden;
|
extern EXPCL_PANDAEGG ConfigVariableBool egg_suppress_hidden;
|
||||||
extern EXPCL_PANDAEGG ConfigVariableEnum<EggRenderMode::AlphaMode> egg_alpha_mode;
|
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();
|
extern EXPCL_PANDAEGG void init_libegg2pg();
|
||||||
|
|
||||||
|
@ -322,11 +322,13 @@ make_polyset(EggBin *egg_bin, PandaNode *parent, const LMatrix4d *transform,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate an optimal vertex pool for the polygons within just the
|
// Generate an optimal vertex pool (or multiple vertex pools, if we
|
||||||
// bin (which translates directly to an optimal GeomVertexData
|
// have a lot of vertex) for the polygons within just the bin. Each
|
||||||
// structure).
|
// EggVertexPool translates directly to an optimal GeomVertexData
|
||||||
PT(EggVertexPool) vertex_pool = new EggVertexPool("bin");
|
// structure.
|
||||||
egg_bin->rebuild_vertex_pool(vertex_pool, false);
|
EggVertexPools vertex_pools;
|
||||||
|
egg_bin->rebuild_vertex_pools(vertex_pools, (unsigned int)egg_max_vertices,
|
||||||
|
false);
|
||||||
|
|
||||||
if (egg_mesh) {
|
if (egg_mesh) {
|
||||||
// If we're using the mesher, mesh now.
|
// 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.
|
// vertices, so we can copy them to the GeomVertexData.
|
||||||
egg_bin->apply_first_attribute(false);
|
egg_bin->apply_first_attribute(false);
|
||||||
egg_bin->post_apply_flat_attribute(false);
|
egg_bin->post_apply_flat_attribute(false);
|
||||||
vertex_pool->remove_unused_vertices();
|
|
||||||
|
|
||||||
// vertex_pool->write(cerr, 0);
|
|
||||||
// egg_bin->write(cerr, 0);
|
// egg_bin->write(cerr, 0);
|
||||||
|
|
||||||
// Now create a handful of GeomPrimitives corresponding to the
|
PT(GeomNode) geom_node;
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!primitives.empty()) {
|
// Now iterate through each EggVertexPool. Normally, there's only
|
||||||
LMatrix4d mat;
|
// one, but if we have a really big mesh, it might have been split
|
||||||
if (transform != NULL) {
|
// into multiple vertex pools (to keep each one within the
|
||||||
mat = (*transform);
|
// egg_max_vertices constraint).
|
||||||
} else {
|
EggVertexPools::iterator vpi;
|
||||||
mat = egg_bin->get_vertex_to_node();
|
for (vpi = vertex_pools.begin(); vpi != vertex_pools.end(); ++vpi) {
|
||||||
}
|
EggVertexPool *vertex_pool = (*vpi);
|
||||||
|
vertex_pool->remove_unused_vertices();
|
||||||
// Now convert the vertex pool to a GeomVertexData.
|
// vertex_pool->write(cerr, 0);
|
||||||
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
|
// Create a handful of GeomPrimitives corresponding to the various
|
||||||
// PandaNode? If it's a GeomNode, we can add the new Geom directly
|
// types of primitives that reference this vertex pool.
|
||||||
// to our parent; otherwise, we need to create a new node.
|
UniquePrimitives unique_primitives;
|
||||||
PT(GeomNode) geom_node;
|
Primitives primitives;
|
||||||
if (parent->is_geom_node() && !render_state->_hidden) {
|
for (ci = egg_bin->begin(); ci != egg_bin->end(); ++ci) {
|
||||||
geom_node = DCAST(GeomNode, parent);
|
EggPrimitive *egg_prim;
|
||||||
|
DCAST_INTO_V(egg_prim, (*ci));
|
||||||
} else {
|
if (egg_prim->get_pool() == vertex_pool) {
|
||||||
geom_node = new GeomNode(egg_bin->get_name());
|
make_primitive(render_state, egg_prim, unique_primitives, primitives);
|
||||||
if (render_state->_hidden) {
|
|
||||||
parent->add_stashed(geom_node);
|
|
||||||
} else {
|
|
||||||
parent->add_child(geom_node);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
geom_node->add_geom(geom, render_state->_state);
|
if (!primitives.empty()) {
|
||||||
if (egg_show_normals) {
|
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);
|
show_normals(vertex_pool, geom_node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2243,6 +2265,7 @@ record_morph(GeomVertexArrayFormat *array_format,
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void EggLoader::
|
void EggLoader::
|
||||||
make_primitive(const EggRenderState *render_state, EggPrimitive *egg_prim,
|
make_primitive(const EggRenderState *render_state, EggPrimitive *egg_prim,
|
||||||
|
EggLoader::UniquePrimitives &unique_primitives,
|
||||||
EggLoader::Primitives &primitives) {
|
EggLoader::Primitives &primitives) {
|
||||||
PT(GeomPrimitive) primitive;
|
PT(GeomPrimitive) primitive;
|
||||||
if (egg_prim->is_of_type(EggPolygon::get_class_type())) {
|
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
|
// Insert the primitive into the set, but if we already have a
|
||||||
// primitive of that type, reset the pointer to that one instead.
|
// primitive of that type, reset the pointer to that one instead.
|
||||||
PrimitiveUnifier pu(primitive);
|
PrimitiveUnifier pu(primitive);
|
||||||
pair<Primitives::iterator, bool> result =
|
pair<UniquePrimitives::iterator, bool> result =
|
||||||
primitives.insert(Primitives::value_type(pu, primitive));
|
unique_primitives.insert(UniquePrimitives::value_type(pu, primitive));
|
||||||
primitive = (*result.first).second;
|
|
||||||
|
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.
|
// Now add the vertices.
|
||||||
EggPrimitive::const_iterator vi;
|
EggPrimitive::const_iterator vi;
|
||||||
|
@ -109,7 +109,8 @@ private:
|
|||||||
TypeHandle _type;
|
TypeHandle _type;
|
||||||
GeomPrimitive::ShadeModel _shade_model;
|
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);
|
void show_normals(EggVertexPool *vertex_pool, GeomNode *geom_node);
|
||||||
|
|
||||||
@ -151,7 +152,9 @@ private:
|
|||||||
InternalName *column_name, int num_components);
|
InternalName *column_name, int num_components);
|
||||||
|
|
||||||
void make_primitive(const EggRenderState *render_state,
|
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);
|
void set_portal_polygon(EggGroup *egg_group, PortalNode *pnode);
|
||||||
PT(EggPolygon) find_first_polygon(EggGroup *egg_group);
|
PT(EggPolygon) find_first_polygon(EggGroup *egg_group);
|
||||||
|
@ -177,15 +177,19 @@ rotate() const {
|
|||||||
// Function: Geom::unify
|
// Function: Geom::unify
|
||||||
// Access: Published
|
// Access: Published
|
||||||
// Description: Unifies all of the primitives contained within this
|
// Description: Unifies all of the primitives contained within this
|
||||||
// Geom into a single primitive object. This may
|
// Geom into a single (or as few as possible, within the
|
||||||
// require decomposing the primitives if, for instance,
|
// constraints of max_indices) primitive objects. This
|
||||||
// the Geom contains both triangle strips and triangle
|
// may require decomposing the primitives if, for
|
||||||
// fans.
|
// 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::
|
INLINE PT(Geom) Geom::
|
||||||
unify() const {
|
unify(int max_indices) const {
|
||||||
PT(Geom) new_geom = make_copy();
|
PT(Geom) new_geom = make_copy();
|
||||||
new_geom->unify_in_place();
|
new_geom->unify_in_place(max_indices);
|
||||||
return new_geom;
|
return new_geom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -512,17 +512,21 @@ rotate_in_place() {
|
|||||||
// Function: Geom::unify_in_place
|
// Function: Geom::unify_in_place
|
||||||
// Access: Published
|
// Access: Published
|
||||||
// Description: Unifies all of the primitives contained within this
|
// Description: Unifies all of the primitives contained within this
|
||||||
// Geom into a single primitive object. This may
|
// Geom into a single (or as few as possible, within the
|
||||||
// require decomposing the primitives if, for instance,
|
// constraints of max_indices) primitive objects. This
|
||||||
// the Geom contains both triangle strips and triangle
|
// may require decomposing the primitives if, for
|
||||||
// fans.
|
// 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 call this in a downstream thread unless you
|
||||||
// don't mind it blowing away other changes you might
|
// don't mind it blowing away other changes you might
|
||||||
// have recently made in an upstream thread.
|
// have recently made in an upstream thread.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void Geom::
|
void Geom::
|
||||||
unify_in_place() {
|
unify_in_place(int max_indices) {
|
||||||
Thread *current_thread = Thread::get_current_thread();
|
Thread *current_thread = Thread::get_current_thread();
|
||||||
if (get_num_primitives() <= 1) {
|
if (get_num_primitives() <= 1) {
|
||||||
// If we don't have more than one primitive to start with, no need
|
// 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
|
// Now we have just one primitive.
|
||||||
// the one primitive in our list of primitives.
|
|
||||||
nassertv(new_prim->check_valid(cdata->_data));
|
nassertv(new_prim->check_valid(cdata->_data));
|
||||||
|
|
||||||
// The new primitive, naturally, inherits the Geom's overall shade
|
// 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);
|
new_prim->set_shade_model(cdata->_shade_model);
|
||||||
|
|
||||||
cdata->_primitives.clear();
|
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();
|
cdata->_modified = Geom::get_next_modified();
|
||||||
clear_cache_stage(current_thread);
|
clear_cache_stage(current_thread);
|
||||||
|
@ -93,11 +93,11 @@ PUBLISHED:
|
|||||||
|
|
||||||
INLINE PT(Geom) decompose() const;
|
INLINE PT(Geom) decompose() const;
|
||||||
INLINE PT(Geom) rotate() const;
|
INLINE PT(Geom) rotate() const;
|
||||||
INLINE PT(Geom) unify() const;
|
INLINE PT(Geom) unify(int max_indices) const;
|
||||||
|
|
||||||
void decompose_in_place();
|
void decompose_in_place();
|
||||||
void rotate_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);
|
virtual bool copy_primitives_from(const Geom *other);
|
||||||
|
|
||||||
|
@ -175,8 +175,8 @@ set_index_type(GeomPrimitive::NumericType index_type) {
|
|||||||
// Access: Published
|
// Access: Published
|
||||||
// Description: Adds the indicated vertex to the list of vertex
|
// Description: Adds the indicated vertex to the list of vertex
|
||||||
// indices used by the graphics primitive type. To
|
// indices used by the graphics primitive type. To
|
||||||
// define primitive, you must call add_vertex() for each
|
// define a primitive, you must call add_vertex() for
|
||||||
// vertex of the new primitve, and then call
|
// each vertex of the new primitive, and then call
|
||||||
// close_primitive() after you have specified the last
|
// close_primitive() after you have specified the last
|
||||||
// vertex of each primitive.
|
// vertex of each primitive.
|
||||||
//
|
//
|
||||||
|
@ -188,7 +188,7 @@ ConfigVariableBool retransform_sprites
|
|||||||
"necessary in order for fog to work correctly on the sprites."));
|
"necessary in order for fog to work correctly on the sprites."));
|
||||||
|
|
||||||
ConfigVariableInt max_collect_vertices
|
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 "
|
PRC_DESC("Specifies the maximum number of vertices that are allowed to be "
|
||||||
"accumulated into any one GeomVertexData structure as a result "
|
"accumulated into any one GeomVertexData structure as a result "
|
||||||
"of collecting objects together during a flatten operation. "
|
"of collecting objects together during a flatten operation. "
|
||||||
@ -198,7 +198,7 @@ ConfigVariableInt max_collect_vertices
|
|||||||
"GeomVertexData structure."));
|
"GeomVertexData structure."));
|
||||||
|
|
||||||
ConfigVariableInt max_collect_indices
|
ConfigVariableInt max_collect_indices
|
||||||
("max-collect-indices", 1024,
|
("max-collect-indices", 65535,
|
||||||
PRC_DESC("Specifies the maximum number of vertex indices that are allowed "
|
PRC_DESC("Specifies the maximum number of vertex indices that are allowed "
|
||||||
"to be accumulated into any one GeomPrimitive as a result "
|
"to be accumulated into any one GeomPrimitive as a result "
|
||||||
"of collecting objects together during a flatten operation. "
|
"of collecting objects together during a flatten operation. "
|
||||||
|
@ -432,13 +432,16 @@ check_valid() const {
|
|||||||
// triangle strips and triangle fans, being decomposed
|
// triangle strips and triangle fans, being decomposed
|
||||||
// into triangles. See also Geom::unify().
|
// 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
|
// In order for this to be successful, the primitives
|
||||||
// must reference the same GeomVertexData, have the same
|
// must reference the same GeomVertexData, have the same
|
||||||
// fundamental primitive type, and have compatible shade
|
// fundamental primitive type, and have compatible shade
|
||||||
// models.
|
// models.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void GeomNode::
|
void GeomNode::
|
||||||
unify() {
|
unify(int max_indices) {
|
||||||
Thread *current_thread = Thread::get_current_thread();
|
Thread *current_thread = Thread::get_current_thread();
|
||||||
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
|
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
|
||||||
CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
|
CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
|
||||||
@ -479,7 +482,7 @@ unify() {
|
|||||||
// Finally, go back through and unify the resulting geom(s).
|
// Finally, go back through and unify the resulting geom(s).
|
||||||
for (gi = new_geoms->begin(); gi != new_geoms->end(); ++gi) {
|
for (gi = new_geoms->begin(); gi != new_geoms->end(); ++gi) {
|
||||||
const GeomEntry &entry = (*gi);
|
const GeomEntry &entry = (*gi);
|
||||||
entry._geom->unify_in_place();
|
entry._geom->unify_in_place(max_indices);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
|
CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
|
||||||
|
@ -72,7 +72,7 @@ PUBLISHED:
|
|||||||
INLINE void remove_all_geoms();
|
INLINE void remove_all_geoms();
|
||||||
bool check_valid() const;
|
bool check_valid() const;
|
||||||
|
|
||||||
void unify();
|
void unify(int max_indices);
|
||||||
|
|
||||||
void write_geoms(ostream &out, int indent_level) const;
|
void write_geoms(ostream &out, int indent_level) const;
|
||||||
void write_verbose(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) {
|
r_unify(PandaNode *node) {
|
||||||
if (node->is_geom_node()) {
|
if (node->is_geom_node()) {
|
||||||
GeomNode *geom_node = DCAST(GeomNode, node);
|
GeomNode *geom_node = DCAST(GeomNode, node);
|
||||||
geom_node->unify();
|
geom_node->unify(max_collect_indices);
|
||||||
}
|
}
|
||||||
|
|
||||||
PandaNode::Children children = node->get_children();
|
PandaNode::Children children = node->get_children();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user