Browse Source

flattening qpgeom

David Rose 21 years ago
parent
commit
c6bcbe88f5

+ 6 - 6
panda/src/display/standardMunger.cxx

@@ -87,12 +87,12 @@ munge_data_impl(const qpGeomVertexData *data) {
                                      _contents);
                                      _contents);
   }
   }
 
 
-  qpGeomVertexAnimationSpec animation = data->get_format()->get_animation();
+  qpGeomVertexAnimationSpec animation = new_data->get_format()->get_animation();
   if (hardware_animated_vertices &&
   if (hardware_animated_vertices &&
       animation.get_animation_type() == qpGeomVertexAnimationSpec::AT_panda &&
       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.
     // 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 &&
     if (palette != (TransformBlendPalette *)NULL &&
         palette->get_max_simultaneous_transforms() <= 
         palette->get_max_simultaneous_transforms() <= 
         _gsg->get_max_vertex_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);
   CPT(qpGeomVertexFormat) new_format = munge_format(orig_format, animation);
 
 
   if (new_format == orig_format) {
   if (new_format == orig_format) {
     // Trivial case.
     // Trivial case.
-    return data;
+    return new_data;
   }
   }
 
 
-  return data->convert_to(new_format);
+  return new_data->convert_to(new_format);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 12 - 0
panda/src/gobj/qpgeomVertexData.I

@@ -74,6 +74,18 @@ get_usage_hint() const {
   return _usage_hint;
   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
 //     Function: qpGeomVertexData::set_num_vertices
 //       Access: Published
 //       Access: Published

+ 11 - 6
panda/src/gobj/qpgeomVertexData.cxx

@@ -85,6 +85,7 @@ qpGeomVertexData(const qpGeomVertexData &copy) :
   TypedWritableReferenceCount(copy),
   TypedWritableReferenceCount(copy),
   _name(copy._name),
   _name(copy._name),
   _format(copy._format),
   _format(copy._format),
+  _usage_hint(copy._usage_hint),
   _cycler(copy._cycler),
   _cycler(copy._cycler),
   _app_char_pcollector(copy._app_char_pcollector),
   _app_char_pcollector(copy._app_char_pcollector),
   _cull_char_pcollector(copy._cull_char_pcollector)
   _cull_char_pcollector(copy._cull_char_pcollector)
@@ -101,6 +102,10 @@ operator = (const qpGeomVertexData &copy) {
   TypedWritableReferenceCount::operator = (copy);
   TypedWritableReferenceCount::operator = (copy);
   _name = copy._name;
   _name = copy._name;
   _format = copy._format;
   _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;
   _cycler = copy._cycler;
   _app_char_pcollector = copy._app_char_pcollector;
   _app_char_pcollector = copy._app_char_pcollector;
   _cull_char_pcollector = copy._cull_char_pcollector;
   _cull_char_pcollector = copy._cull_char_pcollector;
@@ -727,10 +732,10 @@ set_color(const Colorf &color, int num_components,
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 PT(qpGeomVertexData) qpGeomVertexData::
 PT(qpGeomVertexData) qpGeomVertexData::
 replace_column(const InternalName *name, int num_components,
 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);
   PT(qpGeomVertexFormat) new_format = new qpGeomVertexFormat(*_format);
 
 
   // Remove the old description of the type from the format.
   // Remove the old description of the type from the format.
@@ -818,7 +823,7 @@ output(ostream &out) const {
   if (!get_name().empty()) {
   if (!get_name().empty()) {
     out << get_name() << " ";
     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()) {
   if (!get_name().empty()) {
     indent(out, indent_level) << get_name() << "\n";
     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) {
   if (get_transform_blend_palette() != (TransformBlendPalette *)NULL) {
     indent(out, indent_level)
     indent(out, indent_level)
       << "Transform blend palette:\n";
       << "Transform blend palette:\n";

+ 6 - 4
panda/src/gobj/qpgeomVertexData.h

@@ -83,6 +83,8 @@ PUBLISHED:
   INLINE const qpGeomVertexFormat *get_format() const;
   INLINE const qpGeomVertexFormat *get_format() const;
   INLINE qpGeomUsageHint::UsageHint get_usage_hint() const;
   INLINE qpGeomUsageHint::UsageHint get_usage_hint() const;
 
 
+  INLINE bool has_column(const InternalName *name) const;
+
   int get_num_vertices() const;
   int get_num_vertices() const;
   INLINE bool set_num_vertices(int n);
   INLINE bool set_num_vertices(int n);
   void clear_vertices();
   void clear_vertices();
@@ -129,10 +131,10 @@ PUBLISHED:
 
 
   PT(qpGeomVertexData) 
   PT(qpGeomVertexData) 
     replace_column(const InternalName *name, int num_components,
     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 output(ostream &out) const;
   void write(ostream &out, int indent_level = 0) const;
   void write(ostream &out, int indent_level = 0) const;

+ 45 - 0
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
 //     Function: GeomTransformer::SourceVertices::Ordering Operator
 //       Access: Public
 //       Access: Public

+ 225 - 102
panda/src/pgraph/geomTransformer.cxx

@@ -18,6 +18,8 @@
 
 
 #include "geomTransformer.h"
 #include "geomTransformer.h"
 #include "geomNode.h"
 #include "geomNode.h"
+#include "qpgeom.h"
+#include "qpgeomVertexRewriter.h"
 #include "renderState.h"
 #include "renderState.h"
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -51,61 +53,98 @@ transform_vertices(Geom *geom, const LMatrix4f &mat) {
 
 
   nassertr(geom != (Geom *)NULL, false);
   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._mat = mat;
-    sv._coords = coords;
-
-    PTA_Vertexf &new_coords = _vertices[sv];
+    sv._vertex_data = qpgeom->get_vertex_data();
+
+    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();
+
+      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));
 
 
-    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);
+        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;
     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;
   return transformed;
@@ -155,34 +194,78 @@ transform_texcoords(Geom *geom, const InternalName *from_name,
   bool transformed = false;
   bool transformed = false;
 
 
   nassertr(geom != (Geom *)NULL, false);
   nassertr(geom != (Geom *)NULL, false);
+  if (geom->is_exact_type(qpGeom::get_class_type())) {
+    qpGeom *qpgeom = DCAST(qpGeom, geom);
+
+    qpSourceTexCoords st;
+    st._mat = mat;
+    st._from = from_name;
+    st._to = to_name;
+    st._vertex_data = qpgeom->get_vertex_data();
+
+    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);
+      }
 
 
-  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]));
+      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;
     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;
   return transformed;
@@ -229,19 +312,41 @@ transform_texcoords(GeomNode *node, const InternalName *from_name,
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool GeomTransformer::
 bool GeomTransformer::
 set_color(Geom *geom, const Colorf &color) {
 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;
+
+  if (geom->is_exact_type(qpGeom::get_class_type())) {
+    qpGeom *qpgeom = DCAST(qpGeom, geom);
+
+    qpSourceColors sc;
+    sc._color = color;
+    sc._vertex_data = qpgeom->get_vertex_data();
 
 
-  // We do want to share this one-element array between Geoms, though.
-  PTA_Colorf &new_colors = _fcolors[color];
+    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;
 
 
-  if (new_colors.is_null()) {
-    // We haven't seen this color before; define a new color array.
-    new_colors.push_back(color);
+  } 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);
   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;
+    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);
+    }
 
 
-    PTA_Colorf &new_colors = _tcolors[sc];
+    qpgeom->set_vertex_data(new_data);
+    transformed = true;
 
 
-    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);
+  } 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);
       }
       }
-      nassertr(new_colors.size() == colors.size(), false);
+      
+      geom->set_colors(new_colors, bind, index);
+      transformed = true;
     }
     }
