diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx index 4d97dafa17..9510ad1b02 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx @@ -2677,7 +2677,7 @@ begin_draw_primitives(const qpGeomVertexData *vertex_data) { //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian8:: draw_triangles(const qpGeomTriangles *primitive) { - HRESULT hr = _pD3DDevice->DrawIndexedPrimitiveUP + _pD3DDevice->DrawIndexedPrimitiveUP (D3DPT_TRIANGLELIST, primitive->get_min_vertex(), primitive->get_max_vertex() - primitive->get_min_vertex() + 1, @@ -2686,8 +2686,37 @@ draw_triangles(const qpGeomTriangles *primitive) { D3DFMT_INDEX16, _vertex_data->get_array_data(0), _vertex_data->get_format()->get_array(0)->get_stride()); +} - TestDrawPrimFailure(DrawPrim,hr,_pD3DDevice,nPrims,0); +//////////////////////////////////////////////////////////////////// +// Function: DXGraphicsStateGuardian8::draw_tristrips +// Access: Public, Virtual +// Description: Draws a series of triangle strips. +//////////////////////////////////////////////////////////////////// +void DXGraphicsStateGuardian8:: +draw_tristrips(const qpGeomTristrips *primitive) { + int min_vertex = primitive->get_min_vertex(); + int max_vertex = primitive->get_max_vertex(); + CPTA_ushort vertices = primitive->get_flat_first_vertices(); + CPTA_int ends = primitive->get_ends(); + + CPTA_uchar array_data = _vertex_data->get_array_data(0); + int stride = _vertex_data->get_format()->get_array(0)->get_stride(); + + int num_primitives = primitive->get_num_primitives(); + int start = 0; + for (CPTA_int::const_iterator pi = ends.begin(); pi != ends.end(); ++pi) { + int end = (*pi); + + _pD3DDevice->DrawIndexedPrimitiveUP + (D3DPT_TRIANGLESTRIP, + min_vertex, max_vertex - min_vertex + 1, + end - start - 2, + vertices + start, D3DFMT_INDEX16, + array_data, stride); + + start = end; + } } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.h b/panda/src/dxgsg8/dxGraphicsStateGuardian8.h index d9ab3a99b0..12d8aaae14 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.h +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.h @@ -92,6 +92,7 @@ public: virtual bool begin_draw_primitives(const qpGeomVertexData *vertex_data); virtual void draw_triangles(const qpGeomTriangles *primitive); + virtual void draw_tristrips(const qpGeomTristrips *primitive); virtual void end_draw_primitives(); virtual TextureContext *prepare_texture(Texture *tex); diff --git a/panda/src/egg/eggCompositePrimitive.cxx b/panda/src/egg/eggCompositePrimitive.cxx index 414c7955d8..874360623a 100644 --- a/panda/src/egg/eggCompositePrimitive.cxx +++ b/panda/src/egg/eggCompositePrimitive.cxx @@ -145,6 +145,11 @@ unify_attributes(EggPrimitive::Shading shading) { shading = get_shading(); } + // Not having a color is implicitly white. + if (!has_color()) { + set_color(Colorf(1.0f, 1.0f, 1.0f, 1.0f)); + } + switch (shading) { case S_per_vertex: // Propagate everything to the vertices. diff --git a/panda/src/egg/eggGroupNode.cxx b/panda/src/egg/eggGroupNode.cxx index a2235a7d9a..d77b3a1ec5 100644 --- a/panda/src/egg/eggGroupNode.cxx +++ b/panda/src/egg/eggGroupNode.cxx @@ -771,9 +771,11 @@ mesh_triangles(int flags) { // Access: Published // Description: Removes all vertices from VertexPools within this // group or below that are not referenced by at least -// one primitive. Also renumbers all vertices after the +// one primitive. Also collapses together equivalent +// vertices, and renumbers all vertices after the // operation so their indices are consecutive, beginning -// at zero. Returns the total number of vertices removed. +// at zero. Returns the total number of vertices +// removed. // // Note that this operates on the VertexPools within // this group level, without respect to primitives that diff --git a/panda/src/egg/eggPrimitive.I b/panda/src/egg/eggPrimitive.I index fa62fb3d66..966b1ca053 100644 --- a/panda/src/egg/eggPrimitive.I +++ b/panda/src/egg/eggPrimitive.I @@ -102,9 +102,9 @@ clear_connected_shading() { // EggGroupNode). //////////////////////////////////////////////////////////////////// INLINE EggPrimitive::Shading EggPrimitive:: -get_connected_shading() { +get_connected_shading() const { if (_connected_shading == S_unknown) { - set_connected_shading(S_unknown, this); + ((EggPrimitive *)this)->set_connected_shading(S_unknown, this); } return _connected_shading; @@ -150,7 +150,7 @@ has_texture() const { INLINE bool EggPrimitive:: has_texture(EggTexture *texture) const { PT_EggTexture t = texture; - return (find(_textures.begin(), _textures.end(), t) != _textures.end()); + return (::find(_textures.begin(), _textures.end(), t) != _textures.end()); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/egg/eggPrimitive.cxx b/panda/src/egg/eggPrimitive.cxx index 8053306120..35deea3ffd 100644 --- a/panda/src/egg/eggPrimitive.cxx +++ b/panda/src/egg/eggPrimitive.cxx @@ -352,6 +352,11 @@ unify_attributes(EggPrimitive::Shading shading) { shading = get_shading(); } + // Not having a color is implicitly white. + if (!has_color()) { + set_color(Colorf(1.0f, 1.0f, 1.0f, 1.0f)); + } + switch (shading) { case S_per_vertex: // Propagate everything to the vertices. @@ -659,6 +664,19 @@ erase(iterator first, iterator last) { return result; } +//////////////////////////////////////////////////////////////////// +// Function: EggPrimitive::find +// Access: Public +// Description: Returns the iterator pointing to the indicated +// vertex, or end() if the vertex is not part of the +// primitive. +//////////////////////////////////////////////////////////////////// +EggPrimitive::iterator EggPrimitive:: +find(EggVertex *vertex) { + PT_EggVertex vpt = vertex; + return ::find(begin(), end(), vpt); +} + //////////////////////////////////////////////////////////////////// // Function: EggPrimitive::add_vertex @@ -688,7 +706,7 @@ add_vertex(EggVertex *vertex) { EggVertex *EggPrimitive:: remove_vertex(EggVertex *vertex) { PT_EggVertex vpt = vertex; - iterator i = find(begin(), end(), vpt); + iterator i = ::find(begin(), end(), vpt); if (i == end()) { return PT_EggVertex(); } else { @@ -1129,10 +1147,24 @@ set_connected_shading(EggPrimitive::Shading shading, // If both neighbors are overall shaded, check if the two // neighbors have different properties. If they do, elevate to // per_face. - if (!matches_normal(*neighbor) || !matches_color(*neighbor)) { + bool matches_normal = this->matches_normal(*neighbor); + bool matches_color = this->matches_color(*neighbor); + + if (!matches_color) { + // Make a special case for not having an overall color: that's + // implicitly white. + if (!neighbor->has_color() && has_color() && _drgbas.empty() && + get_color() == Colorf(1.0f, 1.0f, 1.0f, 1.0f)) { + matches_color = true; + } else if (!has_color() && neighbor->has_color() && neighbor->_drgbas.empty() && + neighbor->get_color() == Colorf(1.0f, 1.0f, 1.0f, 1.0f)) { + matches_color = true; + } + } + if (!matches_normal || !matches_color) { _connected_shading = S_per_face; propagate = true; - } + } } if (propagate) { diff --git a/panda/src/egg/eggPrimitive.h b/panda/src/egg/eggPrimitive.h index 0393651d7f..34e1c0442d 100644 --- a/panda/src/egg/eggPrimitive.h +++ b/panda/src/egg/eggPrimitive.h @@ -89,7 +89,7 @@ PUBLISHED: virtual Shading get_shading() const; INLINE void clear_connected_shading(); - INLINE Shading get_connected_shading(); + INLINE Shading get_connected_shading() const; INLINE void set_texture(EggTexture *texture); INLINE bool has_texture() const; @@ -163,6 +163,7 @@ public: INLINE iterator erase(iterator position); iterator erase(iterator first, iterator last); INLINE void replace(iterator position, EggVertex *vertex); + iterator find(EggVertex *vertex); PUBLISHED: INLINE void clear(); @@ -178,6 +179,8 @@ PUBLISHED: INLINE EggVertexPool *get_pool() const; + virtual void write(ostream &out, int indent_level) const=0; + #ifndef NDEBUG void test_vref_integrity() const; #else diff --git a/panda/src/egg/eggVertexPool.cxx b/panda/src/egg/eggVertexPool.cxx index 8b7cb0e8f3..7cb885670c 100644 --- a/panda/src/egg/eggVertexPool.cxx +++ b/panda/src/egg/eggVertexPool.cxx @@ -475,8 +475,9 @@ remove_vertex(EggVertex *vertex) { // Function: EggVertexPool::remove_unused_vertices // Access: Public // Description: Removes all vertices from the pool that are not -// referenced by at least one primitive. Also renumbers -// all vertices after the operation so their indices are +// referenced by at least one primitive. Also collapses +// together equivalent vertices, and renumbers all +// vertices after the operation so their indices are // consecutive, beginning at zero. Returns the number // of vertices removed. //////////////////////////////////////////////////////////////////// @@ -497,11 +498,38 @@ remove_unused_vertices() { num_removed++; } else { - // The vertex *is* used somewhere. Renumber it and add it to - // the new lists. - vertex->_index = new_index_vertices.size(); - new_index_vertices.insert(IndexVertices::value_type(vertex->_index, vertex)); - new_unique_vertices.insert(vertex); + // The vertex *is* used somewhere. Is it identical to an + // existing vertex? + UniqueVertices::iterator uvi; + uvi = new_unique_vertices.find(vertex); + if (uvi != new_unique_vertices.end()) { + // Yes, there's already another vertex just like this one. + // Redirect all the primitives currently referencing this + // vertex to reference the other one instead. + EggVertex *orig_vertex = (*uvi); + + EggVertex::PrimitiveRef pref = vertex->_pref; + EggVertex::PrimitiveRef::iterator pi; + for (pi = pref.begin(); pi != pref.end(); ++pi) { + EggPrimitive *prim = (*pi); + EggPrimitive::iterator pvi = prim->find(vertex); + nassertr(pvi != prim->end(), 0); + prim->replace(pvi, orig_vertex); + } + vertex->test_pref_integrity(); + orig_vertex->test_pref_integrity(); + nassertr(vertex->pref_size() == 0, 0); + vertex->clear_grefs(); + vertex->_pool = NULL; + num_removed++; + + } else { + // It's a unique vertex. Renumber it and add it to the new + // lists. + vertex->_index = new_index_vertices.size(); + new_index_vertices.insert(IndexVertices::value_type(vertex->_index, vertex)); + new_unique_vertices.insert(vertex); + } } } diff --git a/panda/src/egg2pg/eggLoader.cxx b/panda/src/egg2pg/eggLoader.cxx index 925af11abd..8f5f5a3aab 100644 --- a/panda/src/egg2pg/eggLoader.cxx +++ b/panda/src/egg2pg/eggLoader.cxx @@ -160,6 +160,7 @@ build_graph() { // Clean up the vertices. _data->clear_connected_shading(); _data->remove_unused_vertices(true); + _data->get_connected_shading(); _data->unify_attributes(true, true); // Then bin up the polysets and LOD nodes. @@ -1462,7 +1463,7 @@ make_polyset(EggBin *egg_bin, PandaNode *parent) { // Now that we've meshed, apply the per-prim attributes onto the // vertices, so we can copy them to the GeomVertexData. - egg_bin->apply_first_attribute(false); + egg_bin->apply_last_attribute(false); egg_bin->post_apply_flat_attribute(false); vertex_pool->remove_unused_vertices(); @@ -1482,7 +1483,7 @@ make_polyset(EggBin *egg_bin, PandaNode *parent) { // Now convert the vertex pool to a GeomVertexData. nassertr(vertex_pool != (EggVertexPool *)NULL, NULL); PT(qpGeomVertexData) vertex_data = - make_vertex_data(vertex_pool, first_prim->get_vertex_to_node()); + make_vertex_data(vertex_pool, egg_bin->get_vertex_to_node()); nassertr(vertex_data != (qpGeomVertexData *)NULL, NULL); // And create a Geom to hold the primitives. @@ -1934,11 +1935,11 @@ make_vertex_data(EggVertexPool *vertex_pool, const LMatrix4d &transform) { gvi.set_vertex(vertex->get_index()); gvi.set_data_type(InternalName::get_vertex()); - gvi.set_data4(LCAST(float, vertex->get_pos4())); + gvi.set_data4(LCAST(float, vertex->get_pos4() * transform)); if (vertex->has_normal()) { gvi.set_data_type(InternalName::get_normal()); - gvi.set_data3(LCAST(float, vertex->get_normal())); + gvi.set_data3(LCAST(float, vertex->get_normal() * transform)); } if (vertex->has_color()) { @@ -1986,12 +1987,12 @@ make_primitive(const EggRenderState *render_state, EggPrimitive *egg_prim, if (primitive == (qpGeomPrimitive *)NULL) { // Don't know how to make this kind of primitive. egg2pg_cat.warning() - << "Ignoring " << egg_prim->get_class_type() << "\n"; + << "Ignoring " << egg_prim->get_type() << "\n"; return; } if (render_state->_flat_shaded) { - primitive->set_shade_model(qpGeomPrimitive::SM_flat_first_vertex); + primitive->set_shade_model(qpGeomPrimitive::SM_flat_last_vertex); } else if (egg_prim->get_shading() == EggPrimitive::S_overall) { primitive->set_shade_model(qpGeomPrimitive::SM_uniform); diff --git a/panda/src/glstuff/glGeomMunger_src.cxx b/panda/src/glstuff/glGeomMunger_src.cxx index ab9dc6c6b5..d81f098b2a 100644 --- a/panda/src/glstuff/glGeomMunger_src.cxx +++ b/panda/src/glstuff/glGeomMunger_src.cxx @@ -48,5 +48,20 @@ munge_format_impl(const qpGeomVertexFormat *orig) { format = qpGeomVertexFormat::register_format(new_format); } + /* + if (true) { + // Split out the interleaved array into n parallel arrays. + PT(qpGeomVertexFormat) new_format = new qpGeomVertexFormat; + for (int i = 0; i < format->get_num_data_types(); i++) { + const qpGeomVertexDataType *data_type = format->get_data_type(i); + PT(qpGeomVertexArrayFormat) new_array_format = new qpGeomVertexArrayFormat; + new_array_format->add_data_type(data_type->get_name(), data_type->get_num_components(), + data_type->get_numeric_type()); + new_format->add_array(new_array_format); + } + format = qpGeomVertexFormat::register_format(new_format); + } + */ + return format; } diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index ef489779ec..d8f72a508a 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -2070,6 +2070,34 @@ draw_triangles(const qpGeomTriangles *primitive) { report_my_gl_errors(); } +//////////////////////////////////////////////////////////////////// +// Function: CLP(GraphicsStateGuardian)::draw_tristrips +// Access: Public, Virtual +// Description: Draws a series of triangle strips. +//////////////////////////////////////////////////////////////////// +void CLP(GraphicsStateGuardian):: +draw_tristrips(const qpGeomTristrips *primitive) { + setup_antialias_polygon(); + + int min_vertex = primitive->get_min_vertex(); + int max_vertex = primitive->get_max_vertex(); + CPTA_ushort vertices = primitive->get_flat_last_vertices(); + CPTA_int ends = primitive->get_ends(); + + int num_primitives = primitive->get_num_primitives(); + int start = 0; + for (CPTA_int::const_iterator pi = ends.begin(); pi != ends.end(); ++pi) { + int end = (*pi); + + _glDrawRangeElements(GL_TRIANGLE_STRIP, + min_vertex, max_vertex, end - start, + GL_UNSIGNED_SHORT, vertices + start); + start = end; + } + + report_my_gl_errors(); +} + //////////////////////////////////////////////////////////////////// // Function: CLP(GraphicsStateGuardian)::end_draw_primitives() // Access: Public, Virtual diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index ee7144ab70..62b81fcf7b 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -91,6 +91,7 @@ public: virtual bool begin_draw_primitives(const qpGeomVertexData *vertex_data); virtual void draw_triangles(const qpGeomTriangles *primitive); + virtual void draw_tristrips(const qpGeomTristrips *primitive); virtual void end_draw_primitives(); INLINE bool draw_display_list(GeomContext *gc); diff --git a/panda/src/gobj/qpgeom.cxx b/panda/src/gobj/qpgeom.cxx index 7d109c1d80..93a6322a60 100644 --- a/panda/src/gobj/qpgeom.cxx +++ b/panda/src/gobj/qpgeom.cxx @@ -217,8 +217,7 @@ get_num_bytes() const { void qpGeom:: munge_geom(const qpGeomMunger *munger, CPT(qpGeom) &result, CPT(qpGeomVertexData) &data) const { - // Look up the format in our cache--maybe we've recently applied the - // indicated munger. + // Look up the munger in our cache--maybe we've recently applied it. { // Use read() and release_read() instead of CDReader, because the // call to record_geom() might recursively call back into this @@ -249,7 +248,7 @@ munge_geom(const qpGeomMunger *munger, data = munger->munge_data(get_vertex_data()); ((qpGeomMunger *)munger)->munge_geom_impl(result, data); - if (result.p() != this) { + { // Record the new result in the cache. { CDWriter cdata(((qpGeom *)this)->_cycler); diff --git a/panda/src/gobj/qpgeomMunger.cxx b/panda/src/gobj/qpgeomMunger.cxx index 03ce282344..536a5f3f69 100644 --- a/panda/src/gobj/qpgeomMunger.cxx +++ b/panda/src/gobj/qpgeomMunger.cxx @@ -148,7 +148,6 @@ do_munge_format(const qpGeomVertexFormat *format) { CPT(qpGeomVertexData) qpGeomMunger:: do_munge_data(const qpGeomVertexData *data) { nassertr(_is_registered, NULL); - PStatTimer timer(_munge_pcollector); CPT(qpGeomVertexFormat) orig_format = data->get_format(); CPT(qpGeomVertexFormat) new_format = munge_format(orig_format); diff --git a/panda/src/gobj/qpgeomVertexData.cxx b/panda/src/gobj/qpgeomVertexData.cxx index 849374c770..6ecd7e1df4 100644 --- a/panda/src/gobj/qpgeomVertexData.cxx +++ b/panda/src/gobj/qpgeomVertexData.cxx @@ -24,6 +24,9 @@ TypeHandle qpGeomVertexData::_type_handle; +// Temporarily not a member of the class. +static PStatCollector _munge_pcollector("Cull:Munge:Data"); + //////////////////////////////////////////////////////////////////// // Function: qpGeomVertexData::Default Constructor // Access: Private @@ -301,6 +304,7 @@ convert_to(const qpGeomVertexFormat *new_format) const { gobj_cat.debug() << "Converting " << num_vertices << " vertices.\n"; } + PStatTimer timer(_munge_pcollector); PT(qpGeomVertexData) new_data = new qpGeomVertexData(new_format);