From ab8ebe6e302fd336169bdf114e0326d2142c91f3 Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 11 Oct 2014 01:28:32 +0000 Subject: [PATCH] Fix issues with point rendering, both software and hardware. --- .../glstuff/glGraphicsStateGuardian_src.cxx | 5 +- panda/src/gobj/geomPrimitive.I | 27 +++++++ panda/src/gobj/geomPrimitive.cxx | 50 +++++++++--- panda/src/gobj/geomPrimitive.h | 11 ++- panda/src/pgraph/cullableObject.cxx | 76 ++++++++++--------- panda/src/pgraph/transformState.cxx | 2 +- 6 files changed, 116 insertions(+), 55 deletions(-) diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 7a95f02a66..fda881333c 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -538,7 +538,7 @@ reset() { } } if (_supports_point_parameters) { - _supported_geom_rendering |= Geom::GR_point_perspective; + _supported_geom_rendering |= Geom::GR_point_perspective | Geom::GR_point_scale; } else { _glPointParameterfv = null_glPointParameterfv; } @@ -2764,7 +2764,7 @@ end_frame(Thread *current_thread) { // And deleted queries, too, unless we're using query timers // in which case we'll need to reuse lots of them. - if (!_timer_queries_active && !_deleted_queries.empty()) { + if (!get_timer_queries_active() && !_deleted_queries.empty()) { if (GLCAT.is_spam()) { DeletedNames::iterator dqi; for (dqi = _deleted_queries.begin(); @@ -11335,6 +11335,7 @@ do_point_size() { // matrix. LVector3 height(0.0f, _point_size, 1.0f); height = height * _projection_mat->get_mat(); + height = height * _internal_transform->get_scale()[1]; PN_stdfloat s = height[1] * _viewport_height / _point_size; if (_current_lens->is_orthographic()) { diff --git a/panda/src/gobj/geomPrimitive.I b/panda/src/gobj/geomPrimitive.I index bda47efc56..8b40eb0813 100644 --- a/panda/src/gobj/geomPrimitive.I +++ b/panda/src/gobj/geomPrimitive.I @@ -429,6 +429,17 @@ add_vertices(int v1, int v2, int v3, int v4) { add_vertex(v4); } +//////////////////////////////////////////////////////////////////// +// Function: GeomPrimitive::get_index_format +// Access: Public +// Description: Returns a registered format appropriate for using to +// store the index table. +//////////////////////////////////////////////////////////////////// +INLINE const GeomVertexArrayFormat *GeomPrimitive:: +get_index_format() const { + return get_index_format(get_index_type()); +} + //////////////////////////////////////////////////////////////////// // Function: GeomPrimitive::make_index_data // Access: Public @@ -439,6 +450,22 @@ make_index_data() const { return new GeomVertexArrayData(get_index_format(), get_usage_hint()); } +//////////////////////////////////////////////////////////////////// +// Function: GeomPrimitive::make_index_format +// Access: Private, Static +// Description: Returns a registered format appropriate for using to +// store the index table. +//////////////////////////////////////////////////////////////////// +INLINE CPT(GeomVertexArrayFormat) GeomPrimitive:: +make_index_format(NumericType index_type) { + PT(GeomVertexArrayFormat) format = new GeomVertexArrayFormat; + // It's important that the index format *not* respect the global + // setting of vertex-column-alignment. It needs to be tightly + // packed, so we specify an explict column_alignment of 1. + format->add_column(InternalName::get_index(), 1, index_type, C_index, 0, 1); + return GeomVertexArrayFormat::register_format(format); +} + //////////////////////////////////////////////////////////////////// // Function: GeomPrimitive::CData::Constructor // Access: Public diff --git a/panda/src/gobj/geomPrimitive.cxx b/panda/src/gobj/geomPrimitive.cxx index 8b7cb19e15..bd7643b971 100644 --- a/panda/src/gobj/geomPrimitive.cxx +++ b/panda/src/gobj/geomPrimitive.cxx @@ -1233,6 +1233,11 @@ set_vertices(const GeomVertexArrayData *vertices, int num_vertices) { cdata->_vertices = (GeomVertexArrayData *)vertices; cdata->_num_vertices = num_vertices; + // Validate the format and make sure to copy its numeric type. + const GeomVertexArrayFormat *format = vertices->get_array_format(); + nassertv(format->get_num_columns() == 1); + cdata->_index_type = format->get_column(0)->get_numeric_type(); + cdata->_modified = Geom::get_next_modified(); cdata->_got_minmax = false; } @@ -1564,18 +1569,41 @@ release_all() { //////////////////////////////////////////////////////////////////// // Function: GeomPrimitive::get_index_format -// Access: Public -// Description: Returns a registered format appropriate for using to -// store the index table. +// Access: Public, Static +// Description: Returns a registered GeomVertexArrayFormat of the +// indicated unsigned integer numeric type for storing +// index values. //////////////////////////////////////////////////////////////////// -CPT(GeomVertexArrayFormat) GeomPrimitive:: -get_index_format() const { - PT(GeomVertexArrayFormat) format = new GeomVertexArrayFormat; - // It's important that the index format *not* respect the global - // setting of vertex-column-alignment. It needs to be tightly - // packed, so we specify an explict column_alignment of 1. - format->add_column(InternalName::get_index(), 1, get_index_type(), C_index, 0, 1); - return GeomVertexArrayFormat::register_format(format); +const GeomVertexArrayFormat *GeomPrimitive:: +get_index_format(NumericType index_type) { + switch (index_type) { + case NT_uint8: + { + static CPT(GeomVertexArrayFormat) cformat = NULL; + if (cformat == NULL) { + cformat = make_index_format(NT_uint8); + } + return cformat; + } + case NT_uint16: + { + static CPT(GeomVertexArrayFormat) cformat = NULL; + if (cformat == NULL) { + cformat = make_index_format(NT_uint16); + } + return cformat; + } + case NT_uint32: + { + static CPT(GeomVertexArrayFormat) cformat = NULL; + if (cformat == NULL) { + cformat = make_index_format(NT_uint32); + } + return cformat; + } + } + + return NULL; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/geomPrimitive.h b/panda/src/gobj/geomPrimitive.h index ef26ad4977..298ea6dd90 100644 --- a/panda/src/gobj/geomPrimitive.h +++ b/panda/src/gobj/geomPrimitive.h @@ -185,15 +185,18 @@ public: void prepare(PreparedGraphicsObjects *prepared_objects); bool is_prepared(PreparedGraphicsObjects *prepared_objects) const; - IndexBufferContext *prepare_now(PreparedGraphicsObjects *prepared_objects, + IndexBufferContext *prepare_now(PreparedGraphicsObjects *prepared_objects, GraphicsStateGuardianBase *gsg); bool release(PreparedGraphicsObjects *prepared_objects); int release_all(); - CPT(GeomVertexArrayFormat) get_index_format() const; + static const GeomVertexArrayFormat *get_index_format(NumericType index_type); + INLINE const GeomVertexArrayFormat *get_index_format() const; INLINE PT(GeomVertexArrayData) make_index_data() const; private: + static CPT(GeomVertexArrayFormat) make_index_format(NumericType index_type); + void clear_prepared(PreparedGraphicsObjects *prepared_objects); static int get_highest_index_value(NumericType index_type); static int get_strip_cut_index(NumericType index_type); @@ -204,7 +207,7 @@ public: bool force) const=0; void calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, - bool &found_any, + bool &found_any, const GeomVertexData *vertex_data, bool got_mat, const LMatrix4 &mat, const InternalName *column_name, @@ -216,7 +219,7 @@ protected: virtual CPT(GeomPrimitive) doubleside_impl() const; virtual CPT(GeomPrimitive) reverse_impl() const; virtual bool requires_unused_vertices() const; - virtual void append_unused_vertices(GeomVertexArrayData *vertices, + virtual void append_unused_vertices(GeomVertexArrayData *vertices, int vertex); private: diff --git a/panda/src/pgraph/cullableObject.cxx b/panda/src/pgraph/cullableObject.cxx index 4ea54f5923..5f6d6d61b3 100644 --- a/panda/src/pgraph/cullableObject.cxx +++ b/panda/src/pgraph/cullableObject.cxx @@ -76,11 +76,11 @@ munge_geom(GraphicsStateGuardianBase *gsg, nassertr(geom_reader.check_valid(&data_reader), false); } #endif // _DEBUG - + 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) { @@ -90,7 +90,7 @@ munge_geom(GraphicsStateGuardianBase *gsg, } } } - + GraphicsStateGuardianBase *gsg = traverser->get_gsg(); int gsg_bits = gsg->get_supported_geom_rendering(); if (!hardware_point_sprites) { @@ -113,7 +113,7 @@ munge_geom(GraphicsStateGuardianBase *gsg, // _munged_data, and might also replace _state. if (pgraph_cat.is_spam()) { pgraph_cat.spam() - << "munge_points_to_quads() for geometry with bits: " + << "munge_points_to_quads() for geometry with bits: " << hex << geom_rendering << ", unsupported: " << (unsupported_bits & Geom::GR_point_bits) << dec << "\n"; } @@ -128,7 +128,7 @@ munge_geom(GraphicsStateGuardianBase *gsg, // If we have to compute the light vector, we have to animate // the vertices in the CPU--and we have to do it before we call // munge_geom(), which might lose the tangent and binormal. - CPT(GeomVertexData) animated_vertices = + CPT(GeomVertexData) animated_vertices = _munged_data->animate_vertices(force, current_thread); if (animated_vertices != _munged_data) { cpu_animated = true; @@ -154,7 +154,7 @@ munge_geom(GraphicsStateGuardianBase *gsg, // has been munged--that is, we couldn't arrange to handle the // animation in hardware--then we have to calculate that // animation now. - CPT(GeomVertexData) animated_vertices = + CPT(GeomVertexData) animated_vertices = _munged_data->animate_vertices(force, current_thread); if (animated_vertices != _munged_data) { cpu_animated = true; @@ -238,7 +238,7 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) { // Better get the animated vertices, in case we're showing sprites // on an animated model for some reason. - CPT(GeomVertexData) source_data = + CPT(GeomVertexData) source_data = _munged_data->animate_vertices(force, current_thread); if (!force && !source_data->request_resident()) { @@ -306,22 +306,22 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) { FormatMap::iterator fmi = _format_map.find(sformat); if (fmi != _format_map.end()) { new_format = (*fmi).second; - + } else { // We have to construct the format now. PT(GeomVertexArrayFormat) new_array_format; if (sformat._retransform_sprites) { // With retransform_sprites in effect, we will be sending ordinary // 3-D points to the graphics API. - new_array_format = - new GeomVertexArrayFormat(InternalName::get_vertex(), 3, + new_array_format = + new GeomVertexArrayFormat(InternalName::get_vertex(), 3, Geom::NT_stdfloat, Geom::C_point); } else { // Without retransform_sprites, we will be sending 4-component // clip-space points. - new_array_format = - new GeomVertexArrayFormat(InternalName::get_vertex(), 4, + new_array_format = + new GeomVertexArrayFormat(InternalName::get_vertex(), 4, Geom::NT_stdfloat, Geom::C_clip_point); } @@ -342,14 +342,14 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) { (InternalName::get_texcoord(), 2, Geom::NT_stdfloat, Geom::C_texcoord); - + } else if (has_texcoord) { const GeomVertexColumn *c = texcoord.get_column(); new_array_format->add_column (InternalName::get_texcoord(), c->get_num_components(), c->get_numeric_type(), c->get_contents()); } - + new_format = GeomVertexFormat::register_format(new_array_format); _format_map[sformat] = new_format; } @@ -406,7 +406,7 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) { LPoint3 eye = modelview.xform_point(vertex.get_data3()); points[vi]._eye = eye; points[vi]._dist = gsg->compute_distance_to(points[vi]._eye); - + // The point in clip coordinates. LPoint4 p4 = LPoint4(eye[0], eye[1], eye[2], 1.0f) * projection; @@ -431,7 +431,7 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) { scale_y /= gsg->compute_distance_to(eye); } } - + // Also factor in the homogeneous scale for being in clip // coordinates still. scale_y *= p4[3]; @@ -445,7 +445,7 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) { LPoint2 c0(scale_x, scale_y); LPoint2 c1(-scale_x, scale_y); - if (has_rotate) { + if (has_rotate) { // If we have a rotate factor, apply it to those two corners. PN_stdfloat r = rotate.get_data1f(); LMatrix3 mat = LMatrix3::rotate_mat(r); @@ -459,7 +459,7 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) { PN_stdfloat ry = 1.0f / viewport_height; c0.set(c0[0] * rx, c0[1] * ry); c1.set(c1[0] * rx, c1[1] * ry); - + if (retransform_sprites) { // With retransform_sprites in effect, we must reconvert the // resulting quad back into the original 3-D space. @@ -467,7 +467,7 @@ 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] - 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); @@ -475,7 +475,7 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) { new_normal.set_data3(c); new_normal.set_data3(c); } - + } else { // Without retransform_sprites, we can simply load the // clip-space coordinates. @@ -483,7 +483,7 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) { new_vertex.set_data4(p4[0] + c1[0], p4[1] + c1[1], p4[2], p4[3]); new_vertex.set_data4(p4[0] - c1[0], p4[1] - c1[1], p4[2], p4[3]); new_vertex.set_data4(p4[0] - c0[0], p4[1] - c0[1], p4[2], p4[3]); - + if (has_normal) { LNormal c = render_transform.xform_vec(normal.get_data3()); new_normal.set_data3(c); @@ -519,18 +519,20 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) { nassertr(new_data->get_num_rows() == new_verts, false); } - PT(Geom) new_geom = new Geom(new_data); - - // Create an appropriate GeomVertexArrayFormat for the primitive - // index. - static CPT(GeomVertexArrayFormat) new_prim_format; - if (new_prim_format == (GeomVertexArrayFormat *)NULL) { - new_prim_format = - GeomVertexArrayFormat::register_format - (new GeomVertexArrayFormat(InternalName::get_index(), 1, - GeomEnums::NT_uint16, GeomEnums::C_index)); + // Determine the format we should use to store the indices. + const GeomVertexArrayFormat *new_prim_format = NULL; + if (new_verts < 0xff) { + new_prim_format = GeomPrimitive::get_index_format(GeomEnums::NT_uint8); + + } else if (new_verts < 0xffff) { + new_prim_format = GeomPrimitive::get_index_format(GeomEnums::NT_uint16); + + } else { + new_prim_format = GeomPrimitive::get_index_format(GeomEnums::NT_uint32); } + PT(Geom) new_geom = new Geom(new_data); + // Replace each primitive in the Geom (it's presumably a GeomPoints // primitive, although it might be some other kind of primitive if // we got here because RenderModeAttrib::M_point is enabled) with a @@ -573,11 +575,11 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) { vertices[i] = v; } } - + // Now sort the points in order from back-to-front so they will // render properly with transparency, at least with each other. sort(vertices, vertices_end, SortPoints(points)); - + // Go through the points, now in sorted order, and generate a pair // of triangles for each one. We generate indexed triangles // instead of two-triangle strips, since this seems to be @@ -587,7 +589,7 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) { PT(GeomPrimitive) new_primitive = new GeomTriangles(Geom::UH_stream); int new_prim_verts = 6 * num_vertices; // two triangles per point. - PT(GeomVertexArrayData) new_index + PT(GeomVertexArrayData) new_index = new GeomVertexArrayData(new_prim_format, GeomEnums::UH_stream); new_index->unclean_set_num_rows(new_prim_verts); @@ -667,14 +669,14 @@ munge_texcoord_light_vector(const CullTraverser *traverser, bool force) { string source_name = tex_gen->get_source_name(stage); Light *light_obj = light.node()->as_light(); nassertr(light_obj != (Light *)NULL, false); - + // Determine the names of the tangent and binormal columns // associated with the stage's texcoord name. PT(InternalName) tangent_name = InternalName::get_tangent_name(source_name); PT(InternalName) binormal_name = InternalName::get_binormal_name(source_name); - + PT(InternalName) texcoord_name = stage->get_texcoord_name(); - + if (_munged_data->has_column(tangent_name) && _munged_data->has_column(binormal_name)) { diff --git a/panda/src/pgraph/transformState.cxx b/panda/src/pgraph/transformState.cxx index 84fa387080..a9ec305914 100644 --- a/panda/src/pgraph/transformState.cxx +++ b/panda/src/pgraph/transformState.cxx @@ -2322,7 +2322,7 @@ do_calc_components() { _hpr.set(0.0f, 0.0f, 0.0f); _quat = LQuaternion::ident_quat(); _pos.set(0.0f, 0.0f, 0.0f); - _flags |= F_has_components | F_components_known | F_hpr_known | F_quat_known | F_uniform_scale; + _flags |= F_has_components | F_components_known | F_hpr_known | F_quat_known | F_uniform_scale | F_identity_scale; } else { // If we don't have components and we're not identity, the only