Browse Source

optimize GeomVertexReader/Writer some more

David Rose 20 years ago
parent
commit
01f8f950ab

+ 4 - 4
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -2520,8 +2520,8 @@ draw_tristrips(const qpGeomTristrips *primitive) {
 
     qpGeomVertexReader mins(primitive->get_mins(), 0);
     qpGeomVertexReader maxs(primitive->get_maxs(), 0);
-    nassertv(mins.get_num_vertices() == (int)ends.size() && 
-             maxs.get_num_vertices() == (int)ends.size());
+    nassertv(primitive->get_mins()->get_num_vertices() == (int)ends.size() && 
+             primitive->get_maxs()->get_num_vertices() == (int)ends.size());
     
     unsigned int start = 0;
     for (size_t i = 0; i < ends.size(); i++) {
@@ -2554,8 +2554,8 @@ draw_trifans(const qpGeomTrifans *primitive) {
 
   qpGeomVertexReader mins(primitive->get_mins(), 0);
   qpGeomVertexReader maxs(primitive->get_maxs(), 0);
-  nassertv(mins.get_num_vertices() == (int)ends.size() && 
-           maxs.get_num_vertices() == (int)ends.size());
+  nassertv(primitive->get_mins()->get_num_vertices() == (int)ends.size() && 
+           primitive->get_maxs()->get_num_vertices() == (int)ends.size());
 
   unsigned int start = 0;
   for (size_t i = 0; i < ends.size(); i++) {

+ 3 - 3
panda/src/gobj/qpgeomPrimitive.cxx

@@ -166,7 +166,7 @@ add_vertex(int vertex) {
   }
 
   qpGeomVertexWriter index(cdata->_vertices, 0);
-  index.set_vertex(index.get_num_vertices());
+  index.set_vertex(cdata->_vertices->get_num_vertices());
 
   index.add_data1i(vertex);
 
@@ -197,7 +197,7 @@ add_consecutive_vertices(int start, int num_vertices) {
   }
 
   qpGeomVertexWriter index(cdata->_vertices, 0);
-  index.set_vertex(index.get_num_vertices());
+  index.set_vertex(cdata->_vertices->get_num_vertices());
 
   for (int v = start; v <= end; ++v) {
     index.add_data1i(v);
@@ -990,7 +990,7 @@ recompute_minmax(qpGeomPrimitive::CDWriter &cdata) {
     }
     mins.add_data1i(min_prim);
     maxs.add_data1i(max_prim);
-    nassertv(mins.get_num_vertices() == (int)cdata->_ends.size());
+    nassertv(cdata->_mins->get_num_vertices() == (int)cdata->_ends.size());
 
   } else {
     // This is a simple primitive type like a triangle; just compute

+ 2 - 2
panda/src/gobj/qpgeomTristrips.cxx

@@ -285,11 +285,11 @@ rotate_impl() const {
 void qpGeomTristrips::
 append_unused_vertices(qpGeomVertexArrayData *vertices, int vertex) {
   qpGeomVertexReader from(vertices, 0);
-  from.set_vertex(from.get_num_vertices() - 1);
+  from.set_vertex(vertices->get_num_vertices() - 1);
   int prev = from.get_data1i();
 
   qpGeomVertexWriter to(vertices, 0);
-  to.set_vertex(to.get_num_vertices());
+  to.set_vertex(vertices->get_num_vertices());
 
   to.add_data1i(prev);
   to.add_data1i(vertex);

+ 158 - 16
panda/src/gobj/qpgeomVertexColumn.I

@@ -24,7 +24,9 @@
 //               from a bam file.
 ////////////////////////////////////////////////////////////////////
 INLINE qpGeomVertexColumn::
-qpGeomVertexColumn() {
+qpGeomVertexColumn() :
+  _packer(NULL)
+{
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -40,7 +42,8 @@ qpGeomVertexColumn(const InternalName *name, int num_components,
   _num_components(num_components),
   _numeric_type(numeric_type),
   _contents(contents),
-  _start(start)
+  _start(start),
+  _packer(NULL)
 {
   setup();
 }
@@ -54,30 +57,22 @@ INLINE qpGeomVertexColumn::
 qpGeomVertexColumn(const qpGeomVertexColumn &copy) :
   _name(copy._name),
   _num_components(copy._num_components),
-  _num_values(copy._num_values),
   _numeric_type(copy._numeric_type),
   _contents(copy._contents),
   _start(copy._start),
-  _component_bytes(copy._component_bytes),
-  _total_bytes(copy._total_bytes)
+  _packer(NULL)
 {
+  setup();
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexColumn::Copy Assignment Operator
+//     Function: qpGeomVertexColumn::Destructor
 //       Access: Published
 //  Description: 
 ////////////////////////////////////////////////////////////////////
-INLINE void qpGeomVertexColumn::
-operator = (const qpGeomVertexColumn &copy) {
-  _name = copy._name;
-  _num_components = copy._num_components;
-  _num_values = copy._num_values;
-  _numeric_type = copy._numeric_type;
-  _contents = copy._contents;
-  _start = copy._start;
-  _component_bytes = copy._component_bytes;
-  _total_bytes = copy._total_bytes;
+INLINE qpGeomVertexColumn::
+~qpGeomVertexColumn() {
+  delete _packer;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -331,3 +326,150 @@ operator << (ostream &out, const qpGeomVertexColumn &obj) {
   obj.output(out);
   return out;
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer::maybe_scale_color
+//       Access: Public
+//  Description: Converts an integer (typically a uint8) value to a
+//               floating-point value.  If the contents value
+//               indicates this is a color value, scales it into the
+//               range 0..1 per convention; otherwise leaves it alone.
+////////////////////////////////////////////////////////////////////
+INLINE float qpGeomVertexColumn::Packer::
+maybe_scale_color(unsigned int value) {
+  if (_column->get_contents() == C_color) {
+    return (float)value / 255.0f;
+  } else {
+    return (float)value;
+  }
+}
+    
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer::maybe_scale_color
+//       Access: Public
+//  Description: Converts a pair of integers into the _v2 member.  See
+//               one-parameter maybe_scale_color() for more info.
+////////////////////////////////////////////////////////////////////
+INLINE void qpGeomVertexColumn::Packer::
+maybe_scale_color(unsigned int a, unsigned int b) {
+  if (_column->get_contents() == C_color) {
+    _v2.set((float)a / 255.0f,
+            (float)b / 255.0f);
+  } else {    
+    _v2.set((float)a, (float)b);
+  }
+}
+    
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer::maybe_scale_color
+//       Access: Public
+//  Description: Converts a pair of integers into the _v3 member.  See
+//               one-parameter maybe_scale_color() for more info.
+////////////////////////////////////////////////////////////////////
+INLINE void qpGeomVertexColumn::Packer::
+maybe_scale_color(unsigned int a, unsigned int b, unsigned int c) {
+  if (_column->get_contents() == C_color) {
+    _v3.set((float)a / 255.0f,
+            (float)b / 255.0f,
+            (float)c / 255.0f);
+  } else {    
+    _v3.set((float)a, (float)b, (float)c);
+  }
+}
+    
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer::maybe_scale_color
+//       Access: Public
+//  Description: Converts a pair of integers into the _v4 member.  See
+//               one-parameter maybe_scale_color() for more info.
+////////////////////////////////////////////////////////////////////
+INLINE void qpGeomVertexColumn::Packer::
+maybe_scale_color(unsigned int a, unsigned int b, unsigned int c,
+                  unsigned int d) {
+  if (_column->get_contents() == C_color) {
+    _v4.set((float)a / 255.0f,
+            (float)b / 255.0f,
+            (float)c / 255.0f,
+            (float)d / 255.0f);
+  } else {
+    _v4.set((float)a, (float)b, (float)c, (float)d);
+  }
+}
+    
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer::maybe_unscale_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 qpGeomVertexColumn::Packer::
+maybe_unscale_color(float data) {
+  if (_column->get_contents() == C_color) {
+    return (unsigned int)(data * 255.0f);
+  } else {
+    return (unsigned int)data;
+  }
+}
+    
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer::maybe_unscale_color
+//       Access: Public
+//  Description: Converts an LVecBase2f into a pair of uint8
+//               values.  See one-parameter maybe_unscale_color() for
+//               more info.
+////////////////////////////////////////////////////////////////////
+INLINE void qpGeomVertexColumn::Packer::
+maybe_unscale_color(const LVecBase2f &data) {
+  if (_column->get_contents() == C_color) {
+    _a = (unsigned int)(data[0] * 255.0f);
+    _b = (unsigned int)(data[1] * 255.0f);
+  } else {
+    _a = (unsigned int)data[0];
+    _b = (unsigned int)data[1];
+  }
+}
+    
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer::maybe_unscale_color
+//       Access: Public
+//  Description: Converts an LVecBase3f into a pair of uint8
+//               values.  See one-parameter maybe_unscale_color() for
+//               more info.
+////////////////////////////////////////////////////////////////////
+INLINE void qpGeomVertexColumn::Packer::
+maybe_unscale_color(const LVecBase3f &data) {
+  if (_column->get_contents() == C_color) {
+    _a = (unsigned int)(data[0] * 255.0f);
+    _b = (unsigned int)(data[1] * 255.0f);
+    _c = (unsigned int)(data[2] * 255.0f);
+  } else {
+    _a = (unsigned int)data[0];
+    _b = (unsigned int)data[1];
+    _c = (unsigned int)data[2];
+  }
+}
+    
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer::maybe_unscale_color
+//       Access: Public
+//  Description: Converts an LVecBase4f into a pair of uint8
+//               values.  See one-parameter maybe_unscale_color() for
+//               more info.
+////////////////////////////////////////////////////////////////////
+INLINE void qpGeomVertexColumn::Packer::
+maybe_unscale_color(const LVecBase4f &data) {
+  if (_column->get_contents() == C_color) {
+    _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);
+  } else {
+    _a = (unsigned int)data[0];
+    _b = (unsigned int)data[1];
+    _c = (unsigned int)data[2];
+    _d = (unsigned int)data[3];
+  }
+}

+ 1768 - 0
panda/src/gobj/qpgeomVertexColumn.cxx

@@ -20,6 +20,25 @@
 #include "bamReader.h"
 #include "bamWriter.h"
 
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Copy Assignment Operator
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexColumn::
+operator = (const qpGeomVertexColumn &copy) {
+  _name = copy._name;
+  _num_components = copy._num_components;
+  _numeric_type = copy._numeric_type;
+  _contents = copy._contents;
+  _start = copy._start;
+
+  delete _packer;
+  _packer = NULL;
+
+  setup();
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: qpGeomVertexColumn::output
 //       Access: Published
@@ -67,6 +86,117 @@ setup() {
   }
 
   _total_bytes = _component_bytes * _num_components;
+
+  _packer = make_packer();
+  _packer->_column = this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::make_packer
+//       Access: Private
+//  Description: Returns a newly-allocated Packer object suitable for
+//               packing and unpacking this column.  The _column
+//               member of the packer is not filled in.
+////////////////////////////////////////////////////////////////////
+qpGeomVertexColumn::Packer *qpGeomVertexColumn::
+make_packer() const {
+  switch (get_contents()) {
+  case C_point:
+  case C_clip_point:
+  case C_texcoord:
+    // These types are read as a 4-d homogeneous point.
+    switch (get_numeric_type()) {
+    case NT_float32:
+      if (sizeof(float) == sizeof(PN_float32)) {
+        // Use the native float type implementation for a tiny bit
+        // more optimization.
+        switch (get_num_components()) {
+        case 2:
+          return new Packer_point_nativefloat_2;
+        case 3:
+          return new Packer_point_nativefloat_3;
+        case 4:
+          return new Packer_point_nativefloat_4;
+        }
+      } else {
+        switch (get_num_components()) {
+        case 2:
+          return new Packer_point_float32_2;
+        case 3:
+          return new Packer_point_float32_3;
+        case 4:
+          return new Packer_point_float32_4;
+        }
+      }
+      break;
+    default:
+      break;
+    }
+    return new Packer_point;
+
+  case C_color:
+    switch (get_numeric_type()) {
+    case NT_uint8:
+      switch (get_num_components()) {
+      case 4:
+        return new Packer_rgba_uint8_4;
+        
+      default:
+        break;
+      }
+      break;
+    case NT_packed_dabc:
+      switch (get_num_components()) {
+      case 1:
+        return new Packer_argb_packed;
+        
+      default:
+        break;
+      }
+      break;
+    case NT_float32:
+      switch (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 Packer_rgba_nativefloat_4;
+        } else {
+          return new Packer_rgba_float32_4;
+        }
+        
+      default:
+        break;
+      }
+      break;
+    default:
+      break;
+    }
+    return new Packer_color;
+
+  default:
+    // Otherwise, we just read it as a generic value.
+    switch (get_numeric_type()) {
+    case NT_float32:
+      switch (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 Packer_nativefloat_3;
+        } else {
+          return new Packer_float32_3;
+        }
+
+      default:
+        break;
+      }
+      break;
+    default:
+      break;
+    }
+    return new Packer;
+  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -118,3 +248,1641 @@ fillin(DatagramIterator &scan, BamReader *manager) {
 
   setup();
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer::Destructor
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+qpGeomVertexColumn::Packer::
+~Packer() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer::get_data1f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+float qpGeomVertexColumn::Packer::
+get_data1f(const unsigned char *pointer) {
+  switch (_column->get_numeric_type()) {
+  case NT_uint8:
+    return maybe_scale_color(*pointer);
+
+  case NT_uint16:
+    return *(const PN_uint16 *)pointer;
+
+  case NT_uint32:
+    return *(const PN_uint32 *)pointer;
+
+  case NT_packed_dcba:
+    {
+      PN_uint32 dword = *(const PN_uint32 *)pointer;
+      return maybe_scale_color(qpGeomVertexData::unpack_abcd_d(dword));
+    }
+
+  case NT_packed_dabc:
+    {
+      PN_uint32 dword = *(const PN_uint32 *)pointer;
+      return maybe_scale_color(qpGeomVertexData::unpack_abcd_b(dword));
+    }
+
+  case NT_float32:
+    return *(const PN_float32 *)pointer;
+  }
+
+  return 0.0f;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer::get_data2f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase2f &qpGeomVertexColumn::Packer::
+get_data2f(const unsigned char *pointer) {
+  if (_column->get_num_values() == 1) {
+    _v2.set(get_data1i(pointer), 0.0f);
+    return _v2;
+
+  } else {
+    switch (_column->get_numeric_type()) {
+    case NT_uint8:
+      maybe_scale_color(pointer[0], pointer[1]);
+      return _v2;
+      
+    case NT_uint16:
+      {
+        const PN_uint16 *pi = (const PN_uint16 *)pointer;
+        _v2.set(pi[0], pi[1]);
+      }
+      return _v2;
+      
+    case NT_uint32:
+      {
+        const PN_uint32 *pi = (const PN_uint32 *)pointer;
+        _v2.set(pi[0], pi[1]);
+      }
+      return _v2;
+      
+    case NT_packed_dcba:
+      {
+        PN_uint32 dword = *(const PN_uint32 *)pointer;
+        maybe_scale_color(qpGeomVertexData::unpack_abcd_d(dword),
+                          qpGeomVertexData::unpack_abcd_c(dword));
+      }
+      return _v2;
+      
+    case NT_packed_dabc:
+      {
+        PN_uint32 dword = *(const PN_uint32 *)pointer;
+        maybe_scale_color(qpGeomVertexData::unpack_abcd_b(dword),
+                          qpGeomVertexData::unpack_abcd_c(dword));
+      }
+      return _v2;
+      
+    case NT_float32:
+      {
+        const PN_float32 *pi = (const PN_float32 *)pointer;
+        _v2.set(pi[0], pi[1]);
+      }
+      return _v2;
+    }
+  }
+
+  return _v2;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer::get_data3f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase3f &qpGeomVertexColumn::Packer::
+get_data3f(const unsigned char *pointer) {
+  switch (_column->get_num_values()) {
+  case 1:
+    _v3.set(get_data1f(pointer), 0.0f, 0.0f);
+    return _v3;
+
+  case 2:
+    {
+      const LVecBase2f &v2 = get_data2f(pointer);
+      _v3.set(v2[0], v2[1], 0.0f);
+    }
+    return _v3;
+
+  default:
+    switch (_column->get_numeric_type()) {
+    case NT_uint8:
+      maybe_scale_color(pointer[0], pointer[1], pointer[2]);
+      return _v3;
+      
+    case NT_uint16:
+      {
+        const PN_uint16 *pi = (const PN_uint16 *)pointer;
+        _v3.set(pi[0], pi[1], pi[2]);
+      }
+      return _v3;
+      
+    case NT_uint32:
+      {
+        const PN_uint32 *pi = (const PN_uint32 *)pointer;
+        _v3.set(pi[0], pi[1], pi[2]);
+      }
+      return _v3;
+      
+    case NT_packed_dcba:
+      {
+        PN_uint32 dword = *(const PN_uint32 *)pointer;
+        maybe_scale_color(qpGeomVertexData::unpack_abcd_d(dword),
+                          qpGeomVertexData::unpack_abcd_c(dword),
+                          qpGeomVertexData::unpack_abcd_b(dword));
+      }
+      return _v3;
+      
+    case NT_packed_dabc:
+      {
+        PN_uint32 dword = *(const PN_uint32 *)pointer;
+        maybe_scale_color(qpGeomVertexData::unpack_abcd_b(dword),
+                          qpGeomVertexData::unpack_abcd_c(dword),
+                          qpGeomVertexData::unpack_abcd_d(dword));
+      }
+      return _v3;
+      
+    case NT_float32:
+      {
+        const PN_float32 *pi = (const PN_float32 *)pointer;
+        _v3.set(pi[0], pi[1], pi[2]);
+      }
+      return _v3;
+    }
+  }
+
+  return _v3;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer::get_data4f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase4f &qpGeomVertexColumn::Packer::
+get_data4f(const unsigned char *pointer) {
+  switch (_column->get_num_values()) {
+  case 1:
+    _v4.set(get_data1i(pointer), 0.0f, 0.0f, 0.0f);
+    return _v4;
+
+  case 2:
+    {
+      const LVecBase2f &v2 = get_data2f(pointer);
+      _v4.set(v2[0], v2[1], 0.0f, 0.0f);
+    }
+    return _v4;
+
+  case 3:
+    {
+      const LVecBase3f &v3 = get_data3f(pointer);
+      _v4.set(v3[0], v3[1], v3[2], 0.0f);
+    }
+    return _v4;
+
+  default:
+    switch (_column->get_numeric_type()) {
+    case NT_uint8:
+      maybe_scale_color(pointer[0], pointer[1], pointer[2], pointer[3]);
+      return _v4;
+      
+    case NT_uint16:
+      {
+        const PN_uint16 *pi = (const PN_uint16 *)pointer;
+        _v4.set(pi[0], pi[1], pi[2], pi[3]);
+      }
+      return _v4;
+      
+    case NT_uint32:
+      {
+        const PN_uint32 *pi = (const PN_uint32 *)pointer;
+        _v4.set(pi[0], pi[1], pi[2], pi[3]);
+      }
+      return _v4;
+      
+    case NT_packed_dcba:
+      {
+        PN_uint32 dword = *(const PN_uint32 *)pointer;
+        maybe_scale_color(qpGeomVertexData::unpack_abcd_d(dword),
+                          qpGeomVertexData::unpack_abcd_c(dword),
+                          qpGeomVertexData::unpack_abcd_b(dword),
+                          qpGeomVertexData::unpack_abcd_a(dword));
+      }
+      return _v4;
+      
+    case NT_packed_dabc:
+      {
+        PN_uint32 dword = *(const PN_uint32 *)pointer;
+        maybe_scale_color(qpGeomVertexData::unpack_abcd_b(dword),
+                          qpGeomVertexData::unpack_abcd_c(dword),
+                          qpGeomVertexData::unpack_abcd_d(dword),
+                          qpGeomVertexData::unpack_abcd_a(dword));
+      }
+      return _v4;
+      
+    case NT_float32:
+      {
+        const PN_float32 *pi = (const PN_float32 *)pointer;
+        _v4.set(pi[0], pi[1], pi[2], pi[3]);
+      }
+      return _v4;
+    }
+  }
+
+  return _v4;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer::get_data1i
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+int qpGeomVertexColumn::Packer::
+get_data1i(const unsigned char *pointer) {
+  switch (_column->get_numeric_type()) {
+  case NT_uint8:
+    return *pointer;
+
+  case NT_uint16:
+    return *(const PN_uint16 *)pointer;
+
+  case NT_uint32:
+    return *(const PN_uint32 *)pointer;
+
+  case NT_packed_dcba:
+    {
+      PN_uint32 dword = *(const PN_uint32 *)pointer;
+      return qpGeomVertexData::unpack_abcd_d(dword);
+    }
+    break;
+
+  case NT_packed_dabc:
+    {
+      PN_uint32 dword = *(const PN_uint32 *)pointer;
+      return qpGeomVertexData::unpack_abcd_b(dword);
+    }
+    break;
+
+  case NT_float32:
+    return (int)*(const PN_float32 *)pointer;
+  }
+
+  return 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer::get_data2i
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const int *qpGeomVertexColumn::Packer::
+get_data2i(const unsigned char *pointer) {
+  switch (_column->get_num_values()) {
+  case 1:
+    _i[0] = get_data1i(pointer);
+    _i[1] = 0;
+    return _i;
+
+  default:
+    switch (_column->get_numeric_type()) {
+    case NT_uint8:
+      _i[0] = pointer[0];
+      _i[1] = pointer[1];
+      return _i;
+      
+    case NT_uint16:
+      {
+        const PN_uint16 *pi = (const PN_uint16 *)pointer;
+        _i[0] = pi[0];
+        _i[1] = pi[1];
+      }
+      return _i;
+      
+    case NT_uint32:
+      {
+        const PN_uint32 *pi = (const PN_uint32 *)pointer;
+        _i[0] = pi[0];
+        _i[1] = pi[1];
+      }
+      return _i;
+      
+    case NT_packed_dcba:
+      {
+        PN_uint32 dword = *(const PN_uint32 *)pointer;
+        _i[0] = qpGeomVertexData::unpack_abcd_d(dword);
+        _i[1] = qpGeomVertexData::unpack_abcd_c(dword);
+      }
+      return _i;
+      
+    case NT_packed_dabc:
+      {
+        PN_uint32 dword = *(const PN_uint32 *)pointer;
+        _i[0] = qpGeomVertexData::unpack_abcd_b(dword);
+        _i[1] = qpGeomVertexData::unpack_abcd_c(dword);
+      }
+      return _i;
+      
+    case NT_float32:
+      {
+        const PN_float32 *pi = (const PN_float32 *)pointer;
+        _i[0] = (int)pi[0];
+        _i[1] = (int)pi[1];
+      }
+      return _i;
+    }
+  }
+
+  return _i;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer::get_data3i
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const int *qpGeomVertexColumn::Packer::
+get_data3i(const unsigned char *pointer) {
+  switch (_column->get_num_values()) {
+  case 1:
+    _i[0] = get_data1i(pointer);
+    _i[1] = 0;
+    _i[2] = 0;
+    return _i;
+
+  case 2:
+    {
+      const int *i = get_data2i(pointer);
+      _i[0] = i[0];
+      _i[1] = i[1];
+      _i[2] = 0;
+    }
+    return _i;
+
+  default:
+    switch (_column->get_numeric_type()) {
+    case NT_uint8:
+      _i[0] = pointer[0];
+      _i[1] = pointer[1];
+      _i[2] = pointer[2];
+      return _i;
+      
+    case NT_uint16:
+      {
+        const PN_uint16 *pi = (const PN_uint16 *)pointer;
+        _i[0] = pi[0];
+        _i[1] = pi[1];
+        _i[2] = pi[2];
+      }
+      return _i;
+      
+    case NT_uint32:
+      {
+        const PN_uint32 *pi = (const PN_uint32 *)pointer;
+        _i[0] = pi[0];
+        _i[1] = pi[1];
+        _i[2] = pi[2];
+      }
+      return _i;
+      
+    case NT_packed_dcba:
+      {
+        PN_uint32 dword = *(const PN_uint32 *)pointer;
+        _i[0] = qpGeomVertexData::unpack_abcd_d(dword);
+        _i[1] = qpGeomVertexData::unpack_abcd_c(dword);
+        _i[2] = qpGeomVertexData::unpack_abcd_b(dword);
+      }
+      return _i;
+      
+    case NT_packed_dabc:
+      {
+        PN_uint32 dword = *(const PN_uint32 *)pointer;
+        _i[0] = qpGeomVertexData::unpack_abcd_b(dword);
+        _i[1] = qpGeomVertexData::unpack_abcd_c(dword);
+        _i[2] = qpGeomVertexData::unpack_abcd_d(dword);
+      }
+      return _i;
+      
+    case NT_float32:
+      {
+        const PN_float32 *pi = (const PN_float32 *)pointer;
+        _i[0] = (int)pi[0];
+        _i[1] = (int)pi[1];
+        _i[2] = (int)pi[2];
+      }
+      return _i;
+    }
+  }
+
+  return _i;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer::get_data4i
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const int *qpGeomVertexColumn::Packer::
+get_data4i(const unsigned char *pointer) {
+  switch (_column->get_num_values()) {
+  case 1:
+    _i[0] = get_data1i(pointer);
+    _i[1] = 0;
+    _i[2] = 0;
+    _i[3] = 0;
+    return _i;
+
+  case 2:
+    {
+      const int *i = get_data2i(pointer);
+      _i[0] = i[0];
+      _i[1] = i[1];
+      _i[2] = 0;
+      _i[3] = 0;
+    }
+    return _i;
+
+  case 3:
+    {
+      const int *i = get_data3i(pointer);
+      _i[0] = i[0];
+      _i[1] = i[1];
+      _i[2] = i[2];
+      _i[3] = 0;
+    }
+    return _i;
+
+  default:
+    switch (_column->get_numeric_type()) {
+    case NT_uint8:
+      _i[0] = pointer[0];
+      _i[1] = pointer[1];
+      _i[2] = pointer[2];
+      _i[3] = pointer[3];
+      return _i;
+      
+    case NT_uint16:
+      {
+        const PN_uint16 *pi = (const PN_uint16 *)pointer;
+        _i[0] = pi[0];
+        _i[1] = pi[1];
+        _i[2] = pi[2];
+        _i[3] = pi[3];
+      }
+      return _i;
+      
+    case NT_uint32:
+      {
+        const PN_uint32 *pi = (const PN_uint32 *)pointer;
+        _i[0] = pi[0];
+        _i[1] = pi[1];
+        _i[2] = pi[2];
+        _i[3] = pi[3];
+      }
+      return _i;
+      
+    case NT_packed_dcba:
+      {
+        PN_uint32 dword = *(const PN_uint32 *)pointer;
+        _i[0] = qpGeomVertexData::unpack_abcd_d(dword);
+        _i[1] = qpGeomVertexData::unpack_abcd_c(dword);
+        _i[2] = qpGeomVertexData::unpack_abcd_b(dword);
+        _i[3] = qpGeomVertexData::unpack_abcd_a(dword);
+      }
+      return _i;
+      
+    case NT_packed_dabc:
+      {
+        PN_uint32 dword = *(const PN_uint32 *)pointer;
+        _i[0] = qpGeomVertexData::unpack_abcd_b(dword);
+        _i[1] = qpGeomVertexData::unpack_abcd_c(dword);
+        _i[2] = qpGeomVertexData::unpack_abcd_d(dword);
+        _i[3] = qpGeomVertexData::unpack_abcd_a(dword);
+      }
+      return _i;
+      
+    case NT_float32:
+      {
+        const PN_float32 *pi = (const PN_float32 *)pointer;
+        _i[0] = (int)pi[0];
+        _i[1] = (int)pi[1];
+        _i[2] = (int)pi[2];
+        _i[3] = (int)pi[3];
+      }
+      return _i;
+    }
+  }
+
+  return _i;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer::set_data1f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexColumn::Packer::
+set_data1f(unsigned char *pointer, float data) {
+  switch (_column->get_num_values()) {
+  case 1:
+    switch (_column->get_numeric_type()) {
+    case NT_uint8:
+      *pointer = maybe_unscale_color(data);
+      break;
+      
+    case NT_uint16:
+      *(PN_uint16 *)pointer = (unsigned int)data;
+      break;
+      
+    case NT_uint32:
+      *(PN_uint32 *)pointer = (unsigned int)data;
+      break;
+      
+    case NT_packed_dcba:
+    case NT_packed_dabc:
+      nassertv(false);
+      break;
+      
+    case 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: qpGeomVertexColumn::Packer::set_data2f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexColumn::Packer::
+set_data2f(unsigned char *pointer, const LVecBase2f &data) {
+  switch (_column->get_num_values()) {
+  case 1:
+    set_data1f(pointer, data[0]);
+
+  case 2:
+    switch (_column->get_numeric_type()) {
+    case NT_uint8:
+      maybe_unscale_color(data);
+      pointer[0] = _a;
+      pointer[1] = _b;
+      break;
+      
+    case NT_uint16:
+      {
+        PN_uint16 *pi = (PN_uint16 *)pointer;
+        pi[0] = (unsigned int)data[0];
+        pi[1] = (unsigned int)data[1];
+      }
+      break;
+      
+    case NT_uint32:
+      {
+        PN_uint32 *pi = (PN_uint32 *)pointer;
+        pi[0] = (unsigned int)data[0];
+        pi[1] = (unsigned int)data[1];
+      }
+      break;
+      
+    case NT_packed_dcba:
+    case NT_packed_dabc:
+      nassertv(false);
+      break;
+      
+    case 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: qpGeomVertexColumn::Packer::set_data3f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexColumn::Packer::
+set_data3f(unsigned char *pointer, const LVecBase3f &data) {
+  switch (_column->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 (_column->get_numeric_type()) {
+    case NT_uint8:
+      maybe_unscale_color(data);
+      pointer[0] = _a;
+      pointer[1] = _b;
+      pointer[2] = _c;
+      break;
+      
+    case 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 NT_uint32:
+      {
+        PN_uint32 *pi = (PN_uint32 *)pointer;
+        pi[0] = (unsigned int)data[0];
+        pi[1] = (unsigned int)data[1];
+        pi[2] = (unsigned int)data[2];
+      }
+      break;
+      
+    case NT_packed_dcba:
+    case NT_packed_dabc:
+      nassertv(false);
+      break;
+      
+    case 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: qpGeomVertexColumn::Packer::set_data4f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexColumn::Packer::
+set_data4f(unsigned char *pointer, const LVecBase4f &data) {
+  switch (_column->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 (_column->get_numeric_type()) {
+    case NT_uint8:
+      maybe_unscale_color(data);
+      pointer[0] = _a;
+      pointer[1] = _b;
+      pointer[2] = _c;
+      pointer[3] = _d;
+      break;
+
+    case 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 NT_uint32:
+      {
+        PN_uint32 *pi = (PN_uint32 *)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 NT_packed_dcba:
+      maybe_unscale_color(data);
+      *(PN_uint32 *)pointer = qpGeomVertexData::pack_abcd(_d, _c, _b, _a);
+      break;
+      
+    case NT_packed_dabc:
+      maybe_unscale_color(data);
+      *(PN_uint32 *)pointer = qpGeomVertexData::pack_abcd(_d, _a, _b, _c);
+      break;
+      
+    case 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: qpGeomVertexColumn::Packer::set_data1i
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexColumn::Packer::
+set_data1i(unsigned char *pointer, int a) {
+  switch (_column->get_num_values()) {
+  case 1:
+    switch (_column->get_numeric_type()) {
+    case NT_uint8:
+      *pointer = a;
+      nassertv((*pointer) == a);
+      break;
+      
+    case NT_uint16:
+      *(PN_uint16 *)pointer = a;
+      nassertv(*(PN_uint16 *)pointer == a);
+      break;
+      
+    case NT_uint32:
+      *(PN_uint32 *)pointer = a;
+      break;
+      
+    case NT_packed_dcba:
+    case NT_packed_dabc:
+      nassertv(false);
+      break;
+      
+    case NT_float32:
+      *(PN_float32 *)pointer = (float)a;
+      break;
+    }
+    break;
+
+  case 2:
+    set_data2i(pointer, a, 0);
+    break;
+
+  case 3:
+    set_data3i(pointer, a, 0, 0);
+    break;
+
+  default:
+    set_data4i(pointer, a, 0, 0, 0);
+    break;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer::set_data2i
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexColumn::Packer::
+set_data2i(unsigned char *pointer, int a, int b) {
+  switch (_column->get_num_values()) {
+  case 1:
+    set_data1i(pointer, a);
+    break;
+
+  case 2:
+    switch (_column->get_numeric_type()) {
+    case NT_uint8:
+      pointer[0] = a;
+      pointer[1] = b;
+      break;
+
+    case NT_uint16:
+      {
+        PN_uint16 *pi = (PN_uint16 *)pointer;
+        pi[0] = a;
+        pi[1] = b;
+      }
+      break;
+
+    case NT_uint32:
+      {
+        PN_uint32 *pi = (PN_uint32 *)pointer;
+        pi[0] = a;
+        pi[1] = b;
+      }
+      break;
+      
+    case NT_packed_dcba:
+    case NT_packed_dabc:
+      nassertv(false);
+      break;
+      
+    case NT_float32:
+      {
+        PN_float32 *pi = (PN_float32 *)pointer;
+        pi[0] = a;
+        pi[1] = b;
+      }
+      break;
+    }
+    break;
+
+  case 3:
+    set_data3i(pointer, a, b, 0);
+    break;
+
+  default:
+    set_data4i(pointer, a, b, 0, 0);
+    break;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer::set_data3i
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexColumn::Packer::
+set_data3i(unsigned char *pointer, int a, int b, int c) {
+  switch (_column->get_num_values()) {
+  case 1:
+    set_data1i(pointer, a);
+    break;
+
+  case 2:
+    set_data2i(pointer, a, b);
+    break;
+
+  case 3:
+    switch (_column->get_numeric_type()) {
+    case NT_uint8:
+      pointer[0] = a;
+      pointer[1] = b;
+      pointer[2] = c;
+      break;
+
+    case NT_uint16:
+      {
+        PN_uint16 *pi = (PN_uint16 *)pointer;
+        pi[0] = a;
+        pi[1] = b;
+        pi[2] = c;
+      }
+      break;
+
+    case NT_uint32:
+      {
+        PN_uint32 *pi = (PN_uint32 *)pointer;
+        pi[0] = a;
+        pi[1] = b;
+        pi[2] = c;
+      }
+      break;
+      
+    case NT_packed_dcba:
+    case NT_packed_dabc:
+      nassertv(false);
+      break;
+      
+    case NT_float32:
+      {
+        PN_float32 *pi = (PN_float32 *)pointer;
+        pi[0] = a;
+        pi[1] = b;
+        pi[2] = c;
+      }
+      break;
+    }
+    break;
+
+  default:
+    set_data4i(pointer, a, b, c, 0);
+    break;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer::set_data4i
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexColumn::Packer::
+set_data4i(unsigned char *pointer, int a, int b, int c, int d) {
+  switch (_column->get_num_values()) {
+  case 1:
+    set_data1i(pointer, a);
+    break;
+
+  case 2:
+    set_data2i(pointer, a, b);
+    break;
+
+  case 3:
+    set_data3i(pointer, a, b, c);
+    break;
+
+  default:
+    switch (_column->get_numeric_type()) {
+    case NT_uint8:
+      pointer[0] = a;
+      pointer[1] = b;
+      pointer[2] = c;
+      pointer[3] = d;
+      break;
+
+    case NT_uint16:
+      {
+        PN_uint16 *pi = (PN_uint16 *)pointer;
+        pi[0] = a;
+        pi[1] = b;
+        pi[2] = c;
+        pi[3] = d;
+      }
+      break;
+
+    case NT_uint32:
+      {
+        PN_uint32 *pi = (PN_uint32 *)pointer;
+        pi[0] = a;
+        pi[1] = b;
+        pi[2] = c;
+        pi[3] = d;
+      }
+      break;
+      
+    case NT_packed_dcba:
+      *(PN_uint32 *)pointer = qpGeomVertexData::pack_abcd(d, c, b, a);
+      break;
+      
+    case NT_packed_dabc:
+      *(PN_uint32 *)pointer = qpGeomVertexData::pack_abcd(d, a, b, c);
+      break;
+      
+    case NT_float32:
+      {
+        PN_float32 *pi = (PN_float32 *)pointer;
+        pi[0] = a;
+        pi[1] = b;
+        pi[2] = c;
+        pi[3] = d;
+      }
+      break;
+    }
+    break;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer_point::get_data1f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+float qpGeomVertexColumn::Packer_point::
+get_data1f(const unsigned char *pointer) {
+  if (_column->get_num_values() == 4) {
+    const LVecBase4f &v4 = get_data4f(pointer);
+    return v4[0] / v4[3];
+  } else {
+    return Packer::get_data1f(pointer);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer_point::get_data2f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase2f &qpGeomVertexColumn::Packer_point::
+get_data2f(const unsigned char *pointer) {
+  if (_column->get_num_values() == 4) {
+    const LVecBase4f &v4 = get_data4f(pointer);
+    _v2.set(v4[0] / v4[3], v4[1] / v4[3]);
+    return _v2;
+  } else {
+    return Packer::get_data2f(pointer);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer_point::get_data3f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase3f &qpGeomVertexColumn::Packer_point::
+get_data3f(const unsigned char *pointer) {
+  if (_column->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 Packer::get_data3f(pointer);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer_point::get_data4f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase4f &qpGeomVertexColumn::Packer_point::
+get_data4f(const unsigned char *pointer) {
+  switch (_column->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 (_column->get_numeric_type()) {
+    case NT_uint8:
+      maybe_scale_color(pointer[0], pointer[1], pointer[2], pointer[3]);
+      return _v4;
+      
+    case NT_uint16:
+      {
+        const PN_uint16 *pi = (const PN_uint16 *)pointer;
+        _v4.set(pi[0], pi[1], pi[2], pi[3]);
+      }
+      return _v4;
+      
+    case NT_uint32:
+      {
+        const PN_uint32 *pi = (const PN_uint32 *)pointer;
+        _v4.set(pi[0], pi[1], pi[2], pi[3]);
+      }
+      return _v4;
+      
+    case NT_packed_dcba:
+      {
+        PN_uint32 dword = *(const PN_uint32 *)pointer;
+        maybe_scale_color(qpGeomVertexData::unpack_abcd_d(dword),
+                          qpGeomVertexData::unpack_abcd_c(dword),
+                          qpGeomVertexData::unpack_abcd_b(dword),
+                          qpGeomVertexData::unpack_abcd_a(dword));
+      }
+      return _v4;
+      
+    case NT_packed_dabc:
+      {
+        PN_uint32 dword = *(const PN_uint32 *)pointer;
+        maybe_scale_color(qpGeomVertexData::unpack_abcd_b(dword),
+                          qpGeomVertexData::unpack_abcd_c(dword),
+                          qpGeomVertexData::unpack_abcd_d(dword),
+                          qpGeomVertexData::unpack_abcd_a(dword));
+      }
+      return _v4;
+      
+    case NT_float32:
+      {
+        const PN_float32 *pi = (const PN_float32 *)pointer;
+        _v4.set(pi[0], pi[1], pi[2], pi[3]);
+      }
+      return _v4;
+    }
+  }
+
+  return _v4;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer_point::set_data1f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexColumn::Packer_point::
+set_data1f(unsigned char *pointer, float data) {
+  if (_column->get_num_values() == 4) {
+    set_data4f(pointer, LVecBase4f(data, 0.0f, 0.0f, 1.0f));
+  } else {
+    Packer::set_data1f(pointer, data);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer_point::set_data2f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexColumn::Packer_point::
+set_data2f(unsigned char *pointer, const LVecBase2f &data) {
+  if (_column->get_num_values() == 4) {
+    set_data4f(pointer, LVecBase4f(data[0], data[1], 0.0f, 1.0f));
+  } else {
+    Packer::set_data2f(pointer, data);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer_point::set_data3f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexColumn::Packer_point::
+set_data3f(unsigned char *pointer, const LVecBase3f &data) {
+  if (_column->get_num_values() == 4) {
+    set_data4f(pointer, LVecBase4f(data[0], data[1], data[2], 1.0f));
+  } else {
+    Packer::set_data3f(pointer, data);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer_point::set_data4f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexColumn::Packer_point::
+set_data4f(unsigned char *pointer, const LVecBase4f &data) {
+  switch (_column->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 (_column->get_numeric_type()) {
+    case NT_uint8:
+      maybe_unscale_color(data);
+      pointer[0] = _a;
+      pointer[1] = _b;
+      pointer[2] = _c;
+      pointer[3] = _d;
+      break;
+
+    case 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 NT_uint32:
+      {
+        PN_uint32 *pi = (PN_uint32 *)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 NT_packed_dcba:
+      maybe_unscale_color(data);
+      *(PN_uint32 *)pointer = qpGeomVertexData::pack_abcd(_d, _c, _b, _a);
+      break;
+      
+    case NT_packed_dabc:
+      maybe_unscale_color(data);
+      *(PN_uint32 *)pointer = qpGeomVertexData::pack_abcd(_d, _a, _b, _c);
+      break;
+      
+    case 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: qpGeomVertexColumn::Packer_color::get_data4f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase4f &qpGeomVertexColumn::Packer_color::
+get_data4f(const unsigned char *pointer) {
+  switch (_column->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 (_column->get_numeric_type()) {
+    case NT_uint8:
+      maybe_scale_color(pointer[0], pointer[1], pointer[2], pointer[3]);
+      return _v4;
+      
+    case NT_uint16:
+      {
+        const PN_uint16 *pi = (const PN_uint16 *)pointer;
+        _v4.set(pi[0], pi[1], pi[2], pi[3]);
+      }
+      return _v4;
+      
+    case NT_uint32:
+      {
+        const PN_uint32 *pi = (const PN_uint32 *)pointer;
+        _v4.set(pi[0], pi[1], pi[2], pi[3]);
+      }
+      return _v4;
+      
+    case NT_packed_dcba:
+      {
+        PN_uint32 dword = *(const PN_uint32 *)pointer;
+        maybe_scale_color(qpGeomVertexData::unpack_abcd_d(dword),
+                          qpGeomVertexData::unpack_abcd_c(dword),
+                          qpGeomVertexData::unpack_abcd_b(dword),
+                          qpGeomVertexData::unpack_abcd_a(dword));
+      }
+      return _v4;
+      
+    case NT_packed_dabc:
+      {
+        PN_uint32 dword = *(const PN_uint32 *)pointer;
+        maybe_scale_color(qpGeomVertexData::unpack_abcd_b(dword),
+                          qpGeomVertexData::unpack_abcd_c(dword),
+                          qpGeomVertexData::unpack_abcd_d(dword),
+                          qpGeomVertexData::unpack_abcd_a(dword));
+      }
+      return _v4;
+      
+    case NT_float32:
+      {
+        const PN_float32 *pi = (const PN_float32 *)pointer;
+        _v4.set(pi[0], pi[1], pi[2], pi[3]);
+      }
+      return _v4;
+    }
+  }
+
+  return _v4;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer_color::set_data1f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexColumn::Packer_color::
+set_data1f(unsigned char *pointer, float data) {
+  if (_column->get_num_values() == 4) {
+    set_data4f(pointer, LVecBase4f(data, 0.0f, 0.0f, 1.0f));
+  } else {
+    Packer::set_data1f(pointer, data);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer_color::set_data2f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexColumn::Packer_color::
+set_data2f(unsigned char *pointer, const LVecBase2f &data) {
+  if (_column->get_num_values() == 4) {
+    set_data4f(pointer, LVecBase4f(data[0], data[1], 0.0f, 1.0f));
+  } else {
+    Packer::set_data2f(pointer, data);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer_color::set_data3f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexColumn::Packer_color::
+set_data3f(unsigned char *pointer, const LVecBase3f &data) {
+  if (_column->get_num_values() == 4) {
+    set_data4f(pointer, LVecBase4f(data[0], data[1], data[2], 1.0f));
+  } else {
+    Packer::set_data3f(pointer, data);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer_float32_3::get_data3f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase3f &qpGeomVertexColumn::Packer_float32_3::
+get_data3f(const unsigned char *pointer) {
+  const PN_float32 *pi = (const PN_float32 *)pointer;
+  _v3.set(pi[0], pi[1], pi[2]);
+  return _v3;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer_float32_3::set_data3f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexColumn::Packer_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: qpGeomVertexColumn::Packer_point_float32_2::get_data2f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase2f &qpGeomVertexColumn::Packer_point_float32_2::
+get_data2f(const unsigned char *pointer) {
+  const PN_float32 *pi = (const PN_float32 *)pointer;
+  _v2.set(pi[0], pi[1]);
+  return _v2;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer_point_float32_2::set_data2f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexColumn::Packer_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: qpGeomVertexColumn::Packer_point_float32_3::get_data3f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase3f &qpGeomVertexColumn::Packer_point_float32_3::
+get_data3f(const unsigned char *pointer) {
+  const PN_float32 *pi = (const PN_float32 *)pointer;
+  _v3.set(pi[0], pi[1], pi[2]);
+  return _v3;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer_point_float32_3::set_data3f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexColumn::Packer_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: qpGeomVertexColumn::Packer_point_float32_4::get_data4f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase4f &qpGeomVertexColumn::Packer_point_float32_4::
+get_data4f(const unsigned char *pointer) {
+  const PN_float32 *pi = (const PN_float32 *)pointer;
+  _v4.set(pi[0], pi[1], pi[2], pi[3]);
+  return _v4;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer_point_float32_4::set_data4f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexColumn::Packer_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: qpGeomVertexColumn::Packer_nativefloat_3::get_data3f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase3f &qpGeomVertexColumn::Packer_nativefloat_3::
+get_data3f(const unsigned char *pointer) {
+  return *(const LVecBase3f *)pointer;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer_point_nativefloat_2::get_data2f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase2f &qpGeomVertexColumn::Packer_point_nativefloat_2::
+get_data2f(const unsigned char *pointer) {
+  return *(const LVecBase2f *)pointer;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer_point_nativefloat_3::get_data3f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase3f &qpGeomVertexColumn::Packer_point_nativefloat_3::
+get_data3f(const unsigned char *pointer) {
+  return *(const LVecBase3f *)pointer;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer_point_nativefloat_4::get_data4f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase4f &qpGeomVertexColumn::Packer_point_nativefloat_4::
+get_data4f(const unsigned char *pointer) {
+  return *(const LVecBase4f *)pointer;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer_argb_packed::get_data4f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase4f &qpGeomVertexColumn::Packer_argb_packed::
+get_data4f(const unsigned char *pointer) {
+  PN_uint32 dword = *(const PN_uint32 *)pointer;
+  _v4.set((float)qpGeomVertexData::unpack_abcd_b(dword) / 255.0f,
+          (float)qpGeomVertexData::unpack_abcd_c(dword) / 255.0f,
+          (float)qpGeomVertexData::unpack_abcd_d(dword) / 255.0f,
+          (float)qpGeomVertexData::unpack_abcd_a(dword) / 255.0f);
+  return _v4;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer_argb_packed::set_data4f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexColumn::Packer_argb_packed::
+set_data4f(unsigned char *pointer, const LVecBase4f &data) {
+  *(PN_uint32 *)pointer = qpGeomVertexData::pack_abcd
+    ((unsigned int)(data[3] * 255.0f),
+     (unsigned int)(data[0] * 255.0f),
+     (unsigned int)(data[1] * 255.0f),
+     (unsigned int)(data[2] * 255.0f));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer_rgba_uint8_4::get_data4f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase4f &qpGeomVertexColumn::Packer_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: qpGeomVertexColumn::Packer_rgba_uint8_4::set_data4f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexColumn::Packer_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: qpGeomVertexColumn::Packer_rgba_float32_4::get_data4f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase4f &qpGeomVertexColumn::Packer_rgba_float32_4::
+get_data4f(const unsigned char *pointer) {
+  const PN_float32 *pi = (const PN_float32 *)pointer;
+  _v4.set(pi[0], pi[1], pi[2], pi[3]);
+  return _v4;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer_rgba_float32_4::set_data4f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexColumn::Packer_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: qpGeomVertexColumn::Packer_rgba_nativefloat_4::get_data4f
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const LVecBase4f &qpGeomVertexColumn::Packer_rgba_nativefloat_4::
+get_data4f(const unsigned char *pointer) {
+  return *(const LVecBase4f *)pointer;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer_uint16_1::get_data1i
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+int qpGeomVertexColumn::Packer_uint16_1::
+get_data1i(const unsigned char *pointer) {
+  return *(const PN_uint16 *)pointer;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexColumn::Packer_uint16_1::set_data1i
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexColumn::Packer_uint16_1::
+set_data1i(unsigned char *pointer, int data) {
+  *(PN_uint16 *)pointer = data;
+  nassertv(*(PN_uint16 *)pointer == data);
+}

+ 165 - 1
panda/src/gobj/qpgeomVertexColumn.h

@@ -23,6 +23,7 @@
 #include "qpgeomEnums.h"
 #include "internalName.h"
 #include "pointerTo.h"
+#include "luse.h"
 
 class TypedWritable;
 class BamWriter;
@@ -30,6 +31,9 @@ class BamReader;
 class Datagram;
 class DatagramIterator;
 
+class qpGeomVertexReader;
+class qpGeomVertexWriter;
+
 ////////////////////////////////////////////////////////////////////
 //       Class : qpGeomVertexColumn
 // Description : This defines how a single column is interleaved
@@ -48,7 +52,8 @@ PUBLISHED:
                             NumericType numeric_type, Contents contents,
                             int start);
   INLINE qpGeomVertexColumn(const qpGeomVertexColumn &copy);
-  INLINE void operator = (const qpGeomVertexColumn &copy);
+  void operator = (const qpGeomVertexColumn &copy);
+  INLINE ~qpGeomVertexColumn();
 
   INLINE const InternalName *get_name() const;
   INLINE int get_num_components() const;
@@ -75,7 +80,10 @@ public:
   INLINE bool operator < (const qpGeomVertexColumn &other) const;
 
 private:
+  class Packer;
+
   void setup();
+  Packer *make_packer() const;
 
 public:
   void write_datagram(BamWriter *manager, Datagram &dg);
@@ -91,8 +99,164 @@ private:
   int _start;
   int _component_bytes;
   int _total_bytes;
+  Packer *_packer;
+
+  // This nested class provides the implementation for packing and
+  // 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 Packer {
+  public:
+    virtual ~Packer();
+    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);
+    virtual int get_data1i(const unsigned char *pointer);
+    virtual const int *get_data2i(const unsigned char *pointer);
+    virtual const int *get_data3i(const unsigned char *pointer);
+    virtual const int *get_data4i(const unsigned char *pointer);
+
+    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 a);
+    virtual void set_data2i(unsigned char *pointer, int a, int b);
+    virtual void set_data3i(unsigned char *pointer, int a, int b, int c);
+    virtual void set_data4i(unsigned char *pointer, int a, int b, int c, int d);
+
+    INLINE float maybe_scale_color(unsigned int value);
+    INLINE void maybe_scale_color(unsigned int a, unsigned int b);
+    INLINE void maybe_scale_color(unsigned int a, unsigned int b,
+                                  unsigned int c);
+    INLINE void maybe_scale_color(unsigned int a, unsigned int b,
+                                  unsigned int c, unsigned int d);
+
+    INLINE unsigned int maybe_unscale_color(float data);
+    INLINE void maybe_unscale_color(const LVecBase2f &data);
+    INLINE void maybe_unscale_color(const LVecBase3f &data);
+    INLINE void maybe_unscale_color(const LVecBase4f &data);
+
+    const qpGeomVertexColumn *_column;
+    LVecBase2f _v2;
+    LVecBase3f _v3;
+    LVecBase4f _v4;
+    int _i[4];
+    unsigned int _a, _b, _c, _d;
+  };
+
+
+  // This is a specialization on the generic Packer that handles
+  // 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 Packer_point : public Packer {
+  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);
+    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 Packer_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 Packer_color : public Packer {
+  public:
+    virtual const LVecBase4f &get_data4f(const unsigned char *pointer);
+    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 Packer that handle
+  // the direct code paths.
+
+  class Packer_float32_3 : public Packer {
+  public:
+    virtual const LVecBase3f &get_data3f(const unsigned char *pointer);
+    virtual void set_data3f(unsigned char *pointer, const LVecBase3f &value);
+  };
+
+  class Packer_point_float32_2 : public Packer_point {
+  public:
+    virtual const LVecBase2f &get_data2f(const unsigned char *pointer);
+    virtual void set_data2f(unsigned char *pointer, const LVecBase2f &value);
+  };
+
+  class Packer_point_float32_3 : public Packer_point {
+  public:
+    virtual const LVecBase3f &get_data3f(const unsigned char *pointer);
+    virtual void set_data3f(unsigned char *pointer, const LVecBase3f &value);
+  };
+
+  class Packer_point_float32_4 : public Packer_point {
+  public:
+    virtual const LVecBase4f &get_data4f(const unsigned char *pointer);
+    virtual void set_data4f(unsigned char *pointer, const LVecBase4f &value);
+  };
+
+  class Packer_nativefloat_3 : public Packer_float32_3 {
+  public:
+    virtual const LVecBase3f &get_data3f(const unsigned char *pointer);
+  };
+
+  class Packer_point_nativefloat_2 : public Packer_point_float32_2 {
+  public:
+    virtual const LVecBase2f &get_data2f(const unsigned char *pointer);
+  };
+
+  class Packer_point_nativefloat_3 : public Packer_point_float32_3 {
+  public:
+    virtual const LVecBase3f &get_data3f(const unsigned char *pointer);
+  };
+
+  class Packer_point_nativefloat_4 : public Packer_point_float32_4 {
+  public:
+    virtual const LVecBase4f &get_data4f(const unsigned char *pointer);
+  };
+
+  class Packer_argb_packed : public Packer_color {
+  public:
+    virtual const LVecBase4f &get_data4f(const unsigned char *pointer);
+    virtual void set_data4f(unsigned char *pointer, const LVecBase4f &value);
+  };
+
+  class Packer_rgba_uint8_4 : public Packer_color {
+  public:
+    virtual const LVecBase4f &get_data4f(const unsigned char *pointer);
+    virtual void set_data4f(unsigned char *pointer, const LVecBase4f &value);
+  };
+
+  class Packer_rgba_float32_4 : public Packer_color {
+  public:
+    virtual const LVecBase4f &get_data4f(const unsigned char *pointer);
+    virtual void set_data4f(unsigned char *pointer, const LVecBase4f &value);
+  };
+
+  class Packer_rgba_nativefloat_4 : public Packer_rgba_float32_4 {
+  public:
+    virtual const LVecBase4f &get_data4f(const unsigned char *pointer);
+  };
+
+  class Packer_uint16_1 : public Packer {
+  public:
+    virtual int get_data1i(const unsigned char *pointer);
+    virtual void set_data1i(unsigned char *pointer, int value);
+  };
 
   friend class qpGeomVertexArrayFormat;
+  friend class qpGeomVertexReader;
+  friend class qpGeomVertexWriter;
 };
 
 INLINE ostream &operator << (ostream &out, const qpGeomVertexColumn &obj);

+ 37 - 125
panda/src/gobj/qpgeomVertexReader.I

@@ -95,10 +95,6 @@ qpGeomVertexReader(const qpGeomVertexArrayData *array_data, int column) :
 ////////////////////////////////////////////////////////////////////
 INLINE qpGeomVertexReader::
 ~qpGeomVertexReader() {
-  if (_reader != (Reader *)NULL) {
-    delete _reader;
-    _reader = NULL;
-  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -202,7 +198,7 @@ set_column(const InternalName *name) {
 ////////////////////////////////////////////////////////////////////
 INLINE bool qpGeomVertexReader::
 has_column() const {
-  return (_column != (qpGeomVertexColumn *)NULL);
+  return (_packer != (qpGeomVertexColumn::Packer *)NULL);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -224,7 +220,10 @@ get_array() const {
 ////////////////////////////////////////////////////////////////////
 INLINE const qpGeomVertexColumn *qpGeomVertexReader::
 get_column() const {
-  return _column;
+  if (_packer != (qpGeomVertexColumn::Packer *)NULL) {
+    return _packer->_column;
+  }
+  return NULL;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -237,7 +236,7 @@ get_column() const {
 INLINE void qpGeomVertexReader::
 set_vertex(int vertex) {
   _start_vertex = vertex;
-  if (_column != (qpGeomVertexColumn *)NULL) {
+  if (has_column()) {
     set_pointer(_start_vertex);
   }
 }
@@ -254,28 +253,6 @@ get_start_vertex() const {
   return _start_vertex;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexReader::get_read_vertex
-//       Access: Published
-//  Description: Returns the current read vertex index of the
-//               reader.  This is the index whose value will be
-//               returned by the next call to get_data*().
-////////////////////////////////////////////////////////////////////
-INLINE int qpGeomVertexReader::
-get_read_vertex() const {
-  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
@@ -286,7 +263,7 @@ get_num_vertices() const {
 ////////////////////////////////////////////////////////////////////
 INLINE bool qpGeomVertexReader::
 is_at_end() const {
-  return _read_vertex >= _num_vertices;
+  return _pointer >= _pointer_end;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -298,8 +275,8 @@ is_at_end() const {
 ////////////////////////////////////////////////////////////////////
 INLINE float qpGeomVertexReader::
 get_data1f() {
-  nassertr(_column != (qpGeomVertexColumn *)NULL, 0.0f);
-  return _reader->get_data1f(inc_pointer());
+  nassertr(has_column(), 0.0f);
+  return _packer->get_data1f(inc_pointer());
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -311,8 +288,8 @@ get_data1f() {
 ////////////////////////////////////////////////////////////////////
 INLINE const LVecBase2f &qpGeomVertexReader::
 get_data2f() {
-  nassertr(_column != (qpGeomVertexColumn *)NULL, LVecBase2f::zero());
-  return _reader->get_data2f(inc_pointer());
+  nassertr(has_column(), LVecBase2f::zero());
+  return _packer->get_data2f(inc_pointer());
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -324,8 +301,8 @@ get_data2f() {
 ////////////////////////////////////////////////////////////////////
 INLINE const LVecBase3f &qpGeomVertexReader::
 get_data3f() {
-  nassertr(_column != (qpGeomVertexColumn *)NULL, LVecBase3f::zero());
-  return _reader->get_data3f(inc_pointer());
+  nassertr(has_column(), LVecBase3f::zero());
+  return _packer->get_data3f(inc_pointer());
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -337,8 +314,8 @@ get_data3f() {
 ////////////////////////////////////////////////////////////////////
 INLINE const LVecBase4f &qpGeomVertexReader::
 get_data4f() {
-  nassertr(_column != (qpGeomVertexColumn *)NULL, LVecBase4f::zero());
-  return _reader->get_data4f(inc_pointer());
+  nassertr(has_column(), LVecBase4f::zero());
+  return _packer->get_data4f(inc_pointer());
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -350,8 +327,8 @@ get_data4f() {
 ////////////////////////////////////////////////////////////////////
 INLINE int qpGeomVertexReader::
 get_data1i() {
-  nassertr(_column != (qpGeomVertexColumn *)NULL, 0);
-  return _reader->get_data1i(inc_pointer());
+  nassertr(has_column(), 0);
+  return _packer->get_data1i(inc_pointer());
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -363,8 +340,8 @@ get_data1i() {
 ////////////////////////////////////////////////////////////////////
 INLINE const int *qpGeomVertexReader::
 get_data2i() {
-  nassertr(_column != (qpGeomVertexColumn *)NULL, 0);
-  return _reader->get_data2i(inc_pointer());
+  nassertr(has_column(), 0);
+  return _packer->get_data2i(inc_pointer());
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -376,8 +353,8 @@ get_data2i() {
 ////////////////////////////////////////////////////////////////////
 INLINE const int *qpGeomVertexReader::
 get_data3i() {
-  nassertr(_column != (qpGeomVertexColumn *)NULL, 0);
-  return _reader->get_data3i(inc_pointer());
+  nassertr(has_column(), 0);
+  return _packer->get_data3i(inc_pointer());
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -389,8 +366,8 @@ get_data3i() {
 ////////////////////////////////////////////////////////////////////
 INLINE const int *qpGeomVertexReader::
 get_data4i() {
-  nassertr(_column != (qpGeomVertexColumn *)NULL, 0);
-  return _reader->get_data4i(inc_pointer());
+  nassertr(has_column(), 0);
+  return _packer->get_data4i(inc_pointer());
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -401,13 +378,18 @@ get_data4i() {
 ////////////////////////////////////////////////////////////////////
 INLINE void qpGeomVertexReader::
 set_pointer(int vertex) {
-  nassertv(_column != (qpGeomVertexColumn *)NULL);
-  _read_vertex = vertex;
+  nassertv(has_column());
   if (_vertex_data != (const qpGeomVertexData *)NULL) {
-    _array_data = _vertex_data->get_array(_array);
+    const qpGeomVertexArrayData *array_data = _vertex_data->get_array(_array);
+    _pointer = array_data->get_data();
+    _pointer_end = _pointer + array_data->get_data_size_bytes();
+    _pointer += _packer->_column->get_start() + _stride * vertex;
+
+  } else {
+    _pointer = _array_data->get_data();
+    _pointer_end = _pointer + _array_data->get_data_size_bytes();
+    _pointer += _packer->_column->get_start() + _stride * vertex;
   }
-  _pointer = _array_data->get_data() + _column->get_start() + _stride * _read_vertex;
-  _num_vertices = _array_data->get_num_vertices();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -419,86 +401,16 @@ set_pointer(int vertex) {
 INLINE const unsigned char *qpGeomVertexReader::
 inc_pointer() {
 #ifndef NDEBUG
-  nassertr(_read_vertex < _num_vertices, empty_buffer);
+  nassertr(_pointer < _pointer_end, empty_buffer);
   if (_vertex_data != (const qpGeomVertexData *)NULL){ 
-    nassertr(_pointer == _vertex_data->get_array(_array)->get_data() + _column->get_start() + _stride * _read_vertex, empty_buffer);
+    const qpGeomVertexArrayData *array_data = _vertex_data->get_array(_array);
+    nassertr(_pointer >= array_data->get_data() && _pointer < array_data->get_data() + array_data->get_data_size_bytes(), empty_buffer);
   } else {
-    nassertr(_pointer == _array_data->get_data() + _column->get_start() + _stride * _read_vertex, empty_buffer);
+    nassertr(_pointer >= _array_data->get_data() && _pointer < _array_data->get_data() + _array_data->get_data_size_bytes(), empty_buffer);
   }
 #endif
 
   const unsigned char *orig_pointer = _pointer;
   _pointer += _stride;
-  ++_read_vertex;
   return orig_pointer;
 }
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexReader::Reader::maybe_scale_color
-//       Access: Public
-//  Description: Converts an integer (typically a uint8) value to a
-//               floating-point value.  If the contents value
-//               indicates this is a color value, scales it into the
-//               range 0..1 per convention; otherwise leaves it alone.
-////////////////////////////////////////////////////////////////////
-INLINE float qpGeomVertexReader::Reader::
-maybe_scale_color(unsigned int value) {
-  if (_column->get_contents() == C_color) {
-    return (float)value / 255.0f;
-  } else {
-    return (float)value;
-  }
-}
-    
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexReader::Reader::maybe_scale_color
-//       Access: Public
-//  Description: Converts a pair of integers into the _v2 member.  See
-//               one-parameter maybe_scale_color() for more info.
-////////////////////////////////////////////////////////////////////
-INLINE void qpGeomVertexReader::Reader::
-maybe_scale_color(unsigned int a, unsigned int b) {
-  if (_column->get_contents() == C_color) {
-    _v2.set((float)a / 255.0f,
-            (float)b / 255.0f);
-  } else {    
-    _v2.set((float)a, (float)b);
-  }
-}
-    
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexReader::Reader::maybe_scale_color
-//       Access: Public
-//  Description: Converts a pair of integers into the _v3 member.  See
-//               one-parameter maybe_scale_color() for more info.
-////////////////////////////////////////////////////////////////////
-INLINE void qpGeomVertexReader::Reader::
-maybe_scale_color(unsigned int a, unsigned int b, unsigned int c) {
-  if (_column->get_contents() == C_color) {
-    _v3.set((float)a / 255.0f,
-            (float)b / 255.0f,
-            (float)c / 255.0f);
-  } else {    
-    _v3.set((float)a, (float)b, (float)c);
-  }
-}
-    
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexReader::Reader::maybe_scale_color
-//       Access: Public
-//  Description: Converts a pair of integers into the _v4 member.  See
-//               one-parameter maybe_scale_color() for more info.
-////////////////////////////////////////////////////////////////////
-INLINE void qpGeomVertexReader::Reader::
-maybe_scale_color(unsigned int a, unsigned int b, unsigned int c,
-                  unsigned int d) {
-  if (_column->get_contents() == C_color) {
-    _v4.set((float)a / 255.0f,
-            (float)b / 255.0f,
-            (float)c / 255.0f,
-            (float)d / 255.0f);
-  } else {
-    _v4.set((float)a, (float)b, (float)c, (float)d);
-  }
-}
-    

+ 23 - 1027
panda/src/gobj/qpgeomVertexReader.cxx

@@ -46,45 +46,36 @@ set_column(int array, const qpGeomVertexColumn *column) {
     return false;
   }
 
-  // Delete the old reader, if we've got one.
-  if (_reader != (Reader *)NULL) {
-    delete _reader;
-    _reader = NULL;
-  }
-
-  int num_arrays = 1;
-  if (_vertex_data != (const qpGeomVertexData *)NULL) {
-    num_arrays = _vertex_data->get_num_arrays();
-  }
-
-  if (array < 0 || array >= num_arrays || 
-      column == (const qpGeomVertexColumn *)NULL) {
+  if (column == (const qpGeomVertexColumn *)NULL) {
     // Clear the data type.
     _array = -1;
-    _column = NULL;
+    _packer = NULL;
     _stride = 0;
-    _read_vertex = _start_vertex;
-    _num_vertices = 0;
+    _pointer = NULL;
+    _pointer_end = NULL;
 
     return false;
+  }
 
-  } else {
+  if (_vertex_data != (const qpGeomVertexData *)NULL) {
+#ifndef NDEBUG
+    _array = -1;
+    _packer = NULL;
+    nassertr(array >= 0 && array < _vertex_data->get_num_arrays(), false);
+#endif
     _array = array;
-    _column = column;
-    if (_vertex_data != (const qpGeomVertexData *)NULL) {
-      _stride = _vertex_data->get_format()->get_array(_array)->get_stride();
-    } else {
-      _stride = _array_data->get_array_format()->get_stride();
-    }
-
-    set_pointer(_start_vertex);
+    const qpGeomVertexArrayData *array_data =_vertex_data->get_array(_array);
+    _stride = array_data->get_array_format()->get_stride();
 
-    // Now set up a new reader.
-    _reader = make_reader();
-    _reader->_column = _column;
-
-    return true;
+  } else {
+    _stride = _array_data->get_array_format()->get_stride();
   }
+
+  _packer = column->_packer;
+  
+  set_pointer(_start_vertex);
+  
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -95,1003 +86,8 @@ set_column(int array, const qpGeomVertexColumn *column) {
 void qpGeomVertexReader::
 initialize() {
   _array = 0;
-  _column = NULL;
+  _packer = NULL;
   _pointer = NULL;
+  _pointer_end = NULL;
   _start_vertex = 0;
-  _read_vertex = 0;
-  _num_vertices = 0;
-  _reader = NULL;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexReader::make_reader
-//       Access: Private
-//  Description: Returns a newly-allocated Reader object suitable for
-//               reading the current data type.
-////////////////////////////////////////////////////////////////////
-qpGeomVertexReader::Reader *qpGeomVertexReader::
-make_reader() const {
-  switch (_column->get_contents()) {
-  case C_point:
-  case C_clip_point:
-  case C_texcoord:
-    // These types are read as a 4-d homogeneous point.
-    switch (_column->get_numeric_type()) {
-    case NT_float32:
-      if (sizeof(float) == sizeof(PN_float32)) {
-        // Use the native float type implementation for a tiny bit
-        // more optimization.
-        switch (_column->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 (_column->get_num_components()) {
-        case 2:
-          return new Reader_point_float32_2;
-        case 3:
-          return new Reader_point_float32_3;
-        case 4:
-          return new Reader_point_float32_4;
-        }
-      }
-      break;
-    default:
-      break;
-    }
-    return new Reader_point;
-
-  case C_color:
-    switch (_column->get_numeric_type()) {
-    case NT_uint8:
-      switch (_column->get_num_components()) {
-      case 4:
-        return new Reader_rgba_uint8_4;
-        
-      default:
-        break;
-      }
-      break;
-    case NT_packed_dabc:
-      switch (_column->get_num_components()) {
-      case 1:
-        return new Reader_argb_packed;
-        
-      default:
-        break;
-      }
-      break;
-    case NT_float32:
-      switch (_column->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;
-
-  default:
-    // Otherwise, we just read it as a generic value.
-    switch (_column->get_numeric_type()) {
-    case NT_float32:
-      switch (_column->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:
-      break;
-    }
-    return new Reader;
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexReader::Reader::Destructor
-//       Access: Public, Virtual
-//  Description: 
-////////////////////////////////////////////////////////////////////
-qpGeomVertexReader::Reader::
-~Reader() {
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexReader::Reader::get_data1f
-//       Access: Public, Virtual
-//  Description: 
-////////////////////////////////////////////////////////////////////
-float qpGeomVertexReader::Reader::
-get_data1f(const unsigned char *pointer) {
-  switch (_column->get_numeric_type()) {
-  case NT_uint8:
-    return maybe_scale_color(*pointer);
-
-  case NT_uint16:
-    return *(const PN_uint16 *)pointer;
-
-  case NT_uint32:
-    return *(const PN_uint32 *)pointer;
-
-  case NT_packed_dcba:
-    {
-      PN_uint32 dword = *(const PN_uint32 *)pointer;
-      return maybe_scale_color(qpGeomVertexData::unpack_abcd_d(dword));
-    }
-
-  case NT_packed_dabc:
-    {
-      PN_uint32 dword = *(const PN_uint32 *)pointer;
-      return maybe_scale_color(qpGeomVertexData::unpack_abcd_b(dword));
-    }
-
-  case NT_float32:
-    return *(const PN_float32 *)pointer;
-  }
-
-  return 0.0f;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexReader::Reader::get_data2f
-//       Access: Public, Virtual
-//  Description: 
-////////////////////////////////////////////////////////////////////
-const LVecBase2f &qpGeomVertexReader::Reader::
-get_data2f(const unsigned char *pointer) {
-  if (_column->get_num_values() == 1) {
-    _v2.set(get_data1i(pointer), 0.0f);
-    return _v2;
-
-  } else {
-    switch (_column->get_numeric_type()) {
-    case NT_uint8:
-      maybe_scale_color(pointer[0], pointer[1]);
-      return _v2;
-      
-    case NT_uint16:
-      {
-        const PN_uint16 *pi = (const PN_uint16 *)pointer;
-        _v2.set(pi[0], pi[1]);
-      }
-      return _v2;
-      
-    case NT_uint32:
-      {
-        const PN_uint32 *pi = (const PN_uint32 *)pointer;
-        _v2.set(pi[0], pi[1]);
-      }
-      return _v2;
-      
-    case NT_packed_dcba:
-      {
-        PN_uint32 dword = *(const PN_uint32 *)pointer;
-        maybe_scale_color(qpGeomVertexData::unpack_abcd_d(dword),
-                          qpGeomVertexData::unpack_abcd_c(dword));
-      }
-      return _v2;
-      
-    case NT_packed_dabc:
-      {
-        PN_uint32 dword = *(const PN_uint32 *)pointer;
-        maybe_scale_color(qpGeomVertexData::unpack_abcd_b(dword),
-                          qpGeomVertexData::unpack_abcd_c(dword));
-      }
-      return _v2;
-      
-    case NT_float32:
-      {
-        const PN_float32 *pi = (const PN_float32 *)pointer;
-        _v2.set(pi[0], pi[1]);
-      }
-      return _v2;
-    }
-  }
-
-  return _v2;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexReader::Reader::get_data3f
-//       Access: Public, Virtual
-//  Description: 
-////////////////////////////////////////////////////////////////////
-const LVecBase3f &qpGeomVertexReader::Reader::
-get_data3f(const unsigned char *pointer) {
-  switch (_column->get_num_values()) {
-  case 1:
-    _v3.set(get_data1f(pointer), 0.0f, 0.0f);
-    return _v3;
-
-  case 2:
-    {
-      const LVecBase2f &v2 = get_data2f(pointer);
-      _v3.set(v2[0], v2[1], 0.0f);
-    }
-    return _v3;
-
-  default:
-    switch (_column->get_numeric_type()) {
-    case NT_uint8:
-      maybe_scale_color(pointer[0], pointer[1], pointer[2]);
-      return _v3;
-      
-    case NT_uint16:
-      {
-        const PN_uint16 *pi = (const PN_uint16 *)pointer;
-        _v3.set(pi[0], pi[1], pi[2]);
-      }
-      return _v3;
-      
-    case NT_uint32:
-      {
-        const PN_uint32 *pi = (const PN_uint32 *)pointer;
-        _v3.set(pi[0], pi[1], pi[2]);
-      }
-      return _v3;
-      
-    case NT_packed_dcba:
-      {
-        PN_uint32 dword = *(const PN_uint32 *)pointer;
-        maybe_scale_color(qpGeomVertexData::unpack_abcd_d(dword),
-                          qpGeomVertexData::unpack_abcd_c(dword),
-                          qpGeomVertexData::unpack_abcd_b(dword));
-      }
-      return _v3;
-      
-    case NT_packed_dabc:
-      {
-        PN_uint32 dword = *(const PN_uint32 *)pointer;
-        maybe_scale_color(qpGeomVertexData::unpack_abcd_b(dword),
-                          qpGeomVertexData::unpack_abcd_c(dword),
-                          qpGeomVertexData::unpack_abcd_d(dword));
-      }
-      return _v3;
-      
-    case NT_float32:
-      {
-        const PN_float32 *pi = (const PN_float32 *)pointer;
-        _v3.set(pi[0], pi[1], pi[2]);
-      }
-      return _v3;
-    }
-  }
-
-  return _v3;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexReader::Reader::get_data4f
-//       Access: Public, Virtual
-//  Description: 
-////////////////////////////////////////////////////////////////////
-const LVecBase4f &qpGeomVertexReader::Reader::
-get_data4f(const unsigned char *pointer) {
-  switch (_column->get_num_values()) {
-  case 1:
-    _v4.set(get_data1i(pointer), 0.0f, 0.0f, 0.0f);
-    return _v4;
-
-  case 2:
-    {
-      const LVecBase2f &v2 = get_data2f(pointer);
-      _v4.set(v2[0], v2[1], 0.0f, 0.0f);
-    }
-    return _v4;
-
-  case 3:
-    {
-      const LVecBase3f &v3 = get_data3f(pointer);
-      _v4.set(v3[0], v3[1], v3[2], 0.0f);
-    }
-    return _v4;
-
-  default:
-    switch (_column->get_numeric_type()) {
-    case NT_uint8:
-      maybe_scale_color(pointer[0], pointer[1], pointer[2], pointer[3]);
-      return _v4;
-      
-    case NT_uint16:
-      {
-        const PN_uint16 *pi = (const PN_uint16 *)pointer;
-        _v4.set(pi[0], pi[1], pi[2], pi[3]);
-      }
-      return _v4;
-      
-    case NT_uint32:
-      {
-        const PN_uint32 *pi = (const PN_uint32 *)pointer;
-        _v4.set(pi[0], pi[1], pi[2], pi[3]);
-      }
-      return _v4;
-      
-    case NT_packed_dcba:
-      {
-        PN_uint32 dword = *(const PN_uint32 *)pointer;
-        maybe_scale_color(qpGeomVertexData::unpack_abcd_d(dword),
-                          qpGeomVertexData::unpack_abcd_c(dword),
-                          qpGeomVertexData::unpack_abcd_b(dword),
-                          qpGeomVertexData::unpack_abcd_a(dword));
-      }
-      return _v4;
-      
-    case NT_packed_dabc:
-      {
-        PN_uint32 dword = *(const PN_uint32 *)pointer;
-        maybe_scale_color(qpGeomVertexData::unpack_abcd_b(dword),
-                          qpGeomVertexData::unpack_abcd_c(dword),
-                          qpGeomVertexData::unpack_abcd_d(dword),
-                          qpGeomVertexData::unpack_abcd_a(dword));
-      }
-      return _v4;
-      
-    case NT_float32:
-      {
-        const PN_float32 *pi = (const PN_float32 *)pointer;
-        _v4.set(pi[0], pi[1], pi[2], pi[3]);
-      }
-      return _v4;
-    }
-  }
-
-  return _v4;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexReader::Reader::get_data1i
-//       Access: Public, Virtual
-//  Description: 
-////////////////////////////////////////////////////////////////////
-int qpGeomVertexReader::Reader::
-get_data1i(const unsigned char *pointer) {
-  switch (_column->get_numeric_type()) {
-  case NT_uint8:
-    return *pointer;
-
-  case NT_uint16:
-    return *(const PN_uint16 *)pointer;
-
-  case NT_uint32:
-    return *(const PN_uint32 *)pointer;
-
-  case NT_packed_dcba:
-    {
-      PN_uint32 dword = *(const PN_uint32 *)pointer;
-      return qpGeomVertexData::unpack_abcd_d(dword);
-    }
-    break;
-
-  case NT_packed_dabc:
-    {
-      PN_uint32 dword = *(const PN_uint32 *)pointer;
-      return qpGeomVertexData::unpack_abcd_b(dword);
-    }
-    break;
-
-  case NT_float32:
-    return (int)*(const PN_float32 *)pointer;
-  }
-
-  return 0;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexReader::Reader::get_data2i
-//       Access: Public, Virtual
-//  Description: 
-////////////////////////////////////////////////////////////////////
-const int *qpGeomVertexReader::Reader::
-get_data2i(const unsigned char *pointer) {
-  switch (_column->get_num_values()) {
-  case 1:
-    _i[0] = get_data1i(pointer);
-    _i[1] = 0;
-    return _i;
-
-  default:
-    switch (_column->get_numeric_type()) {
-    case NT_uint8:
-      _i[0] = pointer[0];
-      _i[1] = pointer[1];
-      return _i;
-      
-    case NT_uint16:
-      {
-        const PN_uint16 *pi = (const PN_uint16 *)pointer;
-        _i[0] = pi[0];
-        _i[1] = pi[1];
-      }
-      return _i;
-      
-    case NT_uint32:
-      {
-        const PN_uint32 *pi = (const PN_uint32 *)pointer;
-        _i[0] = pi[0];
-        _i[1] = pi[1];
-      }
-      return _i;
-      
-    case NT_packed_dcba:
-      {
-        PN_uint32 dword = *(const PN_uint32 *)pointer;
-        _i[0] = qpGeomVertexData::unpack_abcd_d(dword);
-        _i[1] = qpGeomVertexData::unpack_abcd_c(dword);
-      }
-      return _i;
-      
-    case NT_packed_dabc:
-      {
-        PN_uint32 dword = *(const PN_uint32 *)pointer;
-        _i[0] = qpGeomVertexData::unpack_abcd_b(dword);
-        _i[1] = qpGeomVertexData::unpack_abcd_c(dword);
-      }
-      return _i;
-      
-    case NT_float32:
-      {
-        const PN_float32 *pi = (const PN_float32 *)pointer;
-        _i[0] = (int)pi[0];
-        _i[1] = (int)pi[1];
-      }
-      return _i;
-    }
-  }
-
-  return _i;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexReader::Reader::get_data3i
-//       Access: Public, Virtual
-//  Description: 
-////////////////////////////////////////////////////////////////////
-const int *qpGeomVertexReader::Reader::
-get_data3i(const unsigned char *pointer) {
-  switch (_column->get_num_values()) {
-  case 1:
-    _i[0] = get_data1i(pointer);
-    _i[1] = 0;
-    _i[2] = 0;
-    return _i;
-
-  case 2:
-    {
-      const int *i = get_data2i(pointer);
-      _i[0] = i[0];
-      _i[1] = i[1];
-      _i[2] = 0;
-    }
-    return _i;
-
-  default:
-    switch (_column->get_numeric_type()) {
-    case NT_uint8:
-      _i[0] = pointer[0];
-      _i[1] = pointer[1];
-      _i[2] = pointer[2];
-      return _i;
-      
-    case NT_uint16:
-      {
-        const PN_uint16 *pi = (const PN_uint16 *)pointer;
-        _i[0] = pi[0];
-        _i[1] = pi[1];
-        _i[2] = pi[2];
-      }
-      return _i;
-      
-    case NT_uint32:
-      {
-        const PN_uint32 *pi = (const PN_uint32 *)pointer;
-        _i[0] = pi[0];
-        _i[1] = pi[1];
-        _i[2] = pi[2];
-      }
-      return _i;
-      
-    case NT_packed_dcba:
-      {
-        PN_uint32 dword = *(const PN_uint32 *)pointer;
-        _i[0] = qpGeomVertexData::unpack_abcd_d(dword);
-        _i[1] = qpGeomVertexData::unpack_abcd_c(dword);
-        _i[2] = qpGeomVertexData::unpack_abcd_b(dword);
-      }
-      return _i;
-      
-    case NT_packed_dabc:
-      {
-        PN_uint32 dword = *(const PN_uint32 *)pointer;
-        _i[0] = qpGeomVertexData::unpack_abcd_b(dword);
-        _i[1] = qpGeomVertexData::unpack_abcd_c(dword);
-        _i[2] = qpGeomVertexData::unpack_abcd_d(dword);
-      }
-      return _i;
-      
-    case NT_float32:
-      {
-        const PN_float32 *pi = (const PN_float32 *)pointer;
-        _i[0] = (int)pi[0];
-        _i[1] = (int)pi[1];
-        _i[2] = (int)pi[2];
-      }
-      return _i;
-    }
-  }
-
-  return _i;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexReader::Reader::get_data4i
-//       Access: Public, Virtual
-//  Description: 
-////////////////////////////////////////////////////////////////////
-const int *qpGeomVertexReader::Reader::
-get_data4i(const unsigned char *pointer) {
-  switch (_column->get_num_values()) {
-  case 1:
-    _i[0] = get_data1i(pointer);
-    _i[1] = 0;
-    _i[2] = 0;
-    _i[3] = 0;
-    return _i;
-
-  case 2:
-    {
-      const int *i = get_data2i(pointer);
-      _i[0] = i[0];
-      _i[1] = i[1];
-      _i[2] = 0;
-      _i[3] = 0;
-    }
-    return _i;
-
-  case 3:
-    {
-      const int *i = get_data3i(pointer);
-      _i[0] = i[0];
-      _i[1] = i[1];
-      _i[2] = i[2];
-      _i[3] = 0;
-    }
-    return _i;
-
-  default:
-    switch (_column->get_numeric_type()) {
-    case NT_uint8:
-      _i[0] = pointer[0];
-      _i[1] = pointer[1];
-      _i[2] = pointer[2];
-      _i[3] = pointer[3];
-      return _i;
-      
-    case NT_uint16:
-      {
-        const PN_uint16 *pi = (const PN_uint16 *)pointer;
-        _i[0] = pi[0];
-        _i[1] = pi[1];
-        _i[2] = pi[2];
-        _i[3] = pi[3];
-      }
-      return _i;
-      
-    case NT_uint32:
-      {
-        const PN_uint32 *pi = (const PN_uint32 *)pointer;
-        _i[0] = pi[0];
-        _i[1] = pi[1];
-        _i[2] = pi[2];
-        _i[3] = pi[3];
-      }
-      return _i;
-      
-    case NT_packed_dcba:
-      {
-        PN_uint32 dword = *(const PN_uint32 *)pointer;
-        _i[0] = qpGeomVertexData::unpack_abcd_d(dword);
-        _i[1] = qpGeomVertexData::unpack_abcd_c(dword);
-        _i[2] = qpGeomVertexData::unpack_abcd_b(dword);
-        _i[3] = qpGeomVertexData::unpack_abcd_a(dword);
-      }
-      return _i;
-      
-    case NT_packed_dabc:
-      {
-        PN_uint32 dword = *(const PN_uint32 *)pointer;
-        _i[0] = qpGeomVertexData::unpack_abcd_b(dword);
-        _i[1] = qpGeomVertexData::unpack_abcd_c(dword);
-        _i[2] = qpGeomVertexData::unpack_abcd_d(dword);
-        _i[3] = qpGeomVertexData::unpack_abcd_a(dword);
-      }
-      return _i;
-      
-    case NT_float32:
-      {
-        const PN_float32 *pi = (const PN_float32 *)pointer;
-        _i[0] = (int)pi[0];
-        _i[1] = (int)pi[1];
-        _i[2] = (int)pi[2];
-        _i[3] = (int)pi[3];
-      }
-      return _i;
-    }
-  }
-
-  return _i;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexReader::Reader_point::get_data1f
-//       Access: Public, Virtual
-//  Description: 
-////////////////////////////////////////////////////////////////////
-float qpGeomVertexReader::Reader_point::
-get_data1f(const unsigned char *pointer) {
-  if (_column->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 (_column->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 (_column->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
-//       Access: Public, Virtual
-//  Description: 
-////////////////////////////////////////////////////////////////////
-const LVecBase4f &qpGeomVertexReader::Reader_point::
-get_data4f(const unsigned char *pointer) {
-  switch (_column->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 (_column->get_numeric_type()) {
-    case NT_uint8:
-      maybe_scale_color(pointer[0], pointer[1], pointer[2], pointer[3]);
-      return _v4;
-      
-    case NT_uint16:
-      {
-        const PN_uint16 *pi = (const PN_uint16 *)pointer;
-        _v4.set(pi[0], pi[1], pi[2], pi[3]);
-      }
-      return _v4;
-      
-    case NT_uint32:
-      {
-        const PN_uint32 *pi = (const PN_uint32 *)pointer;
-        _v4.set(pi[0], pi[1], pi[2], pi[3]);
-      }
-      return _v4;
-      
-    case NT_packed_dcba:
-      {
-        PN_uint32 dword = *(const PN_uint32 *)pointer;
-        maybe_scale_color(qpGeomVertexData::unpack_abcd_d(dword),
-                          qpGeomVertexData::unpack_abcd_c(dword),
-                          qpGeomVertexData::unpack_abcd_b(dword),
-                          qpGeomVertexData::unpack_abcd_a(dword));
-      }
-      return _v4;
-      
-    case NT_packed_dabc:
-      {
-        PN_uint32 dword = *(const PN_uint32 *)pointer;
-        maybe_scale_color(qpGeomVertexData::unpack_abcd_b(dword),
-                          qpGeomVertexData::unpack_abcd_c(dword),
-                          qpGeomVertexData::unpack_abcd_d(dword),
-                          qpGeomVertexData::unpack_abcd_a(dword));
-      }
-      return _v4;
-      
-    case NT_float32:
-      {
-        const PN_float32 *pi = (const PN_float32 *)pointer;
-        _v4.set(pi[0], pi[1], pi[2], pi[3]);
-      }
-      return _v4;
-    }
-  }
-
-  return _v4;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexReader::Reader_color::get_data4f
-//       Access: Public, Virtual
-//  Description: 
-////////////////////////////////////////////////////////////////////
-const LVecBase4f &qpGeomVertexReader::Reader_color::
-get_data4f(const unsigned char *pointer) {
-  switch (_column->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 (_column->get_numeric_type()) {
-    case NT_uint8:
-      maybe_scale_color(pointer[0], pointer[1], pointer[2], pointer[3]);
-      return _v4;
-      
-    case NT_uint16:
-      {
-        const PN_uint16 *pi = (const PN_uint16 *)pointer;
-        _v4.set(pi[0], pi[1], pi[2], pi[3]);
-      }
-      return _v4;
-      
-    case NT_uint32:
-      {
-        const PN_uint32 *pi = (const PN_uint32 *)pointer;
-        _v4.set(pi[0], pi[1], pi[2], pi[3]);
-      }
-      return _v4;
-      
-    case NT_packed_dcba:
-      {
-        PN_uint32 dword = *(const PN_uint32 *)pointer;
-        maybe_scale_color(qpGeomVertexData::unpack_abcd_d(dword),
-                          qpGeomVertexData::unpack_abcd_c(dword),
-                          qpGeomVertexData::unpack_abcd_b(dword),
-                          qpGeomVertexData::unpack_abcd_a(dword));
-      }
-      return _v4;
-      
-    case NT_packed_dabc:
-      {
-        PN_uint32 dword = *(const PN_uint32 *)pointer;
-        maybe_scale_color(qpGeomVertexData::unpack_abcd_b(dword),
-                          qpGeomVertexData::unpack_abcd_c(dword),
-                          qpGeomVertexData::unpack_abcd_d(dword),
-                          qpGeomVertexData::unpack_abcd_a(dword));
-      }
-      return _v4;
-      
-    case NT_float32:
-      {
-        const PN_float32 *pi = (const 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) {
-  const PN_float32 *pi = (const 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) {
-  const PN_float32 *pi = (const 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) {
-  const PN_float32 *pi = (const 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) {
-  const PN_float32 *pi = (const 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) {
-  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::get_data4f
-//       Access: Public, Virtual
-//  Description: 
-////////////////////////////////////////////////////////////////////
-const LVecBase4f &qpGeomVertexReader::Reader_argb_packed::
-get_data4f(const unsigned char *pointer) {
-  PN_uint32 dword = *(const PN_uint32 *)pointer;
-  _v4.set((float)qpGeomVertexData::unpack_abcd_b(dword) / 255.0f,
-          (float)qpGeomVertexData::unpack_abcd_c(dword) / 255.0f,
-          (float)qpGeomVertexData::unpack_abcd_d(dword) / 255.0f,
-          (float)qpGeomVertexData::unpack_abcd_a(dword) / 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) {
-  const PN_float32 *pi = (const 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;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexReader::Reader_uint16_1::get_data1i
-//       Access: Public, Virtual
-//  Description: 
-////////////////////////////////////////////////////////////////////
-int qpGeomVertexReader::Reader_uint16_1::
-get_data1i(const unsigned char *pointer) {
-  return *(const PN_uint16 *)pointer;
 }

+ 9 - 131
panda/src/gobj/qpgeomVertexReader.h

@@ -86,8 +86,6 @@ PUBLISHED:
   INLINE void set_vertex(int vertex);
 
   INLINE int get_start_vertex() const;
-  INLINE int get_read_vertex() const;
-  INLINE int get_num_vertices() const;
   INLINE bool is_at_end() const;
 
   INLINE float get_data1f();
@@ -101,153 +99,33 @@ PUBLISHED:
   INLINE const int *get_data4i();
 
 private:
-  class Reader;
-
   void initialize();
 
   INLINE void set_pointer(int vertex);
   INLINE const unsigned char *inc_pointer();
-  Reader *make_reader() const;
 
+  // It is important that we only store *one* of the following two
+  // pointers.  If we are storing a GeomVertexData/array index, we
+  // must not keep a pointer to the particular ArrayData we are
+  // working on (if we do, it may result in an extra copy of the data
+  // due to holding the reference count).
   CPT(qpGeomVertexData) _vertex_data;
-  CPT(qpGeomVertexArrayData) _array_data;
   int _array;
-  const qpGeomVertexColumn *_column;
+  CPT(qpGeomVertexArrayData) _array_data;
+
+  qpGeomVertexColumn::Packer *_packer;
   int _stride;
 
   const unsigned char *_pointer;
+  const unsigned char *_pointer_end;
 
   int _start_vertex;
-  int _read_vertex;
-  int _num_vertices;
-
-  Reader *_reader;
 
 #ifndef NDEBUG
   // This is defined just for the benefit of having something non-NULL
   // to return from a nassertr() call.
   static const unsigned char empty_buffer[100];
 #endif
-
-  // 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 Reader {
-  public:
-    virtual ~Reader();
-    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);
-    virtual int get_data1i(const unsigned char *pointer);
-    virtual const int *get_data2i(const unsigned char *pointer);
-    virtual const int *get_data3i(const unsigned char *pointer);
-    virtual const int *get_data4i(const unsigned char *pointer);
-
-    INLINE float maybe_scale_color(unsigned int value);
-    INLINE void maybe_scale_color(unsigned int a, unsigned int b);
-    INLINE void maybe_scale_color(unsigned int a, unsigned int b,
-                                  unsigned int c);
-    INLINE void maybe_scale_color(unsigned int a, unsigned int b,
-                                  unsigned int c, unsigned int d);
-
-    const qpGeomVertexColumn *_column;
-    LVecBase2f _v2;
-    LVecBase3f _v3;
-    LVecBase4f _v4;
-    int _i[4];
-  };
-
-  // This is a specialization on the generic Reader that handles
-  // 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 {
-  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:
-    virtual const LVecBase4f &get_data4f(const unsigned char *pointer);
-  };
-
-
-  // These are the specializations on the generic Reader that handle
-  // the direct code paths.
-
-  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:
-    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 : 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 {
-  public:
-    virtual int get_data1i(const unsigned char *pointer);
-  };
 };
 
 #include "qpgeomVertexReader.I"

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

@@ -277,18 +277,6 @@ get_start_vertex() const {
   return qpGeomVertexWriter::get_start_vertex();
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexRewriter::get_num_vertices
-//       Access: Published
-//  Description: Returns the number of vertices in the vertex data.
-////////////////////////////////////////////////////////////////////
-INLINE int qpGeomVertexRewriter::
-get_num_vertices() const {
-  nassertr(qpGeomVertexWriter::get_num_vertices() == 
-           qpGeomVertexReader::get_num_vertices(), 0);
-  return qpGeomVertexWriter::get_num_vertices();
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: qpGeomVertexRewriter::is_at_end
 //       Access: Published

+ 0 - 1
panda/src/gobj/qpgeomVertexRewriter.h

@@ -69,7 +69,6 @@ PUBLISHED:
   INLINE void set_vertex(int vertex);
 
   INLINE int get_start_vertex() const;
-  INLINE int get_num_vertices() const;
   INLINE bool is_at_end() const;
 };
 

+ 55 - 148
panda/src/gobj/qpgeomVertexWriter.I

@@ -94,10 +94,6 @@ qpGeomVertexWriter(qpGeomVertexArrayData *array_data, int column) :
 ////////////////////////////////////////////////////////////////////
 INLINE qpGeomVertexWriter::
 ~qpGeomVertexWriter() {
-  if (_writer != (Writer *)NULL) {
-    delete _writer;
-    _writer = NULL;
-  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -201,7 +197,7 @@ set_column(const InternalName *name) {
 ////////////////////////////////////////////////////////////////////
 INLINE bool qpGeomVertexWriter::
 has_column() const {
-  return (_column != (qpGeomVertexColumn *)NULL);
+  return (_packer != (qpGeomVertexColumn::Packer *)NULL);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -223,7 +219,10 @@ get_array() const {
 ////////////////////////////////////////////////////////////////////
 INLINE const qpGeomVertexColumn *qpGeomVertexWriter::
 get_column() const {
-  return _column;
+  if (_packer != (qpGeomVertexColumn::Packer *)NULL) {
+    return _packer->_column;
+  }
+  return NULL;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -236,7 +235,7 @@ get_column() const {
 INLINE void qpGeomVertexWriter::
 set_vertex(int vertex) {
   _start_vertex = vertex;
-  if (_column != (qpGeomVertexColumn *)NULL) {
+  if (has_column()) {
     set_pointer(_start_vertex);
   }
 }
@@ -253,28 +252,6 @@ 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
@@ -286,7 +263,7 @@ get_num_vertices() const {
 ////////////////////////////////////////////////////////////////////
 INLINE bool qpGeomVertexWriter::
 is_at_end() const {
-  return _write_vertex >= _num_vertices;
+  return _pointer >= _pointer_end;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -300,8 +277,8 @@ is_at_end() const {
 ////////////////////////////////////////////////////////////////////
 INLINE void qpGeomVertexWriter::
 set_data1f(float data) {
-  nassertv(_column != (qpGeomVertexColumn *)NULL);
-  _writer->set_data1f(inc_pointer(), data);
+  nassertv(has_column());
+  _packer->set_data1f(inc_pointer(), data);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -329,8 +306,8 @@ set_data2f(float x, float y) {
 ////////////////////////////////////////////////////////////////////
 INLINE void qpGeomVertexWriter::
 set_data2f(const LVecBase2f &data) {
-  nassertv(_column != (qpGeomVertexColumn *)NULL);
-  _writer->set_data2f(inc_pointer(), data);
+  nassertv(has_column());
+  _packer->set_data2f(inc_pointer(), data);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -358,8 +335,8 @@ set_data3f(float x, float y, float z) {
 ////////////////////////////////////////////////////////////////////
 INLINE void qpGeomVertexWriter::
 set_data3f(const LVecBase3f &data) {
-  nassertv(_column != (qpGeomVertexColumn *)NULL);
-  _writer->set_data3f(inc_pointer(), data);
+  nassertv(has_column());
+  _packer->set_data3f(inc_pointer(), data);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -387,8 +364,8 @@ set_data4f(float x, float y, float z, float w) {
 ////////////////////////////////////////////////////////////////////
 INLINE void qpGeomVertexWriter::
 set_data4f(const LVecBase4f &data) {
-  nassertv(_column != (qpGeomVertexColumn *)NULL);
-  _writer->set_data4f(inc_pointer(), data);
+  nassertv(has_column());
+  _packer->set_data4f(inc_pointer(), data);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -402,8 +379,8 @@ set_data4f(const LVecBase4f &data) {
 ////////////////////////////////////////////////////////////////////
 INLINE void qpGeomVertexWriter::
 set_data1i(int data) {
-  nassertv(_column != (qpGeomVertexColumn *)NULL);
-  _writer->set_data1i(inc_pointer(), data);
+  nassertv(has_column());
+  _packer->set_data1i(inc_pointer(), data);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -417,8 +394,8 @@ set_data1i(int data) {
 ////////////////////////////////////////////////////////////////////
 INLINE void qpGeomVertexWriter::
 set_data2i(int a, int b) {
-  nassertv(_column != (qpGeomVertexColumn *)NULL);
-  _writer->set_data2i(inc_pointer(), a, b);
+  nassertv(has_column());
+  _packer->set_data2i(inc_pointer(), a, b);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -446,8 +423,8 @@ set_data2i(const int data[2]) {
 ////////////////////////////////////////////////////////////////////
 INLINE void qpGeomVertexWriter::
 set_data3i(int a, int b, int c) {
-  nassertv(_column != (qpGeomVertexColumn *)NULL);
-  _writer->set_data3i(inc_pointer(), a, b, c);
+  nassertv(has_column());
+  _packer->set_data3i(inc_pointer(), a, b, c);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -475,8 +452,8 @@ set_data3i(const int data[3]) {
 ////////////////////////////////////////////////////////////////////
 INLINE void qpGeomVertexWriter::
 set_data4i(int a, int b, int c, int d) {
-  nassertv(_column != (qpGeomVertexColumn *)NULL);
-  _writer->set_data4i(inc_pointer(), a, b, c, d);
+  nassertv(has_column());
+  _packer->set_data4i(inc_pointer(), a, b, c, d);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -504,8 +481,8 @@ set_data4i(const int data[4]) {
 ////////////////////////////////////////////////////////////////////
 INLINE void qpGeomVertexWriter::
 add_data1f(float data) {
-  nassertv(_column != (qpGeomVertexColumn *)NULL);
-  _writer->set_data1f(inc_add_pointer(), data);
+  nassertv(has_column());
+  _packer->set_data1f(inc_add_pointer(), data);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -533,8 +510,8 @@ add_data2f(float x, float y) {
 ////////////////////////////////////////////////////////////////////
 INLINE void qpGeomVertexWriter::
 add_data2f(const LVecBase2f &data) {
-  nassertv(_column != (qpGeomVertexColumn *)NULL);
-  _writer->set_data2f(inc_add_pointer(), data);
+  nassertv(has_column());
+  _packer->set_data2f(inc_add_pointer(), data);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -562,8 +539,8 @@ add_data3f(float x, float y, float z) {
 ////////////////////////////////////////////////////////////////////
 INLINE void qpGeomVertexWriter::
 add_data3f(const LVecBase3f &data) {
-  nassertv(_column != (qpGeomVertexColumn *)NULL);
-  _writer->set_data3f(inc_add_pointer(), data);
+  nassertv(has_column());
+  _packer->set_data3f(inc_add_pointer(), data);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -591,8 +568,8 @@ add_data4f(float x, float y, float z, float w) {
 ////////////////////////////////////////////////////////////////////
 INLINE void qpGeomVertexWriter::
 add_data4f(const LVecBase4f &data) {
-  nassertv(_column != (qpGeomVertexColumn *)NULL);
-  _writer->set_data4f(inc_add_pointer(), data);
+  nassertv(has_column());
+  _packer->set_data4f(inc_add_pointer(), data);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -606,8 +583,8 @@ add_data4f(const LVecBase4f &data) {
 ////////////////////////////////////////////////////////////////////
 INLINE void qpGeomVertexWriter::
 add_data1i(int data) {
-  nassertv(_column != (qpGeomVertexColumn *)NULL);
-  _writer->set_data1i(inc_add_pointer(), data);
+  nassertv(has_column());
+  _packer->set_data1i(inc_add_pointer(), data);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -621,8 +598,8 @@ add_data1i(int data) {
 ////////////////////////////////////////////////////////////////////
 INLINE void qpGeomVertexWriter::
 add_data2i(int a, int b) {
-  nassertv(_column != (qpGeomVertexColumn *)NULL);
-  _writer->set_data2i(inc_add_pointer(), a, b);
+  nassertv(has_column());
+  _packer->set_data2i(inc_add_pointer(), a, b);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -650,8 +627,8 @@ add_data2i(const int data[2]) {
 ////////////////////////////////////////////////////////////////////
 INLINE void qpGeomVertexWriter::
 add_data3i(int a, int b, int c) {
-  nassertv(_column != (qpGeomVertexColumn *)NULL);
-  _writer->set_data3i(inc_add_pointer(), a, b, c);
+  nassertv(has_column());
+  _packer->set_data3i(inc_add_pointer(), a, b, c);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -679,8 +656,8 @@ add_data3i(const int data[3]) {
 ////////////////////////////////////////////////////////////////////
 INLINE void qpGeomVertexWriter::
 add_data4i(int a, int b, int c, int d) {
-  nassertv(_column != (qpGeomVertexColumn *)NULL);
-  _writer->set_data4i(inc_add_pointer(), a, b, c, d);
+  nassertv(has_column());
+  _packer->set_data4i(inc_add_pointer(), a, b, c, d);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -705,13 +682,19 @@ add_data4i(const int data[4]) {
 ////////////////////////////////////////////////////////////////////
 INLINE void qpGeomVertexWriter::
 set_pointer(int vertex) {
-  nassertv(_column != (qpGeomVertexColumn *)NULL);
-  _write_vertex = vertex;
+  nassertv(has_column());
   if (_vertex_data != (qpGeomVertexData *)NULL) {
-    _array_data = _vertex_data->modify_array(_array);
+    qpGeomVertexArrayData *array_data = _vertex_data->modify_array(_array);
+    _pointer = array_data->modify_data();
+    _pointer_end = _pointer + array_data->get_data_size_bytes();
+    _pointer += _packer->_column->get_start() + _stride * vertex;
+
+  } else {
+    _pointer = _array_data->modify_data();
+    _pointer_end = _pointer + _array_data->get_data_size_bytes();
+    _pointer += _packer->_column->get_start() + _stride * vertex;
   }
-  _pointer = _array_data->modify_data() + _column->get_start() + _stride * _write_vertex;
-  _num_vertices = _array_data->get_num_vertices();
+  _write_vertex = vertex;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -723,11 +706,12 @@ set_pointer(int vertex) {
 INLINE unsigned char *qpGeomVertexWriter::
 inc_pointer() {
 #ifndef NDEBUG
-  nassertr(_write_vertex < _num_vertices, empty_buffer);
+  nassertr(_pointer < _pointer_end, empty_buffer);
   if (_vertex_data != (qpGeomVertexData *)NULL){ 
-    nassertr(_pointer == _vertex_data->get_array(_array)->get_data() + _column->get_start() + _stride * _write_vertex, empty_buffer);
+    const qpGeomVertexArrayData *array_data = _vertex_data->get_array(_array);
+    nassertr(_pointer >= array_data->get_data() && _pointer < array_data->get_data() + array_data->get_data_size_bytes(), empty_buffer);
   } else {
-    nassertr(_pointer == _array_data->get_data() + _column->get_start() + _stride * _write_vertex, empty_buffer);
+    nassertr(_pointer >= _array_data->get_data() && _pointer < _array_data->get_data() + _array_data->get_data_size_bytes(), empty_buffer);
   }
 #endif
 
@@ -747,7 +731,7 @@ inc_pointer() {
 ////////////////////////////////////////////////////////////////////
 INLINE unsigned char *qpGeomVertexWriter::
 inc_add_pointer() {
-  if (_write_vertex >= _num_vertices) {
+  if (_pointer >= _pointer_end) {
     // Reset the data pointer.
     if (_vertex_data != (qpGeomVertexData *)NULL) {
       _vertex_data->set_num_vertices(max(_write_vertex + 1, _vertex_data->get_num_vertices()));
@@ -758,80 +742,3 @@ inc_add_pointer() {
   }
   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) {
-  if (_column->get_contents() == C_color) {
-    return (unsigned int)(data * 255.0f);
-  } else {
-    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) {
-  if (_column->get_contents() == C_color) {
-    _a = (unsigned int)(data[0] * 255.0f);
-    _b = (unsigned int)(data[1] * 255.0f);
-  } else {
-    _a = (unsigned int)data[0];
-    _b = (unsigned int)data[1];
-  }
-}
-    
-////////////////////////////////////////////////////////////////////
-//     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) {
-  if (_column->get_contents() == C_color) {
-    _a = (unsigned int)(data[0] * 255.0f);
-    _b = (unsigned int)(data[1] * 255.0f);
-    _c = (unsigned int)(data[2] * 255.0f);
-  } else {
-    _a = (unsigned int)data[0];
-    _b = (unsigned int)data[1];
-    _c = (unsigned int)data[2];
-  }
-}
-    
-////////////////////////////////////////////////////////////////////
-//     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) {
-  if (_column->get_contents() == C_color) {
-    _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);
-  } else {
-    _a = (unsigned int)data[0];
-    _b = (unsigned int)data[1];
-    _c = (unsigned int)data[2];
-    _d = (unsigned int)data[3];
-  }
-}

+ 25 - 881
panda/src/gobj/qpgeomVertexWriter.cxx

@@ -46,45 +46,36 @@ set_column(int array, const qpGeomVertexColumn *column) {
     return false;
   }
 
-  // Delete the old writer, if we've got one.
-  if (_writer != (Writer *)NULL) {
-    delete _writer;
-    _writer = NULL;
-  }
-
-  int num_arrays = 1;
-  if (_vertex_data != (qpGeomVertexData *)NULL) {
-    num_arrays = _vertex_data->get_num_arrays();
-  }
-
-  if (array < 0 || array >= num_arrays ||
-      column == (const qpGeomVertexColumn *)NULL) {
+  if (column == (const qpGeomVertexColumn *)NULL) {
     // Clear the data type.
     _array = -1;
-    _column = NULL;
+    _packer = NULL;
     _stride = 0;
-    _write_vertex = _start_vertex;
-    _num_vertices = 0;
-    
-    return false;
-    
-  } else {
-    _array = array;
-    _column = column;
-    if (_vertex_data != (qpGeomVertexData *)NULL) {
-      _stride = _vertex_data->get_format()->get_array(_array)->get_stride();
-    } else {
-      _stride = _array_data->get_array_format()->get_stride();
-    }
+    _pointer = NULL;
+    _pointer_end = NULL;
 
-    set_pointer(_start_vertex);
+    return false;
+  }
 
-    // Now set up a new writer.
-    _writer = make_writer();
-    _writer->_column = _column;
+  if (_vertex_data != (qpGeomVertexData *)NULL) {
+#ifndef NDEBUG
+    _array = -1;
+    _packer = NULL;
+    nassertr(array >= 0 && array < _vertex_data->get_num_arrays(), false);
+#endif
+    _array = array;
+    const qpGeomVertexArrayData *array_data =_vertex_data->get_array(_array);
+    _stride = array_data->get_array_format()->get_stride();
 
-    return true;
+  } else {
+    _stride = _array_data->get_array_format()->get_stride();
   }
+
+  _packer = column->_packer;
+  
+  set_pointer(_start_vertex);
+  
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -95,856 +86,9 @@ set_column(int array, const qpGeomVertexColumn *column) {
 void qpGeomVertexWriter::
 initialize() {
   _array = 0;
-  _column = NULL;
+  _packer = NULL;
   _pointer = NULL;
+  _pointer_end = NULL;
   _start_vertex = 0;
   _write_vertex = 0;
-  _num_vertices = 0;
-  _writer = NULL;
-}
-
-////////////////////////////////////////////////////////////////////
-//     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 (_column->get_contents()) {
-  case C_point:
-  case C_clip_point:
-  case C_texcoord:
-    // These types are written as a 4-d homogeneous point.
-    switch (_column->get_numeric_type()) {
-    case NT_float32:
-      switch (_column->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 C_color:
-    switch (_column->get_numeric_type()) {
-    case NT_uint8:
-      switch (_column->get_num_components()) {
-      case 4:
-        return new Writer_rgba_uint8_4;
-        
-      default:
-        break;
-      }
-      break;
-    case NT_packed_dabc:
-      switch (_column->get_num_components()) {
-      case 1:
-        return new Writer_argb_packed;
-        
-      default:
-        break;
-      }
-      break;
-    case NT_float32:
-      switch (_column->get_num_components()) {
-      case 4:
-        return new Writer_rgba_float32_4;
-        
-      default:
-        break;
-      }
-      break;
-    default:
-      break;
-    }
-    return new Writer_color;
-
-  default:
-    // Otherwise, we just write it as a generic value.
-    switch (_column->get_numeric_type()) {
-    case NT_float32:
-      switch (_column->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 (_column->get_num_values()) {
-  case 1:
-    switch (_column->get_numeric_type()) {
-    case NT_uint8:
-      *pointer = maybe_scale_color(data);
-      break;
-      
-    case NT_uint16:
-      *(PN_uint16 *)pointer = (unsigned int)data;
-      break;
-      
-    case NT_uint32:
-      *(PN_uint32 *)pointer = (unsigned int)data;
-      break;
-      
-    case NT_packed_dcba:
-    case NT_packed_dabc:
-      nassertv(false);
-      break;
-      
-    case 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 (_column->get_num_values()) {
-  case 1:
-    set_data1f(pointer, data[0]);
-
-  case 2:
-    switch (_column->get_numeric_type()) {
-    case NT_uint8:
-      maybe_scale_color(data);
-      pointer[0] = _a;
-      pointer[1] = _b;
-      break;
-      
-    case NT_uint16:
-      {
-        PN_uint16 *pi = (PN_uint16 *)pointer;
-        pi[0] = (unsigned int)data[0];
-        pi[1] = (unsigned int)data[1];
-      }
-      break;
-      
-    case NT_uint32:
-      {
-        PN_uint32 *pi = (PN_uint32 *)pointer;
-        pi[0] = (unsigned int)data[0];
-        pi[1] = (unsigned int)data[1];
-      }
-      break;
-      
-    case NT_packed_dcba:
-    case NT_packed_dabc:
-      nassertv(false);
-      break;
-      
-    case 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 (_column->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 (_column->get_numeric_type()) {
-    case NT_uint8:
-      maybe_scale_color(data);
-      pointer[0] = _a;
-      pointer[1] = _b;
-      pointer[2] = _c;
-      break;
-      
-    case 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 NT_uint32:
-      {
-        PN_uint32 *pi = (PN_uint32 *)pointer;
-        pi[0] = (unsigned int)data[0];
-        pi[1] = (unsigned int)data[1];
-        pi[2] = (unsigned int)data[2];
-      }
-      break;
-      
-    case NT_packed_dcba:
-    case NT_packed_dabc:
-      nassertv(false);
-      break;
-      
-    case 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 (_column->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 (_column->get_numeric_type()) {
-    case NT_uint8:
-      maybe_scale_color(data);
-      pointer[0] = _a;
-      pointer[1] = _b;
-      pointer[2] = _c;
-      pointer[3] = _d;
-      break;
-
-    case 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 NT_uint32:
-      {
-        PN_uint32 *pi = (PN_uint32 *)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 NT_packed_dcba:
-      maybe_scale_color(data);
-      *(PN_uint32 *)pointer = qpGeomVertexData::pack_abcd(_d, _c, _b, _a);
-      break;
-      
-    case NT_packed_dabc:
-      maybe_scale_color(data);
-      *(PN_uint32 *)pointer = qpGeomVertexData::pack_abcd(_d, _a, _b, _c);
-      break;
-      
-    case 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 a) {
-  switch (_column->get_num_values()) {
-  case 1:
-    switch (_column->get_numeric_type()) {
-    case NT_uint8:
-      *pointer = a;
-      nassertv((*pointer) == a);
-      break;
-      
-    case NT_uint16:
-      *(PN_uint16 *)pointer = a;
-      nassertv(*(PN_uint16 *)pointer == a);
-      break;
-      
-    case NT_uint32:
-      *(PN_uint32 *)pointer = a;
-      break;
-      
-    case NT_packed_dcba:
-    case NT_packed_dabc:
-      nassertv(false);
-      break;
-      
-    case NT_float32:
-      *(PN_float32 *)pointer = (float)a;
-      break;
-    }
-    break;
-
-  case 2:
-    set_data2i(pointer, a, 0);
-    break;
-
-  case 3:
-    set_data3i(pointer, a, 0, 0);
-    break;
-
-  default:
-    set_data4i(pointer, a, 0, 0, 0);
-    break;
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexWriter::Writer::set_data2i
-//       Access: Public, Virtual
-//  Description: 
-////////////////////////////////////////////////////////////////////
-void qpGeomVertexWriter::Writer::
-set_data2i(unsigned char *pointer, int a, int b) {
-  switch (_column->get_num_values()) {
-  case 1:
-    set_data1i(pointer, a);
-    break;
-
-  case 2:
-    switch (_column->get_numeric_type()) {
-    case NT_uint8:
-      pointer[0] = a;
-      pointer[1] = b;
-      break;
-
-    case NT_uint16:
-      {
-        PN_uint16 *pi = (PN_uint16 *)pointer;
-        pi[0] = a;
-        pi[1] = b;
-      }
-      break;
-
-    case NT_uint32:
-      {
-        PN_uint32 *pi = (PN_uint32 *)pointer;
-        pi[0] = a;
-        pi[1] = b;
-      }
-      break;
-      
-    case NT_packed_dcba:
-    case NT_packed_dabc:
-      nassertv(false);
-      break;
-      
-    case NT_float32:
-      {
-        PN_float32 *pi = (PN_float32 *)pointer;
-        pi[0] = a;
-        pi[1] = b;
-      }
-      break;
-    }
-    break;
-
-  case 3:
-    set_data3i(pointer, a, b, 0);
-    break;
-
-  default:
-    set_data4i(pointer, a, b, 0, 0);
-    break;
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexWriter::Writer::set_data3i
-//       Access: Public, Virtual
-//  Description: 
-////////////////////////////////////////////////////////////////////
-void qpGeomVertexWriter::Writer::
-set_data3i(unsigned char *pointer, int a, int b, int c) {
-  switch (_column->get_num_values()) {
-  case 1:
-    set_data1i(pointer, a);
-    break;
-
-  case 2:
-    set_data2i(pointer, a, b);
-    break;
-
-  case 3:
-    switch (_column->get_numeric_type()) {
-    case NT_uint8:
-      pointer[0] = a;
-      pointer[1] = b;
-      pointer[2] = c;
-      break;
-
-    case NT_uint16:
-      {
-        PN_uint16 *pi = (PN_uint16 *)pointer;
-        pi[0] = a;
-        pi[1] = b;
-        pi[2] = c;
-      }
-      break;
-
-    case NT_uint32:
-      {
-        PN_uint32 *pi = (PN_uint32 *)pointer;
-        pi[0] = a;
-        pi[1] = b;
-        pi[2] = c;
-      }
-      break;
-      
-    case NT_packed_dcba:
-    case NT_packed_dabc:
-      nassertv(false);
-      break;
-      
-    case NT_float32:
-      {
-        PN_float32 *pi = (PN_float32 *)pointer;
-        pi[0] = a;
-        pi[1] = b;
-        pi[2] = c;
-      }
-      break;
-    }
-    break;
-
-  default:
-    set_data4i(pointer, a, b, c, 0);
-    break;
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexWriter::Writer::set_data4i
-//       Access: Public, Virtual
-//  Description: 
-////////////////////////////////////////////////////////////////////
-void qpGeomVertexWriter::Writer::
-set_data4i(unsigned char *pointer, int a, int b, int c, int d) {
-  switch (_column->get_num_values()) {
-  case 1:
-    set_data1i(pointer, a);
-    break;
-
-  case 2:
-    set_data2i(pointer, a, b);
-    break;
-
-  case 3:
-    set_data3i(pointer, a, b, c);
-    break;
-
-  default:
-    switch (_column->get_numeric_type()) {
-    case NT_uint8:
-      pointer[0] = a;
-      pointer[1] = b;
-      pointer[2] = c;
-      pointer[3] = d;
-      break;
-
-    case NT_uint16:
-      {
-        PN_uint16 *pi = (PN_uint16 *)pointer;
-        pi[0] = a;
-        pi[1] = b;
-        pi[2] = c;
-        pi[3] = d;
-      }
-      break;
-
-    case NT_uint32:
-      {
-        PN_uint32 *pi = (PN_uint32 *)pointer;
-        pi[0] = a;
-        pi[1] = b;
-        pi[2] = c;
-        pi[3] = d;
-      }
-      break;
-      
-    case NT_packed_dcba:
-      *(PN_uint32 *)pointer = qpGeomVertexData::pack_abcd(d, c, b, a);
-      break;
-      
-    case NT_packed_dabc:
-      *(PN_uint32 *)pointer = qpGeomVertexData::pack_abcd(d, a, b, c);
-      break;
-      
-    case NT_float32:
-      {
-        PN_float32 *pi = (PN_float32 *)pointer;
-        pi[0] = a;
-        pi[1] = b;
-        pi[2] = c;
-        pi[3] = d;
-      }
-      break;
-    }
-    break;
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexWriter::Writer_point::set_data1f
-//       Access: Public, Virtual
-//  Description: 
-////////////////////////////////////////////////////////////////////
-void qpGeomVertexWriter::Writer_point::
-set_data1f(unsigned char *pointer, float data) {
-  if (_column->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 (_column->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 (_column->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 (_column->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 (_column->get_numeric_type()) {
-    case NT_uint8:
-      maybe_scale_color(data);
-      pointer[0] = _a;
-      pointer[1] = _b;
-      pointer[2] = _c;
-      pointer[3] = _d;
-      break;
-
-    case 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 NT_uint32:
-      {
-        PN_uint32 *pi = (PN_uint32 *)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 NT_packed_dcba:
-      maybe_scale_color(data);
-      *(PN_uint32 *)pointer = qpGeomVertexData::pack_abcd(_d, _c, _b, _a);
-      break;
-      
-    case NT_packed_dabc:
-      maybe_scale_color(data);
-      *(PN_uint32 *)pointer = qpGeomVertexData::pack_abcd(_d, _a, _b, _c);
-      break;
-      
-    case 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 (_column->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 (_column->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 (_column->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::set_data4f
-//       Access: Public, Virtual
-//  Description: 
-////////////////////////////////////////////////////////////////////
-void qpGeomVertexWriter::Writer_argb_packed::
-set_data4f(unsigned char *pointer, const LVecBase4f &data) {
-  *(PN_uint32 *)pointer = qpGeomVertexData::pack_abcd
-    ((unsigned int)(data[3] * 255.0f),
-     (unsigned int)(data[0] * 255.0f),
-     (unsigned int)(data[1] * 255.0f),
-     (unsigned int)(data[2] * 255.0f));
-}
-
-////////////////////////////////////////////////////////////////////
-//     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;
-  nassertv(*(PN_uint16 *)pointer == data);
 }

+ 9 - 101
panda/src/gobj/qpgeomVertexWriter.h

@@ -99,8 +99,6 @@ PUBLISHED:
   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);
@@ -143,120 +141,30 @@ private:
   INLINE void set_pointer(int vertex);
   INLINE unsigned char *inc_pointer();
   INLINE unsigned char *inc_add_pointer();
-  Writer *make_writer() const;
 
+  // It is important that we only store *one* of the following two
+  // pointers.  If we are storing a GeomVertexData/array index, we
+  // must not keep a pointer to the particular ArrayData we are
+  // working on (if we do, it may result in an extra copy of the data
+  // due to holding the reference count).
   PT(qpGeomVertexData) _vertex_data;
-  PT(qpGeomVertexArrayData) _array_data;
   int _array;
-  const qpGeomVertexColumn *_column;
+  PT(qpGeomVertexArrayData) _array_data;
+
+  qpGeomVertexColumn::Packer *_packer;
   int _stride;
 
   unsigned char *_pointer;
+  unsigned char *_pointer_end;
 
   int _start_vertex;
   int _write_vertex;
-  int _num_vertices;
-
-  Writer *_writer;
 
 #ifndef NDEBUG
   // This is defined just for the benefit of having something non-NULL
   // to return from a nassertr() call.
   static unsigned char empty_buffer[100];
 #endif
-
-  // 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 a);
-    virtual void set_data2i(unsigned char *pointer, int a, int b);
-    virtual void set_data3i(unsigned char *pointer, int a, int b, int c);
-    virtual void set_data4i(unsigned char *pointer, int a, int b, int c, int d);
-
-    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 qpGeomVertexColumn *_column;
-    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 : 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"