Browse Source

pgraph: fix for additional columns in munge_points_to_quads()

Fixes #870
rdb 5 years ago
parent
commit
18bb8a5559
1 changed files with 94 additions and 44 deletions
  1. 94 44
      panda/src/pgraph/cullableObject.cxx

+ 94 - 44
panda/src/pgraph/cullableObject.cxx

@@ -223,29 +223,23 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
     return false;
   }
 
+  GeomVertexDataPipelineReader reader(source_data, current_thread);
+  reader.check_array_readers();
+
   PStatTimer timer(_munge_sprites_pcollector, current_thread);
-  _sw_sprites_pcollector.add_level(source_data->get_num_rows());
+  _sw_sprites_pcollector.add_level(reader.get_num_rows());
 
   GraphicsStateGuardianBase *gsg = traverser->get_gsg();
 
-  GeomVertexReader vertex(source_data, InternalName::get_vertex(),
-                          current_thread);
-  GeomVertexReader normal(source_data, InternalName::get_normal(),
-                          current_thread);
-  GeomVertexReader color(source_data, InternalName::get_color(),
-                         current_thread);
-  GeomVertexReader texcoord(source_data, InternalName::get_texcoord(),
-                            current_thread);
-  GeomVertexReader rotate(source_data, InternalName::get_rotate(),
-                          current_thread);
-  GeomVertexReader size(source_data, InternalName::get_size(),
-                        current_thread);
-  GeomVertexReader aspect_ratio(source_data, InternalName::get_aspect_ratio(),
-                                current_thread);
+  GeomVertexReader vertex(&reader, InternalName::get_vertex());
+  GeomVertexReader normal(&reader, InternalName::get_normal());
+  GeomVertexReader rotate(&reader, InternalName::get_rotate());
+  GeomVertexReader size(&reader, InternalName::get_size());
+  GeomVertexReader aspect_ratio(&reader, InternalName::get_aspect_ratio());
 
   bool has_normal = (normal.has_column());
-  bool has_color = (color.has_column());
-  bool has_texcoord = (texcoord.has_column());
+  bool has_color = (reader.has_column(InternalName::get_color()));
+  bool has_texcoord = (reader.has_column(InternalName::get_texcoord()));
   bool has_rotate = (rotate.has_column());
   bool has_size = (size.has_column());
   bool has_aspect_ratio = (aspect_ratio.has_column());
@@ -280,7 +274,7 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
 
   {
     LightMutexHolder holder(_format_lock);
-    SourceFormat sformat(source_data->get_format(), sprite_texcoord);
+    SourceFormat sformat(reader.get_format(), sprite_texcoord);
     FormatMap::iterator fmi = _format_map.find(sformat);
     if (fmi != _format_map.end()) {
       new_format = (*fmi).second;
@@ -304,13 +298,13 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
                                     Geom::C_clip_point);
       }
       if (has_normal) {
-        const GeomVertexColumn *c = normal.get_column();
+        const GeomVertexColumn *c = reader.get_format()->get_normal_column();
         new_array_format->add_column
           (InternalName::get_normal(), c->get_num_components(),
            c->get_numeric_type(), c->get_contents());
       }
       if (has_color) {
-        const GeomVertexColumn *c = color.get_column();
+        const GeomVertexColumn *c = reader.get_format()->get_color_column();
         new_array_format->add_column
           (InternalName::get_color(), c->get_num_components(),
            c->get_numeric_type(), c->get_contents());
@@ -322,12 +316,34 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
            Geom::C_texcoord);
 
       } else if (has_texcoord) {
-        const GeomVertexColumn *c = texcoord.get_column();
+        const GeomVertexColumn *c = reader.get_format()->get_column(InternalName::get_texcoord());
         new_array_format->add_column
           (InternalName::get_texcoord(), c->get_num_components(),
            c->get_numeric_type(), c->get_contents());
       }
 
+      // Go through the other columns and copy them from the original.
+      for (size_t ai = 0; ai < sformat._format->get_num_arrays(); ++ai) {
+        const GeomVertexArrayFormat *aformat = sformat._format->get_array(ai);
+
+        for (size_t ci = 0; ci < aformat->get_num_columns(); ++ci) {
+          const GeomVertexColumn *column = aformat->get_column(ci);
+          const InternalName *name = column->get_name();
+          if (name != InternalName::get_vertex() &&
+              name != InternalName::get_normal() &&
+              name != InternalName::get_color() &&
+              name != InternalName::get_texcoord() &&
+              name != InternalName::get_rotate() &&
+              name != InternalName::get_size() &&
+              name != InternalName::get_aspect_ratio()) {
+
+            new_array_format->add_column(name,
+              column->get_num_components(), column->get_numeric_type(),
+              column->get_contents());
+          }
+        }
+      }
+
       new_format = GeomVertexFormat::register_format(new_array_format);
       _format_map[sformat] = new_format;
     }
@@ -362,7 +378,7 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
   // Now convert all of the vertices in the GeomVertexData to quads.  We
   // always convert all the vertices, assuming all the vertices are referenced
   // by GeomPrimitives, because we want to optimize for the most common case.
