Browse Source

use GeomVertexReader/Writer to implement convert_to()

David Rose 21 years ago
parent
commit
5ba9232349

+ 155 - 8
panda/src/gobj/qpgeomVertexData.cxx

@@ -327,19 +327,62 @@ convert_to(const qpGeomVertexFormat *new_format) const {
       int new_i = new_format->get_array_with(data_type->get_name());
       int new_i = new_format->get_array_with(data_type->get_name());
       if (new_i >= 0 && done_arrays.count(new_i) == 0) {
       if (new_i >= 0 && done_arrays.count(new_i) == 0) {
         // The data type exists in the new format; we have to copy it.
         // The data type exists in the new format; we have to copy it.
-        PTA_uchar new_array_data = 
-          new_data->modify_array(new_i)->modify_data();
-
         const qpGeomVertexArrayFormat *new_array_format = 
         const qpGeomVertexArrayFormat *new_array_format = 
           new_format->get_array(new_i);
           new_format->get_array(new_i);
         const qpGeomVertexDataType *new_data_type = 
         const qpGeomVertexDataType *new_data_type = 
           new_array_format->get_data_type(data_type->get_name());
           new_array_format->get_data_type(data_type->get_name());
 
 
-        new_data_type->copy_records
-          (new_array_data + new_data_type->get_start(), 
-           new_array_format->get_stride(),
-           array_data + data_type->get_start(), array_format->get_stride(),
-           data_type, num_vertices);
+        if (new_data_type->is_bytewise_equivalent(*data_type)) {
+          // We can do a quick bytewise copy.
+          PTA_uchar new_array_data = 
+            new_data->modify_array(new_i)->modify_data();
+
+          bytewise_copy(new_array_data + new_data_type->get_start(), 
+                        new_array_format->get_stride(),
+                        array_data + data_type->get_start(), array_format->get_stride(),
+                        data_type, num_vertices);
+
+        } else if (new_data_type->is_packed_argb() && 
+                   data_type->is_uint8_rgba()) {
+          // A common special case: OpenGL color to DirectX color.
+          PTA_uchar new_array_data = 
+            new_data->modify_array(new_i)->modify_data();
+
+          uint8_rgba_to_packed_argb
+            (new_array_data + new_data_type->get_start(), 
+             new_array_format->get_stride(),
+             array_data + data_type->get_start(), array_format->get_stride(),
+             num_vertices);
+
+        } else if (new_data_type->is_uint8_rgba() && 
+                   data_type->is_packed_argb()) {
+          // Another common special case: DirectX color to OpenGL
+          // color.
+          PTA_uchar new_array_data = 
+            new_data->modify_array(new_i)->modify_data();
+
+          packed_argb_to_uint8_rgba
+            (new_array_data + new_data_type->get_start(), 
+             new_array_format->get_stride(),
+             array_data + data_type->get_start(), array_format->get_stride(),
+             num_vertices);
+
+        } else {
+          // A generic copy.
+          if (gobj_cat.is_debug()) {
+            gobj_cat.debug()
+              << "generic copy " << *new_data_type << " from " 
+              << *data_type << "\n";
+          }
+          qpGeomVertexReader from(this);
+          from.set_data_type(i, data_type);
+          qpGeomVertexWriter to(new_data);
+          to.set_data_type(new_i, new_data_type);
+
+          while (!from.is_at_end()) {
+            to.set_data4f(from.get_data4f());
+          }
+        }
       }
       }
     }
     }
   }
   }
