From 18bb8a5559f8db69283ca1505e1d047c9de4d2ab Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 23 Feb 2020 14:48:57 +0100 Subject: [PATCH] pgraph: fix for additional columns in munge_points_to_quads() Fixes #870 --- panda/src/pgraph/cullableObject.cxx | 138 +++++++++++++++++++--------- 1 file changed, 94 insertions(+), 44 deletions(-) diff --git a/panda/src/pgraph/cullableObject.cxx b/panda/src/pgraph/cullableObject.cxx index 920e524659..38f35f7024 100644 --- a/panda/src/pgraph/cullableObject.cxx +++ b/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 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 © : 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;