Browse Source

qpGeomVertexWriter

David Rose 21 years ago
parent
commit
f8acb8d5d4

+ 6 - 1
panda/src/char/character.cxx

@@ -197,7 +197,12 @@ update() {
   PStatTimer timer(_char_pcollector);
   PStatTimer timer(_char_pcollector);
 
 
   // First, update all the joints and sliders.
   // First, update all the joints and sliders.
-  bool any_changed = get_bundle()->update();
+  bool any_changed;
+  if (even_animation) {
+    any_changed = get_bundle()->force_update();
+  } else {
+    any_changed = get_bundle()->update();
+  }
 
 
   // Now update the vertices, if we need to.  This is likely to be a
   // Now update the vertices, if we need to.  This is likely to be a
   // slow operation.
   // slow operation.

+ 5 - 5
panda/src/egg2pg/eggLoader.cxx

@@ -36,7 +36,7 @@
 #include "qpgeomVertexFormat.h"
 #include "qpgeomVertexFormat.h"
 #include "qpgeomVertexArrayFormat.h"
 #include "qpgeomVertexArrayFormat.h"
 #include "qpgeomVertexData.h"
 #include "qpgeomVertexData.h"
-#include "qpgeomVertexIterator.h"
+#include "qpgeomVertexWriter.h"
 #include "qpgeom.h"
 #include "qpgeom.h"
 #include "qpgeomTriangles.h"
 #include "qpgeomTriangles.h"
 #include "qpgeomTristrips.h"
 #include "qpgeomTristrips.h"
@@ -1987,21 +1987,21 @@ make_vertex_data(const EggRenderState *render_state,
   // And fill the data from the vertex pool.
   // And fill the data from the vertex pool.
   EggVertexPool::const_iterator vi;
   EggVertexPool::const_iterator vi;
   for (vi = vertex_pool->begin(); vi != vertex_pool->end(); ++vi) {
   for (vi = vertex_pool->begin(); vi != vertex_pool->end(); ++vi) {
-    qpGeomVertexIterator gvi(vertex_data);
+    qpGeomVertexWriter gvi(vertex_data);
     EggVertex *vertex = (*vi);
     EggVertex *vertex = (*vi);
     gvi.set_vertex(vertex->get_index());
     gvi.set_vertex(vertex->get_index());
 
 
     gvi.set_data_type(InternalName::get_vertex());
     gvi.set_data_type(InternalName::get_vertex());
-    gvi.set_data4f(LCAST(float, vertex->get_pos4() * transform));
+    gvi.add_data4f(LCAST(float, vertex->get_pos4() * transform));
 
 
     if (vertex->has_normal()) {
     if (vertex->has_normal()) {
       gvi.set_data_type(InternalName::get_normal());
       gvi.set_data_type(InternalName::get_normal());
-      gvi.set_data3f(LCAST(float, vertex->get_normal() * transform));
+      gvi.add_data3f(LCAST(float, vertex->get_normal() * transform));
     }
     }
 
 
     if (vertex->has_color()) {
     if (vertex->has_color()) {
       gvi.set_data_type(InternalName::get_color());
       gvi.set_data_type(InternalName::get_color());
-      gvi.set_data4f(vertex->get_color());
+      gvi.add_data4f(vertex->get_color());
     }
     }
 
 
     EggVertex::const_uv_iterator uvi;
     EggVertex::const_uv_iterator uvi;

+ 31 - 31
panda/src/framework/windowFramework.cxx

@@ -31,7 +31,7 @@
 #include "qpgeomTristrips.h"
 #include "qpgeomTristrips.h"
 #include "qpgeomVertexData.h"
 #include "qpgeomVertexData.h"
 #include "qpgeomVertexFormat.h"
 #include "qpgeomVertexFormat.h"
-#include "qpgeomVertexIterator.h"
+#include "qpgeomVertexWriter.h"
 #include "texturePool.h"
 #include "texturePool.h"
 #include "textureAttrib.h"
 #include "textureAttrib.h"
 #include "colorAttrib.h"
 #include "colorAttrib.h"
@@ -635,26 +635,26 @@ load_default_model(const NodePath &parent) {
     PT(qpGeomVertexData) vdata = new qpGeomVertexData
     PT(qpGeomVertexData) vdata = new qpGeomVertexData
       (string(), qpGeomVertexFormat::get_v3n3cpt2(),
       (string(), qpGeomVertexFormat::get_v3n3cpt2(),
        qpGeomUsageHint::UH_static);
        qpGeomUsageHint::UH_static);
-    qpGeomVertexIterator vertex(vdata, InternalName::get_vertex());
-    qpGeomVertexIterator normal(vdata, InternalName::get_normal());
-    qpGeomVertexIterator color(vdata, InternalName::get_color());
-    qpGeomVertexIterator texcoord(vdata, InternalName::get_texcoord());
-
-    vertex.set_data3f(Vertexf::rfu(0.0, 0.0, 0.0));
-    vertex.set_data3f(Vertexf::rfu(1.0, 0.0, 0.0));
-    vertex.set_data3f(Vertexf::rfu(0.0, 0.0, 1.0));
-
-    normal.set_data3f(Normalf::back());
-    normal.set_data3f(Normalf::back());
-    normal.set_data3f(Normalf::back());
-
-    color.set_data4f(0.5, 0.5, 1.0, 1.0);
-    color.set_data4f(0.5, 0.5, 1.0, 1.0);
-    color.set_data4f(0.5, 0.5, 1.0, 1.0);
-
-    texcoord.set_data2f(0.0, 0.0);
-    texcoord.set_data2f(1.0, 0.0);
-    texcoord.set_data2f(0.0, 1.0);
+    qpGeomVertexWriter vertex(vdata, InternalName::get_vertex());
+    qpGeomVertexWriter normal(vdata, InternalName::get_normal());
+    qpGeomVertexWriter color(vdata, InternalName::get_color());
+    qpGeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
+
+    vertex.add_data3f(Vertexf::rfu(0.0, 0.0, 0.0));
+    vertex.add_data3f(Vertexf::rfu(1.0, 0.0, 0.0));
+    vertex.add_data3f(Vertexf::rfu(0.0, 0.0, 1.0));
+
+    normal.add_data3f(Normalf::back());
+    normal.add_data3f(Normalf::back());
+    normal.add_data3f(Normalf::back());
+
+    color.add_data4f(0.5, 0.5, 1.0, 1.0);
+    color.add_data4f(0.5, 0.5, 1.0, 1.0);
+    color.add_data4f(0.5, 0.5, 1.0, 1.0);
+
+    texcoord.add_data2f(0.0, 0.0);
+    texcoord.add_data2f(1.0, 0.0);
+    texcoord.add_data2f(0.0, 1.0);
     
     
     PT(qpGeomTriangles) tri = new qpGeomTriangles(qpGeomUsageHint::UH_static);
     PT(qpGeomTriangles) tri = new qpGeomTriangles(qpGeomUsageHint::UH_static);
     tri->add_consecutive_vertices(0, 3);
     tri->add_consecutive_vertices(0, 3);
@@ -1062,18 +1062,18 @@ load_image_as_model(const Filename &filename) {
     PT(qpGeomVertexData) vdata = new qpGeomVertexData
     PT(qpGeomVertexData) vdata = new qpGeomVertexData
       (string(), qpGeomVertexFormat::get_v3t2(),
       (string(), qpGeomVertexFormat::get_v3t2(),
        qpGeomUsageHint::UH_static);
        qpGeomUsageHint::UH_static);
-    qpGeomVertexIterator vertex(vdata, InternalName::get_vertex());
-    qpGeomVertexIterator texcoord(vdata, InternalName::get_texcoord());
+    qpGeomVertexWriter vertex(vdata, InternalName::get_vertex());
+    qpGeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
 
 
-    vertex.set_data3f(Vertexf::rfu(left, 0.02f, top));
-    vertex.set_data3f(Vertexf::rfu(left, 0.02f, bottom));
-    vertex.set_data3f(Vertexf::rfu(right, 0.02f, top));
-    vertex.set_data3f(Vertexf::rfu(right, 0.02f, bottom));
+    vertex.add_data3f(Vertexf::rfu(left, 0.02f, top));
+    vertex.add_data3f(Vertexf::rfu(left, 0.02f, bottom));
+    vertex.add_data3f(Vertexf::rfu(right, 0.02f, top));
+    vertex.add_data3f(Vertexf::rfu(right, 0.02f, bottom));
     
     
-    texcoord.set_data2f(0.0f, 1.0f);
-    texcoord.set_data2f(0.0f, 0.0f);
-    texcoord.set_data2f(1.0f, 1.0f);
-    texcoord.set_data2f(1.0f, 0.0f);
+    texcoord.add_data2f(0.0f, 1.0f);
+    texcoord.add_data2f(0.0f, 0.0f);
+    texcoord.add_data2f(1.0f, 1.0f);
+    texcoord.add_data2f(1.0f, 0.0f);
     
     
     PT(qpGeomTristrips) strip = new qpGeomTristrips(qpGeomUsageHint::UH_static);
     PT(qpGeomTristrips) strip = new qpGeomTristrips(qpGeomUsageHint::UH_static);
     strip->add_consecutive_vertices(0, 4);
     strip->add_consecutive_vertices(0, 4);

+ 3 - 3
panda/src/gobj/Sources.pp

@@ -35,8 +35,8 @@
     qpgeomVertexData.h qpgeomVertexData.I \
     qpgeomVertexData.h qpgeomVertexData.I \
     qpgeomVertexDataType.h qpgeomVertexDataType.I \
     qpgeomVertexDataType.h qpgeomVertexDataType.I \
     qpgeomVertexFormat.h qpgeomVertexFormat.I \
     qpgeomVertexFormat.h qpgeomVertexFormat.I \
-    qpgeomVertexIterator.h qpgeomVertexIterator.I \
     qpgeomVertexReader.h qpgeomVertexReader.I \
     qpgeomVertexReader.h qpgeomVertexReader.I \
+    qpgeomVertexWriter.h qpgeomVertexWriter.I \
     indexBufferContext.I indexBufferContext.h \
     indexBufferContext.I indexBufferContext.h \
     internalName.I internalName.h \
     internalName.I internalName.h \
     material.I material.h materialPool.I materialPool.h  \
     material.I material.h materialPool.I materialPool.h  \
@@ -81,8 +81,8 @@
     qpgeomVertexData.cxx \
     qpgeomVertexData.cxx \
     qpgeomVertexDataType.cxx \
     qpgeomVertexDataType.cxx \
     qpgeomVertexFormat.cxx \
     qpgeomVertexFormat.cxx \
-    qpgeomVertexIterator.cxx \
     qpgeomVertexReader.cxx \
     qpgeomVertexReader.cxx \
+    qpgeomVertexWriter.cxx \
     indexBufferContext.cxx \
     indexBufferContext.cxx \
     material.cxx  \
     material.cxx  \
     internalName.cxx \
     internalName.cxx \
@@ -125,8 +125,8 @@
     qpgeomVertexData.h qpgeomVertexData.I \
     qpgeomVertexData.h qpgeomVertexData.I \
     qpgeomVertexDataType.h qpgeomVertexDataType.I \
     qpgeomVertexDataType.h qpgeomVertexDataType.I \
     qpgeomVertexFormat.h qpgeomVertexFormat.I \
     qpgeomVertexFormat.h qpgeomVertexFormat.I \
-    qpgeomVertexIterator.h qpgeomVertexIterator.I \
     qpgeomVertexReader.h qpgeomVertexReader.I \
     qpgeomVertexReader.h qpgeomVertexReader.I \
+    qpgeomVertexWriter.h qpgeomVertexWriter.I \
     indexBufferContext.I indexBufferContext.h \
     indexBufferContext.I indexBufferContext.h \
     internalName.I internalName.h \
     internalName.I internalName.h \
     material.I material.h \
     material.I material.h \

+ 1 - 1
panda/src/gobj/gobj_composite1.cxx

@@ -27,5 +27,5 @@
 #include "qpgeomVertexData.cxx"
 #include "qpgeomVertexData.cxx"
 #include "qpgeomVertexDataType.cxx"
 #include "qpgeomVertexDataType.cxx"
 #include "qpgeomVertexFormat.cxx"
 #include "qpgeomVertexFormat.cxx"
-#include "qpgeomVertexIterator.cxx"
 #include "qpgeomVertexReader.cxx"
 #include "qpgeomVertexReader.cxx"
+#include "qpgeomVertexWriter.cxx"

+ 43 - 50
panda/src/gobj/qpgeom.cxx

@@ -17,6 +17,7 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
 #include "qpgeom.h"
 #include "qpgeom.h"
+#include "qpgeomVertexReader.h"
 #include "pStatTimer.h"
 #include "pStatTimer.h"
 #include "bamReader.h"
 #include "bamReader.h"
 #include "bamWriter.h"
 #include "bamWriter.h"
@@ -404,6 +405,32 @@ draw(GraphicsStateGuardianBase *gsg, const qpGeomMunger *munger,
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeom::calc_tight_bounds
+//       Access: Public, Virtual
+//  Description: Expands min_point and max_point to include all of the
+//               vertices in the Geom, if any.  found_any is set true
+//               if any points are found.  It is the caller's
+//               responsibility to initialize min_point, max_point,
+//               and found_any before calling this function.
+////////////////////////////////////////////////////////////////////
+void qpGeom::
+calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
+                  bool &found_any, 
+                  const qpGeomVertexData *vertex_data,
+                  bool got_mat, const LMatrix4f &mat) const {
+
+  CDReader cdata(_cycler);
+  
+  Primitives::const_iterator pi;
+  for (pi = cdata->_primitives.begin(); 
+       pi != cdata->_primitives.end();
+       ++pi) {
+    (*pi)->calc_tight_bounds(min_point, max_point, found_any, vertex_data,
+                             got_mat, mat);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: qpGeom::get_next_modified
 //     Function: qpGeom::get_next_modified
 //       Access: Public, Static
 //       Access: Public, Static
@@ -437,56 +464,22 @@ recompute_bound() {
 
 
   GeometricBoundingVolume *gbv = DCAST(GeometricBoundingVolume, bound);
   GeometricBoundingVolume *gbv = DCAST(GeometricBoundingVolume, bound);
 
 
-  // Now actually compute the bounding volume by putting it around all
-  // of our vertices.
-  CDReader cdata(_cycler);
-
-  const qpGeomVertexFormat *format = cdata->_data->get_format();
-
-  int array_index = format->get_array_with(InternalName::get_vertex());
-  if (array_index < 0) {
-    // No vertex data.
-    return bound;
-  }
-
-  const qpGeomVertexArrayFormat *array_format = format->get_array(array_index);
-  const qpGeomVertexDataType *data_type = 
-    array_format->get_data_type(InternalName::get_vertex());
-
-  int stride = array_format->get_stride();
-  int start = data_type->get_start();
-  int num_components = data_type->get_num_components();
-
-  CPTA_uchar array_data = cdata->_data->get_array(array_index)->get_data();
-
-  if (stride == 3 * sizeof(PN_float32) && start == 0 && num_components == 3 &&
-      (array_data.size() % stride) == 0) {
-    // Here's an easy special case: it's a standalone table of vertex
-    // positions, with nothing else in the middle, so we can use
-    // directly as an array of LPoint3f's.
-    const LPoint3f *vertices_begin = (const LPoint3f *)&array_data[0];
-    const LPoint3f *vertices_end = (const LPoint3f *)&array_data[array_data.size()];
-    gbv->around(vertices_begin, vertices_end);
-
-  } else {
-    // Otherwise, we have to copy the vertex positions out one at time.
-    pvector<LPoint3f> vertices;
-
-    size_t p = start;
-    while (p + stride <= array_data.size()) {
-      const PN_float32 *v = (const PN_float32 *)&array_data[p];
-
-      LPoint3f vertex;
-      qpGeomVertexData::to_vec3(vertex, v, num_components);
-
-      vertices.push_back(vertex);
-      p += stride;
-    }
-
-    const LPoint3f *vertices_begin = &vertices[0];
-    const LPoint3f *vertices_end = vertices_begin + vertices.size();
-
-    gbv->around(vertices_begin, vertices_end);
+  // Now actually compute the bounding volume.  We do this by using
+  // calc_tight_bounds to determine our minmax first.
+  LPoint3f points[2];
+  bool found_any = false;
+  calc_tight_bounds(points[0], points[1], found_any, get_vertex_data(),
+                    false, LMatrix4f::ident_mat());
+  if (found_any) {
+    // Then we put the bounding volume around both of those points.
+    // Technically, we should put it around the eight points at the
+    // corners of the rectangular solid, but we happen to know that
+    // the two diagonally opposite points is good enough to define any
+    // of our bound volume types.
+
+    const LPoint3f *points_begin = &points[0];
+    const LPoint3f *points_end = points_begin + 2;
+    gbv->around(points_begin, points_end);
   }
   }
 
 
   return bound;
   return bound;

+ 5 - 0
panda/src/gobj/qpgeom.h

@@ -97,6 +97,11 @@ public:
             const qpGeomMunger *munger,
             const qpGeomMunger *munger,
             const qpGeomVertexData *vertex_data) const;
             const qpGeomVertexData *vertex_data) const;
 
 
+  void calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
+                         bool &found_any, 
+                         const qpGeomVertexData *vertex_data,
+                         bool got_mat, const LMatrix4f &mat) const;
+
   static UpdateSeq get_next_modified();
   static UpdateSeq get_next_modified();
 
 
 protected:
 protected:

+ 45 - 35
panda/src/gobj/qpgeomPrimitive.cxx

@@ -21,6 +21,7 @@
 #include "qpgeomVertexData.h"
 #include "qpgeomVertexData.h"
 #include "qpgeomVertexArrayFormat.h"
 #include "qpgeomVertexArrayFormat.h"
 #include "qpgeomVertexDataType.h"
 #include "qpgeomVertexDataType.h"
+#include "qpgeomVertexReader.h"
 #include "preparedGraphicsObjects.h"
 #include "preparedGraphicsObjects.h"
 #include "internalName.h"
 #include "internalName.h"
 #include "bamReader.h"
 #include "bamReader.h"
@@ -671,46 +672,55 @@ clear_prepared(PreparedGraphicsObjects *prepared_objects) {
 void qpGeomPrimitive::
 void qpGeomPrimitive::
 calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
 calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
                   bool &found_any, 
                   bool &found_any, 
-                  const qpGeomVertexData *vertex_data) const {
-  CDReader cdata(_cycler);
-
-  const qpGeomVertexFormat *format = vertex_data->get_format();
-
-  int array_index = format->get_array_with(InternalName::get_vertex());
-  if (array_index < 0) {
+                  const qpGeomVertexData *vertex_data,
+                  bool got_mat, const LMatrix4f &mat) const {
+  qpGeomVertexReader reader(vertex_data, InternalName::get_vertex());
+  if (!reader.has_data_type()) {
     // No vertex data.
     // No vertex data.
     return;
     return;
   }
   }
 
 
-  const qpGeomVertexArrayFormat *array_format = format->get_array(array_index);
-  const qpGeomVertexDataType *data_type = 
-    array_format->get_data_type(InternalName::get_vertex());
-
-  int stride = array_format->get_stride();
-  int start = data_type->get_start();
-  int num_components = data_type->get_num_components();
-
-  CPTA_uchar array_data = vertex_data->get_array(array_index)->get_data();
-
-  PTA_ushort::const_iterator ii;
-  for (ii = cdata->_vertices.begin(); ii != cdata->_vertices.end(); ++ii) {
-    int index = (int)(*ii);
-    const PN_float32 *v = (const PN_float32 *)&array_data[start + index * stride];
-
-    LPoint3f vertex;
-    qpGeomVertexData::to_vec3(vertex, v, num_components);
+  CDReader cdata(_cycler);
 
 
-    if (found_any) {
-      min_point.set(min(min_point[0], vertex[0]),
-                    min(min_point[1], vertex[1]),
-                    min(min_point[2], vertex[2]));
-      max_point.set(max(max_point[0], vertex[0]),
-                    max(max_point[1], vertex[1]),
-                    max(max_point[2], vertex[2]));
-    } else {
-      min_point = vertex;
-      max_point = vertex;
-      found_any = true;
+  if (got_mat) {
+    PTA_ushort::const_iterator ii;
+    for (ii = cdata->_vertices.begin(); ii != cdata->_vertices.end(); ++ii) {
+      int index = (int)(*ii);
+      reader.set_vertex(index);
+      const LVecBase3f &vertex = reader.get_data3f();
+      
+      if (found_any) {
+        min_point.set(min(min_point[0], vertex[0]),
+                      min(min_point[1], vertex[1]),
+                      min(min_point[2], vertex[2]));
+        max_point.set(max(max_point[0], vertex[0]),
+                      max(max_point[1], vertex[1]),
+                      max(max_point[2], vertex[2]));
+      } else {
+        min_point = vertex;
+        max_point = vertex;
+        found_any = true;
+      }
+    }
+  } else {
+    PTA_ushort::const_iterator ii;
+    for (ii = cdata->_vertices.begin(); ii != cdata->_vertices.end(); ++ii) {
+      int index = (int)(*ii);
+      reader.set_vertex(index);
+      LPoint3f vertex = mat.xform_point(reader.get_data3f());
+      
+      if (found_any) {
+        min_point.set(min(min_point[0], vertex[0]),
+                      min(min_point[1], vertex[1]),
+                      min(min_point[2], vertex[2]));
+        max_point.set(max(max_point[0], vertex[0]),
+                      max(max_point[1], vertex[1]),
+                      max(max_point[2], vertex[2]));
+      } else {
+        min_point = vertex;
+        max_point = vertex;
+        found_any = true;
+      }
     }
     }
   }
   }
 }
 }

+ 4 - 3
panda/src/gobj/qpgeomPrimitive.h

@@ -162,9 +162,10 @@ private:
 public:
 public:
   virtual void draw(GraphicsStateGuardianBase *gsg) const=0;
   virtual void draw(GraphicsStateGuardianBase *gsg) const=0;
 
 
-  virtual void calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
-                                 bool &found_any, 
-                                 const qpGeomVertexData *vertex_data) const;
+  void calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
+                         bool &found_any, 
+                         const qpGeomVertexData *vertex_data,
+                         bool got_mat, const LMatrix4f &mat) const;
 
 
 protected:
 protected:
   virtual CPT(qpGeomPrimitive) decompose_impl() const;
   virtual CPT(qpGeomPrimitive) decompose_impl() const;

+ 8 - 3
panda/src/gobj/qpgeomVertexArrayFormat.cxx

@@ -19,6 +19,7 @@
 #include "qpgeomVertexFormat.h"
 #include "qpgeomVertexFormat.h"
 #include "qpgeomVertexDataType.h"
 #include "qpgeomVertexDataType.h"
 #include "qpgeomVertexData.h"
 #include "qpgeomVertexData.h"
+#include "qpgeomVertexReader.h"
 #include "indent.h"
 #include "indent.h"
 #include "bamReader.h"
 #include "bamReader.h"
 #include "bamWriter.h"
 #include "bamWriter.h"
@@ -430,20 +431,24 @@ write_with_data(ostream &out, int indent_level,
                 const qpGeomVertexData *data, int array_index) const {
                 const qpGeomVertexData *data, int array_index) const {
   consider_sort_data_types();
   consider_sort_data_types();
   int num_vertices = data->get_num_vertices();
   int num_vertices = data->get_num_vertices();
+
+  qpGeomVertexReader reader(data);
+
   for (int i = 0; i < num_vertices; i++) {
   for (int i = 0; i < num_vertices; i++) {
     indent(out, indent_level)
     indent(out, indent_level)
       << "vertex index " << i << ":\n";
       << "vertex index " << i << ":\n";
+    reader.set_vertex(i);
     DataTypes::const_iterator dti;
     DataTypes::const_iterator dti;
     for (dti = _data_types.begin(); dti != _data_types.end(); ++dti) {
     for (dti = _data_types.begin(); dti != _data_types.end(); ++dti) {
       const qpGeomVertexDataType *data_type = (*dti);
       const qpGeomVertexDataType *data_type = (*dti);
       int num_values = min(data_type->get_num_values(), 4);
       int num_values = min(data_type->get_num_values(), 4);
-      float data_values[4]; 
-      data->get_data(array_index, data_type, i, data_values, num_values);
+      reader.set_data_type(array_index, data_type);
+      const LVecBase4f &d = reader.get_data4f();
 
 
       indent(out, indent_level + 2) 
       indent(out, indent_level + 2) 
         << *data_type->get_name();
         << *data_type->get_name();
       for (int v = 0; v < num_values; v++) {
       for (int v = 0; v < num_values; v++) {
-        out << " " << data_values[v];
+        out << " " << d[v];
       }
       }
       out << "\n";
       out << "\n";
     }
     }

+ 17 - 538
panda/src/gobj/qpgeomVertexData.cxx

@@ -17,8 +17,8 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
 #include "qpgeomVertexData.h"
 #include "qpgeomVertexData.h"
-#include "qpgeomVertexIterator.h"
 #include "qpgeomVertexReader.h"
 #include "qpgeomVertexReader.h"
+#include "qpgeomVertexWriter.h"
 #include "pStatTimer.h"
 #include "pStatTimer.h"
 #include "bamReader.h"
 #include "bamReader.h"
 #include "bamWriter.h"
 #include "bamWriter.h"
@@ -381,8 +381,8 @@ scale_color(const LVecBase4f &color_scale, int num_components,
      contents, get_usage_hint(), true);
      contents, get_usage_hint(), true);
 
 
   // Now go through and apply the scale, copying it to the new data.
   // Now go through and apply the scale, copying it to the new data.
-  qpGeomVertexIterator from(this, InternalName::get_color());
-  qpGeomVertexIterator to(new_data, InternalName::get_color());
+  qpGeomVertexReader from(this, InternalName::get_color());
+  qpGeomVertexWriter to(new_data, InternalName::get_color());
 
 
   for (int i = 0; i < num_vertices; i++) {
   for (int i = 0; i < num_vertices; i++) {
     Colorf color = from.get_data4f();
     Colorf color = from.get_data4f();
@@ -423,7 +423,7 @@ set_color(const Colorf &color, int num_components,
      contents, get_usage_hint(), true);
      contents, get_usage_hint(), true);
 
 
   // Now go through and set the new color value.
   // Now go through and set the new color value.
-  qpGeomVertexIterator to(new_data, InternalName::get_color());
+  qpGeomVertexWriter to(new_data, InternalName::get_color());
 
 
   for (int i = 0; i < num_vertices; i++) {
   for (int i = 0; i < num_vertices; i++) {
     to.set_data4f(color);
     to.set_data4f(color);
@@ -522,16 +522,23 @@ replace_data_type(const InternalName *name, int num_components,
       new qpGeomVertexArrayFormat(name, num_components, numeric_type, contents);
       new qpGeomVertexArrayFormat(name, num_components, numeric_type, contents);
     new_type_array = new_format->add_array(type_array_format);
     new_type_array = new_format->add_array(type_array_format);
   }
   }
-    
+
+  CPT(qpGeomVertexFormat) format = 
+    qpGeomVertexFormat::register_format(new_format);
+
+  if (gobj_cat.is_debug()) {
+    gobj_cat.debug()
+      << "Replacing data type " << *name << "; converting "
+      << get_num_vertices() << " vertices from " 
+      << *_format << " to " << *new_format << "\n";
+  }
+  
   PT(qpGeomVertexData) new_data = 
   PT(qpGeomVertexData) new_data = 
-    new qpGeomVertexData(get_name(),
-                         qpGeomVertexFormat::register_format(new_format),
-                         usage_hint);
+    new qpGeomVertexData(get_name(), format, usage_hint);
   if (keep_animation) {
   if (keep_animation) {
     new_data->set_transform_blend_palette(get_transform_blend_palette());
     new_data->set_transform_blend_palette(get_transform_blend_palette());
   }
   }
 
 
-
   int j = 0;
   int j = 0;
   int num_arrays = get_num_arrays();
   int num_arrays = get_num_arrays();
   for (int i = 0; i < num_arrays; ++i) {
   for (int i = 0; i < num_arrays; ++i) {
@@ -589,398 +596,6 @@ write(ostream &out, int indent_level) const {
   }
   }
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexData::set_data
-//       Access: Public
-//  Description: Sets the nth vertex to a particular value.  Query the
-//               format to get the array index and data_type
-//               parameters for the particular data type you want to
-//               set.
-//
-//               This flavor of set_data() accepts a generic float
-//               array and a specific number of dimensions.  The new
-//               data will be copied from the num_values elements
-//               of data.
-////////////////////////////////////////////////////////////////////
-void qpGeomVertexData::
-set_data(int array, const qpGeomVertexDataType *data_type,
-         int vertex, const float *data, int num_values) {
-  int stride = _format->get_array(array)->get_stride();
-  int element = vertex * stride + data_type->get_start();
-
-  {
-    CDReader cdata(_cycler);
-    int array_size = (int)cdata->_arrays[array]->get_data_size_bytes();
-    if (element + data_type->get_total_bytes() > array_size) {
-      // Whoops, we need more vertices!
-      CDWriter cdataw(_cycler, cdata);
-      do_set_num_vertices(vertex + 1, cdataw);
-    }
-  }
-
-  PTA_uchar array_data = modify_array(array)->modify_data();
-  nassertv(element >= 0 && element + data_type->get_total_bytes() <= (int)array_data.size());
-
-  switch (data_type->get_numeric_type()) {
-  case qpGeomVertexDataType::NT_uint16:
-    {
-      // Elevate or truncate to the right number of components.
-      int i = 0;
-      int min_values = min(num_values, data_type->get_num_values());
-      while (i < min_values) {
-        *(PN_uint16 *)&array_data[element] = (int)data[i];
-        element += sizeof(PN_uint16);
-        ++i;
-      }
-      while (i < data_type->get_num_values()) {
-        *(PN_uint16 *)&array_data[element] = 0;
-        element += sizeof(PN_uint16);
-        ++i;
-      }
-    }
-      
-    break;
-
-  case qpGeomVertexDataType::NT_uint8:
-    {
-      int i = 0;
-      int min_values = min(num_values, data_type->get_num_values());
-      while (i < min_values) {
-        int value = (int)(data[i] * 255.0f);
-        array_data[element] = value;
-        element += 1;
-        ++i;
-      }
-      while (i < data_type->get_num_values()) {
-        array_data[element] = 0;
-        element += 1;
-        ++i;
-      }        
-    }
-    break;
-
-  case qpGeomVertexDataType::NT_packed_8888:
-    {
-      if (num_values == 4) {
-        *(PN_uint32 *)&array_data[element] = pack_argb(data);
-      } else {
-        // Elevate (or truncate) to 4 components.
-        float data4[4];
-        memset(data4, 0, 4 * sizeof(float));
-        memcpy(data4, data, min(4, num_values) * sizeof(float));
-        *(PN_uint32 *)&array_data[element] = pack_argb(data4);
-      }
-    }
-    break;
-
-  case qpGeomVertexDataType::NT_float32:
-    if (num_values == 4 && sizeof(float) == sizeof(PN_float32)) {
-      // The easy way: we can memcpy the data directly in.
-      memcpy(&array_data[element], data, data_type->get_total_bytes());
-
-    } else {
-      // Elevate or truncate to the right number of components.
-      int i = 0;
-      int min_values = min(num_values, data_type->get_num_values());
-      while (i < min_values) {
-        *(PN_float32 *)&array_data[element] = data[i];
-        element += sizeof(PN_float32);
-        ++i;
-      }
-      while (i < data_type->get_num_values()) {
-        if (i == 3 && data_type->get_num_values() == 4) {
-          *(PN_float32 *)&array_data[element] = 1.0f;
-        } else {
-          *(PN_float32 *)&array_data[element] = 0.0f;
-        }
-        element += sizeof(PN_float32);
-        ++i;
-      }
-    }
-      
-    break;
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexData::get_data
-//       Access: Public
-//  Description: Returns the data associated with the nth vertex for a
-//               particular value.  Query the format to get the array
-//               index and data_type parameters for the particular
-//               data type you want to get.
-//
-//               This flavor of get_data() copies its data into a
-//               generic float array.
-////////////////////////////////////////////////////////////////////
-void qpGeomVertexData::
-get_data(int array, const qpGeomVertexDataType *data_type,
-         int vertex, float *data, int num_values) const {
-  CPTA_uchar array_data = get_array(array)->get_data();
-  int stride = _format->get_array(array)->get_stride();
-  int element = vertex * stride + data_type->get_start();
-  nassertv(element >= 0 && element + data_type->get_total_bytes() <= (int)array_data.size());
-
-  switch (data_type->get_numeric_type()) {
-  case qpGeomVertexDataType::NT_uint16:
-    {
-      int i = 0;
-      int min_values = min(num_values, data_type->get_num_values());
-      while (i < min_values) {
-        data[i] = *(PN_uint16 *)&array_data[element];
-        element += sizeof(PN_uint16);
-        ++i;
-      }
-      while (i < num_values) {
-        data[i] = 0;
-        ++i;
-      }
-    }
-    break;
-
-  case qpGeomVertexDataType::NT_uint8:
-    {
-      int i = 0;
-      int min_values = min(num_values, data_type->get_num_values());
-      while (i < min_values) {
-        int value = *(unsigned char *)&array_data[element];
-        element += 1;
-        data[i] = (float)value / 255.0f;
-        ++i;
-      }
-      while (i < num_values) {
-        data[i] = 0.0f;
-        ++i;
-      }
-    }
-    break;
-
-  case qpGeomVertexDataType::NT_packed_8888:
-    {
-      if (num_values == 4) {
-        unpack_argb(data, *(PN_uint32 *)&array_data[element]);
-      } else {
-        float data4[4];
-        unpack_argb(data4, *(PN_uint32 *)&array_data[element]);
-        memset(data, 0, num_values * sizeof(float));
-        memcpy(data, data4, min(num_values, 4) * sizeof(float));
-      }
-    }
-    break;
-
-  case qpGeomVertexDataType::NT_float32:
-    if (num_values == data_type->get_num_values() && 
-        sizeof(float) == sizeof(PN_float32)) {
-      memcpy(data, &array_data[element], num_values * sizeof(PN_float32));
-    } else {
-      int i = 0;
-      int min_values = min(num_values, data_type->get_num_values());
-      while (i < min_values) {
-        data[i] = *(PN_float32 *)&array_data[element];
-        element += sizeof(PN_float32);
-        ++i;
-      }
-      while (i < num_values) {
-        if (i == 3 && num_values == 4) {
-          data[i] = 1.0f;
-        } else {
-          data[i] = 0.0f;
-        }
-        ++i;
-      }
-    }
-    break;
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexData::set_data
-//       Access: Public
-//  Description: Sets the nth vertex to a particular value.  Query the
-//               format to get the array index and data_type
-//               parameters for the particular data type you want to
-//               set.
-//
-//               This flavor of set_data() accepts a generic float
-//               array and a specific number of dimensions.  The new
-//               data will be copied from the num_values elements
-//               of data.
-////////////////////////////////////////////////////////////////////
-void qpGeomVertexData::
-set_data(int array, const qpGeomVertexDataType *data_type,
-         int vertex, const int *data, int num_values) {
-  int stride = _format->get_array(array)->get_stride();
-  int element = vertex * stride + data_type->get_start();
-
-  {
-    CDReader cdata(_cycler);
-    int array_size = (int)cdata->_arrays[array]->get_data_size_bytes();
-    if (element + data_type->get_total_bytes() > array_size) {
-      // Whoops, we need more vertices!
-      CDWriter cdataw(_cycler, cdata);
-      do_set_num_vertices(vertex + 1, cdataw);
-    }
-  }
-
-  PTA_uchar array_data = modify_array(array)->modify_data();
-  nassertv(element >= 0 && element + data_type->get_total_bytes() <= (int)array_data.size());
-
-  switch (data_type->get_numeric_type()) {
-  case qpGeomVertexDataType::NT_uint16:
-    {
-      // Elevate or truncate to the right number of components.
-      int i = 0;
-      int min_values = min(num_values, data_type->get_num_values());
-      while (i < min_values) {
-        *(PN_uint16 *)&array_data[element] = data[i];
-        element += sizeof(PN_uint16);
-        ++i;
-      }
-      while (i < data_type->get_num_values()) {
-        *(PN_uint16 *)&array_data[element] = 0;
-        element += sizeof(PN_uint16);
-        ++i;
-      }
-    }
-      
-    break;
-
-  case qpGeomVertexDataType::NT_uint8:
-    {
-      int i = 0;
-      int min_values = min(num_values, data_type->get_num_values());
-      while (i < min_values) {
-        array_data[element] = data[i];
-        element += 1;
-        ++i;
-      }
-      while (i < data_type->get_num_values()) {
-        array_data[element] = 0;
-        element += 1;
-        ++i;
-      }        
-    }
-    break;
-
-  case qpGeomVertexDataType::NT_packed_8888:
-    {
-      if (num_values == 4) {
-        *(PN_uint32 *)&array_data[element] = pack_argb(data);
-      } else {
-        // Elevate (or truncate) to 4 components.
-        int data4[4];
-        memset(data4, 0, 4 * sizeof(int));
-        memcpy(data4, data, min(4, num_values) * sizeof(int));
-        *(PN_uint32 *)&array_data[element] = pack_argb(data4);
-      }
-    }
-    break;
-
-  case qpGeomVertexDataType::NT_float32:
-    {
-      // Elevate or truncate to the right number of components.
-      int i = 0;
-      int min_values = min(num_values, data_type->get_num_values());
-      while (i < min_values) {
-        *(PN_float32 *)&array_data[element] = data[i];
-        element += sizeof(PN_float32);
-        ++i;
-      }
-      while (i < data_type->get_num_values()) {
-        *(PN_float32 *)&array_data[element] = 0.0f;
-        element += sizeof(PN_float32);
-        ++i;
-      }
-    }
-      
-    break;
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexData::get_data
-//       Access: Public
-//  Description: Returns the data associated with the nth vertex for a
-//               particular value.  Query the format to get the array
-//               index and data_type parameters for the particular
-//               data type you want to get.
-//
-//               This flavor of get_data() copies its data into a
-//               generic float array.
-////////////////////////////////////////////////////////////////////
-void qpGeomVertexData::
-get_data(int array, const qpGeomVertexDataType *data_type,
-         int vertex, int *data, int num_values) const {
-  CPTA_uchar array_data = get_array(array)->get_data();
-  int stride = _format->get_array(array)->get_stride();
-  int element = vertex * stride + data_type->get_start();
-  nassertv(element >= 0 && element + data_type->get_total_bytes() <= (int)array_data.size());
-
-  switch (data_type->get_numeric_type()) {
-  case qpGeomVertexDataType::NT_uint16:
-    {
-      int i = 0;
-      int min_values = min(num_values, data_type->get_num_values());
-      while (i < min_values) {
-        data[i] = *(PN_uint16 *)&array_data[element];
-        element += sizeof(PN_uint16);
-        ++i;
-      }
-      while (i < num_values) {
-        data[i] = 0;
-        ++i;
-      }
-    }
-    break;
-
-  case qpGeomVertexDataType::NT_uint8:
-    {
-      int i = 0;
-      int min_values = min(num_values, data_type->get_num_values());
-      while (i < min_values) {
-        int value = *(unsigned char *)&array_data[element];
-        element += 1;
-        data[i] = value;
-        ++i;
-      }
-      while (i < num_values) {
-        data[i] = 0;
-        ++i;
-      }
-    }
-    break;
-
-  case qpGeomVertexDataType::NT_packed_8888:
-    {
-      if (num_values == 4) {
-        unpack_argb(data, *(PN_uint32 *)&array_data[element]);
-      } else {
-        int data4[4];
-        unpack_argb(data4, *(PN_uint32 *)&array_data[element]);
-        memset(data, 0, num_values * sizeof(int));
-        memcpy(data, data4, min(num_values, 4) * sizeof(int));
-      }
-    }
-    break;
-
-  case qpGeomVertexDataType::NT_float32:
-    {
-      int i = 0;
-      int min_values = min(num_values, data_type->get_num_values());
-      while (i < min_values) {
-        data[i] = (int)*(PN_float32 *)&array_data[element];
-        element += sizeof(PN_float32);
-        ++i;
-      }
-      while (i < num_values) {
-        data[i] = 0;
-        ++i;
-      }
-    }
-    break;
-  }
-}
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: qpGeomVertexData::get_array_info
 //     Function: qpGeomVertexData::get_array_info
 //       Access: Public
 //       Access: Public
@@ -1015,142 +630,6 @@ get_array_info(const InternalName *name,
   return false;
   return false;
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexData::to_vec2
-//       Access: Public, Static
-//  Description: Converts a data element of arbitrary number of
-//               dimensions (1 - 4) into a vec2 in a sensible way.
-////////////////////////////////////////////////////////////////////
-void qpGeomVertexData::
-to_vec2(LVecBase2f &vec, const float *data, int num_values) {
-  switch (num_values) {
-  case 1:
-    vec.set(data[0], 0.0f);
-    break;
-    
-  case 2:
-  case 3:
-    vec.set(data[0], data[1]);
-    break;
-    
-  default:  // 4 or more.
-    vec.set(data[0] / data[3], data[1] / data[3]);
-    break;
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexData::to_vec3
-//       Access: Public, Static
-//  Description: Converts a data element of arbitrary number of
-//               dimensions (1 - 4) into a vec3 in a sensible way.
-////////////////////////////////////////////////////////////////////
-void qpGeomVertexData::
-to_vec3(LVecBase3f &vec, const float *data, int num_values) {
-  switch (num_values) {
-  case 1:
-    vec.set(data[0], 0.0f, 0.0f);
-    break;
-    
-  case 2:
-    vec.set(data[0], data[1], 0.0f);
-    break;
-    
-  case 3:
-    vec.set(data[0], data[1], data[2]);
-    break;
-    
-  default:  // 4 or more.
-    vec.set(data[0] / data[3], data[1] / data[3], data[2] / data[3]);
-    break;
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexData::to_vec4
-//       Access: Public, Static
-//  Description: Converts a data element of arbitrary number of
-//               dimensions (1 - 4) into a vec4 in a sensible way.
-////////////////////////////////////////////////////////////////////
-void qpGeomVertexData::
-to_vec4(LVecBase4f &vec, const float *data, int num_values) {
-  switch (num_values) {
-  case 1:
-    vec.set(data[0], 0.0f, 0.0f, 1.0f);
-    break;
-    
-  case 2:
-    vec.set(data[0], data[1], 0.0f, 1.0f);
-    break;
-    
-  case 3:
-    vec.set(data[0], data[1], data[2], 1.0f);
-    break;
-    
-  default:  // 4 or more.
-    vec.set(data[0], data[1], data[2], data[3]);
-    break;
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexData::pack_argb
-//       Access: Public, Static
-//  Description: Packs four floats, stored R, G, B, A, into a
-//               packed_argb value.
-////////////////////////////////////////////////////////////////////
-unsigned int qpGeomVertexData::
-pack_argb(const float data[4]) {
-  unsigned int r = ((unsigned int)(data[0] * 255.0f)) & 0xff;
-  unsigned int g = ((unsigned int)(data[1] * 255.0f)) & 0xff;
-  unsigned int b = ((unsigned int)(data[2] * 255.0f)) & 0xff;
-  unsigned int a = ((unsigned int)(data[3] * 255.0f)) & 0xff;
-  return ((a << 24) | (r << 16) | (g << 8) | b);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexData::unpack_argb
-//       Access: Public, Static
-//  Description: Unpacks a packed_argb value into four floats, stored
-//               R, G, B, A.
-////////////////////////////////////////////////////////////////////
-void qpGeomVertexData::
-unpack_argb(float data[4], unsigned int packed_argb) {
-  data[0] = (float)((packed_argb >> 16) & 0xff) / 255.0f;
-  data[1] = (float)((packed_argb >> 8) & 0xff) / 255.0f;
-  data[2] = (float)(packed_argb & 0xff) / 255.0f;
-  data[3] = (float)((packed_argb >> 24) & 0xff) / 255.0f;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexData::pack_argb
-//       Access: Public, Static
-//  Description: Packs four ints, stored R, G, B, A, into a
-//               packed_argb value.
-////////////////////////////////////////////////////////////////////
-unsigned int qpGeomVertexData::
-pack_argb(const int data[4]) {
-  unsigned int r = ((unsigned int)data[0]) & 0xff;
-  unsigned int g = ((unsigned int)data[1]) & 0xff;
-  unsigned int b = ((unsigned int)data[2]) & 0xff;
-  unsigned int a = ((unsigned int)data[3]) & 0xff;
-  return ((a << 24) | (r << 16) | (g << 8) | b);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexData::unpack_argb
-//       Access: Public, Static
-//  Description: Unpacks a packed_argb value into four ints, stored
-//               R, G, B, A.
-////////////////////////////////////////////////////////////////////
-void qpGeomVertexData::
-unpack_argb(int data[4], unsigned int packed_argb) {
-  data[0] = (int)((packed_argb >> 16) & 0xff);
-  data[1] = (int)((packed_argb >> 8) & 0xff);
-  data[2] = (int)(packed_argb & 0xff);
-  data[3] = (int)((packed_argb >> 24) & 0xff);
-}
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: qpGeomVertexData::do_set_num_vertices
 //     Function: qpGeomVertexData::do_set_num_vertices
 //       Access: Private
 //       Access: Private
@@ -1234,7 +713,7 @@ update_animated_vertices(qpGeomVertexData::CDWriter &cdata) {
   // Now go through and apply the scale, copying it to the new data.
   // Now go through and apply the scale, copying it to the new data.
   qpGeomVertexReader from(this, InternalName::get_vertex());
   qpGeomVertexReader from(this, InternalName::get_vertex());
   qpGeomVertexReader blendi(this, InternalName::get_transform_blend());
   qpGeomVertexReader blendi(this, InternalName::get_transform_blend());
-  qpGeomVertexIterator to(new_data, InternalName::get_vertex());
+  qpGeomVertexWriter to(new_data, InternalName::get_vertex());
 
 
   if (from.get_data_type()->get_num_values() == 4) {
   if (from.get_data_type()->get_num_values() == 4) {
     for (int i = 0; i < num_vertices; i++) {
     for (int i = 0; i < num_vertices; i++) {

+ 0 - 18
panda/src/gobj/qpgeomVertexData.h

@@ -117,30 +117,12 @@ PUBLISHED:
   void write(ostream &out, int indent_level = 0) const;
   void write(ostream &out, int indent_level = 0) const;
 
 
 public:
 public:
-  void set_data(int array, const qpGeomVertexDataType *data_type,
-                int vertex, const float *data, int num_values);
-  void get_data(int array, const qpGeomVertexDataType *data_type,
-                int vertex, float *data, int num_values) const;
-  void set_data(int array, const qpGeomVertexDataType *data_type,
-                int vertex, const int *data, int num_values);
-  void get_data(int array, const qpGeomVertexDataType *data_type,
-                int vertex, int *data, int num_values) const;
-
   bool get_array_info(const InternalName *name, 
   bool get_array_info(const InternalName *name, 
                       const qpGeomVertexArrayData *&array_data,
                       const qpGeomVertexArrayData *&array_data,
                       int &num_components,
                       int &num_components,
                       qpGeomVertexDataType::NumericType &numeric_type, 
                       qpGeomVertexDataType::NumericType &numeric_type, 
                       int &start, int &stride) const;
                       int &start, int &stride) const;
 
 
-  static void to_vec2(LVecBase2f &vec, const float *data, int num_values);
-  static void to_vec3(LVecBase3f &vec, const float *data, int num_values);
-  static void to_vec4(LVecBase4f &vec, const float *data, int num_values);
-
-  static unsigned int pack_argb(const float data[4]);
-  static void unpack_argb(float data[4], unsigned int packed_argb);
-  static unsigned int pack_argb(const int data[4]);
-  static void unpack_argb(int data[4], unsigned int packed_argb);
-
 private:
 private:
   string _name;
   string _name;
   CPT(qpGeomVertexFormat) _format;
   CPT(qpGeomVertexFormat) _format;

+ 0 - 473
panda/src/gobj/qpgeomVertexIterator.I

@@ -1,473 +0,0 @@
-// Filename: qpgeomVertexIterator.I
-// Created by:  drose (10Mar05)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://etc.cmu.edu/panda3d/docs/license/ .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexIterator::Constructor
-//       Access: Published
-//  Description: Constructs a new iterator to process the vertices of
-//               the indicated data object.
-////////////////////////////////////////////////////////////////////
-INLINE qpGeomVertexIterator::
-qpGeomVertexIterator(qpGeomVertexData *data) :
-  _data(data),
-  _const_data(false),
-  _array(0),
-  _data_type(NULL),
-  _start_vertex(0),
-  _read_vertex(0),
-  _write_vertex(0)
-{
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexIterator::Constructor
-//       Access: Published
-//  Description: Constructs a new iterator to process the vertices of
-//               the indicated data object.  This flavor creates the
-//               iterator specifically to process the named data type.
-////////////////////////////////////////////////////////////////////
-INLINE qpGeomVertexIterator::
-qpGeomVertexIterator(qpGeomVertexData *data, const string &name) :
-  _data(data),
-  _const_data(false),
-  _array(0),
-  _data_type(NULL),
-  _start_vertex(0),
-  _read_vertex(0),
-  _write_vertex(0)
-{
-  set_data_type(name);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexIterator::Constructor
-//       Access: Published
-//  Description: Constructs a new iterator to process the vertices of
-//               the indicated data object.  This flavor creates the
-//               iterator specifically to process the named data type.
-////////////////////////////////////////////////////////////////////
-INLINE qpGeomVertexIterator::
-qpGeomVertexIterator(qpGeomVertexData *data, const InternalName *name) :
-  _data(data),
-  _const_data(false),
-  _array(0),
-  _data_type(NULL),
-  _start_vertex(0),
-  _read_vertex(0),
-  _write_vertex(0)
-{
-  set_data_type(name);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexIterator::Constructor
-//       Access: Published
-//  Description: Constructs a new iterator to process the vertices of
-//               the indicated data object.
-////////////////////////////////////////////////////////////////////
-INLINE qpGeomVertexIterator::
-qpGeomVertexIterator(const qpGeomVertexData *data) :
-  _data((qpGeomVertexData *)data),
-  _const_data(true),
-  _array(0),
-  _data_type(NULL),
-  _start_vertex(0),
-  _read_vertex(0),
-  _write_vertex(0)
-{
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexIterator::Constructor
-//       Access: Published
-//  Description: Constructs a new iterator to process the vertices of
-//               the indicated data object.  This flavor creates the
-//               iterator specifically to process the named data type.
-////////////////////////////////////////////////////////////////////
-INLINE qpGeomVertexIterator::
-qpGeomVertexIterator(const qpGeomVertexData *data, const string &name) :
-  _data((qpGeomVertexData *)data),
-  _const_data(true),
-  _array(0),
-  _data_type(NULL),
-  _start_vertex(0),
-  _read_vertex(0),
-  _write_vertex(0)
-{
-  set_data_type(name);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexIterator::Constructor
-//       Access: Published
-//  Description: Constructs a new iterator to process the vertices of
-//               the indicated data object.  This flavor creates the
-//               iterator specifically to process the named data type.
-////////////////////////////////////////////////////////////////////
-INLINE qpGeomVertexIterator::
-qpGeomVertexIterator(const qpGeomVertexData *data, const InternalName *name) :
-  _data((qpGeomVertexData *)data),
-  _const_data(true),
-  _array(0),
-  _data_type(NULL),
-  _start_vertex(0),
-  _read_vertex(0),
-  _write_vertex(0)
-{
-  set_data_type(name);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexIterator::get_data
-//       Access: Published
-//  Description: Returns the current data object that the iterator is
-//               processing.
-////////////////////////////////////////////////////////////////////
-INLINE const qpGeomVertexData *qpGeomVertexIterator::
-get_data() const {
-  return _data;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexIterator::set_data_type
-//       Access: Published
-//  Description: Sets up the iterator to use the nth data type of the
-//               GeomVertexFormat, numbering from 0.
-//
-//               This also resets the read and write vertex numbers to
-//               the start vertex (the same value passed to a previous
-//               call to set_vertex(), or 0 if set_vertex() was never
-//               called.)
-////////////////////////////////////////////////////////////////////
-INLINE void qpGeomVertexIterator::
-set_data_type(int data_type) {
-  nassertv(_data->get_format()->get_array_with(data_type) >= 0);
-  set_data_type(_data->get_format()->get_array_with(data_type),
-                _data->get_format()->get_data_type(data_type));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexIterator::set_data_type
-//       Access: Published
-//  Description: Sets up the iterator to use the data type with the
-//               indicated name.
-//
-//               This also resets the read and write vertex numbers to
-//               the start vertex (the same value passed to a previous
-//               call to set_vertex(), or 0 if set_vertex() was never
-//               called.)
-////////////////////////////////////////////////////////////////////
-INLINE void qpGeomVertexIterator::
-set_data_type(const string &name) {
-  set_data_type(InternalName::make(name));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexIterator::set_data_type
-//       Access: Published
-//  Description: Sets up the iterator to use the data type with the
-//               indicated name.
-//
-//               This also resets the read and write vertex numbers to
-//               the start vertex (the same value passed to a previous
-//               call to set_vertex(), or 0 if set_vertex() was never
-//               called.)
-////////////////////////////////////////////////////////////////////
-INLINE void qpGeomVertexIterator::
-set_data_type(const InternalName *name) {
-  nassertv(_data->get_format()->get_array_with(name) >= 0);
-  set_data_type(_data->get_format()->get_array_with(name),
-                _data->get_format()->get_data_type(name));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexIterator::set_data_type
-//       Access: Published
-//  Description: Sets up the iterator to use the indicated data_type
-//               description on the given array.
-//
-//               This also resets the read and write vertex numbers to
-//               the start vertex (the same value passed to a previous
-//               call to set_vertex(), or 0 if set_vertex() was never
-//               called.)
-////////////////////////////////////////////////////////////////////
-INLINE void qpGeomVertexIterator::
-set_data_type(int array, const qpGeomVertexDataType *data_type) {
-  nassertv(array >= 0 && array < _data->get_num_arrays());
-  nassertv(data_type != (qpGeomVertexDataType *)NULL);
-  _array = array;
-  _data_type = data_type;
-
-  _read_vertex = _start_vertex;
-  _write_vertex = _start_vertex;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexIterator::get_array
-//       Access: Published
-//  Description: Returns the array index containing the data type that
-//               the iterator is working on.
-////////////////////////////////////////////////////////////////////
-INLINE int qpGeomVertexIterator::
-get_array() const {
-  return _array;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexIterator::get_data_type
-//       Access: Published
-//  Description: Returns the description of the data type that the
-//               iterator is working on.
-////////////////////////////////////////////////////////////////////
-INLINE const qpGeomVertexDataType *qpGeomVertexIterator::
-get_data_type() const {
-  return _data_type;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexIterator::set_vertex
-//       Access: Published
-//  Description: Sets the start, read, and write index to the
-//               indicated value.  The iterator will begin traversing
-//               from the given vertex.
-////////////////////////////////////////////////////////////////////
-INLINE void qpGeomVertexIterator::
-set_vertex(int vertex) {
-  _start_vertex = vertex;
-  _read_vertex = vertex;
-  _write_vertex = vertex;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexIterator::get_start_vertex
-//       Access: Published
-//  Description: Returns the vertex index at which the iterator
-//               started.  It will return to this vertex if you reset
-//               the current data_type.
-////////////////////////////////////////////////////////////////////
-INLINE int qpGeomVertexIterator::
-get_start_vertex() const {
-  return _start_vertex;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexIterator::get_read_vertex
-//       Access: Published
-//  Description: Returns the current read vertex index of the
-//               iterator.  This is the index whose value will be
-//               returned by the next call to get_vertex().
-////////////////////////////////////////////////////////////////////
-INLINE int qpGeomVertexIterator::
-get_read_vertex() const {
-  return _read_vertex;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexIterator::get_write_vertex
-//       Access: Published
-//  Description: Returns the current write vertex index of the
-//               iterator.  This is the index whose value will be
-//               modified by the next call to set_vertex().
-////////////////////////////////////////////////////////////////////
-INLINE int qpGeomVertexIterator::
-get_write_vertex() const {
-  return _write_vertex;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexIterator::set_data1f
-//       Access: Published
-//  Description: Sets the write vertex to a particular 1-component
-//               value, and advances the write vertex.
-////////////////////////////////////////////////////////////////////
-INLINE void qpGeomVertexIterator::
-set_data1f(float data) {
-  nassertv(!_const_data);
-  _data->set_data(_array, _data_type, _write_vertex, &data, 1);
-  ++_write_vertex;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexIterator::set_data2f
-//       Access: Published
-//  Description: Sets the write vertex to a particular 2-component
-//               value, and advances the write vertex.
-////////////////////////////////////////////////////////////////////
-INLINE void qpGeomVertexIterator::
-set_data2f(float x, float y) {
-  set_data2f(LVecBase2f(x, y));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexIterator::set_data2f
-//       Access: Published
-//  Description: Sets the write vertex to a particular 2-component
-//               value, and advances the write vertex.
-////////////////////////////////////////////////////////////////////
-INLINE void qpGeomVertexIterator::
-set_data2f(const LVecBase2f &data) {
-  nassertv(!_const_data);
-  _data->set_data(_array, _data_type, _write_vertex, data.get_data(), 2);
-  ++_write_vertex;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexIterator::set_data3f
-//       Access: Published
-//  Description: Sets the write vertex to a particular 3-component
-//               value, and advances the write vertex.
-////////////////////////////////////////////////////////////////////
-INLINE void qpGeomVertexIterator::
-set_data3f(float x, float y, float z) {
-  set_data3f(LVecBase3f(x, y, z));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexIterator::set_data3f
-//       Access: Published
-//  Description: Sets the write vertex to a particular 3-component
-//               value, and advances the write vertex.
-////////////////////////////////////////////////////////////////////
-INLINE void qpGeomVertexIterator::
-set_data3f(const LVecBase3f &data) {
-  nassertv(!_const_data);
-  _data->set_data(_array, _data_type, _write_vertex, data.get_data(), 3);
-  ++_write_vertex;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexIterator::set_data4f
-//       Access: Published
-//  Description: Sets the write vertex to a particular 4-component
-//               value, and advances the write vertex.
-////////////////////////////////////////////////////////////////////
-INLINE void qpGeomVertexIterator::
-set_data4f(float x, float y, float z, float w) {
-  set_data4f(LVecBase4f(x, y, z, w));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexIterator::set_data4f
-//       Access: Published
-//  Description: Sets the write vertex to a particular 4-component
-//               value, and advances the write vertex.
-////////////////////////////////////////////////////////////////////
-INLINE void qpGeomVertexIterator::
-set_data4f(const LVecBase4f &data) {
-  nassertv(!_const_data);
-  _data->set_data(_array, _data_type, _write_vertex, data.get_data(), 4);
-  ++_write_vertex;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexIterator::get_data1f
-//       Access: Published
-//  Description: Returns the data associated with the read vertex,
-//               expressed as a 1-component value, and advances the
-//               read vertex.
-////////////////////////////////////////////////////////////////////
-INLINE float qpGeomVertexIterator::
-get_data1f() {
-  float data;
-  _data->get_data(_array, _data_type, _read_vertex, &data, 1);
-  ++_read_vertex;
-  return data;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexIterator::get_data2f
-//       Access: Published
-//  Description: Returns the data associated with the read vertex,
-//               expressed as a 2-component value, and advances the
-//               read vertex.
-////////////////////////////////////////////////////////////////////
-INLINE LVecBase2f qpGeomVertexIterator::
-get_data2f() {
-  float data[4];
-  int num_values = min(_data_type->get_num_values(), 4);
-  _data->get_data(_array, _data_type, _read_vertex, data, num_values);
-  ++_read_vertex;
-  LVecBase2f result;
-  qpGeomVertexData::to_vec2(result, data, num_values);
-  return result;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexIterator::get_data3f
-//       Access: Published
-//  Description: Returns the data associated with the read vertex,
-//               expressed as a 3-component value, and advances the
-//               read vertex.
-////////////////////////////////////////////////////////////////////
-INLINE LVecBase3f qpGeomVertexIterator::
-get_data3f() {
-  float data[4];
-  int num_values = min(_data_type->get_num_values(), 4);
-  _data->get_data(_array, _data_type, _read_vertex, data, num_values);
-  ++_read_vertex;
-  LVecBase3f result;
-  qpGeomVertexData::to_vec3(result, data, num_values);
-  return result;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexIterator::get_data4f
-//       Access: Published
-//  Description: Returns the data associated with the read vertex,
-//               expressed as a 4-component value, and advances the
-//               read vertex.
-////////////////////////////////////////////////////////////////////
-INLINE LVecBase4f qpGeomVertexIterator::
-get_data4f() {
-  float data[4];
-  int num_values = min(_data_type->get_num_values(), 4);
-  _data->get_data(_array, _data_type, _read_vertex, data, num_values);
-  ++_read_vertex;
-  LVecBase4f result;
-  qpGeomVertexData::to_vec4(result, data, num_values);
-  return result;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexIterator::set_data1i
-//       Access: Published
-//  Description: Sets the write vertex to a particular 1-component
-//               value, and advances the write vertex.
-////////////////////////////////////////////////////////////////////
-INLINE void qpGeomVertexIterator::
-set_data1i(int data) {
-  nassertv(!_const_data);
-  _data->set_data(_array, _data_type, _write_vertex, &data, 1);
-  ++_write_vertex;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexIterator::get_data1i
-//       Access: Published
-//  Description: Returns the data associated with the read vertex,
-//               expressed as a 1-component value, and advances the
-//               read vertex.
-////////////////////////////////////////////////////////////////////
-INLINE int qpGeomVertexIterator::
-get_data1i() {
-  int data;
-  _data->get_data(_array, _data_type, _read_vertex, &data, 1);
-  ++_read_vertex;
-  return data;
-}

+ 0 - 19
panda/src/gobj/qpgeomVertexIterator.cxx

@@ -1,19 +0,0 @@
-// Filename: qpgeomVertexIterator.cxx
-// Created by:  drose (10Mar05)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://etc.cmu.edu/panda3d/docs/license/ .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#include "qpgeomVertexIterator.h"

+ 0 - 99
panda/src/gobj/qpgeomVertexIterator.h

@@ -1,99 +0,0 @@
-// Filename: qpgeomVertexIterator.h
-// Created by:  drose (10Mar05)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://etc.cmu.edu/panda3d/docs/license/ .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#ifndef qpGEOMVERTEXITERATOR_H
-#define qpGEOMVERTEXITERATOR_H
-
-#include "pandabase.h"
-#include "qpgeomVertexData.h"
-#include "qpgeomVertexDataType.h"
-#include "internalName.h"
-#include "luse.h"
-#include "pointerTo.h"
-
-////////////////////////////////////////////////////////////////////
-//       Class : qpGeomVertexIterator
-// Description : This is used to read or write the vertices of a
-//               GeomVertexData structure, one vertex and data type at
-//               a time.
-//
-//               This is part of the experimental Geom rewrite.
-////////////////////////////////////////////////////////////////////
-class EXPCL_PANDA qpGeomVertexIterator {
-PUBLISHED:
-  INLINE qpGeomVertexIterator(qpGeomVertexData *data);
-  INLINE qpGeomVertexIterator(qpGeomVertexData *data,
-                              const string &name);
-  INLINE qpGeomVertexIterator(qpGeomVertexData *data,
-                              const InternalName *name);
-public:
-  // These const variants are not published, since our Python layer
-  // doesn't know the difference between const and non-const anyway.
-  INLINE qpGeomVertexIterator(const qpGeomVertexData *data);
-  INLINE qpGeomVertexIterator(const qpGeomVertexData *data,
-                              const string &name);
-  INLINE qpGeomVertexIterator(const qpGeomVertexData *data,
-                              const InternalName *name);
-
-PUBLISHED:
-  INLINE const qpGeomVertexData *get_data() const;
-
-  INLINE void set_data_type(int data_type);
-  INLINE void set_data_type(const string &name);
-  INLINE void set_data_type(const InternalName *name);
-  INLINE void set_data_type(int array, const qpGeomVertexDataType *data_type);
-
-  INLINE int get_array() const;
-  INLINE const qpGeomVertexDataType *get_data_type() const;
-
-  INLINE void set_vertex(int vertex);
-
-  INLINE int get_start_vertex() const;
-  INLINE int get_read_vertex() const;
-  INLINE int get_write_vertex() const;
-
-  INLINE void set_data1f(float data);
-  INLINE void set_data2f(float x, float y);
-  INLINE void set_data2f(const LVecBase2f &data);
-  INLINE void set_data3f(float x, float y, float z);
-  INLINE void set_data3f(const LVecBase3f &data);
-  INLINE void set_data4f(float x, float y, float z, float w);
-  INLINE void set_data4f(const LVecBase4f &data);
-
-  INLINE float get_data1f();
-  INLINE LVecBase2f get_data2f();
-  INLINE LVecBase3f get_data3f();
-  INLINE LVecBase4f get_data4f();
-
-  INLINE void set_data1i(int data);
-  INLINE int get_data1i();
-
-private:
-  PT(qpGeomVertexData) _data;
-  bool _const_data;
-  int _array;
-  const qpGeomVertexDataType *_data_type;
-
-  int _start_vertex;
-  int _read_vertex;
-  int _write_vertex;
-};
-
-#include "qpgeomVertexIterator.I"
-
-#endif

+ 74 - 17
panda/src/gobj/qpgeomVertexReader.I

@@ -31,6 +31,7 @@ qpGeomVertexReader(const qpGeomVertexData *vertex_data) :
   _pointer(NULL),
   _pointer(NULL),
   _start_vertex(0),
   _start_vertex(0),
   _read_vertex(0),
   _read_vertex(0),
+  _num_vertices(0),
   _reader(NULL)
   _reader(NULL)
 {
 {
 }
 }
@@ -50,6 +51,7 @@ qpGeomVertexReader(const qpGeomVertexData *vertex_data, const string &name) :
   _pointer(NULL),
   _pointer(NULL),
   _start_vertex(0),
   _start_vertex(0),
   _read_vertex(0),
   _read_vertex(0),
+  _num_vertices(0),
   _reader(NULL)
   _reader(NULL)
 {
 {
   set_data_type(name);
   set_data_type(name);
@@ -71,6 +73,7 @@ qpGeomVertexReader(const qpGeomVertexData *vertex_data,
   _pointer(NULL),
   _pointer(NULL),
   _start_vertex(0),
   _start_vertex(0),
   _read_vertex(0),
   _read_vertex(0),
+  _num_vertices(0),
   _reader(NULL)
   _reader(NULL)
 {
 {
   set_data_type(name);
   set_data_type(name);
@@ -109,12 +112,14 @@ get_vertex_data() const {
 //               This also resets the read vertex number to the start
 //               This also resets the read vertex number to the start
 //               vertex (the same value passed to a previous call to
 //               vertex (the same value passed to a previous call to
 //               set_vertex(), or 0 if set_vertex() was never called.)
 //               set_vertex(), or 0 if set_vertex() was never called.)
+//
+//               The return value is true if the data type is valid,
+//               false otherwise.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE void qpGeomVertexReader::
+INLINE bool qpGeomVertexReader::
 set_data_type(int data_type) {
 set_data_type(int data_type) {
-  nassertv(_vertex_data->get_format()->get_array_with(data_type) >= 0);
-  set_data_type(_vertex_data->get_format()->get_array_with(data_type),
-                _vertex_data->get_format()->get_data_type(data_type));
+  return set_data_type(_vertex_data->get_format()->get_array_with(data_type),
+                       _vertex_data->get_format()->get_data_type(data_type));
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -126,10 +131,13 @@ set_data_type(int data_type) {
 //               This also resets the read vertex number to the start
 //               This also resets the read vertex number to the start
 //               vertex (the same value passed to a previous call to
 //               vertex (the same value passed to a previous call to
 //               set_vertex(), or 0 if set_vertex() was never called.)
 //               set_vertex(), or 0 if set_vertex() was never called.)
+//
+//               The return value is true if the data type is valid,
+//               false otherwise.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE void qpGeomVertexReader::
+INLINE bool qpGeomVertexReader::
 set_data_type(const string &name) {
 set_data_type(const string &name) {
-  set_data_type(InternalName::make(name));
+  return set_data_type(InternalName::make(name));
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -141,12 +149,26 @@ set_data_type(const string &name) {
 //               This also resets the read vertex number to the start
 //               This also resets the read vertex number to the start
 //               vertex (the same value passed to a previous call to
 //               vertex (the same value passed to a previous call to
 //               set_vertex(), or 0 if set_vertex() was never called.)
 //               set_vertex(), or 0 if set_vertex() was never called.)
+//
+//               The return value is true if the data type is valid,
+//               false otherwise.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE void qpGeomVertexReader::
+INLINE bool qpGeomVertexReader::
 set_data_type(const InternalName *name) {
 set_data_type(const InternalName *name) {
-  nassertv(_vertex_data->get_format()->get_array_with(name) >= 0);
-  set_data_type(_vertex_data->get_format()->get_array_with(name),
-                _vertex_data->get_format()->get_data_type(name));
+  return set_data_type(_vertex_data->get_format()->get_array_with(name),
+                       _vertex_data->get_format()->get_data_type(name));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexReader::has_data_type
+//       Access: Published
+//  Description: Returns true if a valid data type has been
+//               successfully set, or false if the data type does not
+//               exist.
+////////////////////////////////////////////////////////////////////
+INLINE bool qpGeomVertexReader::
+has_data_type() const {
+  return (_data_type != (qpGeomVertexDataType *)NULL);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -181,8 +203,9 @@ get_data_type() const {
 INLINE void qpGeomVertexReader::
 INLINE void qpGeomVertexReader::
 set_vertex(int vertex) {
 set_vertex(int vertex) {
   _start_vertex = vertex;
   _start_vertex = vertex;
-  _read_vertex = vertex;
-  set_pointer();
+  if (_data_type != (qpGeomVertexDataType *)NULL) {
+    set_pointer(_start_vertex);
+  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -209,6 +232,29 @@ get_read_vertex() const {
   return _read_vertex;
   return _read_vertex;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexReader::get_num_vertices
+//       Access: Published
+//  Description: Returns the number of vertices in the vertex data.
+////////////////////////////////////////////////////////////////////
+INLINE int qpGeomVertexReader::
+get_num_vertices() const {
+  return _num_vertices;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexReader::is_at_end
+//       Access: Published
+//  Description: Returns true if the reader is currently at the end of
+//               the list of vertices, false otherwise.  If this is
+//               true, another call to get_data*() will result in a
+//               crash.
+////////////////////////////////////////////////////////////////////
+INLINE bool qpGeomVertexReader::
+is_at_end() const {
+  return _read_vertex >= _num_vertices;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: qpGeomVertexReader::get_data1f
 //     Function: qpGeomVertexReader::get_data1f
 //       Access: Published
 //       Access: Published
@@ -218,6 +264,7 @@ get_read_vertex() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE float qpGeomVertexReader::
 INLINE float qpGeomVertexReader::
 get_data1f() {
 get_data1f() {
+  nassertr(_data_type != (qpGeomVertexDataType *)NULL, 0.0f);
   return _reader->get_data1f(inc_pointer());
   return _reader->get_data1f(inc_pointer());
 }
 }
 
 
@@ -230,6 +277,7 @@ get_data1f() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE const LVecBase2f &qpGeomVertexReader::
 INLINE const LVecBase2f &qpGeomVertexReader::
 get_data2f() {
 get_data2f() {
+  nassertr(_data_type != (qpGeomVertexDataType *)NULL, LVecBase2f::zero());
   return _reader->get_data2f(inc_pointer());
   return _reader->get_data2f(inc_pointer());
 }
 }
 
 
@@ -242,6 +290,7 @@ get_data2f() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE const LVecBase3f &qpGeomVertexReader::
 INLINE const LVecBase3f &qpGeomVertexReader::
 get_data3f() {
 get_data3f() {
+  nassertr(_data_type != (qpGeomVertexDataType *)NULL, LVecBase3f::zero());
   return _reader->get_data3f(inc_pointer());
   return _reader->get_data3f(inc_pointer());
 }
 }
 
 
@@ -254,6 +303,7 @@ get_data3f() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE const LVecBase4f &qpGeomVertexReader::
 INLINE const LVecBase4f &qpGeomVertexReader::
 get_data4f() {
 get_data4f() {
+  nassertr(_data_type != (qpGeomVertexDataType *)NULL, LVecBase4f::zero());
   return _reader->get_data4f(inc_pointer());
   return _reader->get_data4f(inc_pointer());
 }
 }
 
 
@@ -266,20 +316,24 @@ get_data4f() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE int qpGeomVertexReader::
 INLINE int qpGeomVertexReader::
 get_data1i() {
 get_data1i() {
+  nassertr(_data_type != (qpGeomVertexDataType *)NULL, 0);
   return _reader->get_data1i(inc_pointer());
   return _reader->get_data1i(inc_pointer());
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: qpGeomVertexReader::set_pointer
 //     Function: qpGeomVertexReader::set_pointer
 //       Access: Private
 //       Access: Private
-//  Description: Sets up the internal pointer, etc. to use the vertex
-//               indicated by _start_vertex.
+//  Description: Sets up the internal write pointer, etc. to use the
+//               indicated vertex.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void qpGeomVertexReader::
 INLINE void qpGeomVertexReader::
-set_pointer() {
-  _read_vertex = _start_vertex;
-  _data = _vertex_data->get_array(_array)->get_data();
+set_pointer(int vertex) {
+  nassertv(_data_type != (qpGeomVertexDataType *)NULL);
+  _read_vertex = vertex;
+  CPT(qpGeomVertexArrayData) array_data = _vertex_data->get_array(_array);
+  _data = array_data->get_data();
   _pointer = _data.p() + _data_type->get_start() + _stride * _read_vertex;
   _pointer = _data.p() + _data_type->get_start() + _stride * _read_vertex;
+  _num_vertices = array_data->get_num_vertices();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -290,6 +344,9 @@ set_pointer() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE const unsigned char *qpGeomVertexReader::
 INLINE const unsigned char *qpGeomVertexReader::
 inc_pointer() {
 inc_pointer() {
+  nassertr(_read_vertex < _num_vertices, NULL);
+  nassertr(_pointer == _vertex_data->get_array(_array)->get_data().p() + _data_type->get_start() + _stride * _read_vertex, NULL);
+
   const unsigned char *orig_pointer = _pointer;
   const unsigned char *orig_pointer = _pointer;
   _pointer += _stride;
   _pointer += _stride;
   ++_read_vertex;
   ++_read_vertex;

+ 381 - 39
panda/src/gobj/qpgeomVertexReader.cxx

@@ -28,26 +28,42 @@
 //               the start vertex (the same value passed to a previous
 //               the start vertex (the same value passed to a previous
 //               call to set_vertex(), or 0 if set_vertex() was never
 //               call to set_vertex(), or 0 if set_vertex() was never
 //               called.)
 //               called.)
+//
+//               The return value is true if the data type is valid,
+//               false otherwise.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-void qpGeomVertexReader::
+bool qpGeomVertexReader::
 set_data_type(int array, const qpGeomVertexDataType *data_type) {
 set_data_type(int array, const qpGeomVertexDataType *data_type) {
-  nassertv(array >= 0 && array < _vertex_data->get_num_arrays());
-  nassertv(data_type != (qpGeomVertexDataType *)NULL);
-  _array = array;
-  _data_type = data_type;
-  _stride = _vertex_data->get_format()->get_array(_array)->get_stride();
-
-  set_pointer();
-
   // Delete the old reader, if we've got one.
   // Delete the old reader, if we've got one.
   if (_reader != (Reader *)NULL) {
   if (_reader != (Reader *)NULL) {
     delete _reader;
     delete _reader;
     _reader = NULL;
     _reader = NULL;
   }
   }
 
 
-  // Now set up a new reader.
-  _reader = make_reader();
-  _reader->_data_type = _data_type;
+  if (array < 0 || array >= _vertex_data->get_num_arrays() || 
+      data_type == (qpGeomVertexDataType *)NULL) {
+    // Clear the data type.
+    _array = -1;
+    _data_type = NULL;
+    _stride = 0;
+    _read_vertex = _start_vertex;
+    _num_vertices = 0;
+
+    return false;
+
+  } else {
+    _array = array;
+    _data_type = data_type;
+    _stride = _vertex_data->get_format()->get_array(_array)->get_stride();
+
+    set_pointer(_start_vertex);
+
+    // Now set up a new reader.
+    _reader = make_reader();
+    _reader->_data_type = _data_type;
+
+    return true;
+  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -58,40 +74,109 @@ set_data_type(int array, const qpGeomVertexDataType *data_type) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 qpGeomVertexReader::Reader *qpGeomVertexReader::
 qpGeomVertexReader::Reader *qpGeomVertexReader::
 make_reader() const {
 make_reader() const {
-  if (_data_type->get_contents() == qpGeomVertexDataType::C_point &&
-      _data_type->get_num_values() < 4) {
-    return new Reader_point;
-
-  } else {
+  switch (_data_type->get_contents()) {
+  case qpGeomVertexDataType::C_point:
+  case qpGeomVertexDataType::C_texcoord:
+    // These types are read as a 4-d homogeneous point.
     switch (_data_type->get_numeric_type()) {
     switch (_data_type->get_numeric_type()) {
     case qpGeomVertexDataType::NT_float32:
     case qpGeomVertexDataType::NT_float32:
-      if (sizeof(float) == 4) {
+      if (sizeof(float) == sizeof(PN_float32)) {
+        // Use the native float type implementation for a tiny bit
+        // more optimization.
+        switch (_data_type->get_num_components()) {
+        case 2:
+          return new Reader_point_nativefloat_2;
+        case 3:
+          return new Reader_point_nativefloat_3;
+        case 4:
+          return new Reader_point_nativefloat_4;
+        }
+      } else {
         switch (_data_type->get_num_components()) {
         switch (_data_type->get_num_components()) {
+        case 2:
+          return new Reader_point_float32_2;
         case 3:
         case 3:
-          return new Reader_float_3;
-          
-        default:
-          break;
+          return new Reader_point_float32_3;
+        case 4:
+          return new Reader_point_float32_4;
         }
         }
       }
       }
       break;
       break;
+    default:
+      break;
+    }
+    return new Reader_point;
 
 
-    case qpGeomVertexDataType::NT_uint16:
+  case qpGeomVertexDataType::C_rgba:
+    switch (_data_type->get_numeric_type()) {
+    case qpGeomVertexDataType::NT_uint8:
+      switch (_data_type->get_num_components()) {
+      case 4:
+        return new Reader_rgba_uint8_4;
+        
+      default:
+        break;
+      }
+      break;
+    case qpGeomVertexDataType::NT_float32:
+      switch (_data_type->get_num_components()) {
+      case 4:
+        if (sizeof(float) == sizeof(PN_float32)) {
+          // Use the native float type implementation for a tiny bit
+          // more optimization.
+          return new Reader_rgba_nativefloat_4;
+        } else {
+          return new Reader_rgba_float32_4;
+        }
+        
+      default:
+        break;
+      }
+      break;
+    default:
+      break;
+    }
+    return new Reader_color;
+
+  case qpGeomVertexDataType::C_argb:
+    switch (_data_type->get_numeric_type()) {
+    case qpGeomVertexDataType::NT_packed_8888:
       switch (_data_type->get_num_components()) {
       switch (_data_type->get_num_components()) {
       case 1:
       case 1:
-        return new Reader_uint16_1;
+        return new Reader_argb_packed_8888;
         
         
       default:
       default:
         break;
         break;
       }
       }
+      break;
+    default:
+      break;
+    }
+    return new Reader_color;
+
+  default:
+    // Otherwise, we just read it as a generic value.
+    switch (_data_type->get_numeric_type()) {
+    case qpGeomVertexDataType::NT_float32:
+      switch (_data_type->get_num_components()) {
+      case 3:
+        if (sizeof(float) == sizeof(PN_float32)) {
+          // Use the native float type implementation for a tiny bit
+          // more optimization.
+          return new Reader_nativefloat_3;
+        } else {
+          return new Reader_float32_3;
+        }
 
 
+      default:
+        break;
+      }
+      break;
     default:
     default:
       break;
       break;
     }
     }
+    return new Reader;
   }
   }
-
-  // If we got here, we have to create a generic reader.
-  return new Reader;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -121,7 +206,11 @@ get_data1f(const unsigned char *pointer) {
     {
     {
       packed_8888 dword;
       packed_8888 dword;
       dword._i = *(PN_uint32 *)pointer;
       dword._i = *(PN_uint32 *)pointer;
-      return maybe_scale_color(dword._b[0]);
+      if (_data_type->get_contents() == qpGeomVertexDataType::C_argb) {
+        return maybe_scale_color(dword._b[1]);
+      } else {
+        return maybe_scale_color(dword._b[0]);
+      }
     }
     }
 
 
   case qpGeomVertexDataType::NT_float32:
   case qpGeomVertexDataType::NT_float32:
@@ -159,7 +248,11 @@ get_data2f(const unsigned char *pointer) {
       {
       {
         packed_8888 dword;
         packed_8888 dword;
         dword._i = *(PN_uint32 *)pointer;
         dword._i = *(PN_uint32 *)pointer;
-        maybe_scale_color(dword._b[0], dword._b[1]);
+        if (_data_type->get_contents() == qpGeomVertexDataType::C_argb) {
+          maybe_scale_color(dword._b[1], dword._b[2]);
+        } else {
+          maybe_scale_color(dword._b[0], dword._b[1]);
+        }
       }
       }
       return _v2;
       return _v2;
       
       
@@ -184,7 +277,7 @@ const LVecBase3f &qpGeomVertexReader::Reader::
 get_data3f(const unsigned char *pointer) {
 get_data3f(const unsigned char *pointer) {
   switch (_data_type->get_num_values()) {
   switch (_data_type->get_num_values()) {
   case 1:
   case 1:
-    _v3.set(get_data1i(pointer), 0.0f, 0.0f);
+    _v3.set(get_data1f(pointer), 0.0f, 0.0f);
     return _v3;
     return _v3;
 
 
   case 2:
   case 2:
@@ -211,7 +304,11 @@ get_data3f(const unsigned char *pointer) {
       {
       {
         packed_8888 dword;
         packed_8888 dword;
         dword._i = *(PN_uint32 *)pointer;
         dword._i = *(PN_uint32 *)pointer;
-        maybe_scale_color(dword._b[0], dword._b[1], dword._b[2]);
+        if (_data_type->get_contents() == qpGeomVertexDataType::C_argb) {
+          maybe_scale_color(dword._b[1], dword._b[2], dword._b[3]);
+        } else {
+          maybe_scale_color(dword._b[0], dword._b[1], dword._b[2]);
+        }
       }
       }
       return _v3;
       return _v3;
       
       
@@ -270,7 +367,11 @@ get_data4f(const unsigned char *pointer) {
       {
       {
         packed_8888 dword;
         packed_8888 dword;
         dword._i = *(PN_uint32 *)pointer;
         dword._i = *(PN_uint32 *)pointer;
-        maybe_scale_color(dword._b[0], dword._b[1], dword._b[2], dword._b[3]);
+        if (_data_type->get_contents() == qpGeomVertexDataType::C_argb) {
+          maybe_scale_color(dword._b[1], dword._b[2], dword._b[3], dword._b[0]);
+        } else {
+          maybe_scale_color(dword._b[0], dword._b[1], dword._b[2], dword._b[3]);
+        }
       }
       }
       return _v4;
       return _v4;
       
       
@@ -315,6 +416,53 @@ get_data1i(const unsigned char *pointer) {
   return 0;
   return 0;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexReader::Reader_point::get_data1f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+float qpGeomVertexReader::Reader_point::
+get_data1f(const unsigned char *pointer) {
+  if (_data_type->get_num_values() == 4) {
+    const LVecBase4f &v4 = get_data4f(pointer);
+    return v4[0] / v4[3];
+  } else {
+    return Reader::get_data1f(pointer);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexReader::Reader_point::get_data2f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase2f &qpGeomVertexReader::Reader_point::
+get_data2f(const unsigned char *pointer) {
+  if (_data_type->get_num_values() == 4) {
+    const LVecBase4f &v4 = get_data4f(pointer);
+    _v2.set(v4[0] / v4[3], v4[1] / v4[3]);
+    return _v2;
+  } else {
+    return Reader::get_data2f(pointer);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexReader::Reader_point::get_data3f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase3f &qpGeomVertexReader::Reader_point::
+get_data3f(const unsigned char *pointer) {
+  if (_data_type->get_num_values() == 4) {
+    const LVecBase4f &v4 = get_data4f(pointer);
+    _v3.set(v4[0] / v4[3], v4[1] / v4[3], v4[2] / v4[3]);
+    return _v3;
+  } else {
+    return Reader::get_data3f(pointer);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: qpGeomVertexReader::Reader_point::get_data4f
 //     Function: qpGeomVertexReader::Reader_point::get_data4f
 //       Access: Public, Virtual
 //       Access: Public, Virtual
@@ -358,7 +506,11 @@ get_data4f(const unsigned char *pointer) {
       {
       {
         packed_8888 dword;
         packed_8888 dword;
         dword._i = *(PN_uint32 *)pointer;
         dword._i = *(PN_uint32 *)pointer;
-        maybe_scale_color(dword._b[0], dword._b[1], dword._b[2], dword._b[3]);
+        if (_data_type->get_contents() == qpGeomVertexDataType::C_argb) {
+          maybe_scale_color(dword._b[1], dword._b[2], dword._b[3], dword._b[0]);
+        } else {
+          maybe_scale_color(dword._b[0], dword._b[1], dword._b[2], dword._b[3]);
+        }
       }
       }
       return _v4;
       return _v4;
       
       
@@ -375,16 +527,206 @@ get_data4f(const unsigned char *pointer) {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexReader::Reader_float_3::get_data3f
+//     Function: qpGeomVertexReader::Reader_color::get_data4f
 //       Access: Public, Virtual
 //       Access: Public, Virtual
 //  Description: 
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-const LVecBase3f &qpGeomVertexReader::Reader_float_3::
+const LVecBase4f &qpGeomVertexReader::Reader_color::
+get_data4f(const unsigned char *pointer) {
+  switch (_data_type->get_num_values()) {
+  case 1:
+    _v4.set(get_data1i(pointer), 0.0f, 0.0f, 1.0f);
+    return _v4;
+
+  case 2:
+    {
+      const LVecBase2f &v2 = get_data2f(pointer);
+      _v4.set(v2[0], v2[1], 0.0f, 1.0f);
+    }
+    return _v4;
+
+  case 3:
+    {
+      const LVecBase3f &v3 = get_data3f(pointer);
+      _v4.set(v3[0], v3[1], v3[2], 1.0f);
+    }
+    return _v4;
+
+  default:
+    switch (_data_type->get_numeric_type()) {
+    case qpGeomVertexDataType::NT_uint8:
+      maybe_scale_color(pointer[0], pointer[1], pointer[2], pointer[3]);
+      return _v4;
+      
+    case qpGeomVertexDataType::NT_uint16:
+      {
+        PN_uint16 *pi = (PN_uint16 *)pointer;
+        _v4.set(pi[0], pi[1], pi[2], pi[3]);
+      }
+      return _v4;
+      
+    case qpGeomVertexDataType::NT_packed_8888:
+      {
+        packed_8888 dword;
+        dword._i = *(PN_uint32 *)pointer;
+        if (_data_type->get_contents() == qpGeomVertexDataType::C_argb) {
+          maybe_scale_color(dword._b[1], dword._b[2], dword._b[3], dword._b[0]);
+        } else {
+          maybe_scale_color(dword._b[0], dword._b[1], dword._b[2], dword._b[3]);
+        }
+      }
+      return _v4;
+      
+    case qpGeomVertexDataType::NT_float32:
+      {
+        PN_float32 *pi = (PN_float32 *)pointer;
+        _v4.set(pi[0], pi[1], pi[2], pi[3]);
+      }
+      return _v4;
+    }
+  }
+
+  return _v4;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexReader::Reader_float32_3::get_data3f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase3f &qpGeomVertexReader::Reader_float32_3::
+get_data3f(const unsigned char *pointer) {
+  PN_float32 *pi = (PN_float32 *)pointer;
+  _v3.set(pi[0], pi[1], pi[2]);
+  return _v3;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexReader::Reader_point_float32_2::get_data2f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase2f &qpGeomVertexReader::Reader_point_float32_2::
+get_data2f(const unsigned char *pointer) {
+  PN_float32 *pi = (PN_float32 *)pointer;
+  _v2.set(pi[0], pi[1]);
+  return _v2;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexReader::Reader_point_float32_3::get_data3f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase3f &qpGeomVertexReader::Reader_point_float32_3::
+get_data3f(const unsigned char *pointer) {
+  PN_float32 *pi = (PN_float32 *)pointer;
+  _v3.set(pi[0], pi[1], pi[2]);
+  return _v3;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexReader::Reader_point_float32_4::get_data4f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase4f &qpGeomVertexReader::Reader_point_float32_4::
+get_data4f(const unsigned char *pointer) {
+  PN_float32 *pi = (PN_float32 *)pointer;
+  _v4.set(pi[0], pi[1], pi[2], pi[3]);
+  return _v4;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexReader::Reader_nativefloat_3::get_data3f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase3f &qpGeomVertexReader::Reader_nativefloat_3::
 get_data3f(const unsigned char *pointer) {
 get_data3f(const unsigned char *pointer) {
-  // We sneakily cast a float[3] array to an LVecBase3f reference,
-  // making all kinds of assumptions about how an LVecBase3f is
-  // stored.
-  return *(LVecBase3f *)pointer;
+  return *(const LVecBase3f *)pointer;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexReader::Reader_point_nativefloat_2::get_data2f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase2f &qpGeomVertexReader::Reader_point_nativefloat_2::
+get_data2f(const unsigned char *pointer) {
+  return *(const LVecBase2f *)pointer;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexReader::Reader_point_nativefloat_3::get_data3f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase3f &qpGeomVertexReader::Reader_point_nativefloat_3::
+get_data3f(const unsigned char *pointer) {
+  return *(const LVecBase3f *)pointer;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexReader::Reader_point_nativefloat_4::get_data4f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase4f &qpGeomVertexReader::Reader_point_nativefloat_4::
+get_data4f(const unsigned char *pointer) {
+  return *(const LVecBase4f *)pointer;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexReader::Reader_argb_packed_8888::get_data4f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase4f &qpGeomVertexReader::Reader_argb_packed_8888::
+get_data4f(const unsigned char *pointer) {
+  packed_8888 dword;
+  dword._i = *(PN_uint32 *)pointer;
+  _v4.set((float)dword._b[1] / 255.0f,
+          (float)dword._b[2] / 255.0f,
+          (float)dword._b[3] / 255.0f,
+          (float)dword._b[0] / 255.0f);
+  return _v4;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexReader::Reader_rgba_uint8_4::get_data4f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase4f &qpGeomVertexReader::Reader_rgba_uint8_4::
+get_data4f(const unsigned char *pointer) {
+  _v4.set((float)pointer[0] / 255.0f,
+          (float)pointer[1] / 255.0f,
+          (float)pointer[2] / 255.0f,
+          (float)pointer[3] / 255.0f);
+  return _v4;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexReader::Reader_rgba_float32_4::get_data4f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase4f &qpGeomVertexReader::Reader_rgba_float32_4::
+get_data4f(const unsigned char *pointer) {
+  PN_float32 *pi = (PN_float32 *)pointer;
+  _v4.set(pi[0], pi[1], pi[2], pi[3]);
+  return _v4;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexReader::Reader_rgba_nativefloat_4::get_data4f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase4f &qpGeomVertexReader::Reader_rgba_nativefloat_4::
+get_data4f(const unsigned char *pointer) {
+  return *(const LVecBase4f *)pointer;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 80 - 8
panda/src/gobj/qpgeomVertexReader.h

@@ -53,11 +53,12 @@ PUBLISHED:
 
 
   INLINE const qpGeomVertexData *get_vertex_data() const;
   INLINE const qpGeomVertexData *get_vertex_data() const;
 
 
-  INLINE void set_data_type(int data_type);
-  INLINE void set_data_type(const string &name);
-  INLINE void set_data_type(const InternalName *name);
-  void set_data_type(int array, const qpGeomVertexDataType *data_type);
+  INLINE bool set_data_type(int data_type);
+  INLINE bool set_data_type(const string &name);
+  INLINE bool set_data_type(const InternalName *name);
+  bool set_data_type(int array, const qpGeomVertexDataType *data_type);
 
 
+  INLINE bool has_data_type() const;
   INLINE int get_array() const;
   INLINE int get_array() const;
   INLINE const qpGeomVertexDataType *get_data_type() const;
   INLINE const qpGeomVertexDataType *get_data_type() const;
 
 
@@ -65,6 +66,8 @@ PUBLISHED:
 
 
   INLINE int get_start_vertex() const;
   INLINE int get_start_vertex() const;
   INLINE int get_read_vertex() const;
   INLINE int get_read_vertex() const;
+  INLINE int get_num_vertices() const;
+  INLINE bool is_at_end() const;
 
 
   INLINE float get_data1f();
   INLINE float get_data1f();
   INLINE const LVecBase2f &get_data2f();
   INLINE const LVecBase2f &get_data2f();
@@ -76,7 +79,7 @@ PUBLISHED:
 private:
 private:
   class Reader;
   class Reader;
 
 
-  INLINE void set_pointer();
+  INLINE void set_pointer(int vertex);
   INLINE const unsigned char *inc_pointer();
   INLINE const unsigned char *inc_pointer();
   Reader *make_reader() const;
   Reader *make_reader() const;
 
 
@@ -90,6 +93,7 @@ private:
 
 
   int _start_vertex;
   int _start_vertex;
   int _read_vertex;
   int _read_vertex;
+  int _num_vertices;
 
 
   Reader *_reader;
   Reader *_reader;
 
 
@@ -126,9 +130,22 @@ private:
   };
   };
 
 
   // This is a specialization on the generic Reader that handles
   // This is a specialization on the generic Reader that handles
-  // points, which are special because the fourth component, if
-  // omitted, is 1.0.
+  // points, which are special because the fourth component, if not
+  // present in the data, is implicitly 1.0; and if it is present,
+  // than any three-component or smaller return is implicitly divided
+  // by the fourth component.
   class Reader_point : public Reader {
   class Reader_point : public Reader {
+  public:
+    virtual float get_data1f(const unsigned char *pointer);
+    virtual const LVecBase2f &get_data2f(const unsigned char *pointer);
+    virtual const LVecBase3f &get_data3f(const unsigned char *pointer);
+    virtual const LVecBase4f &get_data4f(const unsigned char *pointer);
+  };
+
+  // This is similar to Reader_point, in that the fourth component is
+  // implicitly 1.0 if it is not present in the data, but we never
+  // divide by alpha.
+  class Reader_color : public Reader {
   public:
   public:
     virtual const LVecBase4f &get_data4f(const unsigned char *pointer);
     virtual const LVecBase4f &get_data4f(const unsigned char *pointer);
   };
   };
@@ -137,11 +154,66 @@ private:
   // These are the specializations on the generic Reader that handle
   // These are the specializations on the generic Reader that handle
   // the direct code paths.
   // the direct code paths.
 
 
-  class Reader_float_3 : public Reader {
+  class Reader_float32_3 : public Reader {
+  public:
+    virtual const LVecBase3f &get_data3f(const unsigned char *pointer);
+  };
+
+  class Reader_point_float32_2 : public Reader_point {
+  public:
+    virtual const LVecBase2f &get_data2f(const unsigned char *pointer);
+  };
+
+  class Reader_point_float32_3 : public Reader_point {
   public:
   public:
     virtual const LVecBase3f &get_data3f(const unsigned char *pointer);
     virtual const LVecBase3f &get_data3f(const unsigned char *pointer);
   };
   };
 
 
+  class Reader_point_float32_4 : public Reader_point {
+  public:
+    virtual const LVecBase4f &get_data4f(const unsigned char *pointer);
+  };
+
+  class Reader_nativefloat_3 : public Reader {
+  public:
+    virtual const LVecBase3f &get_data3f(const unsigned char *pointer);
+  };
+
+  class Reader_point_nativefloat_2 : public Reader_point {
+  public:
+    virtual const LVecBase2f &get_data2f(const unsigned char *pointer);
+  };
+
+  class Reader_point_nativefloat_3 : public Reader_point {
+  public:
+    virtual const LVecBase3f &get_data3f(const unsigned char *pointer);
+  };
+
+  class Reader_point_nativefloat_4 : public Reader_point {
+  public:
+    virtual const LVecBase4f &get_data4f(const unsigned char *pointer);
+  };
+
+  class Reader_argb_packed_8888 : public Reader_color {
+  public:
+    virtual const LVecBase4f &get_data4f(const unsigned char *pointer);
+  };
+
+  class Reader_rgba_uint8_4 : public Reader_color {
+  public:
+    virtual const LVecBase4f &get_data4f(const unsigned char *pointer);
+  };
+
+  class Reader_rgba_float32_4 : public Reader_color {
+  public:
+    virtual const LVecBase4f &get_data4f(const unsigned char *pointer);
+  };
+
+  class Reader_rgba_nativefloat_4 : public Reader_color {
+  public:
+    virtual const LVecBase4f &get_data4f(const unsigned char *pointer);
+  };
+
   class Reader_uint16_1 : public Reader {
   class Reader_uint16_1 : public Reader {
   public:
   public:
     virtual int get_data1i(const unsigned char *pointer);
     virtual int get_data1i(const unsigned char *pointer);

+ 636 - 0
panda/src/gobj/qpgeomVertexWriter.I

@@ -0,0 +1,636 @@
+// Filename: qpgeomVertexWriter.I
+// Created by:  drose (25Mar05)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::Constructor
+//       Access: Published
+//  Description: Constructs a new writer to process the vertices of
+//               the indicated data object.
+////////////////////////////////////////////////////////////////////
+INLINE qpGeomVertexWriter::
+qpGeomVertexWriter(qpGeomVertexData *vertex_data) :
+  _vertex_data(vertex_data),
+  _array(0),
+  _data_type(NULL),
+  _pointer(NULL),
+  _start_vertex(0),
+  _write_vertex(0),
+  _num_vertices(0),
+  _writer(NULL)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::Constructor
+//       Access: Published
+//  Description: Constructs a new writer to process the vertices of
+//               the indicated data object.  This flavor creates the
+//               writer specifically to process the named data type.
+////////////////////////////////////////////////////////////////////
+INLINE qpGeomVertexWriter::
+qpGeomVertexWriter(qpGeomVertexData *vertex_data, const string &name) :
+  _vertex_data(vertex_data),
+  _array(0),
+  _data_type(NULL),
+  _pointer(NULL),
+  _start_vertex(0),
+  _write_vertex(0),
+  _num_vertices(0),
+  _writer(NULL)
+{
+  set_data_type(name);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::Constructor
+//       Access: Published
+//  Description: Constructs a new writer to process the vertices of
+//               the indicated data object.  This flavor creates the
+//               writer specifically to process the named data type.
+////////////////////////////////////////////////////////////////////
+INLINE qpGeomVertexWriter::
+qpGeomVertexWriter(qpGeomVertexData *vertex_data, const InternalName *name) :
+  _vertex_data(vertex_data),
+  _array(0),
+  _data_type(NULL),
+  _pointer(NULL),
+  _start_vertex(0),
+  _write_vertex(0),
+  _num_vertices(0),
+  _writer(NULL)
+{
+  set_data_type(name);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::Destructor
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE qpGeomVertexWriter::
+~qpGeomVertexWriter() {
+  if (_writer != (Writer *)NULL) {
+    delete _writer;
+    _writer = NULL;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::get_vertex_data
+//       Access: Published
+//  Description: Returns the vertex data object that the
+//               writer is processing.
+////////////////////////////////////////////////////////////////////
+INLINE qpGeomVertexData *qpGeomVertexWriter::
+get_vertex_data() const {
+  return _vertex_data;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::set_data_type
+//       Access: Published
+//  Description: Sets up the writer to use the nth data type of the
+//               GeomVertexFormat, numbering from 0.
+//
+//               This also resets the write vertex number to the start
+//               vertex (the same value passed to a previous call to
+//               set_vertex(), or 0 if set_vertex() was never called.)
+//
+//               The return value is true if the data type is valid,
+//               false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool qpGeomVertexWriter::
+set_data_type(int data_type) {
+  return set_data_type(_vertex_data->get_format()->get_array_with(data_type),
+                       _vertex_data->get_format()->get_data_type(data_type));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::set_data_type
+//       Access: Published
+//  Description: Sets up the writer to use the data type with the
+//               indicated name.
+//
+//               This also resets the write vertex number to the start
+//               vertex (the same value passed to a previous call to
+//               set_vertex(), or 0 if set_vertex() was never called.)
+//
+//               The return value is true if the data type is valid,
+//               false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool qpGeomVertexWriter::
+set_data_type(const string &name) {
+  return set_data_type(InternalName::make(name));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::set_data_type
+//       Access: Published
+//  Description: Sets up the writer to use the data type with the
+//               indicated name.
+//
+//               This also resets the write number to the start vertex
+//               (the same value passed to a previous call to
+//               set_vertex(), or 0 if set_vertex() was never called.)
+//
+//               The return value is true if the data type is valid,
+//               false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool qpGeomVertexWriter::
+set_data_type(const InternalName *name) {
+  return set_data_type(_vertex_data->get_format()->get_array_with(name),
+                       _vertex_data->get_format()->get_data_type(name));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::has_data_type
+//       Access: Published
+//  Description: Returns true if a valid data type has been
+//               successfully set, or false if the data type does not
+//               exist.
+////////////////////////////////////////////////////////////////////
+INLINE bool qpGeomVertexWriter::
+has_data_type() const {
+  return (_data_type != (qpGeomVertexDataType *)NULL);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::get_array
+//       Access: Published
+//  Description: Returns the array index containing the data type that
+//               the writer is working on.
+////////////////////////////////////////////////////////////////////
+INLINE int qpGeomVertexWriter::
+get_array() const {
+  return _array;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::get_data_type
+//       Access: Published
+//  Description: Returns the description of the data type that the
+//               writer is working on.
+////////////////////////////////////////////////////////////////////
+INLINE const qpGeomVertexDataType *qpGeomVertexWriter::
+get_data_type() const {
+  return _data_type;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::set_vertex
+//       Access: Published
+//  Description: Sets the start, write, and write index to the
+//               indicated value.  The writer will begin traversing
+//               from the given vertex.
+////////////////////////////////////////////////////////////////////
+INLINE void qpGeomVertexWriter::
+set_vertex(int vertex) {
+  _start_vertex = vertex;
+  if (_data_type != (qpGeomVertexDataType *)NULL) {
+    set_pointer(_start_vertex);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::get_start_vertex
+//       Access: Published
+//  Description: Returns the vertex index at which the writer
+//               started.  It will return to this vertex if you reset
+//               the current data_type.
+////////////////////////////////////////////////////////////////////
+INLINE int qpGeomVertexWriter::
+get_start_vertex() const {
+  return _start_vertex;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::get_write_vertex
+//       Access: Published
+//  Description: Returns the current write vertex index of the
+//               writer.  This is the index whose value will be
+//               returned by the next call to get_data*().
+////////////////////////////////////////////////////////////////////
+INLINE int qpGeomVertexWriter::
+get_write_vertex() const {
+  return _write_vertex;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::get_num_vertices
+//       Access: Published
+//  Description: Returns the number of vertices in the vertex data.
+////////////////////////////////////////////////////////////////////
+INLINE int qpGeomVertexWriter::
+get_num_vertices() const {
+  return _num_vertices;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::is_at_end
+//       Access: Published
+//  Description: Returns true if the writer is currently at the end of
+//               the list of vertices, false otherwise.  If this is
+//               true, another call to set_data*() will result in a
+//               crash, but another call to add_data*() will add a new
+//               vertex.
+////////////////////////////////////////////////////////////////////
+INLINE bool qpGeomVertexWriter::
+is_at_end() const {
+  return _write_vertex >= _num_vertices;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::set_data1f
+//       Access: Published
+//  Description: Sets the write vertex to a particular 1-component
+//               value, and advances the write vertex.
+//
+//               It is an error for the write vertex to advance past
+//               the end of data.
+////////////////////////////////////////////////////////////////////
+INLINE void qpGeomVertexWriter::
+set_data1f(float data) {
+  nassertv(_data_type != (qpGeomVertexDataType *)NULL);
+  _writer->set_data1f(inc_pointer(), data);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::set_data2f
+//       Access: Published
+//  Description: Sets the write vertex to a particular 2-component
+//               value, and advances the write vertex.
+//
+//               It is an error for the write vertex to advance past
+//               the end of data.
+////////////////////////////////////////////////////////////////////
+INLINE void qpGeomVertexWriter::
+set_data2f(float x, float y) {
+  set_data2f(LVecBase2f(x, y));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::set_data2f
+//       Access: Published
+//  Description: Sets the write vertex to a particular 2-component
+//               value, and advances the write vertex.
+//
+//               It is an error for the write vertex to advance past
+//               the end of data.
+////////////////////////////////////////////////////////////////////
+INLINE void qpGeomVertexWriter::
+set_data2f(const LVecBase2f &data) {
+  nassertv(_data_type != (qpGeomVertexDataType *)NULL);
+  _writer->set_data2f(inc_pointer(), data);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::set_data3f
+//       Access: Published
+//  Description: Sets the write vertex to a particular 3-component
+//               value, and advances the write vertex.
+//
+//               It is an error for the write vertex to advance past
+//               the end of data.
+////////////////////////////////////////////////////////////////////
+INLINE void qpGeomVertexWriter::
+set_data3f(float x, float y, float z) {
+  set_data3f(LVecBase3f(x, y, z));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::set_data3f
+//       Access: Published
+//  Description: Sets the write vertex to a particular 3-component
+//               value, and advances the write vertex.
+//
+//               It is an error for the write vertex to advance past
+//               the end of data.
+////////////////////////////////////////////////////////////////////
+INLINE void qpGeomVertexWriter::
+set_data3f(const LVecBase3f &data) {
+  nassertv(_data_type != (qpGeomVertexDataType *)NULL);
+  _writer->set_data3f(inc_pointer(), data);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::set_data4f
+//       Access: Published
+//  Description: Sets the write vertex to a particular 4-component
+//               value, and advances the write vertex.
+//
+//               It is an error for the write vertex to advance past
+//               the end of data.
+////////////////////////////////////////////////////////////////////
+INLINE void qpGeomVertexWriter::
+set_data4f(float x, float y, float z, float w) {
+  set_data4f(LVecBase4f(x, y, z, w));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::set_data4f
+//       Access: Published
+//  Description: Sets the write vertex to a particular 4-component
+//               value, and advances the write vertex.
+//
+//               It is an error for the write vertex to advance past
+//               the end of data.
+////////////////////////////////////////////////////////////////////
+INLINE void qpGeomVertexWriter::
+set_data4f(const LVecBase4f &data) {
+  nassertv(_data_type != (qpGeomVertexDataType *)NULL);
+  _writer->set_data4f(inc_pointer(), data);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::set_data1i
+//       Access: Published
+//  Description: Sets the write vertex to a particular 1-component
+//               value, and advances the write vertex.
+//
+//               It is an error for the write vertex to advance past
+//               the end of data.
+////////////////////////////////////////////////////////////////////
+INLINE void qpGeomVertexWriter::
+set_data1i(int data) {
+  nassertv(_data_type != (qpGeomVertexDataType *)NULL);
+  _writer->set_data1i(inc_pointer(), data);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::add_data1f
+//       Access: Published
+//  Description: Sets the write vertex to a particular 1-component
+//               value, and advances the write vertex.
+//
+//               If the write vertex advances past the end of data,
+//               implicitly adds a new vertex to the data.
+////////////////////////////////////////////////////////////////////
+INLINE void qpGeomVertexWriter::
+add_data1f(float data) {
+  nassertv(_data_type != (qpGeomVertexDataType *)NULL);
+  _writer->set_data1f(inc_add_pointer(), data);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::add_data2f
+//       Access: Published
+//  Description: Sets the write vertex to a particular 2-component
+//               value, and advances the write vertex.
+//
+//               If the write vertex advances past the end of data,
+//               implicitly adds a new vertex to the data.
+////////////////////////////////////////////////////////////////////
+INLINE void qpGeomVertexWriter::
+add_data2f(float x, float y) {
+  add_data2f(LVecBase2f(x, y));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::add_data2f
+//       Access: Published
+//  Description: Sets the write vertex to a particular 2-component
+//               value, and advances the write vertex.
+//
+//               If the write vertex advances past the end of data,
+//               implicitly adds a new vertex to the data.
+////////////////////////////////////////////////////////////////////
+INLINE void qpGeomVertexWriter::
+add_data2f(const LVecBase2f &data) {
+  nassertv(_data_type != (qpGeomVertexDataType *)NULL);
+  _writer->set_data2f(inc_add_pointer(), data);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::add_data3f
+//       Access: Published
+//  Description: Sets the write vertex to a particular 3-component
+//               value, and advances the write vertex.
+//
+//               If the write vertex advances past the end of data,
+//               implicitly adds a new vertex to the data.
+////////////////////////////////////////////////////////////////////
+INLINE void qpGeomVertexWriter::
+add_data3f(float x, float y, float z) {
+  add_data3f(LVecBase3f(x, y, z));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::add_data3f
+//       Access: Published
+//  Description: Sets the write vertex to a particular 3-component
+//               value, and advances the write vertex.
+//
+//               If the write vertex advances past the end of data,
+//               implicitly adds a new vertex to the data.
+////////////////////////////////////////////////////////////////////
+INLINE void qpGeomVertexWriter::
+add_data3f(const LVecBase3f &data) {
+  nassertv(_data_type != (qpGeomVertexDataType *)NULL);
+  _writer->set_data3f(inc_add_pointer(), data);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::add_data4f
+//       Access: Published
+//  Description: Sets the write vertex to a particular 4-component
+//               value, and advances the write vertex.
+//
+//               If the write vertex advances past the end of data,
+//               implicitly adds a new vertex to the data.
+////////////////////////////////////////////////////////////////////
+INLINE void qpGeomVertexWriter::
+add_data4f(float x, float y, float z, float w) {
+  add_data4f(LVecBase4f(x, y, z, w));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::add_data4f
+//       Access: Published
+//  Description: Sets the write vertex to a particular 4-component
+//               value, and advances the write vertex.
+//
+//               If the write vertex advances past the end of data,
+//               implicitly adds a new vertex to the data.
+////////////////////////////////////////////////////////////////////
+INLINE void qpGeomVertexWriter::
+add_data4f(const LVecBase4f &data) {
+  nassertv(_data_type != (qpGeomVertexDataType *)NULL);
+  _writer->set_data4f(inc_add_pointer(), data);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::add_data1i
+//       Access: Published
+//  Description: Sets the write vertex to a particular 1-component
+//               value, and advances the write vertex.
+//
+//               If the write vertex advances past the end of data,
+//               implicitly adds a new vertex to the data.
+////////////////////////////////////////////////////////////////////
+INLINE void qpGeomVertexWriter::
+add_data1i(int data) {
+  nassertv(_data_type != (qpGeomVertexDataType *)NULL);
+  _writer->set_data1i(inc_add_pointer(), data);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::set_pointer
+//       Access: Private
+//  Description: Sets up the internal write pointer, etc. to use the
+//               indicated vertex.
+////////////////////////////////////////////////////////////////////
+INLINE void qpGeomVertexWriter::
+set_pointer(int vertex) {
+  nassertv(_data_type != (qpGeomVertexDataType *)NULL);
+  _write_vertex = vertex;
+  PT(qpGeomVertexArrayData) array_data = _vertex_data->modify_array(_array);
+  _data = array_data->modify_data();
+  _pointer = _data.p() + _data_type->get_start() + _stride * _write_vertex;
+  _num_vertices = array_data->get_num_vertices();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::inc_pointer
+//       Access: Private
+//  Description: Increments to the next vertex, and returns the data
+//               pointer as it was before incrementing.
+////////////////////////////////////////////////////////////////////
+INLINE unsigned char *qpGeomVertexWriter::
+inc_pointer() {
+  nassertr(_write_vertex < _num_vertices, NULL);
+  nassertr(_pointer == _vertex_data->get_array(_array)->get_data().p() + _data_type->get_start() + _stride * _write_vertex, NULL);
+
+  unsigned char *orig_pointer = _pointer;
+  _pointer += _stride;
+  ++_write_vertex;
+  return orig_pointer;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::inc_add_pointer
+//       Access: Private
+//  Description: Increments to the next vertex, and returns the data
+//               pointer as it was before incrementing.  If we are at
+//               or past the end of data, implicitly adds more
+//               vertices first.
+////////////////////////////////////////////////////////////////////
+INLINE unsigned char *qpGeomVertexWriter::
+inc_add_pointer() {
+  if (_write_vertex >= _num_vertices) {
+    // Reset the data pointer.
+    _vertex_data->set_num_vertices(max(_write_vertex + 1, _vertex_data->get_num_vertices()));
+    set_pointer(_write_vertex);
+  }
+  return inc_pointer();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::Writer::maybe_scale_color
+//       Access: Public
+//  Description: Converts a floating-point value to a uint8 value.  If
+//               the contents value indicates this is a color value,
+//               scales it into the range 0..255 per convention;
+//               otherwise leaves it alone.
+////////////////////////////////////////////////////////////////////
+INLINE unsigned int qpGeomVertexWriter::Writer::
+maybe_scale_color(float data) {
+  switch (_data_type->get_contents()) {
+  case qpGeomVertexDataType::C_rgba:
+  case qpGeomVertexDataType::C_argb:
+    return (unsigned int)(data * 255.0f);
+    
+  default:
+    return (unsigned int)data;
+  }
+}
+    
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::Writer::maybe_scale_color
+//       Access: Public
+//  Description: Converts an LVecBase2f into a pair of uint8
+//               values.  See one-parameter maybe_scale_color() for
+//               more info.
+////////////////////////////////////////////////////////////////////
+INLINE void qpGeomVertexWriter::Writer::
+maybe_scale_color(const LVecBase2f &data) {
+  switch (_data_type->get_contents()) {
+  case qpGeomVertexDataType::C_rgba:
+  case qpGeomVertexDataType::C_argb:
+    _a = (unsigned int)(data[0] * 255.0f);
+    _b = (unsigned int)(data[1] * 255.0f);
+    break;
+    
+  default:
+    _a = (unsigned int)data[0];
+    _b = (unsigned int)data[1];
+    break;
+  }
+}
+    
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::Writer::maybe_scale_color
+//       Access: Public
+//  Description: Converts an LVecBase3f into a pair of uint8
+//               values.  See one-parameter maybe_scale_color() for
+//               more info.
+////////////////////////////////////////////////////////////////////
+INLINE void qpGeomVertexWriter::Writer::
+maybe_scale_color(const LVecBase3f &data) {
+  switch (_data_type->get_contents()) {
+  case qpGeomVertexDataType::C_rgba:
+  case qpGeomVertexDataType::C_argb:
+    _a = (unsigned int)(data[0] * 255.0f);
+    _b = (unsigned int)(data[1] * 255.0f);
+    _c = (unsigned int)(data[2] * 255.0f);
+    break;
+    
+  default:
+    _a = (unsigned int)data[0];
+    _b = (unsigned int)data[1];
+    _c = (unsigned int)data[2];
+    break;
+  }
+}
+    
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::Writer::maybe_scale_color
+//       Access: Public
+//  Description: Converts an LVecBase4f into a pair of uint8
+//               values.  See one-parameter maybe_scale_color() for
+//               more info.
+////////////////////////////////////////////////////////////////////
+INLINE void qpGeomVertexWriter::Writer::
+maybe_scale_color(const LVecBase4f &data) {
+  switch (_data_type->get_contents()) {
+  case qpGeomVertexDataType::C_rgba:
+  case qpGeomVertexDataType::C_argb:
+    _a = (unsigned int)(data[0] * 255.0f);
+    _b = (unsigned int)(data[1] * 255.0f);
+    _c = (unsigned int)(data[2] * 255.0f);
+    _d = (unsigned int)(data[3] * 255.0f);
+    break;
+    
+  default:
+    _a = (unsigned int)data[0];
+    _b = (unsigned int)data[1];
+    _c = (unsigned int)data[2];
+    _d = (unsigned int)data[3];
+    break;
+  }
+}

+ 721 - 0
panda/src/gobj/qpgeomVertexWriter.cxx

@@ -0,0 +1,721 @@
+// Filename: qpgeomVertexWriter.cxx
+// Created by:  drose (25Mar05)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "qpgeomVertexWriter.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::set_data_type
+//       Access: Published
+//  Description: Sets up the writer to use the indicated data_type
+//               description on the given array.
+//
+//               This also resets the current write vertex numbers to
+//               the start vertex (the same value passed to a previous
+//               call to set_vertex(), or 0 if set_vertex() was never
+//               called.)
+//
+//               The return value is true if the data type is valid,
+//               false otherwise.
+////////////////////////////////////////////////////////////////////
+bool qpGeomVertexWriter::
+set_data_type(int array, const qpGeomVertexDataType *data_type) {
+  // Delete the old writer, if we've got one.
+  if (_writer != (Writer *)NULL) {
+    delete _writer;
+    _writer = NULL;
+  }
+
+  if (array < 0 || array >= _vertex_data->get_num_arrays() || 
+      data_type == (qpGeomVertexDataType *)NULL) {
+    // Clear the data type.
+    _array = -1;
+    _data_type = NULL;
+    _stride = 0;
+    _write_vertex = _start_vertex;
+    _num_vertices = 0;
+
+    return false;
+
+  } else {
+    _array = array;
+    _data_type = data_type;
+    _stride = _vertex_data->get_format()->get_array(_array)->get_stride();
+
+    set_pointer(_start_vertex);
+
+    // Now set up a new writer.
+    _writer = make_writer();
+    _writer->_data_type = _data_type;
+
+    return true;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::make_writer
+//       Access: Private
+//  Description: Returns a newly-allocated Writer object suitable for
+//               writing the current data type.
+////////////////////////////////////////////////////////////////////
+qpGeomVertexWriter::Writer *qpGeomVertexWriter::
+make_writer() const {
+  switch (_data_type->get_contents()) {
+  case qpGeomVertexDataType::C_point:
+  case qpGeomVertexDataType::C_texcoord:
+    // These types are written as a 4-d homogeneous point.
+    switch (_data_type->get_numeric_type()) {
+    case qpGeomVertexDataType::NT_float32:
+      switch (_data_type->get_num_components()) {
+      case 2:
+        return new Writer_point_float32_2;
+      case 3:
+        return new Writer_point_float32_3;
+      case 4:
+        return new Writer_point_float32_4;
+        
+      default:
+        break;
+      }
+      break;
+    default:
+      break;
+    }
+    return new Writer_point;
+
+  case qpGeomVertexDataType::C_rgba:
+    switch (_data_type->get_numeric_type()) {
+    case qpGeomVertexDataType::NT_uint8:
+      switch (_data_type->get_num_components()) {
+      case 4:
+        return new Writer_rgba_uint8_4;
+        
+      default:
+        break;
+      }
+      break;
+    case qpGeomVertexDataType::NT_float32:
+      switch (_data_type->get_num_components()) {
+      case 4:
+        return new Writer_rgba_float32_4;
+        
+      default:
+        break;
+      }
+      break;
+    default:
+      break;
+    }
+    return new Writer_color;
+
+  case qpGeomVertexDataType::C_argb:
+    switch (_data_type->get_numeric_type()) {
+    case qpGeomVertexDataType::NT_packed_8888:
+      switch (_data_type->get_num_components()) {
+      case 1:
+        return new Writer_argb_packed_8888;
+        
+      default:
+        break;
+      }
+      break;
+    default:
+      break;
+    }
+    return new Writer_color;
+
+  default:
+    // Otherwise, we just write it as a generic value.
+    switch (_data_type->get_numeric_type()) {
+    case qpGeomVertexDataType::NT_float32:
+      switch (_data_type->get_num_components()) {
+      case 3:
+        return new Writer_float32_3;
+        
+      default:
+        break;
+      }
+      break;
+    default:
+      break;
+    }
+    return new Writer;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::Writer::Destructor
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+qpGeomVertexWriter::Writer::
+~Writer() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::Writer::set_data1f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexWriter::Writer::
+set_data1f(unsigned char *pointer, float data) {
+  switch (_data_type->get_num_values()) {
+  case 1:
+    switch (_data_type->get_numeric_type()) {
+    case qpGeomVertexDataType::NT_uint8:
+      *pointer = maybe_scale_color(data);
+      break;
+      
+    case qpGeomVertexDataType::NT_uint16:
+      *(PN_uint16 *)pointer = (unsigned int)data;
+      break;
+      
+    case qpGeomVertexDataType::NT_packed_8888:
+      {
+        packed_8888 dword;
+        dword._i = 0;
+        if (_data_type->get_contents() == qpGeomVertexDataType::C_argb) {
+          dword._b[1] = maybe_scale_color(data);
+        } else {
+          dword._b[0] = maybe_scale_color(data);
+        }
+        *(PN_uint32 *)pointer = dword._i;
+      }
+      break;
+      
+    case qpGeomVertexDataType::NT_float32:
+      *(PN_float32 *)pointer = data;
+      break;
+    }
+    break;
+
+  case 2:
+    set_data2f(pointer, LVecBase2f(data, 0.0f));
+    break;
+
+  case 3:
+    set_data3f(pointer, LVecBase3f(data, 0.0f, 0.0f));
+    break;
+
+  case 4:
+    set_data4f(pointer, LVecBase4f(data, 0.0f, 0.0f, 0.0f));
+    break;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::Writer::set_data2f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexWriter::Writer::
+set_data2f(unsigned char *pointer, const LVecBase2f &data) {
+  switch (_data_type->get_num_values()) {
+  case 1:
+    set_data1f(pointer, data[0]);
+
+  case 2:
+    switch (_data_type->get_numeric_type()) {
+    case qpGeomVertexDataType::NT_uint8:
+      maybe_scale_color(data);
+      pointer[0] = _a;
+      pointer[1] = _b;
+      break;
+      
+    case qpGeomVertexDataType::NT_uint16:
+      {
+        PN_uint16 *pi = (PN_uint16 *)pointer;
+        pi[0] = (unsigned int)data[0];
+        pi[1] = (unsigned int)data[1];
+      }
+      break;
+      
+    case qpGeomVertexDataType::NT_packed_8888:
+      {
+        packed_8888 dword;
+        maybe_scale_color(data);
+        dword._i = 0;
+        if (_data_type->get_contents() == qpGeomVertexDataType::C_argb) {
+          dword._b[1] = _a;
+          dword._b[2] = _b;
+        } else {
+          dword._b[0] = _a;
+          dword._b[1] = _b;
+        }
+        *(PN_uint32 *)pointer = dword._i;
+      }
+      break;
+      
+    case qpGeomVertexDataType::NT_float32:
+      {
+        PN_float32 *pi = (PN_float32 *)pointer;
+        pi[0] = data[0];
+        pi[1] = data[1];
+      }
+      break;
+    }
+    break;
+
+  case 3:
+    set_data3f(pointer, LVecBase3f(data[0], data[1], 0.0f));
+    break;
+
+  default:
+    set_data4f(pointer, LVecBase4f(data[0], data[1], 0.0f, 0.0f));
+    break;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::Writer::set_data3f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexWriter::Writer::
+set_data3f(unsigned char *pointer, const LVecBase3f &data) {
+  switch (_data_type->get_num_values()) {
+  case 1:
+    set_data1f(pointer, data[0]);
+    break;
+
+  case 2:
+    set_data2f(pointer, LVecBase2f(data[0], data[1]));
+    break;
+    
+  case 3:
+    switch (_data_type->get_numeric_type()) {
+    case qpGeomVertexDataType::NT_uint8:
+      maybe_scale_color(data);
+      pointer[0] = _a;
+      pointer[1] = _b;
+      pointer[2] = _c;
+      break;
+      
+    case qpGeomVertexDataType::NT_uint16:
+      {
+        PN_uint16 *pi = (PN_uint16 *)pointer;
+        pi[0] = (unsigned int)data[0];
+        pi[1] = (unsigned int)data[1];
+        pi[2] = (unsigned int)data[2];
+      }
+      break;
+      
+    case qpGeomVertexDataType::NT_packed_8888:
+      {
+        packed_8888 dword;
+        maybe_scale_color(data);
+        if (_data_type->get_contents() == qpGeomVertexDataType::C_argb) {
+          dword._b[0] = 0;
+          dword._b[1] = _a;
+          dword._b[2] = _b;
+          dword._b[3] = _c;
+        } else {
+          dword._b[0] = _a;
+          dword._b[1] = _b;
+          dword._b[2] = _c;
+          dword._b[3] = 0;
+        }
+        *(PN_uint32 *)pointer = dword._i;
+      }
+      break;
+      
+    case qpGeomVertexDataType::NT_float32:
+      {
+        PN_float32 *pi = (PN_float32 *)pointer;
+        pi[0] = data[0];
+        pi[1] = data[1];
+        pi[2] = data[2];
+      }
+      break;
+    }
+    break;
+
+  default:
+    set_data4f(pointer, LVecBase4f(data[0], data[1], data[2], 0.0f));
+    break;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::Writer::set_data4f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexWriter::Writer::
+set_data4f(unsigned char *pointer, const LVecBase4f &data) {
+  switch (_data_type->get_num_values()) {
+  case 1:
+    set_data1f(pointer, data[0]);
+    break;
+
+  case 2:
+    set_data2f(pointer, LVecBase2f(data[0], data[1]));
+    break;
+
+  case 3:
+    set_data3f(pointer, LVecBase3f(data[0], data[1], data[2]));
+    break;
+
+  default:
+    switch (_data_type->get_numeric_type()) {
+    case qpGeomVertexDataType::NT_uint8:
+      maybe_scale_color(data);
+      pointer[0] = _a;
+      pointer[1] = _b;
+      pointer[2] = _c;
+      pointer[3] = _d;
+      break;
+
+    case qpGeomVertexDataType::NT_uint16:
+      {
+        PN_uint16 *pi = (PN_uint16 *)pointer;
+        pi[0] = (unsigned int)data[0];
+        pi[1] = (unsigned int)data[1];
+        pi[2] = (unsigned int)data[2];
+        pi[3] = (unsigned int)data[3];
+      }
+      break;
+      
+    case qpGeomVertexDataType::NT_packed_8888:
+      {
+        packed_8888 dword;
+        maybe_scale_color(data);
+        if (_data_type->get_contents() == qpGeomVertexDataType::C_argb) {
+          dword._b[0] = _d;
+          dword._b[1] = _a;
+          dword._b[2] = _b;
+          dword._b[3] = _c;
+        } else {
+          dword._b[0] = _a;
+          dword._b[1] = _b;
+          dword._b[2] = _c;
+          dword._b[3] = _d;
+        }
+        *(PN_uint32 *)pointer = dword._i;
+      }
+      break;
+      
+    case qpGeomVertexDataType::NT_float32:
+      {
+        PN_float32 *pi = (PN_float32 *)pointer;
+        pi[0] = data[0];
+        pi[1] = data[1];
+        pi[2] = data[2];
+        pi[3] = data[3];
+      }
+      break;
+    }
+    break;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::Writer::set_data1i
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexWriter::Writer::
+set_data1i(unsigned char *pointer, int data) {
+  switch (_data_type->get_numeric_type()) {
+  case qpGeomVertexDataType::NT_uint8:
+    *pointer = data;
+    break;
+
+  case qpGeomVertexDataType::NT_uint16:
+    *(PN_uint16 *)pointer = data;
+    break;
+
+  case qpGeomVertexDataType::NT_packed_8888:
+    {
+      packed_8888 dword;
+      dword._i = 0;
+      if (_data_type->get_contents() == qpGeomVertexDataType::C_argb) {
+        dword._b[1] = data;
+      } else {
+        dword._b[0] = data;
+      }
+      *(PN_uint32 *)pointer = dword._i;
+    }
+    break;
+
+  case qpGeomVertexDataType::NT_float32:
+    *(PN_float32 *)pointer = (float)data;
+    break;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::Writer_point::set_data1f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexWriter::Writer_point::
+set_data1f(unsigned char *pointer, float data) {
+  if (_data_type->get_num_values() == 4) {
+    set_data4f(pointer, LVecBase4f(data, 0.0f, 0.0f, 1.0f));
+  } else {
+    Writer::set_data1f(pointer, data);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::Writer_point::set_data2f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexWriter::Writer_point::
+set_data2f(unsigned char *pointer, const LVecBase2f &data) {
+  if (_data_type->get_num_values() == 4) {
+    set_data4f(pointer, LVecBase4f(data[0], data[1], 0.0f, 1.0f));
+  } else {
+    Writer::set_data2f(pointer, data);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::Writer_point::set_data3f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexWriter::Writer_point::
+set_data3f(unsigned char *pointer, const LVecBase3f &data) {
+  if (_data_type->get_num_values() == 4) {
+    set_data4f(pointer, LVecBase4f(data[0], data[1], data[2], 1.0f));
+  } else {
+    Writer::set_data3f(pointer, data);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::Writer_point::set_data4f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexWriter::Writer_point::
+set_data4f(unsigned char *pointer, const LVecBase4f &data) {
+  switch (_data_type->get_num_values()) {
+  case 1:
+    set_data1f(pointer, data[0] / data[3]);
+    break;
+
+  case 2:
+    set_data2f(pointer, LVecBase2f(data[0] / data[3], data[1] / data[3]));
+    break;
+
+  case 3:
+    set_data3f(pointer, LVecBase3f(data[0] / data[3], data[1] / data[3], data[2] / data[3]));
+    break;
+
+  default:
+    switch (_data_type->get_numeric_type()) {
+    case qpGeomVertexDataType::NT_uint8:
+      maybe_scale_color(data);
+      pointer[0] = _a;
+      pointer[1] = _b;
+      pointer[2] = _c;
+      pointer[3] = _d;
+      break;
+
+    case qpGeomVertexDataType::NT_uint16:
+      {
+        PN_uint16 *pi = (PN_uint16 *)pointer;
+        pi[0] = (unsigned int)data[0];
+        pi[1] = (unsigned int)data[1];
+        pi[2] = (unsigned int)data[2];
+        pi[3] = (unsigned int)data[3];
+      }
+      break;
+      
+    case qpGeomVertexDataType::NT_packed_8888:
+      {
+        packed_8888 dword;
+        maybe_scale_color(data);
+        if (_data_type->get_contents() == qpGeomVertexDataType::C_argb) {
+          dword._b[0] = _d;
+          dword._b[1] = _a;
+          dword._b[2] = _b;
+          dword._b[3] = _c;
+        } else {
+          dword._b[0] = _a;
+          dword._b[1] = _b;
+          dword._b[2] = _c;
+          dword._b[3] = _d;
+        }
+        *(PN_uint32 *)pointer = dword._i;
+      }
+      break;
+      
+    case qpGeomVertexDataType::NT_float32:
+      {
+        PN_float32 *pi = (PN_float32 *)pointer;
+        pi[0] = data[0];
+        pi[1] = data[1];
+        pi[2] = data[2];
+        pi[3] = data[3];
+      }
+      break;
+    }
+    break;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::Writer_color::set_data1f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexWriter::Writer_color::
+set_data1f(unsigned char *pointer, float data) {
+  if (_data_type->get_num_values() == 4) {
+    set_data4f(pointer, LVecBase4f(data, 0.0f, 0.0f, 1.0f));
+  } else {
+    Writer::set_data1f(pointer, data);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::Writer_color::set_data2f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexWriter::Writer_color::
+set_data2f(unsigned char *pointer, const LVecBase2f &data) {
+  if (_data_type->get_num_values() == 4) {
+    set_data4f(pointer, LVecBase4f(data[0], data[1], 0.0f, 1.0f));
+  } else {
+    Writer::set_data2f(pointer, data);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::Writer_color::set_data3f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexWriter::Writer_color::
+set_data3f(unsigned char *pointer, const LVecBase3f &data) {
+  if (_data_type->get_num_values() == 4) {
+    set_data4f(pointer, LVecBase4f(data[0], data[1], data[2], 1.0f));
+  } else {
+    Writer::set_data3f(pointer, data);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::Writer_float32_3::set_data3f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexWriter::Writer_float32_3::
+set_data3f(unsigned char *pointer, const LVecBase3f &data) {
+  PN_float32 *pi = (PN_float32 *)pointer;
+  pi[0] = data[0];
+  pi[1] = data[1];
+  pi[2] = data[2];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::Writer_point_float32_2::set_data2f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexWriter::Writer_point_float32_2::
+set_data2f(unsigned char *pointer, const LVecBase2f &data) {
+  PN_float32 *pi = (PN_float32 *)pointer;
+  pi[0] = data[0];
+  pi[1] = data[1];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::Writer_point_float32_3::set_data3f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexWriter::Writer_point_float32_3::
+set_data3f(unsigned char *pointer, const LVecBase3f &data) {
+  PN_float32 *pi = (PN_float32 *)pointer;
+  pi[0] = data[0];
+  pi[1] = data[1];
+  pi[2] = data[2];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::Writer_point_float32_4::set_data4f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexWriter::Writer_point_float32_4::
+set_data4f(unsigned char *pointer, const LVecBase4f &data) {
+  PN_float32 *pi = (PN_float32 *)pointer;
+  pi[0] = data[0];
+  pi[1] = data[1];
+  pi[2] = data[2];
+  pi[3] = data[3];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::Writer_argb_packed_8888::set_data4f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexWriter::Writer_argb_packed_8888::
+set_data4f(unsigned char *pointer, const LVecBase4f &data) {
+  packed_8888 dword;
+  dword._b[0] = (unsigned int)(data[3] * 255.0f);
+  dword._b[1] = (unsigned int)(data[0] * 255.0f);
+  dword._b[2] = (unsigned int)(data[1] * 255.0f);
+  dword._b[3] = (unsigned int)(data[2] * 255.0f);
+
+  *(PN_uint32 *)pointer = dword._i;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::Writer_rgba_uint8_4::set_data4f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexWriter::Writer_rgba_uint8_4::
+set_data4f(unsigned char *pointer, const LVecBase4f &data) {
+  pointer[0] = (unsigned int)(data[0] * 255.0f);
+  pointer[1] = (unsigned int)(data[1] * 255.0f);
+  pointer[2] = (unsigned int)(data[2] * 255.0f);
+  pointer[3] = (unsigned int)(data[3] * 255.0f);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::Writer_rgba_float32_4::set_data4f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexWriter::Writer_rgba_float32_4::
+set_data4f(unsigned char *pointer, const LVecBase4f &data) {
+  PN_float32 *pi = (PN_float32 *)pointer;
+  pi[0] = data[0];
+  pi[1] = data[1];
+  pi[2] = data[2];
+  pi[3] = data[3];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexWriter::Writer_uint16_1::set_data1i
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexWriter::Writer_uint16_1::
+set_data1i(unsigned char *pointer, int data) {
+  *(PN_uint16 *)pointer = data;
+}

+ 226 - 0
panda/src/gobj/qpgeomVertexWriter.h

@@ -0,0 +1,226 @@
+// Filename: qpgeomVertexWriter.h
+// Created by:  drose (25Mar05)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef qpGEOMVERTEXWRITER_H
+#define qpGEOMVERTEXWRITER_H
+
+#include "pandabase.h"
+#include "qpgeomVertexData.h"
+#include "qpgeomVertexDataType.h"
+#include "internalName.h"
+#include "luse.h"
+#include "pointerTo.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : qpGeomVertexWriter
+// Description : This object provides a high-level interface for
+//               quickly writing a sequence of numeric values from a
+//               vertex table. 
+//
+//               This object can be used both to replace existing
+//               vertices in the table, or to extend the table with
+//               new vertices.  The set_data*() family of methods can
+//               only be used to replace existing data; it is an error
+//               to allow these to run past the end of the data.  The
+//               add_data*() family of methods, on the other hand, can
+//               be used to replace existing data or add new data; if
+//               you call set_vertex() into the middle of existing
+//               data the add_data*() methods will behave like the
+//               corresponding set_data*(), but if they run past the
+//               end of existing data they will quietly add new data.
+//
+//               Like GeomVertexReader, the writer is particularly
+//               optimized for writing a column of data values for a
+//               series of vertices, without changing data types
+//               between each number.  Although you can use one
+//               GeomVertexWriter to write one complete row at a time,
+//               by calling set_data_type() repeatedly for each
+//               vertex, it is faster to use a different
+//               GeomVertexWriter for each data type.
+//
+//               This is part of the experimental Geom rewrite.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA qpGeomVertexWriter {
+PUBLISHED:
+  INLINE qpGeomVertexWriter(qpGeomVertexData *vertex_data);
+  INLINE qpGeomVertexWriter(qpGeomVertexData *vertex_data,
+                            const string &name);
+  INLINE qpGeomVertexWriter(qpGeomVertexData *vertex_data,
+                            const InternalName *name);
+  INLINE ~qpGeomVertexWriter();
+
+  INLINE qpGeomVertexData *get_vertex_data() const;
+
+  INLINE bool set_data_type(int data_type);
+  INLINE bool set_data_type(const string &name);
+  INLINE bool set_data_type(const InternalName *name);
+  bool set_data_type(int array, const qpGeomVertexDataType *data_type);
+
+  INLINE bool has_data_type() const;
+  INLINE int get_array() const;
+  INLINE const qpGeomVertexDataType *get_data_type() const;
+
+  INLINE void set_vertex(int vertex);
+
+  INLINE int get_start_vertex() const;
+  INLINE int get_write_vertex() const;
+  INLINE int get_num_vertices() const;
+  INLINE bool is_at_end() const;
+
+  INLINE void set_data1f(float data);
+  INLINE void set_data2f(float x, float y);
+  INLINE void set_data2f(const LVecBase2f &data);
+  INLINE void set_data3f(float x, float y, float z);
+  INLINE void set_data3f(const LVecBase3f &data);
+  INLINE void set_data4f(float x, float y, float z, float w);
+  INLINE void set_data4f(const LVecBase4f &data);
+
+  INLINE void set_data1i(int data);
+
+  INLINE void add_data1f(float data);
+  INLINE void add_data2f(float x, float y);
+  INLINE void add_data2f(const LVecBase2f &data);
+  INLINE void add_data3f(float x, float y, float z);
+  INLINE void add_data3f(const LVecBase3f &data);
+  INLINE void add_data4f(float x, float y, float z, float w);
+  INLINE void add_data4f(const LVecBase4f &data);
+
+  INLINE void add_data1i(int data);
+
+private:
+  class Writer;
+
+  INLINE void set_pointer(int vertex);
+  INLINE unsigned char *inc_pointer();
+  INLINE unsigned char *inc_add_pointer();
+  Writer *make_writer() const;
+
+  PT(qpGeomVertexData) _vertex_data;
+  int _array;
+  const qpGeomVertexDataType *_data_type;
+  int _stride;
+
+  PTA_uchar _data;
+  unsigned char *_pointer;
+
+  int _start_vertex;
+  int _write_vertex;
+  int _num_vertices;
+
+  Writer *_writer;
+
+  // This union is handy for packing an NT_packed_8888 value.
+  typedef union {
+    unsigned char _b[4];
+    PN_uint32 _i;
+  } packed_8888;
+
+  // This nested class provides the implementation for unpacking data
+  // in a very general way, but also provides the hooks for
+  // implementing the common, very direct code paths (for instance,
+  // 3-component float32 to LVecBase3f) as quickly as possible.
+  class Writer {
+  public:
+    virtual ~Writer();
+    virtual void set_data1f(unsigned char *pointer, float data);
+    virtual void set_data2f(unsigned char *pointer, const LVecBase2f &data);
+    virtual void set_data3f(unsigned char *pointer, const LVecBase3f &data);
+    virtual void set_data4f(unsigned char *pointer, const LVecBase4f &data);
+    
+    virtual void set_data1i(unsigned char *pointer, int data);
+
+    INLINE unsigned int maybe_scale_color(float data);
+    INLINE void maybe_scale_color(const LVecBase2f &data);
+    INLINE void maybe_scale_color(const LVecBase3f &data);
+    INLINE void maybe_scale_color(const LVecBase4f &data);
+
+    const qpGeomVertexDataType *_data_type;
+    unsigned int _a, _b, _c, _d;
+  };
+
+  // This is a specialization on the generic Writer that handles
+  // points, which are special because the fourth component, if
+  // present in the data but not specified by the caller, is
+  // implicitly 1.0; and if it is not present in the data but is
+  // specified, we have to divide by it.
+  class Writer_point : public Writer {
+  public:
+    virtual void set_data1f(unsigned char *pointer, float data);
+    virtual void set_data2f(unsigned char *pointer, const LVecBase2f &data);
+    virtual void set_data3f(unsigned char *pointer, const LVecBase3f &data);
+    virtual void set_data4f(unsigned char *pointer, const LVecBase4f &data);
+  };
+
+  // This is similar to Writer_point, in that the fourth component
+  // (alpha) is implicitly 1.0 if unspecified, but we never divide by
+  // alpha.
+  class Writer_color : public Writer {
+  public:
+    virtual void set_data1f(unsigned char *pointer, float data);
+    virtual void set_data2f(unsigned char *pointer, const LVecBase2f &data);
+    virtual void set_data3f(unsigned char *pointer, const LVecBase3f &data);
+  };
+
+
+  // These are the specializations on the generic Writer that handle
+  // the direct code paths.
+
+  class Writer_float32_3 : public Writer {
+  public:
+    virtual void set_data3f(unsigned char *pointer, const LVecBase3f &value);
+  };
+
+  class Writer_point_float32_2 : public Writer_point {
+  public:
+    virtual void set_data2f(unsigned char *pointer, const LVecBase2f &value);
+  };
+
+  class Writer_point_float32_3 : public Writer_point {
+  public:
+    virtual void set_data3f(unsigned char *pointer, const LVecBase3f &value);
+  };
+
+  class Writer_point_float32_4 : public Writer_point {
+  public:
+    virtual void set_data4f(unsigned char *pointer, const LVecBase4f &value);
+  };
+
+  class Writer_argb_packed_8888 : public Writer_color {
+  public:
+    virtual void set_data4f(unsigned char *pointer, const LVecBase4f &value);
+  };
+
+  class Writer_rgba_uint8_4 : public Writer_color {
+  public:
+    virtual void set_data4f(unsigned char *pointer, const LVecBase4f &value);
+  };
+
+  class Writer_rgba_float32_4 : public Writer_color {
+  public:
+    virtual void set_data4f(unsigned char *pointer, const LVecBase4f &value);
+  };
+
+  class Writer_uint16_1 : public Writer {
+  public:
+    virtual void set_data1i(unsigned char *pointer, int value);
+  };
+};
+
+#include "qpgeomVertexWriter.I"
+
+#endif

+ 29 - 18
panda/src/pgraph/geomNode.cxx

@@ -17,6 +17,7 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
 #include "geomNode.h"
 #include "geomNode.h"
+#include "qpgeom.h"
 #include "geomTransformer.h"
 #include "geomTransformer.h"
 #include "sceneGraphReducer.h"
 #include "sceneGraphReducer.h"
 #include "accumulatedAttribs.h"
 #include "accumulatedAttribs.h"
@@ -351,25 +352,35 @@ calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point, bool &found_any,
   int num_geoms = get_num_geoms();
   int num_geoms = get_num_geoms();
   for (int i = 0; i < num_geoms; i++) {
   for (int i = 0; i < num_geoms; i++) {
     const Geom *geom = get_geom(i);
     const Geom *geom = get_geom(i);
-    Geom::VertexIterator vi = geom->make_vertex_iterator();
-    int num_prims = geom->get_num_prims();
     
     
-    for (int p = 0; p < num_prims; p++) {
-      int length = geom->get_length(p);
-      for (int v = 0; v < length; v++) {
-        Vertexf vertex = geom->get_next_vertex(vi) * mat;
-        
-        if (found_any) {
-          min_point.set(min(min_point[0], vertex[0]),
-                        min(min_point[1], vertex[1]),
-                        min(min_point[2], vertex[2]));
-          max_point.set(max(max_point[0], vertex[0]),
-                        max(max_point[1], vertex[1]),
-                        max(max_point[2], vertex[2]));
-        } else {
-          min_point = vertex;
-          max_point = vertex;
-          found_any = true;
+    // Temporary test until the experimental Geom rewrite is final.
+    if (geom->is_exact_type(qpGeom::get_class_type())) {
+      const qpGeom *qpgeom = DCAST(qpGeom, geom);
+      qpgeom->calc_tight_bounds(min_point, max_point, found_any,
+                                qpgeom->get_vertex_data()->animate_vertices(),
+                                !transform->is_identity(), mat);
+
+    } else {
+      Geom::VertexIterator vi = geom->make_vertex_iterator();
+      int num_prims = geom->get_num_prims();
+      
+      for (int p = 0; p < num_prims; p++) {
+        int length = geom->get_length(p);
+        for (int v = 0; v < length; v++) {
+          Vertexf vertex = geom->get_next_vertex(vi) * mat;
+          
+          if (found_any) {
+            min_point.set(min(min_point[0], vertex[0]),
+                          min(min_point[1], vertex[1]),
+                          min(min_point[2], vertex[2]));
+            max_point.set(max(max_point[0], vertex[0]),
+                          max(max_point[1], vertex[1]),
+                          max(max_point[2], vertex[2]));
+          } else {
+            min_point = vertex;
+            max_point = vertex;
+            found_any = true;
+          }
         }
         }
       }
       }
     }
     }