diff --git a/panda/src/gobj/geomVertexArrayFormat.cxx b/panda/src/gobj/geomVertexArrayFormat.cxx index fe9c94a7c3..c700490077 100644 --- a/panda/src/gobj/geomVertexArrayFormat.cxx +++ b/panda/src/gobj/geomVertexArrayFormat.cxx @@ -314,6 +314,8 @@ remove_column(const InternalName *name) { //////////////////////////////////////////////////////////////////// void GeomVertexArrayFormat:: clear_columns() { + nassertv(!_is_registered); + _columns.clear(); _columns_by_name.clear(); _columns_unsorted = false; @@ -322,6 +324,29 @@ clear_columns() { _pad_to = 1; } +//////////////////////////////////////////////////////////////////// +// Function: GeomVertexArrayFormat::pack_columns +// Access: Published +// Description: Removes wasted space between columns. +//////////////////////////////////////////////////////////////////// +void GeomVertexArrayFormat:: +pack_columns() { + nassertv(!_is_registered); + + Columns orig_columns; + orig_columns.swap(_columns); + clear_columns(); + + int last_pos = 0; + + Columns::const_iterator ci; + for (ci = orig_columns.begin(); ci != orig_columns.end(); ++ci) { + GeomVertexColumn *column = (*ci); + add_column(column->get_name(), column->get_num_components(), + column->get_numeric_type(), column->get_contents()); + } +} + //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayFormat::get_column // Access: Published diff --git a/panda/src/gobj/geomVertexArrayFormat.h b/panda/src/gobj/geomVertexArrayFormat.h index e8098e6f54..5a8114074c 100644 --- a/panda/src/gobj/geomVertexArrayFormat.h +++ b/panda/src/gobj/geomVertexArrayFormat.h @@ -95,6 +95,7 @@ PUBLISHED: int add_column(const GeomVertexColumn &column); void remove_column(const InternalName *name); void clear_columns(); + void pack_columns(); INLINE int get_num_columns() const; INLINE const GeomVertexColumn *get_column(int i) const; diff --git a/panda/src/gobj/geomVertexFormat.cxx b/panda/src/gobj/geomVertexFormat.cxx index ec40d3d964..d9bffea1ac 100644 --- a/panda/src/gobj/geomVertexFormat.cxx +++ b/panda/src/gobj/geomVertexFormat.cxx @@ -519,6 +519,21 @@ remove_column(const InternalName *name) { // problem; quietly return. } +//////////////////////////////////////////////////////////////////// +// Function: GeomVertexFormat::pack_columns +// Access: Published +// Description: Removes wasted space between columns. +//////////////////////////////////////////////////////////////////// +void GeomVertexFormat:: +pack_columns() { + nassertv(!_is_registered); + Arrays::const_iterator ai; + for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) { + (*ai)->pack_columns(); + } +} + + //////////////////////////////////////////////////////////////////// // Function: GeomVertexFormat::output // Access: Published diff --git a/panda/src/gobj/geomVertexFormat.h b/panda/src/gobj/geomVertexFormat.h index 0778f74894..7623a6f537 100644 --- a/panda/src/gobj/geomVertexFormat.h +++ b/panda/src/gobj/geomVertexFormat.h @@ -98,6 +98,7 @@ PUBLISHED: INLINE bool has_column(const InternalName *name) const; void remove_column(const InternalName *name); + void pack_columns(); INLINE int get_num_points() const; INLINE const InternalName *get_point(int n) const; diff --git a/panda/src/pgraph/geomTransformer.I b/panda/src/pgraph/geomTransformer.I index c111c50cfe..6ca1042664 100644 --- a/panda/src/pgraph/geomTransformer.I +++ b/panda/src/pgraph/geomTransformer.I @@ -86,6 +86,19 @@ operator < (const GeomTransformer::SourceColors &other) const { return (_color.compare_to(other._color) < 0); } +//////////////////////////////////////////////////////////////////// +// Function: GeomTransformer::SourceFormat::Ordering Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool GeomTransformer::SourceFormat:: +operator < (const GeomTransformer::SourceFormat &other) const { + if (_format != other._format) { + return _format < other._format; + } + return _vertex_data < other._vertex_data; +} + //////////////////////////////////////////////////////////////////// // Function: GeomTransformer::NewCollectedKey::Ordering Operator // Access: Public diff --git a/panda/src/pgraph/geomTransformer.cxx b/panda/src/pgraph/geomTransformer.cxx index d57b40b715..11232ae152 100644 --- a/panda/src/pgraph/geomTransformer.cxx +++ b/panda/src/pgraph/geomTransformer.cxx @@ -32,10 +32,11 @@ #include "geomMunger.h" #include "config_pgraph.h" -static PStatCollector apply_vertex_collector("*:Flatten:apply:vertex"); -static PStatCollector apply_texcoord_collector("*:Flatten:apply:texcoord"); -static PStatCollector apply_set_color_collector("*:Flatten:apply:set color"); -static PStatCollector apply_scale_color_collector("*:Flatten:apply:scale color"); +PStatCollector GeomTransformer::_apply_vertex_collector("*:Flatten:apply:vertex"); +PStatCollector GeomTransformer::_apply_texcoord_collector("*:Flatten:apply:texcoord"); +PStatCollector GeomTransformer::_apply_set_color_collector("*:Flatten:apply:set color"); +PStatCollector GeomTransformer::_apply_scale_color_collector("*:Flatten:apply:scale color"); +PStatCollector GeomTransformer::_apply_set_format_collector("*:Flatten:apply:set format"); //////////////////////////////////////////////////////////////////// // Function: GeomTransformer::Constructor @@ -78,7 +79,7 @@ GeomTransformer:: //////////////////////////////////////////////////////////////////// bool GeomTransformer:: transform_vertices(Geom *geom, const LMatrix4f &mat) { - PStatTimer timer(apply_vertex_collector); + PStatTimer timer(_apply_vertex_collector); nassertr(geom != (Geom *)NULL, false); SourceVertices sv; @@ -165,7 +166,7 @@ transform_vertices(GeomNode *node, const LMatrix4f &mat) { bool GeomTransformer:: transform_texcoords(Geom *geom, const InternalName *from_name, InternalName *to_name, const LMatrix4f &mat) { - PStatTimer timer(apply_texcoord_collector); + PStatTimer timer(_apply_texcoord_collector); nassertr(geom != (Geom *)NULL, false); @@ -252,7 +253,7 @@ transform_texcoords(GeomNode *node, const InternalName *from_name, //////////////////////////////////////////////////////////////////// bool GeomTransformer:: set_color(Geom *geom, const Colorf &color) { - PStatTimer timer(apply_set_color_collector); + PStatTimer timer(_apply_set_color_collector); SourceColors sc; sc._color = color; @@ -311,7 +312,7 @@ set_color(GeomNode *node, const Colorf &color) { //////////////////////////////////////////////////////////////////// bool GeomTransformer:: transform_colors(Geom *geom, const LVecBase4f &scale) { - PStatTimer timer(apply_scale_color_collector); + PStatTimer timer(_apply_scale_color_collector); nassertr(geom != (Geom *)NULL, false); @@ -392,6 +393,87 @@ apply_state(GeomNode *node, const RenderState *state) { return any_changed; } +//////////////////////////////////////////////////////////////////// +// Function: GeomTransformer::set_format +// Access: Public +// Description: Changes the GeomVertexData of the indicated Geom to +// use the specified format. +//////////////////////////////////////////////////////////////////// +bool GeomTransformer:: +set_format(Geom *geom, const GeomVertexFormat *new_format) { + PStatTimer timer(_apply_set_format_collector); + + nassertr(geom != (Geom *)NULL, false); + + SourceFormat sf; + sf._format = new_format; + sf._vertex_data = geom->get_vertex_data(); + + PT(GeomVertexData) &new_data = _format[sf]; + if (new_data.is_null()) { + if (sf._vertex_data->get_format() == new_format) { + // No change. + return false; + } + + // We have not yet converted this vertex data. Do so now. + new_data = new GeomVertexData(*sf._vertex_data); + new_data->set_format(new_format); + } + + geom->set_vertex_data(new_data); + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomTransformer::remove_column +// Access: Public +// Description: Removes the named column from the vertex data in the +// Geom. Returns true if the Geom was changed, false +// otherwise. +//////////////////////////////////////////////////////////////////// +bool GeomTransformer:: +remove_column(Geom *geom, const InternalName *column) { + CPT(GeomVertexFormat) format = geom->get_vertex_data()->get_format(); + if (!format->has_column(column)) { + return false; + } + + PT(GeomVertexFormat) new_format = new GeomVertexFormat(*format); + new_format->remove_column(column); + new_format->pack_columns(); + format = GeomVertexFormat::register_format(new_format); + + return set_format(geom, format); +} + + +//////////////////////////////////////////////////////////////////// +// Function: GeomTransformer::remove_column +// Access: Public +// Description: Removes the named column from the vertex datas within +// the GeomNode. Returns true if the GeomNode was +// changed, false otherwise. +//////////////////////////////////////////////////////////////////// +bool GeomTransformer:: +remove_column(GeomNode *node, const InternalName *column) { + bool any_changed = false; + + GeomNode::CDWriter cdata(node->_cycler); + GeomNode::GeomList::iterator gi; + GeomNode::GeomList &geoms = *(cdata->modify_geoms()); + for (gi = geoms.begin(); gi != geoms.end(); ++gi) { + GeomNode::GeomEntry &entry = (*gi); + PT(Geom) new_geom = entry._geom.get_read_pointer()->make_copy(); + if (remove_column(new_geom, column)) { + entry._geom = new_geom; + any_changed = true; + } + } + + return any_changed; +} + //////////////////////////////////////////////////////////////////// // Function: GeomTransformer::collect_vertex_data // Access: Public diff --git a/panda/src/pgraph/geomTransformer.h b/panda/src/pgraph/geomTransformer.h index 822ac1563d..1d52d1d056 100644 --- a/panda/src/pgraph/geomTransformer.h +++ b/panda/src/pgraph/geomTransformer.h @@ -71,6 +71,10 @@ public: bool apply_state(GeomNode *node, const RenderState *state); + bool set_format(Geom *geom, const GeomVertexFormat *new_format); + bool remove_column(Geom *geom, const InternalName *column); + bool remove_column(GeomNode *node, const InternalName *column); + int collect_vertex_data(Geom *geom, int collect_bits); int collect_vertex_data(GeomNode *node, int collect_bits); @@ -116,6 +120,17 @@ private: // modified from the original colors (e.g. via a ColorScaleAttrib). NewColors _fcolors, _tcolors; + // For set_format(): record (format + vertex_data) -> vertex_data. + class SourceFormat { + public: + INLINE bool operator < (const SourceFormat &other) const; + + CPT(GeomVertexFormat) _format; + CPT(GeomVertexData) _vertex_data; + }; + typedef pmap NewFormat; + NewFormat _format; + class AlreadyCollectedData { public: CPT(GeomVertexData) _data; @@ -135,6 +150,12 @@ private: }; typedef pmap< NewCollectedKey, PT(GeomVertexData) > NewCollectedData; NewCollectedData _new_collected_data; + + static PStatCollector _apply_vertex_collector; + static PStatCollector _apply_texcoord_collector; + static PStatCollector _apply_set_color_collector; + static PStatCollector _apply_scale_color_collector; + static PStatCollector _apply_set_format_collector; }; #include "geomTransformer.I" diff --git a/panda/src/pgraph/sceneGraphReducer.cxx b/panda/src/pgraph/sceneGraphReducer.cxx index 96d2b5a880..04ab868b7e 100644 --- a/panda/src/pgraph/sceneGraphReducer.cxx +++ b/panda/src/pgraph/sceneGraphReducer.cxx @@ -28,6 +28,7 @@ PStatCollector SceneGraphReducer::_flatten_collector("*:Flatten:flatten"); PStatCollector SceneGraphReducer::_apply_collector("*:Flatten:apply"); +PStatCollector SceneGraphReducer::_remove_column_collector("*:Flatten:remove column"); PStatCollector SceneGraphReducer::_collect_collector("*:Flatten:collect"); PStatCollector SceneGraphReducer::_make_nonindexed_collector("*:Flatten:make nonindexed"); PStatCollector SceneGraphReducer::_unify_collector("*:Flatten:unify"); @@ -129,6 +130,19 @@ flatten(PandaNode *root, int combine_siblings_bits) { return num_total_nodes; } +//////////////////////////////////////////////////////////////////// +// Function: SceneGraphReducer::remove_column +// Access: Published +// Description: Removes the indicated data column from any +// GeomVertexDatas found at the indicated root and +// below. Returns the number of GeomNodes modified. +//////////////////////////////////////////////////////////////////// +int SceneGraphReducer:: +remove_column(PandaNode *root, const InternalName *column) { + PStatTimer timer(_remove_column_collector); + return r_remove_column(root, column, _transformer); +} + //////////////////////////////////////////////////////////////////// // Function: SceneGraphReducer::unify // Access: Published @@ -675,6 +689,33 @@ choose_name(PandaNode *preserve, PandaNode *source1, PandaNode *source2) { } } +//////////////////////////////////////////////////////////////////// +// Function: SceneGraphReducer::r_remove_column +// Access: Private +// Description: The recursive implementation of remove_column(). +//////////////////////////////////////////////////////////////////// +int SceneGraphReducer:: +r_remove_column(PandaNode *node, const InternalName *column, + GeomTransformer &transformer) { + int num_changed = 0; + + if (node->is_geom_node()) { + // When we come to a geom node, collect. + if (transformer.remove_column(DCAST(GeomNode, node), column)) { + ++num_changed; + } + } + + PandaNode::Children children = node->get_children(); + int num_children = children.get_num_children(); + for (int i = 0; i < num_children; ++i) { + num_changed += + r_remove_column(children.get_child(i), column, transformer); + } + + return num_changed; +} + //////////////////////////////////////////////////////////////////// // Function: SceneGraphReducer::r_collect_vertex_data // Access: Private @@ -702,7 +743,7 @@ r_collect_vertex_data(PandaNode *node, int collect_bits, GeomTransformer new_transformer(transformer); if (node->is_geom_node()) { - // When we come to geom node, collect. + // When we come to a geom node, collect. if (new_transformer.collect_vertex_data(DCAST(GeomNode, node), collect_bits)) { ++num_created; } diff --git a/panda/src/pgraph/sceneGraphReducer.h b/panda/src/pgraph/sceneGraphReducer.h index f2a5736017..3903c9855b 100644 --- a/panda/src/pgraph/sceneGraphReducer.h +++ b/panda/src/pgraph/sceneGraphReducer.h @@ -135,6 +135,8 @@ PUBLISHED: int flatten(PandaNode *root, int combine_siblings_bits); + int remove_column(PandaNode *root, const InternalName *column); + INLINE int collect_vertex_data(PandaNode *root, int collect_bits = ~0); INLINE int make_nonindexed(PandaNode *root, int nonindexed_bits = ~0); void unify(PandaNode *root); @@ -166,6 +168,9 @@ protected: void choose_name(PandaNode *preserve, PandaNode *source1, PandaNode *source2); + int r_remove_column(PandaNode *node, const InternalName *column, + GeomTransformer &transformer); + int r_collect_vertex_data(PandaNode *node, int collect_bits, GeomTransformer &transformer); int r_make_nonindexed(PandaNode *node, int collect_bits); @@ -180,6 +185,7 @@ private: static PStatCollector _flatten_collector; static PStatCollector _apply_collector; + static PStatCollector _remove_column_collector; static PStatCollector _collect_collector; static PStatCollector _make_nonindexed_collector; static PStatCollector _unify_collector;