-
-    geom->set_colors(new_colors, bind, index);
-    transformed = true;
   }
   }
 
 
   return transformed;
   return transformed;

+ 39 - 0
panda/src/pgraph/geomTransformer.h

@@ -23,6 +23,7 @@
 
 
 #include "geom.h"
 #include "geom.h"
 #include "luse.h"
 #include "luse.h"
+#include "qpgeomVertexData.h"
 
 
 class GeomNode;
 class GeomNode;
 class RenderState;
 class RenderState;
@@ -68,6 +69,44 @@ public:
   bool apply_state(GeomNode *node, const RenderState *state);
   bool apply_state(GeomNode *node, const RenderState *state);
 
 
 private:
 private:
+  class qpSourceVertices {
+  public:
+    INLINE bool operator < (const qpSourceVertices &other) const;
+
+    LMatrix4f _mat;
+    CPT(qpGeomVertexData) _vertex_data;
+  };
+  typedef pmap<qpSourceVertices, PT(qpGeomVertexData) > 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<qpSourceTexCoords, PT(qpGeomVertexData) > NewTexCoords;
+  NewTexCoords _qptexcoords;
+
+  class qpSourceColors {
+  public:
+    INLINE bool operator < (const qpSourceColors &other) const;
+
+    LVecBase4f _color;
+    CPT(qpGeomVertexData) _vertex_data;
+  };
+  typedef pmap<qpSourceColors, CPT(qpGeomVertexData) > 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 {
   class SourceVertices {
   public:
   public:
     INLINE bool operator < (const SourceVertices &other) const;
     INLINE bool operator < (const SourceVertices &other) const;