From d4401c9c4342e225da3f13d58dd477b575251338 Mon Sep 17 00:00:00 2001 From: David Rose Date: Tue, 15 Mar 2005 00:22:22 +0000 Subject: [PATCH] more new geom work --- panda/src/egg/eggCompositePrimitive.I | 17 ++ panda/src/egg/eggCompositePrimitive.h | 3 +- panda/src/egg/eggGroupNode.cxx | 2 + panda/src/egg/eggMesher.cxx | 112 ++++++---- panda/src/egg/eggMesher.h | 1 + panda/src/egg/eggTriangleStrip.cxx | 14 +- panda/src/egg/eggTriangleStrip.h | 2 +- panda/src/egg2pg/eggLoader.cxx | 39 +++- panda/src/egg2pg/eggLoader.h | 4 +- panda/src/egg2pg/load_egg_file.cxx | 4 +- panda/src/egg2pg/load_egg_file.h | 2 +- panda/src/gobj/qpgeomPrimitive.I | 12 +- panda/src/gobj/qpgeomPrimitive.cxx | 66 +++--- panda/src/gobj/qpgeomPrimitive.h | 9 +- panda/src/gobj/qpgeomTrifans.cxx | 27 +-- panda/src/gobj/qpgeomTristrips.cxx | 36 ++-- panda/src/gsgbase/graphicsStateGuardianBase.h | 2 + panda/src/pgraph/Sources.pp | 3 + panda/src/pgraph/config_pgraph.cxx | 3 + panda/src/pgraph/pgraph_composite2.cxx | 1 + panda/src/pgraph/shadeModelAttrib.I | 40 ++++ panda/src/pgraph/shadeModelAttrib.cxx | 194 ++++++++++++++++++ panda/src/pgraph/shadeModelAttrib.h | 89 ++++++++ 23 files changed, 561 insertions(+), 121 deletions(-) create mode 100644 panda/src/pgraph/shadeModelAttrib.I create mode 100644 panda/src/pgraph/shadeModelAttrib.cxx create mode 100644 panda/src/pgraph/shadeModelAttrib.h diff --git a/panda/src/egg/eggCompositePrimitive.I b/panda/src/egg/eggCompositePrimitive.I index ec14a71285..f0163485f6 100644 --- a/panda/src/egg/eggCompositePrimitive.I +++ b/panda/src/egg/eggCompositePrimitive.I @@ -104,3 +104,20 @@ set_component(int i, const EggAttributes *attrib) { nassertv(i >= 0 && i < (int)_components.size()); _components[i] = new EggAttributes(*attrib); } + +//////////////////////////////////////////////////////////////////// +// Function: EggCompositePrimitive::triangulate_into +// Access: Published +// Description: Subdivides the composite primitive into triangles and +// adds those triangles to the indicated container. +// Does not remove the primitive from its existing +// parent or modify it in any way. +// +// Returns true if the triangulation is successful, or +// false if there was some error (in which case the +// container may contain some partial triangulation). +//////////////////////////////////////////////////////////////////// +INLINE bool EggCompositePrimitive:: +triangulate_into(EggGroupNode *container) const { + return do_triangulate(container); +} diff --git a/panda/src/egg/eggCompositePrimitive.h b/panda/src/egg/eggCompositePrimitive.h index 9ce0a95342..0fa77814b4 100644 --- a/panda/src/egg/eggCompositePrimitive.h +++ b/panda/src/egg/eggCompositePrimitive.h @@ -42,13 +42,14 @@ PUBLISHED: INLINE EggAttributes *get_component(int i); INLINE void set_component(int i, const EggAttributes *attrib); + INLINE bool triangulate_into(EggGroupNode *container) const; PT(EggCompositePrimitive) triangulate_in_place(); protected: virtual void prepare_add_vertex(EggVertex *vertex, int i, int n); virtual void prepare_remove_vertex(EggVertex *vertex, int i, int n); - virtual void do_triangulate(EggGroupNode *container)=0; + virtual bool do_triangulate(EggGroupNode *container) const=0; void write_body(ostream &out, int indent_level) const; diff --git a/panda/src/egg/eggGroupNode.cxx b/panda/src/egg/eggGroupNode.cxx index 1306925de1..f26faf9da4 100644 --- a/panda/src/egg/eggGroupNode.cxx +++ b/panda/src/egg/eggGroupNode.cxx @@ -1253,6 +1253,8 @@ r_load_externals(const DSearchPath &searchpath, CoordinateSystem coordsys) { void EggGroupNode:: prepare_add_child(EggNode *node) { nassertv(node != (EggNode *)NULL); + test_ref_count_integrity(); + node->test_ref_count_integrity(); // Make sure the node is not already a child of some other group. nassertv(node->get_parent() == NULL); nassertv(node->get_depth() == 0); diff --git a/panda/src/egg/eggMesher.cxx b/panda/src/egg/eggMesher.cxx index c9af1b57c2..4ab366c8f9 100644 --- a/panda/src/egg/eggMesher.cxx +++ b/panda/src/egg/eggMesher.cxx @@ -42,54 +42,74 @@ EggMesher() { // Access: Public // Description: Accepts an EggGroupNode, which contains a set of // EggPrimitives--typically, triangles and quads--as -// children. All of the EggPrimitives must reference -// the same vertex pool. -// -// At the completion of this function, the triangles in -// the group will have been replaced with -// EggTriangleStrips as appropriate. +// children. Removes these primitives and replaces them +// with (mostly) equivalent EggTriangleStrips and +// EggTriangleFans where possible. //////////////////////////////////////////////////////////////////// void EggMesher:: mesh(EggGroupNode *group) { - _vertex_pool = NULL; - _strip_index = 0; + // Create a temporary node to hold the children of group that aren't + // involved in the meshing, as well as the newly-generate triangle + // strips. + PT(EggGroupNode) output_children = new EggGroupNode; - // Create a temporary node to hold the children of groupthat aren't - // involved in the meshing. - PT(EggGroupNode) saved_children = new EggGroupNode; + // And another to hold the children that will be processed next + // time. + PT(EggGroupNode) next_children = new EggGroupNode; + PT(EggGroupNode) this_children = group; - // Add each primitive in the group to the mesh pool. - EggGroupNode::iterator ci = group->begin(); - while (ci != group->end()) { - EggGroupNode::iterator cnext = ci; - ++cnext; + // Only primitives that share a common vertex pool can be meshed + // together. Thus, pull out the primitives with the same vertex + // pool in groups. + while (this_children->size() != 0) { + clear(); - if ((*ci)->is_of_type(EggPolygon::get_class_type())) { - add_polygon(DCAST(EggPolygon, *ci), EggMesherStrip::MO_user); - } else { - // If it's not a polygon, preserve it. - saved_children->add_child(*ci); + // Add each polygon in the group to the mesh pool. + while (!this_children->empty()) { + PT(EggNode) child = this_children->get_first_child(); + this_children->remove_child(child); + + if (child->is_of_type(EggPolygon::get_class_type())) { + EggPolygon *poly = DCAST(EggPolygon, child); + + if (_vertex_pool == (EggVertexPool *)NULL) { + _vertex_pool = poly->get_pool(); + add_polygon(poly, EggMesherStrip::MO_user); + + } else if (_vertex_pool == poly->get_pool()) { + add_polygon(poly, EggMesherStrip::MO_user); + + } else { + // A different vertex pool; save this one for next pass. + next_children->add_child(poly); + } + + } else { + // If it's not a polygon of any kind, just output it + // unchanged. + output_children->add_child(child); + } + } + + do_mesh(); + + Strips::iterator si; + for (si = _done.begin(); si != _done.end(); ++si) { + PT(EggPrimitive) egg_prim = get_prim(*si); + if (egg_prim != (EggPrimitive *)NULL) { + output_children->add_child(egg_prim); + } } - ci = cnext; - } - do_mesh(); + this_children = next_children; + next_children = new EggGroupNode; + } // Now copy the newly-meshed primitives back to the group. group->clear(); - group->steal_children(*saved_children); + group->steal_children(*output_children); - Strips::iterator si; - for (si = _done.begin(); si != _done.end(); ++si) { - PT(EggPrimitive) egg_prim = get_prim(*si); - if (egg_prim != (EggPrimitive *)NULL) { - group->add_child(egg_prim); - } - } - - _vertex_pool = NULL; - _strip_index = 0; - _color_sheets.clear(); + clear(); } //////////////////////////////////////////////////////////////////// @@ -136,6 +156,26 @@ write(ostream &out) const { } } +//////////////////////////////////////////////////////////////////// +// Function: EggMesher::clear +// Access: Private +// Description: Empties the pool of meshable primitives and resets to +// an initial state. +//////////////////////////////////////////////////////////////////// +void EggMesher:: +clear() { + _tris.clear(); + _quads.clear(); + _strips.clear(); + _dead.clear(); + _done.clear(); + _verts.clear(); + _edges.clear(); + _strip_index = 0; + _vertex_pool = NULL; + _color_sheets.clear(); +} + //////////////////////////////////////////////////////////////////// // Function: EggMesher::add_polygon // Access: Private diff --git a/panda/src/egg/eggMesher.h b/panda/src/egg/eggMesher.h index 94b7531d7b..92e5c189f7 100644 --- a/panda/src/egg/eggMesher.h +++ b/panda/src/egg/eggMesher.h @@ -53,6 +53,7 @@ public: bool _show_qsheets; private: + void clear(); bool add_polygon(const EggPolygon *egg_poly, EggMesherStrip::MesherOrigin origin); void do_mesh(); diff --git a/panda/src/egg/eggTriangleStrip.cxx b/panda/src/egg/eggTriangleStrip.cxx index 3e340f1354..30f0c03668 100644 --- a/panda/src/egg/eggTriangleStrip.cxx +++ b/panda/src/egg/eggTriangleStrip.cxx @@ -65,13 +65,17 @@ write(ostream &out, int indent_level) const { // It is assumed that the EggTriangleStrip is not // already a child of any other group when this function // is called. +// +// Returns true if the triangulation is successful, or +// false if there was some error (in which case the +// container may contain some partial triangulation). //////////////////////////////////////////////////////////////////// -void EggTriangleStrip:: -do_triangulate(EggGroupNode *container) { +bool EggTriangleStrip:: +do_triangulate(EggGroupNode *container) const { if (size() < 3) { - return; + return false; } - iterator vi = begin(); + const_iterator vi = begin(); EggVertex *v0 = (*vi); ++vi; EggVertex *v1 = (*vi); @@ -104,4 +108,6 @@ do_triangulate(EggGroupNode *container) { container->add_child(poly); ++vi; } + + return true; } diff --git a/panda/src/egg/eggTriangleStrip.h b/panda/src/egg/eggTriangleStrip.h index b89d8f373f..85c7b6b1d3 100644 --- a/panda/src/egg/eggTriangleStrip.h +++ b/panda/src/egg/eggTriangleStrip.h @@ -40,7 +40,7 @@ PUBLISHED: virtual void write(ostream &out, int indent_level) const; protected: - virtual void do_triangulate(EggGroupNode *container); + virtual bool do_triangulate(EggGroupNode *container) const; public: static TypeHandle get_class_type() { diff --git a/panda/src/egg2pg/eggLoader.cxx b/panda/src/egg2pg/eggLoader.cxx index 5e3ede7727..cef70a1a2a 100644 --- a/panda/src/egg2pg/eggLoader.cxx +++ b/panda/src/egg2pg/eggLoader.cxx @@ -134,11 +134,12 @@ EggLoader() { //////////////////////////////////////////////////////////////////// // Function: EggLoader::Constructor // Access: Public -// Description: +// Description: The EggLoader constructor makes a copy of the EggData +// passed in. //////////////////////////////////////////////////////////////////// EggLoader:: -EggLoader(const EggData &data) : - _data(new EggData(data)) +EggLoader(const EggData *data) : + _data(new EggData(*data)) { _error = false; } @@ -1595,8 +1596,8 @@ make_node(EggGroup *egg_group, PandaNode *parent) { if (pnode->get_num_vertices() == 0) { egg2pg_cat.warning() << "Portal " << egg_group->get_name() << " has no vertices!\n"; - } - + } + } else if (egg_group->get_polylight_flag()) { // Create a polylight instead of a regular polyset. // use make_sphere to get the center, radius and color @@ -1987,7 +1988,7 @@ void EggLoader:: set_portal_polygon(EggGroup *egg_group, PortalNode *pnode) { pnode->clear_vertices(); - EggPolygon *poly = find_first_polygon(egg_group); + PT(EggPolygon) poly = find_first_polygon(egg_group); if (poly != (EggPolygon *)NULL) { LMatrix4d mat = poly->get_vertex_to_node(); @@ -2005,7 +2006,7 @@ set_portal_polygon(EggGroup *egg_group, PortalNode *pnode) { // Description: Returns the first EggPolygon found at or below the // indicated node. //////////////////////////////////////////////////////////////////// -EggPolygon *EggLoader:: +PT(EggPolygon) EggLoader:: find_first_polygon(EggGroup *egg_group) { // Does this group have any polygons? EggGroup::const_iterator ci; @@ -2021,8 +2022,8 @@ find_first_polygon(EggGroup *egg_group) { for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) { if ((*ci)->is_of_type(EggGroup::get_class_type())) { EggGroup *child_group = DCAST(EggGroup, *ci); - EggPolygon *found = find_first_polygon(child_group); - if (found != NULL) { + PT(EggPolygon) found = find_first_polygon(child_group); + if (found != (EggPolygon *)NULL) { return found; } } @@ -2181,6 +2182,13 @@ make_collision_plane(EggGroup *egg_group, CollisionNode *cnode, cnode->add_solid(csplane); return; } + } else if ((*ci)->is_of_type(EggCompositePrimitive::get_class_type())) { + EggCompositePrimitive *comp = DCAST(EggCompositePrimitive, *ci); + PT(EggGroup) temp_group = new EggGroup; + if (comp->triangulate_into(temp_group)) { + make_collision_plane(temp_group, cnode, flags); + return; + } } } } @@ -2203,6 +2211,13 @@ make_collision_polygon(EggGroup *egg_group, CollisionNode *cnode, if ((*ci)->is_of_type(EggPolygon::get_class_type())) { create_collision_polygons(cnode, DCAST(EggPolygon, *ci), egg_group, flags); + } else if ((*ci)->is_of_type(EggCompositePrimitive::get_class_type())) { + EggCompositePrimitive *comp = DCAST(EggCompositePrimitive, *ci); + PT(EggGroup) temp_group = new EggGroup; + if (comp->triangulate_into(temp_group)) { + make_collision_polygon(temp_group, cnode, flags); + return; + } } } } @@ -2224,6 +2239,12 @@ make_collision_polyset(EggGroup *egg_group, CollisionNode *cnode, if ((*ci)->is_of_type(EggPolygon::get_class_type())) { create_collision_polygons(cnode, DCAST(EggPolygon, *ci), egg_group, flags); + } else if ((*ci)->is_of_type(EggCompositePrimitive::get_class_type())) { + EggCompositePrimitive *comp = DCAST(EggCompositePrimitive, *ci); + PT(EggGroup) temp_group = new EggGroup; + if (comp->triangulate_into(temp_group)) { + make_collision_polyset(temp_group, cnode, flags); + } } } } diff --git a/panda/src/egg2pg/eggLoader.h b/panda/src/egg2pg/eggLoader.h index bfada1a296..2909399ae9 100644 --- a/panda/src/egg2pg/eggLoader.h +++ b/panda/src/egg2pg/eggLoader.h @@ -69,7 +69,7 @@ class PolylightNode; class EggLoader { public: EggLoader(); - EggLoader(const EggData &data); + EggLoader(const EggData *data); void build_graph(); void reparent_decals(); @@ -133,7 +133,7 @@ private: void make_primitive(EggPrimitive *egg_prim, Primitives &primitives); void set_portal_polygon(EggGroup *egg_group, PortalNode *pnode); - EggPolygon *find_first_polygon(EggGroup *egg_group); + PT(EggPolygon) find_first_polygon(EggGroup *egg_group); bool make_sphere(EggGroup *start_group, EggGroup::CollideFlags flags, LPoint3f ¢er, float &radius, Colorf &color); diff --git a/panda/src/egg2pg/load_egg_file.cxx b/panda/src/egg2pg/load_egg_file.cxx index caf4614218..c686b7b820 100644 --- a/panda/src/egg2pg/load_egg_file.cxx +++ b/panda/src/egg2pg/load_egg_file.cxx @@ -117,11 +117,11 @@ load_egg_file(const string &filename, CoordinateSystem cs) { // loading. //////////////////////////////////////////////////////////////////// PT(PandaNode) -load_egg_data(EggData &data, CoordinateSystem cs) { +load_egg_data(EggData *data, CoordinateSystem cs) { // We temporarily shuttle the children to a holding node so we can // copy them into the EggLoader's structure without it complaining. EggGroupNode children_holder; - children_holder.steal_children(data); + children_holder.steal_children(*data); EggLoader loader(data); loader._data->steal_children(children_holder); diff --git a/panda/src/egg2pg/load_egg_file.h b/panda/src/egg2pg/load_egg_file.h index 2b4bc9c78b..5dd19a9654 100644 --- a/panda/src/egg2pg/load_egg_file.h +++ b/panda/src/egg2pg/load_egg_file.h @@ -48,7 +48,7 @@ load_egg_file(const string &filename, CoordinateSystem cs = CS_default); // loading. //////////////////////////////////////////////////////////////////// EXPCL_PANDAEGG PT(PandaNode) -load_egg_data(EggData &data, CoordinateSystem cs = CS_default); +load_egg_data(EggData *data, CoordinateSystem cs = CS_default); END_PUBLISH #endif diff --git a/panda/src/gobj/qpgeomPrimitive.I b/panda/src/gobj/qpgeomPrimitive.I index de69f0fc6c..e5a984119b 100644 --- a/panda/src/gobj/qpgeomPrimitive.I +++ b/panda/src/gobj/qpgeomPrimitive.I @@ -58,19 +58,19 @@ get_vertices() const { //////////////////////////////////////////////////////////////////// // Function: qpGeomPrimitive::get_vertices // Access: Published -// Description: Returns a const pointer to the primitive lengths +// Description: Returns a const pointer to the primitive ends // array so application code can read it directly. Do // not attempt to modify the returned array; use -// modify_lengths() or set_lengths() for this. +// modify_ends() or set_ends() for this. // // Note that simple primitive types, like triangles, do -// not have a lengths array: since all the primitives +// not have a ends array: since all the primitives // have the same number of vertices, it is not needed. //////////////////////////////////////////////////////////////////// INLINE CPTA_int qpGeomPrimitive:: -get_lengths() const { +get_ends() const { CDReader cdata(_cycler); - return cdata->_lengths; + return cdata->_ends; } //////////////////////////////////////////////////////////////////// @@ -124,7 +124,7 @@ CData() : INLINE qpGeomPrimitive::CData:: CData(const qpGeomPrimitive::CData ©) : _vertices(copy._vertices), - _lengths(copy._lengths), + _ends(copy._ends), _got_minmax(copy._got_minmax), _min_vertex(copy._min_vertex), _max_vertex(copy._max_vertex) diff --git a/panda/src/gobj/qpgeomPrimitive.cxx b/panda/src/gobj/qpgeomPrimitive.cxx index e83f1208d3..f6ee135872 100644 --- a/panda/src/gobj/qpgeomPrimitive.cxx +++ b/panda/src/gobj/qpgeomPrimitive.cxx @@ -141,11 +141,16 @@ close_primitive() { if (num_vertices_per_primitive == 0) { // This is a complex primitive type like a triangle strip: each // primitive uses a different number of vertices. - if (cdata->_lengths.empty()) { - cdata->_lengths.push_back((int)cdata->_vertices.size()); - } else if (cdata->_lengths.back() != (int)cdata->_vertices.size()) { - cdata->_lengths.push_back((int)cdata->_vertices.size() - cdata->_lengths.back()); +#ifndef NDEBUG + int num_added; + if (cdata->_ends.empty()) { + num_added = (int)cdata->_vertices.size(); + } else { + num_added = (int)cdata->_vertices.size() - cdata->_ends.back(); } + nassertv(num_added >= get_min_num_vertices_per_primitive()); +#endif + cdata->_ends.push_back((int)cdata->_vertices.size()); } else { // This is a simple primitive type like a triangle: each primitive @@ -166,7 +171,7 @@ clear_vertices() { clear_cache(); CDWriter cdata(_cycler); cdata->_vertices.clear(); - cdata->_lengths.clear(); + cdata->_ends.clear(); } //////////////////////////////////////////////////////////////////// @@ -189,7 +194,7 @@ modify_vertices() { // Access: Published // Description: Completely replaces the vertex index list with a new // table. Chances are good that you should also replace -// the lengths list with set_lengths() at the same time. +// the ends list with set_ends() at the same time. //////////////////////////////////////////////////////////////////// void qpGeomPrimitive:: set_vertices(PTA_ushort vertices) { @@ -199,41 +204,41 @@ set_vertices(PTA_ushort vertices) { } //////////////////////////////////////////////////////////////////// -// Function: qpGeomPrimitive::modify_lengths +// Function: qpGeomPrimitive::modify_ends // Access: Published -// Description: Returns a modifiable pointer to the primitive lengths +// Description: Returns a modifiable pointer to the primitive ends // array, so application code can directly fiddle with // this data. Use with caution, since there are no // checks that the data will be left in a stable state. // // Note that simple primitive types, like triangles, do -// not have a lengths array: since all the primitives +// not have a ends array: since all the primitives // have the same number of vertices, it is not needed. //////////////////////////////////////////////////////////////////// PTA_int qpGeomPrimitive:: -modify_lengths() { +modify_ends() { clear_cache(); CDWriter cdata(_cycler); - return cdata->_lengths; + return cdata->_ends; } //////////////////////////////////////////////////////////////////// -// Function: qpGeomPrimitive::set_lengths +// Function: qpGeomPrimitive::set_ends // Access: Published -// Description: Completely replaces the primitive lengths array with +// Description: Completely replaces the primitive ends array with // a new table. Chances are good that you should also // replace the vertices list with set_vertices() at the // same time. // // Note that simple primitive types, like triangles, do -// not have a lengths array: since all the primitives +// not have a ends array: since all the primitives // have the same number of vertices, it is not needed. //////////////////////////////////////////////////////////////////// void qpGeomPrimitive:: -set_lengths(PTA_int lengths) { +set_ends(PTA_int ends) { clear_cache(); CDWriter cdata(_cycler); - cdata->_lengths = lengths; + cdata->_ends = ends; } //////////////////////////////////////////////////////////////////// @@ -246,7 +251,7 @@ int qpGeomPrimitive:: get_num_bytes() const { CDReader cdata(_cycler); return cdata->_vertices.size() * sizeof(short) + - cdata->_lengths.size() * sizeof(int); + cdata->_ends.size() * sizeof(int); } //////////////////////////////////////////////////////////////////// @@ -265,6 +270,17 @@ get_num_vertices_per_primitive() const { return 0; } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::get_min_num_vertices_per_primitive +// Access: Published, Virtual +// Description: Returns the minimum number of vertices that must be +// added before close_primitive() may legally be called. +//////////////////////////////////////////////////////////////////// +int qpGeomPrimitive:: +get_min_num_vertices_per_primitive() const { + return 3; +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomPrimitive::get_num_primitives // Access: Published @@ -280,7 +296,7 @@ get_num_primitives() const { if (num_vertices_per_primitive == 0) { // This is a complex primitive type like a triangle strip: each // primitive uses a different number of vertices. - return cdata->_lengths.size(); + return cdata->_ends.size(); } else { // This is a simple primitive type like a triangle: each primitive @@ -293,7 +309,7 @@ get_num_primitives() const { // Function: qpGeomPrimitive::get_primitive_start // Access: Published // Description: Returns the element within the _vertices list at which -// the ith primitive starts. +// the ith primitive ends. // // If i is one more than the highest valid primitive // vertex, the return value will be one more than the @@ -310,11 +326,11 @@ get_primitive_start(int i) const { // This is a complex primitive type like a triangle strip: each // primitive uses a different number of vertices. CDReader cdata(_cycler); - nassertr(i >= 0 && i <= (int)cdata->_lengths.size(), -1); + nassertr(i >= 0 && i <= (int)cdata->_ends.size(), -1); if (i == 0) { return 0; } else { - return cdata->_lengths[i - 1]; + return cdata->_ends[i - 1]; } } else { @@ -338,8 +354,12 @@ get_primitive_num_vertices(int i) const { // This is a complex primitive type like a triangle strip: each // primitive uses a different number of vertices. CDReader cdata(_cycler); - nassertr(i >= 0 && i < (int)cdata->_lengths.size(), 0); - return cdata->_lengths[i]; + nassertr(i >= 0 && i < (int)cdata->_ends.size(), 0); + if (i == 0) { + return cdata->_ends[0]; + } else { + return cdata->_ends[i] - cdata->_ends[i - 1]; + } } else { // This is a simple primitive type like a triangle: each primitive diff --git a/panda/src/gobj/qpgeomPrimitive.h b/panda/src/gobj/qpgeomPrimitive.h index 1d1923f6a2..35c4b0f669 100644 --- a/panda/src/gobj/qpgeomPrimitive.h +++ b/panda/src/gobj/qpgeomPrimitive.h @@ -75,9 +75,9 @@ PUBLISHED: PTA_ushort modify_vertices(); void set_vertices(PTA_ushort vertices); - INLINE CPTA_int get_lengths() const; - PTA_int modify_lengths(); - void set_lengths(PTA_int lengths); + INLINE CPTA_int get_ends() const; + PTA_int modify_ends(); + void set_ends(PTA_int ends); int get_num_bytes() const; @@ -85,6 +85,7 @@ PUBLISHED: INLINE int get_max_vertex() const; virtual int get_num_vertices_per_primitive() const; + virtual int get_min_num_vertices_per_primitive() const; int get_num_primitives() const; int get_primitive_start(int i) const; int get_primitive_num_vertices(int i) const; @@ -121,7 +122,7 @@ private: virtual void fillin(DatagramIterator &scan, BamReader *manager); PTA_ushort _vertices; - PTA_int _lengths; + PTA_int _ends; bool _got_minmax; unsigned short _min_vertex; diff --git a/panda/src/gobj/qpgeomTrifans.cxx b/panda/src/gobj/qpgeomTrifans.cxx index e367012b61..180de49677 100644 --- a/panda/src/gobj/qpgeomTrifans.cxx +++ b/panda/src/gobj/qpgeomTrifans.cxx @@ -81,28 +81,31 @@ PT(qpGeomPrimitive) qpGeomTrifans:: decompose_impl() { PT(qpGeomTriangles) triangles = new qpGeomTriangles; CPTA_ushort vertices = get_vertices(); - CPTA_int lengths = get_lengths(); + CPTA_int ends = get_ends(); - CPTA_ushort::const_iterator vi; - vi = vertices.begin(); - - CPTA_int::const_iterator li; - for (li = lengths.begin(); li != lengths.end(); ++li) { - int length = (*li); - nassertr(length >= 2, triangles.p()); - int v0 = (*vi); + int vi = 0; + int li = 0; + while (li < (int)ends.size()) { + int end = ends[li]; + nassertr(vi + 2 <= end, triangles.p()); + nassertr(vi < (int)vertices.size(), this); + int v0 = vertices[vi]; ++vi; - int v1 = (*vi); + nassertr(vi < (int)vertices.size(), this); + int v1 = vertices[vi]; ++vi; - for (int i = 2; i < length; i++) { + while (vi < end) { triangles->add_vertex(v0); triangles->add_vertex(v1); - triangles->add_vertex(*vi); + triangles->add_vertex(vertices[vi]); triangles->close_primitive(); ++vi; } + ++li; } + nassertr(vi == (int)vertices.size(), triangles.p()); + return triangles.p(); } diff --git a/panda/src/gobj/qpgeomTristrips.cxx b/panda/src/gobj/qpgeomTristrips.cxx index 0cf3ade808..53a1e757c7 100644 --- a/panda/src/gobj/qpgeomTristrips.cxx +++ b/panda/src/gobj/qpgeomTristrips.cxx @@ -81,26 +81,21 @@ PT(qpGeomPrimitive) qpGeomTristrips:: decompose_impl() { PT(qpGeomTriangles) triangles = new qpGeomTriangles; CPTA_ushort vertices = get_vertices(); - CPTA_int lengths = get_lengths(); + CPTA_int ends = get_ends(); - CPTA_ushort::const_iterator vi; - vi = vertices.begin(); - - cerr << "starting vertices, size = " << vertices.size() << "\n"; - - CPTA_int::const_iterator li; - for (li = lengths.begin(); li != lengths.end(); ++li) { - int length = (*li); - cerr << "length = " << length << "\n"; - nassertr(length >= 2, triangles.p()); - nassertr(vi != vertices.end(), this); - int v0 = (*vi); + int vi = 0; + int li = 0; + while (li < (int)ends.size()) { + int end = ends[li]; + nassertr(vi + 2 <= end, triangles.p()); + nassertr(vi < (int)vertices.size(), this); + int v0 = vertices[vi]; ++vi; - nassertr(vi != vertices.end(), this); - int v1 = (*vi); + nassertr(vi < (int)vertices.size(), this); + int v1 = vertices[vi]; ++vi; bool reversed = false; - for (int i = 2; i < length; i++) { + while (vi < end) { if (reversed) { triangles->add_vertex(v1); triangles->add_vertex(v0); @@ -110,16 +105,17 @@ decompose_impl() { triangles->add_vertex(v1); reversed = true; } - triangles->add_vertex(*vi); + triangles->add_vertex(vertices[vi]); v0 = v1; - nassertr(vi != vertices.end(), this); - v1 = *vi; + nassertr(vi < (int)vertices.size(), this); + v1 = vertices[vi]; triangles->close_primitive(); ++vi; } + ++li; } - triangles->write(cerr, 0); + nassertr(vi == (int)vertices.size(), triangles.p()); return triangles.p(); } diff --git a/panda/src/gsgbase/graphicsStateGuardianBase.h b/panda/src/gsgbase/graphicsStateGuardianBase.h index f1678e4c3e..b47a02257d 100644 --- a/panda/src/gsgbase/graphicsStateGuardianBase.h +++ b/panda/src/gsgbase/graphicsStateGuardianBase.h @@ -78,6 +78,7 @@ class CgShaderAttrib; class CullFaceAttrib; class StencilAttrib; class ClipPlaneAttrib; +class ShadeModelAttrib; class TransparencyAttrib; class FogAttrib; class LinesmoothAttrib; @@ -212,6 +213,7 @@ public: virtual void issue_cg_shader_bind(const CgShaderAttrib *){} virtual void issue_stencil(const StencilAttrib *) { } virtual void issue_clip_plane(const ClipPlaneAttrib *) { } + virtual void issue_shade_model(const ShadeModelAttrib *) { } virtual void bind_light(PointLight *light_obj, const NodePath &light, int light_id) { } diff --git a/panda/src/pgraph/Sources.pp b/panda/src/pgraph/Sources.pp index bb6afb5008..8e58845734 100644 --- a/panda/src/pgraph/Sources.pp +++ b/panda/src/pgraph/Sources.pp @@ -87,6 +87,7 @@ sceneSetup.I sceneSetup.h \ selectiveChildNode.I selectiveChildNode.h \ sequenceNode.I sequenceNode.h \ + shadeModelAttrib.I shadeModelAttrib.h \ showBoundsEffect.I showBoundsEffect.h \ spotlight.I spotlight.h \ switchNode.I switchNode.h \ @@ -181,6 +182,7 @@ sceneSetup.cxx \ selectiveChildNode.cxx \ sequenceNode.cxx \ + shadeModelAttrib.cxx \ showBoundsEffect.cxx \ spotlight.cxx \ switchNode.cxx \ @@ -273,6 +275,7 @@ sceneSetup.I sceneSetup.h \ selectiveChildNode.I selectiveChildNode.h \ sequenceNode.I sequenceNode.h \ + shadeModelAttrib.I shadeModelAttrib.h \ showBoundsEffect.I showBoundsEffect.h \ spotlight.I spotlight.h \ switchNode.I switchNode.h \ diff --git a/panda/src/pgraph/config_pgraph.cxx b/panda/src/pgraph/config_pgraph.cxx index 34be844a88..6c107461c2 100644 --- a/panda/src/pgraph/config_pgraph.cxx +++ b/panda/src/pgraph/config_pgraph.cxx @@ -78,6 +78,7 @@ #include "rescaleNormalAttrib.h" #include "selectiveChildNode.h" #include "sequenceNode.h" +#include "shadeModelAttrib.h" #include "showBoundsEffect.h" #include "spotlight.h" #include "switchNode.h" @@ -277,6 +278,7 @@ init_libpgraph() { RescaleNormalAttrib::init_type(); SelectiveChildNode::init_type(); SequenceNode::init_type(); + ShadeModelAttrib::init_type(); ShowBoundsEffect::init_type(); Spotlight::init_type(); SwitchNode::init_type(); @@ -332,6 +334,7 @@ init_libpgraph() { RenderModeAttrib::register_with_read_factory(); RenderState::register_with_read_factory(); SequenceNode::register_with_read_factory(); + ShadeModelAttrib::register_with_read_factory(); ShowBoundsEffect::register_with_read_factory(); Spotlight::register_with_read_factory(); SwitchNode::register_with_read_factory(); diff --git a/panda/src/pgraph/pgraph_composite2.cxx b/panda/src/pgraph/pgraph_composite2.cxx index 585fe5b6e1..56278b5cf5 100644 --- a/panda/src/pgraph/pgraph_composite2.cxx +++ b/panda/src/pgraph/pgraph_composite2.cxx @@ -32,6 +32,7 @@ #include "sceneGraphReducer.cxx" #include "selectiveChildNode.cxx" #include "sequenceNode.cxx" +#include "shadeModelAttrib.cxx" #include "showBoundsEffect.cxx" #include "spotlight.cxx" #include "switchNode.cxx" diff --git a/panda/src/pgraph/shadeModelAttrib.I b/panda/src/pgraph/shadeModelAttrib.I new file mode 100644 index 0000000000..64712b869b --- /dev/null +++ b/panda/src/pgraph/shadeModelAttrib.I @@ -0,0 +1,40 @@ +// Filename: shadeModelAttrib.I +// Created by: drose (14Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: ShadeModelAttrib::Constructor +// Access: Private +// Description: Use ShadeModelAttrib::make() to construct a new +// ShadeModelAttrib object. +//////////////////////////////////////////////////////////////////// +INLINE ShadeModelAttrib:: +ShadeModelAttrib(ShadeModelAttrib::Mode mode) : + _mode(mode) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: ShadeModelAttrib::get_mode +// Access: Published +// Description: Returns the shade mode. +//////////////////////////////////////////////////////////////////// +INLINE ShadeModelAttrib::Mode ShadeModelAttrib:: +get_mode() const { + return _mode; +} diff --git a/panda/src/pgraph/shadeModelAttrib.cxx b/panda/src/pgraph/shadeModelAttrib.cxx new file mode 100644 index 0000000000..3534af16a9 --- /dev/null +++ b/panda/src/pgraph/shadeModelAttrib.cxx @@ -0,0 +1,194 @@ +// Filename: shadeModelAttrib.cxx +// Created by: drose (14Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "shadeModelAttrib.h" +#include "graphicsStateGuardianBase.h" +#include "dcast.h" +#include "bamReader.h" +#include "bamWriter.h" +#include "datagram.h" +#include "datagramIterator.h" + +TypeHandle ShadeModelAttrib::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: ShadeModelAttrib::make +// Access: Published, Static +// Description: Constructs a new ShadeModelAttrib object that specifies +// whether to draw polygons with flat shading or with +// per-vertex (smooth) shading. +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) ShadeModelAttrib:: +make(ShadeModelAttrib::Mode mode) { + ShadeModelAttrib *attrib = new ShadeModelAttrib(mode); + return return_new(attrib); +} + +//////////////////////////////////////////////////////////////////// +// Function: ShadeModelAttrib::issue +// Access: Public, Virtual +// Description: Calls the appropriate method on the indicated GSG +// to issue the graphics commands appropriate to the +// given attribute. This is normally called +// (indirectly) only from +// GraphicsStateGuardian::set_state() or modify_state(). +//////////////////////////////////////////////////////////////////// +void ShadeModelAttrib:: +issue(GraphicsStateGuardianBase *gsg) const { + gsg->issue_shade_model(this); +} + +//////////////////////////////////////////////////////////////////// +// Function: ShadeModelAttrib::output +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void ShadeModelAttrib:: +output(ostream &out) const { + out << get_type() << ":"; + switch (get_mode()) { + case M_flat: + out << "flat"; + + case M_smooth: + out << "smooth"; + break; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: ShadeModelAttrib::compare_to_impl +// Access: Protected, Virtual +// Description: Intended to be overridden by derived ShadeModelAttrib +// types to return a unique number indicating whether +// this ShadeModelAttrib is equivalent to the other one. +// +// This should return 0 if the two ShadeModelAttrib objects +// are equivalent, a number less than zero if this one +// should be sorted before the other one, and a number +// greater than zero otherwise. +// +// This will only be called with two ShadeModelAttrib +// objects whose get_type() functions return the same. +//////////////////////////////////////////////////////////////////// +int ShadeModelAttrib:: +compare_to_impl(const RenderAttrib *other) const { + const ShadeModelAttrib *ta; + DCAST_INTO_R(ta, other, 0); + return (int)_mode - (int)ta->_mode; +} + +//////////////////////////////////////////////////////////////////// +// Function: ShadeModelAttrib::compose_impl +// Access: Protected, Virtual +// Description: Intended to be overridden by derived RenderAttrib +// types to specify how two consecutive RenderAttrib +// objects of the same type interact. +// +// This should return the result of applying the other +// RenderAttrib to a node in the scene graph below this +// RenderAttrib, which was already applied. In most +// cases, the result is the same as the other +// RenderAttrib (that is, a subsequent RenderAttrib +// completely replaces the preceding one). On the other +// hand, some kinds of RenderAttrib (for instance, +// ColorTransformAttrib) might combine in meaningful +// ways. +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) ShadeModelAttrib:: +compose_impl(const RenderAttrib *other) const { + const ShadeModelAttrib *ta; + DCAST_INTO_R(ta, other, 0); + + Mode mode = ta->get_mode(); + return make(mode); +} + +//////////////////////////////////////////////////////////////////// +// Function: ShadeModelAttrib::make_default_impl +// Access: Protected, Virtual +// Description: Intended to be overridden by derived ShadeModelAttrib +// types to specify what the default property for a +// ShadeModelAttrib of this type should be. +// +// This should return a newly-allocated ShadeModelAttrib of +// the same type that corresponds to whatever the +// standard default for this kind of ShadeModelAttrib is. +//////////////////////////////////////////////////////////////////// +RenderAttrib *ShadeModelAttrib:: +make_default_impl() const { + return new ShadeModelAttrib(M_smooth); +} + +//////////////////////////////////////////////////////////////////// +// Function: ShadeModelAttrib::register_with_read_factory +// Access: Public, Static +// Description: Tells the BamReader how to create objects of type +// ShadeModelAttrib. +//////////////////////////////////////////////////////////////////// +void ShadeModelAttrib:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: ShadeModelAttrib::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void ShadeModelAttrib:: +write_datagram(BamWriter *manager, Datagram &dg) { + RenderAttrib::write_datagram(manager, dg); + + dg.add_int8(_mode); +} + +//////////////////////////////////////////////////////////////////// +// Function: ShadeModelAttrib::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type ShadeModelAttrib is encountered +// in the Bam file. It should create the ShadeModelAttrib +// and extract its information from the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *ShadeModelAttrib:: +make_from_bam(const FactoryParams ¶ms) { + ShadeModelAttrib *attrib = new ShadeModelAttrib(M_smooth); + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + attrib->fillin(scan, manager); + + return attrib; +} + +//////////////////////////////////////////////////////////////////// +// Function: ShadeModelAttrib::fillin +// Access: Protected +// Description: This internal function is called by make_from_bam to +// read in all of the relevant data from the BamFile for +// the new ShadeModelAttrib. +//////////////////////////////////////////////////////////////////// +void ShadeModelAttrib:: +fillin(DatagramIterator &scan, BamReader *manager) { + RenderAttrib::fillin(scan, manager); + + _mode = (Mode)scan.get_int8(); +} diff --git a/panda/src/pgraph/shadeModelAttrib.h b/panda/src/pgraph/shadeModelAttrib.h new file mode 100644 index 0000000000..a4c13999e0 --- /dev/null +++ b/panda/src/pgraph/shadeModelAttrib.h @@ -0,0 +1,89 @@ +// Filename: shadeModelAttrib.h +// Created by: drose (14Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef SHADEMODELATTRIB_H +#define SHADEMODELATTRIB_H + +#include "pandabase.h" + +#include "renderAttrib.h" + +class FactoryParams; + +//////////////////////////////////////////////////////////////////// +// Class : ShadeModelAttrib +// Description : Specifies whether flat shading (per-polygon) or +// smooth shading (per-vertex) is in effect. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA ShadeModelAttrib : public RenderAttrib { +PUBLISHED: + enum Mode { + M_flat, + M_smooth, + }; + +private: + INLINE ShadeModelAttrib(Mode mode); + +PUBLISHED: + static CPT(RenderAttrib) make(Mode mode); + + INLINE Mode get_mode() const; + +public: + virtual void issue(GraphicsStateGuardianBase *gsg) const; + virtual void output(ostream &out) const; + +protected: + virtual int compare_to_impl(const RenderAttrib *other) const; + virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const; + virtual RenderAttrib *make_default_impl() const; + +private: + Mode _mode; + +public: + static void register_with_read_factory(); + virtual void write_datagram(BamWriter *manager, Datagram &dg); + +protected: + static TypedWritable *make_from_bam(const FactoryParams ¶ms); + void fillin(DatagramIterator &scan, BamReader *manager); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + RenderAttrib::init_type(); + register_type(_type_handle, "ShadeModelAttrib", + RenderAttrib::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#include "shadeModelAttrib.I" + +#endif +