Browse Source

more fixes to point rendering

David Rose 17 years ago
parent
commit
7051a28f8e

+ 8 - 0
panda/src/gobj/config_gobj.cxx

@@ -197,6 +197,14 @@ ConfigVariableBool hardware_points
           "rendering large points.  When false, large points (even if "
           "untextured) will be simulated via quads computed in software."));
 
+ConfigVariableBool singular_points
+("singular-points", true,
+ PRC_DESC("Set this true to insist that when RenderModeAttrib::M_points is "
+          "used, each point appears only once in the result, even if "
+          "the vertex is referenced multiple times.  This is particularly "
+          "important when rendering points from a triangle mesh and you "
+          "don't want the points to appear repeatedly."));
+
 ConfigVariableBool matrix_palette
 ("matrix-palette", false,
  PRC_DESC("Set this true to allow the use of the matrix palette when "

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

@@ -63,6 +63,7 @@ extern EXPCL_PANDA_GOBJ ConfigVariableBool display_lists;
 extern EXPCL_PANDA_GOBJ ConfigVariableBool hardware_animated_vertices;
 extern EXPCL_PANDA_GOBJ ConfigVariableBool hardware_point_sprites;
 extern EXPCL_PANDA_GOBJ ConfigVariableBool hardware_points;
+extern EXPCL_PANDA_GOBJ ConfigVariableBool singular_points;
 extern EXPCL_PANDA_GOBJ ConfigVariableBool matrix_palette;
 extern EXPCL_PANDA_GOBJ ConfigVariableBool display_list_animation;
 extern EXPCL_PANDA_GOBJ ConfigVariableBool connect_triangle_strips;

+ 13 - 0
panda/src/gobj/geom.I

@@ -230,6 +230,19 @@ unify(int max_indices, bool preserve_order) const {
   return new_geom;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: Geom::make_points
+//       Access: Published
+//  Description: Returns a new Geom with points at all the vertices.
+//               See GeomPrimitive::make_points().
+////////////////////////////////////////////////////////////////////
+INLINE PT(Geom) Geom::
+make_points() const {
+  PT(Geom) new_geom = make_copy();
+  new_geom->make_points_in_place();
+  return new_geom;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: Geom::get_modified
 //       Access: Published

+ 38 - 0
panda/src/gobj/geom.cxx

@@ -737,6 +737,44 @@ unify_in_place(int max_indices, bool preserve_order) {
   reset_geom_rendering(cdata);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: Geom::make_points_in_place
+//       Access: Published
+//  Description: Replaces the GeomPrimitives within this Geom with
+//               corresponding GeomPoints.  See
+//               GeomPrimitive::make_points().
+//
+//               Don't call this in a downstream thread unless you
+//               don't mind it blowing away other changes you might
+//               have recently made in an upstream thread.
+////////////////////////////////////////////////////////////////////
+void Geom::
+make_points_in_place() {
+  Thread *current_thread = Thread::get_current_thread();
+  CDWriter cdata(_cycler, true, current_thread);
+
+#ifndef NDEBUG
+  bool all_is_valid = true;
+#endif
+  Primitives::iterator pi;
+  for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
+    CPT(GeomPrimitive) new_prim = (*pi).get_read_pointer()->make_points();
+    (*pi) = (GeomPrimitive *)new_prim.p();
+
+#ifndef NDEBUG
+    if (!new_prim->check_valid(cdata->_data.get_read_pointer())) {
+      all_is_valid = false;
+    }
+#endif
+  }
+
+  cdata->_modified = Geom::get_next_modified();
+  reset_geom_rendering(cdata);
+  clear_cache_stage(current_thread);
+
+  nassertv(all_is_valid);
+}
+
 
 ////////////////////////////////////////////////////////////////////
 //     Function: Geom::copy_primitives_from

+ 2 - 0
panda/src/gobj/geom.h

@@ -101,12 +101,14 @@ PUBLISHED:
   INLINE PT(Geom) reverse() const;
   INLINE PT(Geom) rotate() const;
   INLINE PT(Geom) unify(int max_indices, bool preserve_order) const;
+  INLINE PT(Geom) make_points() const;
 
   void decompose_in_place();
   void doubleside_in_place();
   void reverse_in_place();
   void rotate_in_place();
   void unify_in_place(int max_indices, bool preserve_order);
+  void make_points_in_place();
 
   virtual bool copy_primitives_from(const Geom *other);
 

+ 1 - 1
panda/src/gobj/geomPrimitive.I

@@ -129,7 +129,7 @@ get_first_vertex() const {
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomPrimitive::get_num_vertices
 //       Access: Published
-//  Description: Returns the number of vertex vertices used by all the
+//  Description: Returns the number of vertices used by all the
 //               primitives in this object.
 ////////////////////////////////////////////////////////////////////
 INLINE int GeomPrimitive::

+ 54 - 0
panda/src/gobj/geomPrimitive.cxx

@@ -20,6 +20,7 @@
 #include "geomVertexReader.h"
 #include "geomVertexWriter.h"
 #include "geomVertexRewriter.h"
+#include "geomPoints.h"
 #include "preparedGraphicsObjects.h"
 #include "internalName.h"
 #include "bamReader.h"
@@ -831,6 +832,59 @@ match_shade_model(GeomPrimitive::ShadeModel shade_model) const {
   return NULL;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GeomPrimitive::make_points
+//       Access: Published
+//  Description: Returns a new GeomPoints primitive that represents
+//               each of the vertices in the original primitive,
+//               rendered exactly once.  If the original primitive is
+//               already a GeomPoints primitive, returns the original
+//               primitive unchanged.
+////////////////////////////////////////////////////////////////////
+CPT(GeomPrimitive) GeomPrimitive::
+make_points() const {
+  if (is_exact_type(GeomPoints::get_class_type())) {
+    return this;
+  }
+
+  // First, get a list of all of the vertices referenced by the
+  // original primitive.
+  BitArray bits;
+  int num_vertices = get_num_vertices();
+  if (is_indexed()) {
+    CPT(GeomVertexArrayData) vertices = get_vertices();
+    GeomVertexReader index(vertices, 0);
+    for (int vi = 0; vi < num_vertices; ++vi) {
+      nassertr(!index.is_at_end(), NULL);
+      bits.set_bit(index.get_data1i());
+    }
+  } else {
+    int first_vertex = get_first_vertex();
+    bits.set_range(first_vertex, num_vertices);
+  }
+
+  // Now construct a new index array with just those bits.
+  PT(GeomVertexArrayData) new_vertices = make_index_data();
+  GeomVertexWriter new_index(new_vertices, 0);
+  int p = bits.get_lowest_on_bit();
+  while (p != -1) {
+    while (bits.get_bit(p)) {
+      new_index.add_data1i(p);
+      ++p;
+    }
+    int q = bits.get_next_higher_different_bit(p);
+    if (q == p) {
+      break;
+    }
+    p = q;
+  }
+
+  PT(GeomPrimitive) points = new GeomPoints(UH_dynamic);
+  points->set_vertices(new_vertices);
+
+  return points;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomPrimitive::get_num_bytes
 //       Access: Published

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

@@ -130,6 +130,7 @@ PUBLISHED:
   CPT(GeomPrimitive) doubleside() const;
   CPT(GeomPrimitive) reverse() const;
   CPT(GeomPrimitive) match_shade_model(ShadeModel shade_model) const;
+  CPT(GeomPrimitive) make_points() const;
 
   int get_num_bytes() const;
   INLINE int get_data_size_bytes() const;

+ 27 - 14
panda/src/pgraph/cullableObject.cxx

@@ -62,20 +62,33 @@ munge_geom(GraphicsStateGuardianBase *gsg,
   if (_geom != (Geom *)NULL) {
     _munger = munger;
 
-    GeomPipelineReader geom_reader(_geom, current_thread);
-    _munged_data = geom_reader.get_vertex_data();
+    int geom_rendering;
 
-#ifdef _DEBUG
     {
-      GeomVertexDataPipelineReader data_reader(_munged_data, current_thread);
-      data_reader.check_array_readers();
-      nassertr(geom_reader.check_valid(&data_reader), false);
-    }
+      GeomPipelineReader geom_reader(_geom, current_thread);
+      _munged_data = geom_reader.get_vertex_data();
+      
+#ifdef _DEBUG
+      {
+        GeomVertexDataPipelineReader data_reader(_munged_data, current_thread);
+        data_reader.check_array_readers();
+        nassertr(geom_reader.check_valid(&data_reader), false);
+      }
 #endif  // _DEBUG
-
-    int geom_rendering = geom_reader.get_geom_rendering();
-    geom_rendering = _state->get_geom_rendering(geom_rendering);
-    geom_rendering = _modelview_transform->get_geom_rendering(geom_rendering);
+      
+      geom_rendering = geom_reader.get_geom_rendering();
+      geom_rendering = _state->get_geom_rendering(geom_rendering);
+      geom_rendering = _modelview_transform->get_geom_rendering(geom_rendering);
+      
+      if (geom_rendering & Geom::GR_point_bits) {
+        if (geom_reader.get_primitive_type() != Geom::PT_points) {
+          if (singular_points) {
+            // Isolate the points so there's no unneeded overlap.
+            _geom = _geom->make_points();
+          }
+        }
+      }
+    }
     
     GraphicsStateGuardianBase *gsg = traverser->get_gsg();
     int gsg_bits = gsg->get_supported_geom_rendering();
@@ -356,9 +369,9 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
   inv_render_transform.invert_from(render_transform);
 
   // Now convert all of the vertices in the GeomVertexData to quads.
-  // We always convert all the vertices, assuming all the vertices
-  // will referenced by GeomPrimitives, because we want to optimize
-  // for the most common case.
+  // 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 new_verts = 4 * orig_verts;        // each vertex becomes four.