-  int orig_verts = source_data->get_num_rows();
+  int orig_verts = reader.get_num_rows();
   int new_verts = 4 * orig_verts;        // each vertex becomes four.
 
   PT(GeomVertexData) new_data = new GeomVertexData
@@ -371,9 +387,50 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
 
   GeomVertexWriter new_vertex(new_data, InternalName::get_vertex());
   GeomVertexWriter new_normal(new_data, InternalName::get_normal());
-  GeomVertexWriter new_color(new_data, InternalName::get_color());
   GeomVertexWriter new_texcoord(new_data, InternalName::get_texcoord());
 
+  nassertr(new_vertex.has_column(), false);
+  unsigned char *write_ptr = new_vertex.get_array_handle()->get_write_pointer();
+
+  // Collect all other columns that we just need to copy the data of.
+  struct CopyOp {
+    unsigned char *_to_pointer;
+    const unsigned char *_from_pointer;
+    size_t _num_bytes;
+    size_t _from_stride;
+  };
+  pvector<CopyOp> copies;
+
+  const GeomVertexArrayFormat *aformat = new_format->get_array(0);
+  for (size_t ci = 0; ci < aformat->get_num_columns(); ++ci) {
+    const GeomVertexColumn *column = aformat->get_column(ci);
+    const InternalName *name = column->get_name();
+    if (name != InternalName::get_vertex() &&
+        (retransform_sprites || name != InternalName::get_normal()) &&
+        (!sprite_texcoord || name != InternalName::get_texcoord())) {
+
+      int source_array;
+      const GeomVertexColumn *source_column;
+      if (reader.get_format()->get_array_info(name, source_array, source_column)) {
+        CopyOp copy;
+        copy._to_pointer = write_ptr + (size_t)column->get_start();
+        copy._from_pointer = reader.get_array_reader(source_array)->get_read_pointer(true) + (size_t)source_column->get_start();
+        copy._num_bytes = (size_t)column->get_total_bytes();
+        copy._from_stride = reader.get_format()->get_array(source_array)->get_stride();
+
+        if (!copies.empty() &&
+            (copy._to_pointer == copies.back()._to_pointer + copies.back()._num_bytes) &&
+            (copy._from_pointer == copies.back()._from_pointer + copies.back()._num_bytes)) {
+          // Merge with previous.
+          copies.back()._num_bytes += copy._num_bytes;
+        } else {
+          copies.push_back(copy);
+        }
+      }
+    }
+  }
+  size_t to_stride = aformat->get_stride();
+
   // We'll keep an array of all of the points' eye-space coordinates, and
   // their distance from the camera, so we can sort the points for each
   // primitive, below.
@@ -447,14 +504,6 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
         new_vertex.set_data4(inv_render_transform.xform(LPoint4(p4[0] - c1[0], p4[1] - c1[1], p4[2], p4[3])));
         new_vertex.set_data4(inv_render_transform.xform(LPoint4(p4[0] - c0[0], p4[1] - c0[1], p4[2], p4[3])));
 
-        if (has_normal) {
-          const LNormal &c = normal.get_data3();
-          new_normal.set_data3(c);
-          new_normal.set_data3(c);
-          new_normal.set_data3(c);
-          new_normal.set_data3(c);
-        }
-
       } else {
         // Without retransform_sprites, we can simply load the clip-space
         // coordinates.
@@ -464,6 +513,7 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
         new_vertex.set_data4(p4[0] - c0[0], p4[1] - c0[1], p4[2], p4[3]);
 
         if (has_normal) {
+          // We need to transform the normals to clip-space too, then.
           LNormal c = render_transform.xform_vec(normal.get_data3());
           new_normal.set_data3(c);
           new_normal.set_data3(c);
@@ -471,24 +521,24 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
           new_normal.set_data3(c);
         }
       }
-      if (has_color) {
-        const LColor &c = color.get_data4();
-        new_color.set_data4(c);
-        new_color.set_data4(c);
-        new_color.set_data4(c);
-        new_color.set_data4(c);
-      }
       if (sprite_texcoord) {
         new_texcoord.set_data2(1.0f, 0.0f);
         new_texcoord.set_data2(0.0f, 0.0f);
         new_texcoord.set_data2(1.0f, 1.0f);
         new_texcoord.set_data2(0.0f, 1.0f);
-      } else if (has_texcoord) {
-        const LVecBase4 &c = texcoord.get_data4();
-        new_texcoord.set_data4(c);
-        new_texcoord.set_data4(c);
-        new_texcoord.set_data4(c);
-        new_texcoord.set_data4(c);
+      }
+
+      // Other columns are simply duplicated for each vertex.
+      for (CopyOp &copy : copies) {
+        memcpy(copy._to_pointer, copy._from_pointer, copy._num_bytes);
+        copy._to_pointer += to_stride;
+        memcpy(copy._to_pointer, copy._from_pointer, copy._num_bytes);
+        copy._to_pointer += to_stride;
+        memcpy(copy._to_pointer, copy._from_pointer, copy._num_bytes);
+        copy._to_pointer += to_stride;
+        memcpy(copy._to_pointer, copy._from_pointer, copy._num_bytes);
+        copy._to_pointer += to_stride;
+        copy._from_pointer += copy._from_stride;
       }
 
       ++vi;