@@ -630,6 +673,110 @@ get_array_info(const InternalName *name,
   return false;
   return false;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexData::bytewise_copy
+//       Access: Private, Static
+//  Description: Quickly copies data without the need to convert it.
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexData::
+bytewise_copy(unsigned char *to, int to_stride,
+              const unsigned char *from, int from_stride,
+              const qpGeomVertexDataType *from_type,
+              int num_records) {
+  if (gobj_cat.is_debug()) {
+    gobj_cat.debug()
+      << "bytewise_copy(" << (void *)to << ", " << to_stride
+      << ", " << (const void *)from << ", " << from_stride
+      << ", " << *from_type << ", " << num_records << ")\n";
+  }
+  if (to_stride == from_type->get_total_bytes() && 
+      from_stride == from_type->get_total_bytes()) {
+    // Fantastic!  It's just a linear array of this one data type.
+    // Copy the whole thing all at once.
+    memcpy(to, from, num_records * from_type->get_total_bytes());
+
+  } else {
+    // Ok, it's interleaved in with other data.  Copy them one record
+    // at a time.
+    while (num_records > 0) {
+      memcpy(to, from, from_type->get_total_bytes());
+      to += to_stride;
+      from += from_stride;
+      num_records--;
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexData::packed_argb_to_uint8_rgba
+//       Access: Private, Static
+//  Description: Quickly converts DirectX-style color to OpenGL-style
+//               color.
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexData::
+packed_argb_to_uint8_rgba(unsigned char *to, int to_stride,
+                          const unsigned char *from, int from_stride,
+                          int num_records) {
+  if (gobj_cat.is_debug()) {
+    gobj_cat.debug()
+      << "packed_argb_to_uint8_rgba(" << (void *)to << ", " << to_stride
+      << ", " << (const void *)from << ", " << from_stride
+      << ", " << num_records << ")\n";
+  }
+  typedef union {
+    unsigned char _b[4];
+    PN_uint32 _i;
+  } packed_8888;
+
+  while (num_records > 0) {
+    packed_8888 dword;
+    dword._i = *(const PN_uint32 *)from;
+    to[0] = dword._b[1];
+    to[1] = dword._b[2];
+    to[2] = dword._b[3];
+    to[3] = dword._b[0];
+
+    to += to_stride;
+    from += from_stride;
+    num_records--;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexData::uint8_rgba_to_packed_argb
+//       Access: Private, Static
+//  Description: Quickly converts OpenGL-style color to DirectX-style
+//               color.
+////////////////////////////////////////////////////////////////////
+void qpGeomVertexData::
+uint8_rgba_to_packed_argb(unsigned char *to, int to_stride,
+                          const unsigned char *from, int from_stride,
+                          int num_records) {
+  if (gobj_cat.is_debug()) {
+    gobj_cat.debug()
+      << "uint8_rgba_to_packed_argb(" << (void *)to << ", " << to_stride
+      << ", " << (const void *)from << ", " << from_stride
+      << ", " << num_records << ")\n";
+  }
+  typedef union {
+    unsigned char _b[4];
+    PN_uint32 _i;
+  } packed_8888;
+
+  while (num_records > 0) {
+    packed_8888 dword;
+    dword._b[0] = from[3];
+    dword._b[1] = from[0];
+    dword._b[2] = from[1];
+    dword._b[3] = from[2];
+    *(PN_uint32 *)to = dword._i;
+
+    to += to_stride;
+    from += from_stride;
+    num_records--;
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: qpGeomVertexData::do_set_num_vertices
 //     Function: qpGeomVertexData::do_set_num_vertices
 //       Access: Private
 //       Access: Private

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

@@ -123,6 +123,20 @@ public:
                       qpGeomVertexDataType::NumericType &numeric_type, 
                       qpGeomVertexDataType::NumericType &numeric_type, 
                       int &start, int &stride) const;
                       int &start, int &stride) const;
 
 
+private:
+  static void bytewise_copy(unsigned char *to, int to_stride,
+                            const unsigned char *from, int from_stride,
+                            const qpGeomVertexDataType *from_type,
+                            int num_records);
+  static void
+  packed_argb_to_uint8_rgba(unsigned char *to, int to_stride,
+                            const unsigned char *from, int from_stride,
+                            int num_records);
+  static void
+  uint8_rgba_to_packed_argb(unsigned char *to, int to_stride,
+                            const unsigned char *from, int from_stride,
+                            int num_records);
+  
 private:
 private:
   string _name;
   string _name;
   CPT(qpGeomVertexFormat) _format;
   CPT(qpGeomVertexFormat) _format;

+ 44 - 0
panda/src/gobj/qpgeomVertexDataType.I

@@ -164,6 +164,50 @@ overlaps_with(int start_byte, int num_bytes) const {
           _start + _total_bytes > start_byte);
           _start + _total_bytes > start_byte);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexDataType::is_bytewise_equivalent
+//       Access: Published
+//  Description: Returns true if the data store of this data type is
+//               exactly the same as that of the other, irrespective
+//               of name or start position within the record.
+////////////////////////////////////////////////////////////////////
+INLINE bool qpGeomVertexDataType::
+is_bytewise_equivalent(const qpGeomVertexDataType &other) const {
+  // The _contents are relevant, because they specify such things as
+  // the difference between C_rgba and C_argb.
+  return (_num_components == other._num_components &&
+          _numeric_type == other._numeric_type &&
+          _contents == other._contents);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexDataType::is_packed_argb
+//       Access: Public
+//  Description: Returns true if this data type is the standard
+//               DirectX representation of 4-component color: C_argb,
+//               in NT_packed_8888, with 1 component (4 values).
+////////////////////////////////////////////////////////////////////
+INLINE bool qpGeomVertexDataType::
+is_packed_argb() const {
+  return (_num_components == 1 &&
+          _numeric_type == NT_packed_8888 &&
+          _contents == C_argb);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexDataType::is_uint8_rgba
+//       Access: Public
+//  Description: Returns true if this data type is the standard
+//               OpenGL representation of 4-component color: C_rgba,
+//               in NT_uint8, with 4 components.
+////////////////////////////////////////////////////////////////////
+INLINE bool qpGeomVertexDataType::
+is_uint8_rgba() const {
+  return (_num_components == 4 &&
+          _numeric_type == NT_uint8 &&
+          _contents == C_rgba);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: qpGeomVertexDataType::compare_to
 //     Function: qpGeomVertexDataType::compare_to
 //       Access: Public
 //       Access: Public

+ 0 - 240
panda/src/gobj/qpgeomVertexDataType.cxx

@@ -80,243 +80,3 @@ void qpGeomVertexDataType::
 output(ostream &out) const {
 output(ostream &out) const {
   out << *get_name() << "(" << get_num_components() << ")";
   out << *get_name() << "(" << get_num_components() << ")";
 }
 }
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexDataType::copy_records
-//       Access: Published
-//  Description: Copies and converts from one data type to another.
-//               Copies the num_records records from the "from"
-//               buffer, encoded with from_type, to the "to" buffer,
-//               encoded with this current type, converting each one
-//               as necessary.
-////////////////////////////////////////////////////////////////////
-void qpGeomVertexDataType::
-copy_records(unsigned char *to, int to_stride,
-             const unsigned char *from, int from_stride,
-             const qpGeomVertexDataType *from_type,
-             int num_records) const {
-  // Temp for debugging.
-  static ConfigVariableBool do_copy_generic("copy-generic", false);
-  if (do_copy_generic) {
-    copy_generic(to, to_stride, from, from_stride, from_type, num_records);
-    return;
-  }
-
-  if (get_numeric_type() == from_type->get_numeric_type() &&
-      get_num_values() == from_type->get_num_values()) {
-      // An easy case.
-    copy_no_convert(to, to_stride, from, from_stride, from_type, num_records);
-
-  } else if (get_numeric_type() == NT_uint8 && from_type->get_numeric_type() == NT_packed_8888 &&
-             get_num_values() == from_type->get_num_values()) {
-    copy_argb_to_uint8(to, to_stride, from, from_stride, from_type, num_records);
-  } else if (get_numeric_type() == NT_packed_8888 && from_type->get_numeric_type() == NT_uint8 &&
-             get_num_values() == from_type->get_num_values()) {
-    copy_uint8_to_argb(to, to_stride, from, from_stride, from_type, num_records);
-  } else {
-    copy_generic(to, to_stride, from, from_stride, from_type, num_records);
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexDataType::copy_no_convert
-//       Access: Private
-//  Description: Quickly copies data without the need to convert it.
-////////////////////////////////////////////////////////////////////
-void qpGeomVertexDataType::
-copy_no_convert(unsigned char *to, int to_stride,
-                const unsigned char *from, int from_stride,
-                const qpGeomVertexDataType *from_type,
-                int num_records) const {
-  if (to_stride == _total_bytes && from_stride == _total_bytes) {
-    // Fantastic!  It's just a linear array of this one data type.
-    // Copy the whole thing all at once.
-    memcpy(to, from, num_records * _total_bytes);
-
-  } else {
-    // Ok, it's interleaved in with other data.  Copy them one record
-    // at a time.
-    while (num_records > 0) {
-      memcpy(to, from, _total_bytes);
-      to += to_stride;
-      from += from_stride;
-      num_records--;
-    }
-  }
-}
-  
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexDataType::copy_argb_to_uint8
-//       Access: Private
-//  Description: Converts packed_argb to uint8-based r, g, b, a.
-////////////////////////////////////////////////////////////////////
-void qpGeomVertexDataType::
-copy_argb_to_uint8(unsigned char *to, int to_stride,
-                   const unsigned char *from, int from_stride,
-                   const qpGeomVertexDataType *from_type,
-                   int num_records) const {
-  while (num_records > 0) {
-    PN_uint32 packed_argb = *(const PN_uint32 *)from;
-    to[0] = ((packed_argb >> 16) & 0xff);
-    to[1] = ((packed_argb >> 8) & 0xff);
-    to[2] = (packed_argb & 0xff);
-    to[3] = ((packed_argb >> 24) & 0xff);
-
-    to += to_stride;
-    from += from_stride;
-    num_records--;
-  }
-}
-  
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexDataType::copy_uint8_to_argb
-//       Access: Private
-//  Description: Converts uint8-based r, g, b, a to packed_argb.
-////////////////////////////////////////////////////////////////////
-void qpGeomVertexDataType::
-copy_uint8_to_argb(unsigned char *to, int to_stride,
-                   const unsigned char *from, int from_stride,
-                   const qpGeomVertexDataType *from_type,
-                   int num_records) const {
-  while (num_records > 0) {
-    PN_uint32 packed_argb = ((from[3] << 24) | (from[0] << 16) | (from[1] << 8) | from[2]);
-    *(PN_uint32 *)to = packed_argb;
-
-    to += to_stride;
-    from += from_stride;
-    num_records--;
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexDataType::copy_generic
-//       Access: Private
-//  Description: A more general anything-to-anything copy (somewhat
-//               more expensive than the above).
-////////////////////////////////////////////////////////////////////
-void qpGeomVertexDataType::
-copy_generic(unsigned char *to, int to_stride,
-             const unsigned char *from, int from_stride,
-             const qpGeomVertexDataType *from_type,
-             int num_records) const {
-  int num_values_to_copy = min(get_num_values(), from_type->get_num_values());
-  int num_values_to_fill = get_num_values() - num_values_to_copy;
-
-  while (num_records > 0) {
-    int vi = 0;
-    while (vi < num_values_to_copy) {
-      float value = from_type->get_value(from, vi);
-      set_value(to, vi, value);
-      ++vi;
-    }
-    while (vi < num_values_to_fill) {
-      set_value(to, vi, 0.0f);
-      ++vi;
-    }
-
-    to += to_stride;
-    from += from_stride;
-    num_records--;
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexDataType::get_value
-//       Access: Private
-//  Description: Returns the nth value of the data type, expressed as
-//               a float.
-////////////////////////////////////////////////////////////////////
-float qpGeomVertexDataType::
-get_value(const unsigned char *data, int n) const {
-  switch (get_numeric_type()) {
-  case NT_uint16:
-    return (float)data[n];
-
-  case NT_uint8:
-    return (float)data[n] / 255.0f;
-
-  case qpGeomVertexDataType::NT_packed_8888:
-    {
-      int element = n / 4;
-      const PN_uint32 *int_array = (const PN_uint32 *)data;
-
-      PN_uint32 packed_argb = int_array[element];
-      switch (n % 4) {
-      case 0:
-        return (float)((packed_argb >> 16) & 0xff) / 255.0f;
-      case 1:
-        return (float)((packed_argb >> 8) & 0xff) / 255.0f;
-      case 2:
-        return (float)(packed_argb & 0xff) / 255.0f;
-      case 3:
-        return (float)((packed_argb >> 24) & 0xff) / 255.0f;
-      }
-    }
-    break;
-
-  case qpGeomVertexDataType::NT_float32:
-    {
-      const PN_float32 *float_array = (const PN_float32 *)data;
-      return float_array[n];
-    }
-  }
-
-  return 0.0f;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomVertexDataType::set_value
-//       Access: Private
-//  Description: Modifies the nth value of the data type.
-////////////////////////////////////////////////////////////////////
-void qpGeomVertexDataType::
-set_value(unsigned char *data, int n, float value) const {
-  switch (get_numeric_type()) {
-  case NT_uint16:
-    data[n] = (int)value;
-    break;
-
-  case NT_uint8:
-    data[n] = (int)(value * 255.0f);
-    break;
-
-  case qpGeomVertexDataType::NT_packed_8888:
-    {
-      int element = n / 4;
-
-      union {
-        PN_uint32 _packed_argb;
-        struct {
-          unsigned char _a;
-          unsigned char _r;
-          unsigned char _g;
-          unsigned char _b;
-        } _argb;
-      } color;
-
-      PN_uint32 *int_array = (PN_uint32 *)data;
-      color._packed_argb = int_array[element];
-      switch (n % 4) {
-      case 0:
-        color._argb._r = (int)(value * 255.0f);
-        break;
-      case 1:
-        color._argb._g = (int)(value * 255.0f);
-        break;
-      case 2:
-        color._argb._b = (int)(value * 255.0f);
-        break;
-      case 3:
-        color._argb._a = (int)(value * 255.0f);
-        break;
-      }
-      int_array[element] = color._packed_argb;
-    }
-    break;
-
-  case qpGeomVertexDataType::NT_float32:
-    PN_float32 *float_array = (PN_float32 *)data;
-    float_array[n] = value;
-    break;
-  }
-}

+ 5 - 28
panda/src/gobj/qpgeomVertexDataType.h

@@ -37,7 +37,7 @@ PUBLISHED:
   enum NumericType {
   enum NumericType {
     NT_uint8,        // An integer 0..255
     NT_uint8,        // An integer 0..255
     NT_uint16,       // An integer 0..65535
     NT_uint16,       // An integer 0..65535
-    NT_packed_8888,  // DirectX style, four byte values packed in a dword
+    NT_packed_8888,  // DirectX style, four byte values packed in a uint32
     NT_float32,      // A floating-point number
     NT_float32,      // A floating-point number
   };
   };
 
 
@@ -69,42 +69,19 @@ PUBLISHED:
   INLINE int get_total_bytes() const;
   INLINE int get_total_bytes() const;
 
 
   INLINE bool overlaps_with(int start_byte, int num_bytes) const;
   INLINE bool overlaps_with(int start_byte, int num_bytes) const;
+  INLINE bool is_bytewise_equivalent(const qpGeomVertexDataType &other) const;
 
 
   void output(ostream &out) const;
   void output(ostream &out) const;
 
 
 public:
 public:
+  INLINE bool is_packed_argb() const;
+  INLINE bool is_uint8_rgba() const;
+
   INLINE int compare_to(const qpGeomVertexDataType &other) const;
   INLINE int compare_to(const qpGeomVertexDataType &other) const;
   INLINE bool operator == (const qpGeomVertexDataType &other) const;
   INLINE bool operator == (const qpGeomVertexDataType &other) const;
   INLINE bool operator != (const qpGeomVertexDataType &other) const;
   INLINE bool operator != (const qpGeomVertexDataType &other) const;
   INLINE bool operator < (const qpGeomVertexDataType &other) const;
   INLINE bool operator < (const qpGeomVertexDataType &other) const;
 
 
-  void copy_records(unsigned char *to, int to_stride,
-                    const unsigned char *from, int from_stride,
-                    const qpGeomVertexDataType *from_type,
-                    int num_records) const;
-
-private:
-  void copy_no_convert(unsigned char *to, int to_stride,
-                       const unsigned char *from, int from_stride,
-                       const qpGeomVertexDataType *from_type,
-                       int num_records) const;
-  void copy_argb_to_uint8(unsigned char *to, int to_stride,
-                          const unsigned char *from, int from_stride,
-                          const qpGeomVertexDataType *from_type,
-                          int num_records) const;
-  void copy_uint8_to_argb(unsigned char *to, int to_stride,
-                          const unsigned char *from, int from_stride,
-                          const qpGeomVertexDataType *from_type,
-                          int num_records) const;
-
-  void copy_generic(unsigned char *to, int to_stride,
-                    const unsigned char *from, int from_stride,
-                    const qpGeomVertexDataType *from_type,
-                    int num_records) const;
-
-  float get_value(const unsigned char *data, int n) const;
-  void set_value(unsigned char *data, int n, float value) const;
-
 private:
 private:
   CPT(InternalName) _name;
   CPT(InternalName) _name;
   int _num_components;
   int _num_components;