From 7051a28f8e8e6ccd643d1aca3587faed9835be2d Mon Sep 17 00:00:00 2001 From: David Rose Date: Tue, 3 Mar 2009 23:15:10 +0000 Subject: [PATCH] more fixes to point rendering --- panda/src/gobj/config_gobj.cxx | 8 +++++ panda/src/gobj/config_gobj.h | 1 + panda/src/gobj/geom.I | 13 +++++++ panda/src/gobj/geom.cxx | 38 ++++++++++++++++++++ panda/src/gobj/geom.h | 2 ++ panda/src/gobj/geomPrimitive.I | 2 +- panda/src/gobj/geomPrimitive.cxx | 54 +++++++++++++++++++++++++++++ panda/src/gobj/geomPrimitive.h | 1 + panda/src/pgraph/cullableObject.cxx | 41 ++++++++++++++-------- 9 files changed, 145 insertions(+), 15 deletions(-) diff --git a/panda/src/gobj/config_gobj.cxx b/panda/src/gobj/config_gobj.cxx index 13024e019e..231d70a3cd 100644 --- a/panda/src/gobj/config_gobj.cxx +++ b/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 " diff --git a/panda/src/gobj/config_gobj.h b/panda/src/gobj/config_gobj.h index f35d3fed6a..a572dccfa6 100644 --- a/panda/src/gobj/config_gobj.h +++ b/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; diff --git a/panda/src/gobj/geom.I b/panda/src/gobj/geom.I index afc9e99adf..c8e498bcbc 100644 --- a/panda/src/gobj/geom.I +++ b/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 diff --git a/panda/src/gobj/geom.cxx b/panda/src/gobj/geom.cxx index 924a1dba8c..5a816456b7 100644 --- a/panda/src/gobj/geom.cxx +++ b/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 diff --git a/panda/src/gobj/geom.h b/panda/src/gobj/geom.h index 3b7ebe44d2..b52304f6d6 100644 --- a/panda/src/gobj/geom.h +++ b/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); diff --git a/panda/src/gobj/geomPrimitive.I b/panda/src/gobj/geomPrimitive.I index ae9ed95cb9..550cf19a91 100644 --- a/panda/src/gobj/geomPrimitive.I +++ b/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:: diff --git a/panda/src/gobj/geomPrimitive.cxx b/panda/src/gobj/geomPrimitive.cxx index d59de4f0e3..748c187ec6 100644 --- a/panda/src/gobj/geomPrimitive.cxx +++ b/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 diff --git a/panda/src/gobj/geomPrimitive.h b/panda/src/gobj/geomPrimitive.h index 5a31058f30..a115837e04 100644 --- a/panda/src/gobj/geomPrimitive.h +++ b/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; diff --git a/panda/src/pgraph/cullableObject.cxx b/panda/src/pgraph/cullableObject.cxx index c6b1b00d79..7c45589f3e 100644 --- a/panda/src/pgraph/cullableObject.cxx +++ b/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.