From c6bcbe88f577832697b465fcd395158adeb09b17 Mon Sep 17 00:00:00 2001 From: David Rose Date: Thu, 31 Mar 2005 18:28:01 +0000 Subject: [PATCH] flattening qpgeom --- panda/src/display/standardMunger.cxx | 12 +- panda/src/gobj/qpgeomVertexData.I | 12 + panda/src/gobj/qpgeomVertexData.cxx | 17 +- panda/src/gobj/qpgeomVertexData.h | 10 +- panda/src/pgraph/geomTransformer.I | 45 ++++ panda/src/pgraph/geomTransformer.cxx | 325 ++++++++++++++++++--------- panda/src/pgraph/geomTransformer.h | 39 ++++ 7 files changed, 343 insertions(+), 117 deletions(-) diff --git a/panda/src/display/standardMunger.cxx b/panda/src/display/standardMunger.cxx index 6f62c68bef..ba570425f4 100644 --- a/panda/src/display/standardMunger.cxx +++ b/panda/src/display/standardMunger.cxx @@ -87,12 +87,12 @@ munge_data_impl(const qpGeomVertexData *data) { _contents); } - qpGeomVertexAnimationSpec animation = data->get_format()->get_animation(); + qpGeomVertexAnimationSpec animation = new_data->get_format()->get_animation(); if (hardware_animated_vertices && animation.get_animation_type() == qpGeomVertexAnimationSpec::AT_panda && - data->get_slider_table() == (SliderTable *)NULL) { + new_data->get_slider_table() == (SliderTable *)NULL) { // Maybe we can animate the vertices with hardware. - const TransformBlendPalette *palette = data->get_transform_blend_palette(); + const TransformBlendPalette *palette = new_data->get_transform_blend_palette(); if (palette != (TransformBlendPalette *)NULL && palette->get_max_simultaneous_transforms() <= _gsg->get_max_vertex_transforms()) { @@ -121,15 +121,15 @@ munge_data_impl(const qpGeomVertexData *data) { } } - CPT(qpGeomVertexFormat) orig_format = data->get_format(); + CPT(qpGeomVertexFormat) orig_format = new_data->get_format(); CPT(qpGeomVertexFormat) new_format = munge_format(orig_format, animation); if (new_format == orig_format) { // Trivial case. - return data; + return new_data; } - return data->convert_to(new_format); + return new_data->convert_to(new_format); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/qpgeomVertexData.I b/panda/src/gobj/qpgeomVertexData.I index 943be225c3..9d06fef856 100644 --- a/panda/src/gobj/qpgeomVertexData.I +++ b/panda/src/gobj/qpgeomVertexData.I @@ -74,6 +74,18 @@ get_usage_hint() const { return _usage_hint; } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::has_column +// Access: Published +// Description: Returns true if the data has the named column, +// false otherwise. This is really just a shortcut for +// asking the same thing from the format. +//////////////////////////////////////////////////////////////////// +INLINE bool qpGeomVertexData:: +has_column(const InternalName *name) const { + return _format->has_column(name); +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomVertexData::set_num_vertices // Access: Published diff --git a/panda/src/gobj/qpgeomVertexData.cxx b/panda/src/gobj/qpgeomVertexData.cxx index 9f9c728249..f9c55d4a80 100644 --- a/panda/src/gobj/qpgeomVertexData.cxx +++ b/panda/src/gobj/qpgeomVertexData.cxx @@ -85,6 +85,7 @@ qpGeomVertexData(const qpGeomVertexData ©) : TypedWritableReferenceCount(copy), _name(copy._name), _format(copy._format), + _usage_hint(copy._usage_hint), _cycler(copy._cycler), _app_char_pcollector(copy._app_char_pcollector), _cull_char_pcollector(copy._cull_char_pcollector) @@ -101,6 +102,10 @@ operator = (const qpGeomVertexData ©) { TypedWritableReferenceCount::operator = (copy); _name = copy._name; _format = copy._format; + + // The assignment operator does not copy the usage_hint, which is + // not supposed to change over the lifetime of a GeomVertexData. + _cycler = copy._cycler; _app_char_pcollector = copy._app_char_pcollector; _cull_char_pcollector = copy._cull_char_pcollector; @@ -727,10 +732,10 @@ set_color(const Colorf &color, int num_components, //////////////////////////////////////////////////////////////////// PT(qpGeomVertexData) qpGeomVertexData:: replace_column(const InternalName *name, int num_components, - qpGeomVertexColumn::NumericType numeric_type, - qpGeomVertexColumn::Contents contents, - qpGeomUsageHint::UsageHint usage_hint, - bool keep_animation) const { + qpGeomVertexColumn::NumericType numeric_type, + qpGeomVertexColumn::Contents contents, + qpGeomUsageHint::UsageHint usage_hint, + bool keep_animation) const { PT(qpGeomVertexFormat) new_format = new qpGeomVertexFormat(*_format); // Remove the old description of the type from the format. @@ -818,7 +823,7 @@ output(ostream &out) const { if (!get_name().empty()) { out << get_name() << " "; } - out << get_num_vertices() << ": " << *get_format(); + out << get_num_vertices() << " vertices: " << *get_format(); } //////////////////////////////////////////////////////////////////// @@ -831,7 +836,7 @@ write(ostream &out, int indent_level) const { if (!get_name().empty()) { indent(out, indent_level) << get_name() << "\n"; } - _format->write_with_data(out, indent_level, this); + _format->write_with_data(out, indent_level + 2, this); if (get_transform_blend_palette() != (TransformBlendPalette *)NULL) { indent(out, indent_level) << "Transform blend palette:\n"; diff --git a/panda/src/gobj/qpgeomVertexData.h b/panda/src/gobj/qpgeomVertexData.h index cc3b66034b..96fdfa4a2b 100644 --- a/panda/src/gobj/qpgeomVertexData.h +++ b/panda/src/gobj/qpgeomVertexData.h @@ -83,6 +83,8 @@ PUBLISHED: INLINE const qpGeomVertexFormat *get_format() const; INLINE qpGeomUsageHint::UsageHint get_usage_hint() const; + INLINE bool has_column(const InternalName *name) const; + int get_num_vertices() const; INLINE bool set_num_vertices(int n); void clear_vertices(); @@ -129,10 +131,10 @@ PUBLISHED: PT(qpGeomVertexData) replace_column(const InternalName *name, int num_components, - qpGeomVertexColumn::NumericType numeric_type, - qpGeomVertexColumn::Contents contents, - qpGeomUsageHint::UsageHint usage_hint, - bool keep_animation) const; + qpGeomVertexColumn::NumericType numeric_type, + qpGeomVertexColumn::Contents contents, + qpGeomUsageHint::UsageHint usage_hint, + bool keep_animation) const; void output(ostream &out) const; void write(ostream &out, int indent_level = 0) const; diff --git a/panda/src/pgraph/geomTransformer.I b/panda/src/pgraph/geomTransformer.I index 322343a74e..14d80920b4 100644 --- a/panda/src/pgraph/geomTransformer.I +++ b/panda/src/pgraph/geomTransformer.I @@ -17,6 +17,51 @@ //////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////// +// Function: GeomTransformer::qpSourceVertices::Ordering Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool GeomTransformer::qpSourceVertices:: +operator < (const GeomTransformer::qpSourceVertices &other) const { + if (_vertex_data != other._vertex_data) { + return _vertex_data < other._vertex_data; + } + return (_mat.compare_to(other._mat) < 0); +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomTransformer::qpSourceTexCoords::Ordering Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool GeomTransformer::qpSourceTexCoords:: +operator < (const GeomTransformer::qpSourceTexCoords &other) const { + if (_vertex_data != other._vertex_data) { + return _vertex_data < other._vertex_data; + } + if (_from != other._from) { + return _from < other._from; + } + if (_to != other._to) { + return _to < other._to; + } + return (_mat.compare_to(other._mat) < 0); +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomTransformer::qpSourceColors::Ordering Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool GeomTransformer::qpSourceColors:: +operator < (const GeomTransformer::qpSourceColors &other) const { + if (_vertex_data != other._vertex_data) { + return _vertex_data < other._vertex_data; + } + return (_color.compare_to(other._color) < 0); +} + //////////////////////////////////////////////////////////////////// // Function: GeomTransformer::SourceVertices::Ordering Operator // Access: Public diff --git a/panda/src/pgraph/geomTransformer.cxx b/panda/src/pgraph/geomTransformer.cxx index 770b8b553e..e1034fb17e 100644 --- a/panda/src/pgraph/geomTransformer.cxx +++ b/panda/src/pgraph/geomTransformer.cxx @@ -18,6 +18,8 @@ #include "geomTransformer.h" #include "geomNode.h" +#include "qpgeom.h" +#include "qpgeomVertexRewriter.h" #include "renderState.h" //////////////////////////////////////////////////////////////////// @@ -51,61 +53,98 @@ transform_vertices(Geom *geom, const LMatrix4f &mat) { nassertr(geom != (Geom *)NULL, false); - PTA_Vertexf coords; - PTA_ushort index; + if (geom->is_exact_type(qpGeom::get_class_type())) { + qpGeom *qpgeom = DCAST(qpGeom, geom); - geom->get_coords(coords, index); - - if (!coords.empty()) { - // Look up the Geom's coords in our table--have we already - // transformed this array? - SourceVertices sv; + qpSourceVertices sv; sv._mat = mat; - sv._coords = coords; + sv._vertex_data = qpgeom->get_vertex_data(); - PTA_Vertexf &new_coords = _vertices[sv]; + PT(qpGeomVertexData) &new_data = _qpvertices[sv]; + if (new_data.is_null()) { + // We have not yet converted these vertices. Do so now. + new_data = new qpGeomVertexData(*sv._vertex_data); + CPT(qpGeomVertexFormat) format = new_data->get_format(); - if (new_coords.is_null()) { - // We have not transformed the array yet. Do so now. - new_coords.reserve(coords.size()); - PTA_Vertexf::const_iterator vi; - for (vi = coords.begin(); vi != coords.end(); ++vi) { - new_coords.push_back((*vi) * mat); + int ci; + for (ci = 0; ci < format->get_num_points(); ci++) { + qpGeomVertexRewriter data(new_data, format->get_point(ci)); + + while (!data.is_at_end()) { + const LPoint3f &point = data.get_data3f(); + data.set_data3f(point * mat); + } + } + for (ci = 0; ci < format->get_num_vectors(); ci++) { + qpGeomVertexRewriter data(new_data, format->get_vector(ci)); + + while (!data.is_at_end()) { + const LVector3f &vector = data.get_data3f(); + data.set_data3f(normalize(vector * mat)); + } } - nassertr(new_coords.size() == coords.size(), false); } - geom->set_coords(new_coords, index); + qpgeom->set_vertex_data(new_data); transformed = true; - } - // Now do the same thing for normals. - PTA_Normalf norms; - GeomBindType bind; - - geom->get_normals(norms, bind, index); - - if (bind != G_OFF) { - SourceNormals sn; - sn._mat = mat; - sn._norms = norms; - - PTA_Normalf &new_norms = _normals[sn]; - - if (new_norms.is_null()) { - // We have not transformed the array yet. Do so now. - new_norms.reserve(norms.size()); - PTA_Normalf::const_iterator ni; - for (ni = norms.begin(); ni != norms.end(); ++ni) { - Normalf new_norm = (*ni) * mat; - new_norm.normalize(); - new_norms.push_back(new_norm); + } else { + PTA_Vertexf coords; + PTA_ushort index; + + geom->get_coords(coords, index); + + if (!coords.empty()) { + // Look up the Geom's coords in our table--have we already + // transformed this array? + SourceVertices sv; + sv._mat = mat; + sv._coords = coords; + + PTA_Vertexf &new_coords = _vertices[sv]; + + if (new_coords.is_null()) { + // We have not transformed the array yet. Do so now. + new_coords.reserve(coords.size()); + PTA_Vertexf::const_iterator vi; + for (vi = coords.begin(); vi != coords.end(); ++vi) { + new_coords.push_back((*vi) * mat); + } + nassertr(new_coords.size() == coords.size(), false); } - nassertr(new_norms.size() == norms.size(), false); + + geom->set_coords(new_coords, index); + transformed = true; } - geom->set_normals(new_norms, bind, index); - transformed = true; + // Now do the same thing for normals. + PTA_Normalf norms; + GeomBindType bind; + + geom->get_normals(norms, bind, index); + + if (bind != G_OFF) { + SourceNormals sn; + sn._mat = mat; + sn._norms = norms; + + PTA_Normalf &new_norms = _normals[sn]; + + if (new_norms.is_null()) { + // We have not transformed the array yet. Do so now. + new_norms.reserve(norms.size()); + PTA_Normalf::const_iterator ni; + for (ni = norms.begin(); ni != norms.end(); ++ni) { + Normalf new_norm = (*ni) * mat; + new_norm.normalize(); + new_norms.push_back(new_norm); + } + nassertr(new_norms.size() == norms.size(), false); + } + + geom->set_normals(new_norms, bind, index); + transformed = true; + } } return transformed; @@ -155,34 +194,78 @@ transform_texcoords(Geom *geom, const InternalName *from_name, bool transformed = false; nassertr(geom != (Geom *)NULL, false); + if (geom->is_exact_type(qpGeom::get_class_type())) { + qpGeom *qpgeom = DCAST(qpGeom, geom); - PTA_TexCoordf texcoords = geom->get_texcoords_array(from_name); - PTA_ushort index = geom->get_texcoords_index(from_name); + qpSourceTexCoords st; + st._mat = mat; + st._from = from_name; + st._to = to_name; + st._vertex_data = qpgeom->get_vertex_data(); - if (!texcoords.is_null()) { - // Look up the Geom's texcoords in our table--have we already - // transformed this array? - SourceTexCoords stc; - stc._mat = mat; - stc._texcoords = texcoords; - - PTA_TexCoordf &new_texcoords = _texcoords[stc]; - - if (new_texcoords.is_null()) { - // We have not transformed the array yet. Do so now. - new_texcoords.reserve(texcoords.size()); - PTA_TexCoordf::const_iterator tci; - for (tci = texcoords.begin(); tci != texcoords.end(); ++tci) { - const TexCoordf &tc = (*tci); - LVecBase4f v4(tc[0], tc[1], 0.0f, 1.0f); - v4 = v4 * mat; - new_texcoords.push_back(TexCoordf(v4[0] / v4[3], v4[1] / v4[3])); + PT(qpGeomVertexData) &new_data = _qptexcoords[st]; + if (new_data.is_null()) { + if (!st._vertex_data->has_column(from_name)) { + // No from_name column; no change. + return false; + } + + // We have not yet converted these texcoords. Do so now. + if (st._vertex_data->has_column(to_name)) { + new_data = new qpGeomVertexData(*st._vertex_data); + } else { + const qpGeomVertexColumn *old_column = + st._vertex_data->get_format()->get_column(from_name); + new_data = st._vertex_data->replace_column + (to_name, old_column->get_num_components(), + old_column->get_numeric_type(), + old_column->get_contents(), st._vertex_data->get_usage_hint(), + false); + } + + CPT(qpGeomVertexFormat) format = new_data->get_format(); + + qpGeomVertexWriter tdata(new_data, to_name); + qpGeomVertexReader fdata(new_data, from_name); + + while (!fdata.is_at_end()) { + const LPoint4f &coord = fdata.get_data4f(); + tdata.set_data4f(coord * mat); } - nassertr(new_texcoords.size() == texcoords.size(), false); } - geom->set_texcoords(to_name, new_texcoords, index); + qpgeom->set_vertex_data(new_data); transformed = true; + + } else { + PTA_TexCoordf texcoords = geom->get_texcoords_array(from_name); + PTA_ushort index = geom->get_texcoords_index(from_name); + + if (!texcoords.is_null()) { + // Look up the Geom's texcoords in our table--have we already + // transformed this array? + SourceTexCoords stc; + stc._mat = mat; + stc._texcoords = texcoords; + + PTA_TexCoordf &new_texcoords = _texcoords[stc]; + + if (new_texcoords.is_null()) { + // We have not transformed the array yet. Do so now. + new_texcoords.reserve(texcoords.size()); + PTA_TexCoordf::const_iterator tci; + for (tci = texcoords.begin(); tci != texcoords.end(); ++tci) { + const TexCoordf &tc = (*tci); + LVecBase4f v4(tc[0], tc[1], 0.0f, 1.0f); + v4 = v4 * mat; + new_texcoords.push_back(TexCoordf(v4[0] / v4[3], v4[1] / v4[3])); + } + nassertr(new_texcoords.size() == texcoords.size(), false); + } + + geom->set_texcoords(to_name, new_texcoords, index); + transformed = true; + } } return transformed; @@ -229,19 +312,41 @@ transform_texcoords(GeomNode *node, const InternalName *from_name, //////////////////////////////////////////////////////////////////// bool GeomTransformer:: set_color(Geom *geom, const Colorf &color) { - // In this case, we always replace whatever color array was there - // with a new color array containing just this color. + bool transformed = false; - // We do want to share this one-element array between Geoms, though. - PTA_Colorf &new_colors = _fcolors[color]; + if (geom->is_exact_type(qpGeom::get_class_type())) { + qpGeom *qpgeom = DCAST(qpGeom, geom); - if (new_colors.is_null()) { - // We haven't seen this color before; define a new color array. - new_colors.push_back(color); + qpSourceColors sc; + sc._color = color; + sc._vertex_data = qpgeom->get_vertex_data(); + + CPT(qpGeomVertexData) &new_data = _qpfcolors[sc]; + if (new_data.is_null()) { + // We have not yet converted these colors. Do so now. + new_data = sc._vertex_data->set_color(color); + } + + qpgeom->set_vertex_data(new_data); + transformed = true; + + } else { + // In this case, we always replace whatever color array was there + // with a new color array containing just this color. + + // We do want to share this one-element array between Geoms, though. + PTA_Colorf &new_colors = _fcolors[color]; + + if (new_colors.is_null()) { + // We haven't seen this color before; define a new color array. + new_colors.push_back(color); + } + + geom->set_colors(new_colors, G_OVERALL); + transformed = true; } - geom->set_colors(new_colors, G_OVERALL); - return true; + return transformed; } @@ -284,38 +389,56 @@ transform_colors(Geom *geom, const LVecBase4f &scale) { nassertr(geom != (Geom *)NULL, false); - PTA_Colorf colors; - GeomBindType bind; - PTA_ushort index; + if (geom->is_exact_type(qpGeom::get_class_type())) { + qpGeom *qpgeom = DCAST(qpGeom, geom); - geom->get_colors(colors, bind, index); + qpSourceColors sc; + sc._color = scale; + sc._vertex_data = qpgeom->get_vertex_data(); - if (bind != G_OFF) { - // Look up the Geom's colors in our table--have we already - // transformed this array? - SourceColors sc; - sc._scale = scale; - sc._colors = colors; - - PTA_Colorf &new_colors = _tcolors[sc]; - - if (new_colors.is_null()) { - // We have not transformed the array yet. Do so now. - new_colors.reserve(colors.size()); - PTA_Colorf::const_iterator ci; - for (ci = colors.begin(); ci != colors.end(); ++ci) { - const Colorf &c = (*ci); - Colorf transformed(c[0] * scale[0], - c[1] * scale[1], - c[2] * scale[2], - c[3] * scale[3]); - new_colors.push_back(transformed); - } - nassertr(new_colors.size() == colors.size(), false); + CPT(qpGeomVertexData) &new_data = _qptcolors[sc]; + if (new_data.is_null()) { + // We have not yet converted these colors. Do so now. + new_data = sc._vertex_data->scale_color(scale); } - geom->set_colors(new_colors, bind, index); + qpgeom->set_vertex_data(new_data); transformed = true; + + } else { + PTA_Colorf colors; + GeomBindType bind; + PTA_ushort index; + + geom->get_colors(colors, bind, index); + + if (bind != G_OFF) { + // Look up the Geom's colors in our table--have we already + // transformed this array? + SourceColors sc; + sc._scale = scale; + sc._colors = colors; + + PTA_Colorf &new_colors = _tcolors[sc]; + + if (new_colors.is_null()) { + // We have not transformed the array yet. Do so now. + new_colors.reserve(colors.size()); + PTA_Colorf::const_iterator ci; + for (ci = colors.begin(); ci != colors.end(); ++ci) { + const Colorf &c = (*ci); + Colorf transformed(c[0] * scale[0], + c[1] * scale[1], + c[2] * scale[2], + c[3] * scale[3]); + new_colors.push_back(transformed); + } + nassertr(new_colors.size() == colors.size(), false); + } + + geom->set_colors(new_colors, bind, index); + transformed = true; + } } return transformed; diff --git a/panda/src/pgraph/geomTransformer.h b/panda/src/pgraph/geomTransformer.h index ac43b97457..b1c52a9dd1 100644 --- a/panda/src/pgraph/geomTransformer.h +++ b/panda/src/pgraph/geomTransformer.h @@ -23,6 +23,7 @@ #include "geom.h" #include "luse.h" +#include "qpgeomVertexData.h" class GeomNode; class RenderState; @@ -68,6 +69,44 @@ public: bool apply_state(GeomNode *node, const RenderState *state); private: + class qpSourceVertices { + public: + INLINE bool operator < (const qpSourceVertices &other) const; + + LMatrix4f _mat; + CPT(qpGeomVertexData) _vertex_data; + }; + typedef pmap NewVertices; + NewVertices _qpvertices; + + class qpSourceTexCoords { + public: + INLINE bool operator < (const qpSourceTexCoords &other) const; + + LMatrix4f _mat; + CPT(InternalName) _from; + CPT(InternalName) _to; + CPT(qpGeomVertexData) _vertex_data; + }; + typedef pmap NewTexCoords; + NewTexCoords _qptexcoords; + + class qpSourceColors { + public: + INLINE bool operator < (const qpSourceColors &other) const; + + LVecBase4f _color; + CPT(qpGeomVertexData) _vertex_data; + }; + typedef pmap NewColors; + + // We have two concepts of colors: the "fixed" colors, which are + // slapped in complete replacement of the original colors (e.g. via + // a ColorAttrib), and the "transformed" colors, which are modified + // from the original colors (e.g. via a ColorScaleAttrib). + NewColors _qpfcolors, _qptcolors; + + class SourceVertices { public: INLINE bool operator < (const SourceVertices &other) const;