From c975b7cd499c609a00d4c02994b3478a3e657b59 Mon Sep 17 00:00:00 2001 From: David Rose Date: Fri, 11 Mar 2005 02:28:51 +0000 Subject: [PATCH] initial checkin of experimental Geom rewrite--preliminary --- panda/src/builder/builderBucket.I | 4 +- panda/src/builder/builderBucket.h | 8 +- panda/src/builder/builderFuncs.I | 14 +- panda/src/builder/builderPrim.cxx | 6 +- panda/src/builder/builderPrimTempl.I | 10 +- panda/src/builder/builderPrimTempl.h | 10 +- panda/src/builder/builderVertex.I | 8 +- panda/src/builder/builderVertex.h | 8 +- panda/src/builder/builderVertexTempl.I | 10 +- panda/src/builder/builderVertexTempl.h | 12 +- panda/src/display/graphicsStateGuardian.I | 12 + panda/src/display/graphicsStateGuardian.cxx | 69 ++ panda/src/display/graphicsStateGuardian.h | 12 + panda/src/distort/projectionScreen.I | 4 +- panda/src/distort/projectionScreen.cxx | 2 +- panda/src/distort/projectionScreen.h | 6 +- panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx | 77 +++ panda/src/dxgsg8/dxGraphicsStateGuardian8.h | 4 + panda/src/egg2pg/computedVerticesMaker.cxx | 10 +- panda/src/egg2pg/computedVerticesMaker.h | 10 +- panda/src/egg2pg/eggLoader.cxx | 35 +- panda/src/egg2pg/eggLoader.h | 4 +- panda/src/express/numeric_types.h | 4 + panda/src/express/pointerToArray.I | 26 +- panda/src/express/pointerToArray.h | 8 +- panda/src/framework/windowFramework.cxx | 182 +++-- panda/src/glstuff/Sources.pp | 3 + panda/src/glstuff/glGeomMunger_src.I | 27 + panda/src/glstuff/glGeomMunger_src.cxx | 52 ++ panda/src/glstuff/glGeomMunger_src.h | 54 ++ .../glstuff/glGraphicsStateGuardian_src.cxx | 192 ++++++ .../src/glstuff/glGraphicsStateGuardian_src.h | 11 + panda/src/glstuff/glstuff_src.cxx | 1 + panda/src/glstuff/glstuff_src.h | 1 + panda/src/gobj/Sources.pp | 35 +- panda/src/gobj/config_gobj.cxx | 37 +- panda/src/gobj/config_gobj.h | 2 + panda/src/gobj/geom.I | 18 +- panda/src/gobj/geom.cxx | 88 ++- panda/src/gobj/geom.h | 30 +- panda/src/gobj/gobj_composite1.cxx | 12 +- panda/src/gobj/gobj_composite2.cxx | 2 +- panda/src/gobj/internalName.I | 185 +++++ panda/src/gobj/internalName.cxx | 231 +++++++ panda/src/gobj/internalName.h | 129 ++++ panda/src/gobj/qpgeom.I | 114 +++ panda/src/gobj/qpgeom.cxx | 395 +++++++++++ panda/src/gobj/qpgeom.h | 139 ++++ panda/src/gobj/qpgeomMunger.I | 113 +++ panda/src/gobj/qpgeomMunger.cxx | 282 ++++++++ panda/src/gobj/qpgeomMunger.h | 121 ++++ panda/src/gobj/qpgeomPrimitive.I | 132 ++++ panda/src/gobj/qpgeomPrimitive.cxx | 520 ++++++++++++++ panda/src/gobj/qpgeomPrimitive.h | 156 +++++ panda/src/gobj/qpgeomTriangles.cxx | 110 +++ panda/src/gobj/qpgeomTriangles.h | 68 ++ panda/src/gobj/qpgeomTrifans.cxx | 138 ++++ panda/src/gobj/qpgeomTrifans.h | 68 ++ panda/src/gobj/qpgeomTristrips.cxx | 148 ++++ panda/src/gobj/qpgeomTristrips.h | 68 ++ panda/src/gobj/qpgeomVertexArrayFormat.I | 121 ++++ panda/src/gobj/qpgeomVertexArrayFormat.cxx | 556 +++++++++++++++ panda/src/gobj/qpgeomVertexArrayFormat.h | 162 +++++ panda/src/gobj/qpgeomVertexData.I | 82 +++ panda/src/gobj/qpgeomVertexData.cxx | 650 ++++++++++++++++++ panda/src/gobj/qpgeomVertexData.h | 155 +++++ panda/src/gobj/qpgeomVertexDataType.I | 221 ++++++ panda/src/gobj/qpgeomVertexDataType.cxx | 309 +++++++++ panda/src/gobj/qpgeomVertexDataType.h | 109 +++ panda/src/gobj/qpgeomVertexFormat.I | 260 +++++++ panda/src/gobj/qpgeomVertexFormat.cxx | 632 +++++++++++++++++ panda/src/gobj/qpgeomVertexFormat.h | 211 ++++++ panda/src/gobj/qpgeomVertexIterator.I | 380 ++++++++++ panda/src/gobj/qpgeomVertexIterator.cxx | 19 + panda/src/gobj/qpgeomVertexIterator.h | 86 +++ panda/src/gobj/texCoordName.I | 49 -- panda/src/gobj/texCoordName.cxx | 161 ----- panda/src/gobj/texCoordName.h | 92 --- panda/src/gobj/textureStage.I | 8 +- panda/src/gobj/textureStage.cxx | 6 +- panda/src/gobj/textureStage.h | 8 +- panda/src/grutil/multitexReducer.cxx | 10 +- panda/src/grutil/multitexReducer.h | 2 +- panda/src/gsgbase/graphicsStateGuardianBase.h | 10 + panda/src/pgraph/geomNode.I | 8 +- panda/src/pgraph/geomNode.cxx | 4 +- panda/src/pgraph/geomNode.h | 6 +- panda/src/pgraph/geomTransformer.cxx | 8 +- panda/src/pgraph/geomTransformer.h | 10 +- 89 files changed, 8036 insertions(+), 536 deletions(-) create mode 100644 panda/src/glstuff/glGeomMunger_src.I create mode 100644 panda/src/glstuff/glGeomMunger_src.cxx create mode 100644 panda/src/glstuff/glGeomMunger_src.h create mode 100644 panda/src/gobj/internalName.I create mode 100644 panda/src/gobj/internalName.cxx create mode 100644 panda/src/gobj/internalName.h create mode 100644 panda/src/gobj/qpgeom.I create mode 100644 panda/src/gobj/qpgeom.cxx create mode 100644 panda/src/gobj/qpgeom.h create mode 100644 panda/src/gobj/qpgeomMunger.I create mode 100644 panda/src/gobj/qpgeomMunger.cxx create mode 100644 panda/src/gobj/qpgeomMunger.h create mode 100644 panda/src/gobj/qpgeomPrimitive.I create mode 100644 panda/src/gobj/qpgeomPrimitive.cxx create mode 100644 panda/src/gobj/qpgeomPrimitive.h create mode 100644 panda/src/gobj/qpgeomTriangles.cxx create mode 100644 panda/src/gobj/qpgeomTriangles.h create mode 100644 panda/src/gobj/qpgeomTrifans.cxx create mode 100644 panda/src/gobj/qpgeomTrifans.h create mode 100644 panda/src/gobj/qpgeomTristrips.cxx create mode 100644 panda/src/gobj/qpgeomTristrips.h create mode 100644 panda/src/gobj/qpgeomVertexArrayFormat.I create mode 100644 panda/src/gobj/qpgeomVertexArrayFormat.cxx create mode 100644 panda/src/gobj/qpgeomVertexArrayFormat.h create mode 100644 panda/src/gobj/qpgeomVertexData.I create mode 100644 panda/src/gobj/qpgeomVertexData.cxx create mode 100644 panda/src/gobj/qpgeomVertexData.h create mode 100644 panda/src/gobj/qpgeomVertexDataType.I create mode 100644 panda/src/gobj/qpgeomVertexDataType.cxx create mode 100644 panda/src/gobj/qpgeomVertexDataType.h create mode 100644 panda/src/gobj/qpgeomVertexFormat.I create mode 100644 panda/src/gobj/qpgeomVertexFormat.cxx create mode 100644 panda/src/gobj/qpgeomVertexFormat.h create mode 100644 panda/src/gobj/qpgeomVertexIterator.I create mode 100644 panda/src/gobj/qpgeomVertexIterator.cxx create mode 100644 panda/src/gobj/qpgeomVertexIterator.h delete mode 100755 panda/src/gobj/texCoordName.I delete mode 100755 panda/src/gobj/texCoordName.cxx delete mode 100644 panda/src/gobj/texCoordName.h diff --git a/panda/src/builder/builderBucket.I b/panda/src/builder/builderBucket.I index b487f7604d..a40909c36a 100644 --- a/panda/src/builder/builderBucket.I +++ b/panda/src/builder/builderBucket.I @@ -73,7 +73,7 @@ get_normals() const { // associated with this bucket. //////////////////////////////////////////////////////////////////// INLINE void BuilderBucket:: -set_texcoords(const TexCoordName *name, const PTA_TexCoordf &texcoords) { +set_texcoords(const InternalName *name, const PTA_TexCoordf &texcoords) { _texcoords[name] = texcoords; } @@ -84,7 +84,7 @@ set_texcoords(const TexCoordName *name, const PTA_TexCoordf &texcoords) { // Description: //////////////////////////////////////////////////////////////////// INLINE PTA_TexCoordf BuilderBucket:: -get_texcoords(const TexCoordName *name) const { +get_texcoords(const InternalName *name) const { TexCoords::const_iterator ti = _texcoords.find(name); if (ti != _texcoords.end()) { return (*ti).second; diff --git a/panda/src/builder/builderBucket.h b/panda/src/builder/builderBucket.h index 16b58690f6..8cea8ed359 100644 --- a/panda/src/builder/builderBucket.h +++ b/panda/src/builder/builderBucket.h @@ -30,7 +30,7 @@ #include "pta_Normalf.h" #include "pta_Colorf.h" #include "pta_TexCoordf.h" -#include "texCoordName.h" +#include "internalName.h" #include "renderState.h" #include "stdlib.h" @@ -77,8 +77,8 @@ public: INLINE void set_normals(const PTA_Normalf &normals); INLINE PTA_Normalf get_normals() const; - INLINE void set_texcoords(const TexCoordName *name, const PTA_TexCoordf &texcoords); - INLINE PTA_TexCoordf get_texcoords(const TexCoordName *name) const; + INLINE void set_texcoords(const InternalName *name, const PTA_TexCoordf &texcoords); + INLINE PTA_TexCoordf get_texcoords(const InternalName *name) const; INLINE void set_colors(const PTA_Colorf &colors); INLINE PTA_Colorf get_colors() const; @@ -96,7 +96,7 @@ protected: PTA_Normalf _normals; PTA_Colorf _colors; - typedef pmap TexCoords; + typedef pmap TexCoords; TexCoords _texcoords; static BuilderBucket *_default_bucket; diff --git a/panda/src/builder/builderFuncs.I b/panda/src/builder/builderFuncs.I index 518fb33230..fec85820cd 100644 --- a/panda/src/builder/builderFuncs.I +++ b/panda/src/builder/builderFuncs.I @@ -555,13 +555,13 @@ build_geoms(InputIterator first, InputIterator last, // // Texcoords are an exception to the above, since they are either // per vertex or not at all, and since there may be a different set - // of texcoords for each of a number of TexCoordName objects. + // of texcoords for each of a number of InternalName objects. GeomBindType bind_normals = G_OVERALL; GeomBindType bind_colors = G_OVERALL; - typedef pset TexCoordNames; - TexCoordNames texcoord_names; + typedef pset InternalNames; + InternalNames texcoord_names; NType overall_normal(0); CType overall_color(0); @@ -623,11 +623,11 @@ build_geoms(InputIterator first, InputIterator last, } } - // Texcoords. Get the union of all TexCoordNames defined on the + // Texcoords. Get the union of all InternalNames defined on the // prims. TYPENAME PrimType::tcn_const_iterator tni; for (tni = (*i).tcn_begin(); tni != (*i).tcn_end(); ++tni) { - const TexCoordName *name = (*tni); + const InternalName *name = (*tni); texcoord_names.insert(name); } } @@ -719,7 +719,7 @@ build_geoms(InputIterator first, InputIterator last, typedef TYPENAME PrimType::TexCoordFill TexCoordFill; TexCoordFill texcoords; - TexCoordNames::const_iterator tni; + InternalNames::const_iterator tni; for (tni = texcoord_names.begin(); tni != texcoord_names.end(); ++tni) { texcoords[*tni] = PTA(TType)::empty_array(0); } @@ -744,7 +744,7 @@ build_geoms(InputIterator first, InputIterator last, } TYPENAME TexCoordFill::iterator tci; for (tci = texcoords.begin(); tci != texcoords.end(); ++tci) { - const TexCoordName *name = (*tci).first; + const InternalName *name = (*tci).first; if ((*i).get_vertex(v).has_texcoord(name)) { (*tci).second.push_back((*i).get_vertex(v).get_texcoord(name)); } else { diff --git a/panda/src/builder/builderPrim.cxx b/panda/src/builder/builderPrim.cxx index a264f0a38e..9adc234f79 100644 --- a/panda/src/builder/builderPrim.cxx +++ b/panda/src/builder/builderPrim.cxx @@ -68,7 +68,7 @@ nonindexed_copy(const BuilderPrimTempl ©, BuilderVertexI::tc_const_iterator tci; for (tci = cv.tc_begin(); tci != cv.tc_end(); ++tci) { - const TexCoordName *name = (*tci).first; + const InternalName *name = (*tci).first; v.set_texcoord(name, cv.get_texcoord_value(name, bucket)); } @@ -153,7 +153,7 @@ fill_geom(Geom *geom, const PTA_BuilderV &v_array, TexCoordFill::const_iterator tci; for (tci = texcoords.begin(); tci != texcoords.end(); ++tci) { - const TexCoordName *name = (*tci).first; + const InternalName *name = (*tci).first; geom->set_texcoords(name, (*tci).second); } } @@ -238,7 +238,7 @@ fill_geom(Geom *geom, const PTA_ushort &v_array, TexCoordFill::const_iterator tci; for (tci = texcoords.begin(); tci != texcoords.end(); ++tci) { - const TexCoordName *name = (*tci).first; + const InternalName *name = (*tci).first; PTA_ushort t_array = (*tci).second; PTA_TexCoordf t_data = bucket.get_texcoords(name); diff --git a/panda/src/builder/builderPrimTempl.I b/panda/src/builder/builderPrimTempl.I index 9ba8a06f47..0c8d1a4d2a 100644 --- a/panda/src/builder/builderPrimTempl.I +++ b/panda/src/builder/builderPrimTempl.I @@ -328,7 +328,7 @@ has_any_pixel_size() const { // Function: BuilderPrimTempl::tcn_begin // Access: Public // Description: Returns an iterator that can be used to walk through -// the list of TexCoordNames that are common to all +// the list of InternalNames that are common to all // vertices on this primitive. //////////////////////////////////////////////////////////////////// template @@ -341,7 +341,7 @@ tcn_begin() const { // Function: BuilderPrimTempl::tcn_end // Access: Public // Description: Returns an iterator that can be used to walk through -// the list of TexCoordNames that are common to all +// the list of InternalNames that are common to all // vertices on this primitive. //////////////////////////////////////////////////////////////////// template @@ -353,7 +353,7 @@ tcn_end() const { //////////////////////////////////////////////////////////////////// // Function: BuilderPrimTempl::tcn_size // Access: Public -// Description: Returns the number of TexCoordNames that are common +// Description: Returns the number of InternalNames that are common // to all vertices on this primitive. //////////////////////////////////////////////////////////////////// template @@ -885,12 +885,12 @@ update_overall_attrib() { int i; if (num_verts > 0) { - // Get the intersection of TexCoordNames that are defined on all + // Get the intersection of InternalNames that are defined on all // vertices. const Vertex &vtx = get_vertex(0); TYPENAME Vertex::tc_const_iterator tci; for (tci = vtx.tc_begin(); tci != vtx.tc_end(); ++tci) { - const TexCoordName *name = (*tci).first; + const InternalName *name = (*tci).first; bool has_texcoord = true; for (i = 1; i < num_verts && has_texcoord; i++) { has_texcoord = get_vertex(i).has_texcoord(name); diff --git a/panda/src/builder/builderPrimTempl.h b/panda/src/builder/builderPrimTempl.h index 716803c3dc..4b722e918f 100644 --- a/panda/src/builder/builderPrimTempl.h +++ b/panda/src/builder/builderPrimTempl.h @@ -45,12 +45,12 @@ public: typedef TYPENAME VTX::TType TType; typedef TYPENAME VTX::CType CType; typedef TYPENAME VTX::Attrib DAttrib; - typedef pset TexCoordNames; - typedef TexCoordNames::const_iterator tcn_const_iterator; - typedef TexCoordNames::size_type tcn_size_type; + typedef pset InternalNames; + typedef InternalNames::const_iterator tcn_const_iterator; + typedef InternalNames::size_type tcn_size_type; // This type is passed to fill_geom() for the texcoords. - typedef pmap TexCoordFill; + typedef pmap TexCoordFill; INLINE BuilderPrimTempl(); INLINE BuilderPrimTempl(const BuilderPrimTempl ©); @@ -151,7 +151,7 @@ protected: Verts _verts; Components _components; - TexCoordNames _texcoord_names; + InternalNames _texcoord_names; BuilderPrimType _type; int _overall; }; diff --git a/panda/src/builder/builderVertex.I b/panda/src/builder/builderVertex.I index cfd44fca0b..5fd7ab5f8f 100644 --- a/panda/src/builder/builderVertex.I +++ b/panda/src/builder/builderVertex.I @@ -60,7 +60,7 @@ set_normal_value(const BuilderN *array, ushort index) { // assumes the array is the same one it's indexing on). //////////////////////////////////////////////////////////////////// INLINE void BuilderVertex:: -set_texcoord_value(const TexCoordName *name, const BuilderTC *array, ushort index) { +set_texcoord_value(const InternalName *name, const BuilderTC *array, ushort index) { set_texcoord(name, array[index]); } @@ -130,7 +130,7 @@ get_normal_value(const BuilderBucket &) const { // get_coord_value(). //////////////////////////////////////////////////////////////////// INLINE BuilderTC BuilderVertex:: -get_texcoord_value(const TexCoordName *name, const BuilderBucket &) const { +get_texcoord_value(const InternalName *name, const BuilderBucket &) const { return get_texcoord(name); } @@ -191,7 +191,7 @@ set_normal_value(const BuilderN *, ushort index) { // assumes the array is the same one it's indexing on). //////////////////////////////////////////////////////////////////// INLINE void BuilderVertexI:: -set_texcoord_value(const TexCoordName *name,const BuilderTC *, ushort index) { +set_texcoord_value(const InternalName *name,const BuilderTC *, ushort index) { set_texcoord(name, index); } @@ -259,7 +259,7 @@ get_normal_value(const BuilderBucket &bucket) const { // get_coord_value(). //////////////////////////////////////////////////////////////////// INLINE BuilderTC BuilderVertexI:: -get_texcoord_value(const TexCoordName *name, const BuilderBucket &bucket) const { +get_texcoord_value(const InternalName *name, const BuilderBucket &bucket) const { nassertr(bucket.get_texcoords(name) != (TexCoordf *)NULL, BuilderTC()); return bucket.get_texcoords(name)[get_texcoord(name)]; } diff --git a/panda/src/builder/builderVertex.h b/panda/src/builder/builderVertex.h index 816c73aaf5..9e0d37231e 100644 --- a/panda/src/builder/builderVertex.h +++ b/panda/src/builder/builderVertex.h @@ -80,12 +80,12 @@ public: INLINE void set_coord_value(const BuilderV *array, ushort index); INLINE void set_normal_value(const BuilderN *array, ushort index); - INLINE void set_texcoord_value(const TexCoordName *name, const BuilderTC *array, ushort index); + INLINE void set_texcoord_value(const InternalName *name, const BuilderTC *array, ushort index); INLINE void set_color_value(const BuilderC *array, ushort index); INLINE BuilderV get_coord_value(const BuilderBucket &bucket) const; INLINE BuilderN get_normal_value(const BuilderBucket &bucket) const; - INLINE BuilderTC get_texcoord_value(const TexCoordName *name, const BuilderBucket &bucket) const; + INLINE BuilderTC get_texcoord_value(const InternalName *name, const BuilderBucket &bucket) const; INLINE BuilderC get_color_value(const BuilderBucket &bucket) const; }; @@ -111,12 +111,12 @@ public: INLINE void set_coord_value(const BuilderV *array, ushort index); INLINE void set_normal_value(const BuilderN *array, ushort index); - INLINE void set_texcoord_value(const TexCoordName *name, const BuilderTC *array, ushort index); + INLINE void set_texcoord_value(const InternalName *name, const BuilderTC *array, ushort index); INLINE void set_color_value(const BuilderC *array, ushort index); INLINE BuilderV get_coord_value(const BuilderBucket &bucket) const; INLINE BuilderN get_normal_value(const BuilderBucket &bucket) const; - INLINE BuilderTC get_texcoord_value(const TexCoordName *name, const BuilderBucket &bucket) const; + INLINE BuilderTC get_texcoord_value(const InternalName *name, const BuilderBucket &bucket) const; INLINE BuilderC get_color_value(const BuilderBucket &bucket) const; }; diff --git a/panda/src/builder/builderVertexTempl.I b/panda/src/builder/builderVertexTempl.I index a299447af8..8ef98e9463 100644 --- a/panda/src/builder/builderVertexTempl.I +++ b/panda/src/builder/builderVertexTempl.I @@ -170,7 +170,7 @@ clear_normal() { //////////////////////////////////////////////////////////////////// template INLINE bool BuilderVertexTempl:: -has_texcoord(const TexCoordName *name) const { +has_texcoord(const InternalName *name) const { TYPENAME TexCoords::const_iterator ti = _texcoords.find(name); return (ti != _texcoords.end()); } @@ -185,7 +185,7 @@ has_texcoord(const TexCoordName *name) const { //////////////////////////////////////////////////////////////////// template INLINE TYPENAME BuilderVertexTempl::TType BuilderVertexTempl:: -get_texcoord(const TexCoordName *name) const { +get_texcoord(const InternalName *name) const { TYPENAME TexCoords::const_iterator ti = _texcoords.find(name); nassertr(ti != _texcoords.end(), (*ti).second); return (*ti).second; @@ -199,7 +199,7 @@ get_texcoord(const TexCoordName *name) const { //////////////////////////////////////////////////////////////////// template INLINE BuilderVertexTempl &BuilderVertexTempl:: -set_texcoord(const TexCoordName *name, const TType &t) { +set_texcoord(const InternalName *name, const TType &t) { _texcoords[name] = t; return *this; } @@ -211,7 +211,7 @@ set_texcoord(const TexCoordName *name, const TType &t) { //////////////////////////////////////////////////////////////////// template INLINE BuilderVertexTempl &BuilderVertexTempl:: -clear_texcoord(const TexCoordName *name) { +clear_texcoord(const InternalName *name) { _texcoords.erase(name); return *this; } @@ -422,7 +422,7 @@ output(ostream &out) const { TYPENAME TexCoords::const_iterator ti; for (ti = _texcoords.begin(); ti != _texcoords.end(); ++ti) { - const TexCoordName *name = (*ti).first; + const InternalName *name = (*ti).first; out << " texcoord \"" << name->get_name() << "\" " << (*ti).second; } diff --git a/panda/src/builder/builderVertexTempl.h b/panda/src/builder/builderVertexTempl.h index 409219d654..9e980d96c9 100644 --- a/panda/src/builder/builderVertexTempl.h +++ b/panda/src/builder/builderVertexTempl.h @@ -24,7 +24,7 @@ #include "builderTypes.h" #include "builderAttribTempl.h" #include "builder_compare.h" -#include "texCoordName.h" +#include "internalName.h" #include "pointerTo.h" #include "notify.h" @@ -45,7 +45,7 @@ public: typedef NT NType; typedef TT TType; typedef CT CType; - typedef pmap TexCoords; + typedef pmap TexCoords; typedef TYPENAME TexCoords::const_iterator tc_const_iterator; typedef TYPENAME TexCoords::size_type tc_size_type; @@ -64,10 +64,10 @@ public: INLINE BuilderVertexTempl &set_normal(const NType &c); INLINE BuilderVertexTempl &clear_normal(); - INLINE bool has_texcoord(const TexCoordName *name) const; - INLINE TType get_texcoord(const TexCoordName *name) const; - INLINE BuilderVertexTempl &set_texcoord(const TexCoordName *name, const TType &t); - INLINE BuilderVertexTempl &clear_texcoord(const TexCoordName *name); + INLINE bool has_texcoord(const InternalName *name) const; + INLINE TType get_texcoord(const InternalName *name) const; + INLINE BuilderVertexTempl &set_texcoord(const InternalName *name, const TType &t); + INLINE BuilderVertexTempl &clear_texcoord(const InternalName *name); INLINE tc_const_iterator tc_begin() const; INLINE tc_const_iterator tc_end() const; INLINE tc_size_type tc_size() const; diff --git a/panda/src/display/graphicsStateGuardian.I b/panda/src/display/graphicsStateGuardian.I index f7650d04c0..3bf0c9e9b9 100644 --- a/panda/src/display/graphicsStateGuardian.I +++ b/panda/src/display/graphicsStateGuardian.I @@ -285,6 +285,16 @@ get_scene() const { return _scene_setup; } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::get_geom_munger +// Access: Public +// Description: Returns the current GeomMunger object. +//////////////////////////////////////////////////////////////////// +INLINE const qpGeomMunger *GraphicsStateGuardian:: +get_geom_munger() const { + return _geom_munger; +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::clear // Access: Public @@ -373,6 +383,7 @@ modify_state(const RenderState *state) { _state_pcollector.add_level(1); _state = _state->issue_delta_modify(state, this); finish_modify_state(); + setup_geom_munger(NULL); } } @@ -400,6 +411,7 @@ set_state(const RenderState *state) { _state_pcollector.add_level(1); _state = _state->issue_delta_set(state, this); finish_modify_state(); + setup_geom_munger(NULL); } } diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 32f912e0ea..863b62cc10 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -37,6 +37,8 @@ #include "throw_event.h" #include "clockObject.h" #include "pStatTimer.h" +#include "qpgeomTristrips.h" +#include "qpgeomTrifans.h" #include @@ -592,6 +594,58 @@ finish_decal() { // No need to do anything special here. } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::begin_draw_primitives() +// Access: Public, Virtual +// Description: Called before a sequence of draw_primitive() +// functions are called, this should prepare the vertex +// data for rendering. +//////////////////////////////////////////////////////////////////// +void GraphicsStateGuardian:: +begin_draw_primitives(const qpGeomVertexData *data) { + _vertex_data = get_geom_munger()->munge_data(data); +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::draw_triangles +// Access: Public, Virtual +// Description: Draws a series of disconnected triangles. +//////////////////////////////////////////////////////////////////// +void GraphicsStateGuardian:: +draw_triangles(qpGeomTriangles *) { +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::draw_tristrips +// Access: Public, Virtual +// Description: Draws a series of triangle strips. +//////////////////////////////////////////////////////////////////// +void GraphicsStateGuardian:: +draw_tristrips(qpGeomTristrips *primitive) { + primitive->decompose(_vertex_data)->draw(this); +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::draw_trifans +// Access: Public, Virtual +// Description: Draws a series of triangle fans. +//////////////////////////////////////////////////////////////////// +void GraphicsStateGuardian:: +draw_trifans(qpGeomTrifans *primitive) { + primitive->decompose(_vertex_data)->draw(this); +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::end_draw_primitives() +// Access: Public, Virtual +// Description: Called after a sequence of draw_primitive() +// functions are called, this should do whatever cleanup +// is appropriate. +//////////////////////////////////////////////////////////////////// +void GraphicsStateGuardian:: +end_draw_primitives() { +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::framebuffer_bind_to_texture // Access: Public, Virtual @@ -1270,6 +1324,21 @@ finish_modify_state() { } } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::setup_geom_munger +// Access: Protected, Virtual +// Description: Called after finish_modify_state has completed, this +// method sets up the GeomMunger for rendering with the +// current state. +//////////////////////////////////////////////////////////////////// +void GraphicsStateGuardian:: +setup_geom_munger(PT(qpGeomMunger) munger) { + if (munger == (qpGeomMunger *)NULL) { + munger = new qpGeomMunger; + } + _geom_munger = qpGeomMunger::register_munger(munger); +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::free_pointers // Access: Protected, Virtual diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index ea85f60f80..348b0aec39 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -44,6 +44,8 @@ #include "textureAttrib.h" #include "transparencyAttrib.h" #include "config_display.h" +#include "qpgeomMunger.h" +#include "qpgeomVertexData.h" #include "notify.h" #include "pvector.h" @@ -95,6 +97,7 @@ PUBLISHED: public: INLINE bool set_scene(SceneSetup *scene_setup); INLINE SceneSetup *get_scene() const; + INLINE const qpGeomMunger *get_geom_munger() const; virtual PreparedGraphicsObjects *get_prepared_objects(); @@ -139,6 +142,12 @@ public: virtual CPT(RenderState) begin_decal_base_second(); virtual void finish_decal(); + virtual void begin_draw_primitives(const qpGeomVertexData *vertex_data); + virtual void draw_triangles(qpGeomTriangles *primitive); + virtual void draw_tristrips(qpGeomTristrips *primitive); + virtual void draw_trifans(qpGeomTrifans *primitive); + virtual void end_draw_primitives(); + virtual bool framebuffer_bind_to_texture(GraphicsOutput *win, Texture *tex); virtual void framebuffer_release_texture(GraphicsOutput *win, Texture *tex); @@ -200,6 +209,7 @@ protected: virtual void set_blend_mode(); virtual void finish_modify_state(); + virtual void setup_geom_munger(PT(qpGeomMunger) munger); virtual void free_pointers(); virtual void close_gsg(); @@ -232,6 +242,8 @@ protected: CPT(RenderState) _state; CPT(TransformState) _transform; + CPT(qpGeomMunger) _geom_munger; + CPT(qpGeomVertexData) _vertex_data; int _buffer_mask; Colorf _color_clear_value; diff --git a/panda/src/distort/projectionScreen.I b/panda/src/distort/projectionScreen.I index 7eab1c216f..c9321255c4 100644 --- a/panda/src/distort/projectionScreen.I +++ b/panda/src/distort/projectionScreen.I @@ -41,7 +41,7 @@ get_projector() const { //////////////////////////////////////////////////////////////////// INLINE void ProjectionScreen:: set_texcoord_name(const string &texcoord_name) { - _texcoord_name = TexCoordName::make(texcoord_name); + _texcoord_name = InternalName::get_texcoord_name(texcoord_name); _stale = true; } @@ -52,7 +52,7 @@ set_texcoord_name(const string &texcoord_name) { // will be generated by this particular // ProjectionScreen, as set by set_texcoord_name(). //////////////////////////////////////////////////////////////////// -INLINE const string &ProjectionScreen:: +INLINE string ProjectionScreen:: get_texcoord_name() const { return _texcoord_name->get_name(); } diff --git a/panda/src/distort/projectionScreen.cxx b/panda/src/distort/projectionScreen.cxx index 999577568a..c04ae41fd2 100644 --- a/panda/src/distort/projectionScreen.cxx +++ b/panda/src/distort/projectionScreen.cxx @@ -34,7 +34,7 @@ TypeHandle ProjectionScreen::_type_handle; ProjectionScreen:: ProjectionScreen(const string &name) : PandaNode(name) { - _texcoord_name = TexCoordName::get_default(); + _texcoord_name = InternalName::get_texcoord(); _invert_uvs = project_invert_uvs; _vignette_on = false; diff --git a/panda/src/distort/projectionScreen.h b/panda/src/distort/projectionScreen.h index 8658322736..f35ac06d60 100644 --- a/panda/src/distort/projectionScreen.h +++ b/panda/src/distort/projectionScreen.h @@ -25,7 +25,7 @@ #include "lensNode.h" #include "geomNode.h" #include "nodePath.h" -#include "texCoordName.h" +#include "internalName.h" #include "pointerTo.h" class Geom; @@ -82,7 +82,7 @@ PUBLISHED: PT(PandaNode) make_flat_mesh(const NodePath &this_np, const NodePath &camera); INLINE void set_texcoord_name(const string &texcoord_name); - INLINE const string &get_texcoord_name() const; + INLINE string get_texcoord_name() const; INLINE void set_invert_uvs(bool invert_uvs); INLINE bool get_invert_uvs() const; @@ -124,7 +124,7 @@ private: NodePath _projector; PT(LensNode) _projector_node; - CPT(TexCoordName) _texcoord_name; + CPT(InternalName) _texcoord_name; bool _invert_uvs; bool _vignette_on; Colorf _vignette_color; diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx index 1ff257001f..bba410a41d 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx @@ -48,6 +48,11 @@ #include "depthOffsetAttrib.h" #include "fog.h" #include "throw_event.h" +#include "qpgeomVertexFormat.h" +#include "qpgeomVertexData.h" +#include "qpgeomTriangles.h" +#include "qpgeomTristrips.h" +#include "qpgeomTrifans.h" #ifdef DO_PSTATS #include "pStatTimer.h" @@ -2575,6 +2580,78 @@ draw_sphere(GeomSphere *geom, GeomContext *gc) { _pCurFvfBufPtr = NULL; } +//////////////////////////////////////////////////////////////////// +// Function: DXGraphicsStateGuardian8::begin_draw_primitives +// Access: Public, Virtual +// Description: Called before a sequence of draw_primitive() +// functions are called, this should prepare the vertex +// buffer if necessary. +//////////////////////////////////////////////////////////////////// +void DXGraphicsStateGuardian8:: +begin_draw_primitives(const qpGeomVertexData *vertex_data) { + DO_PSTATS_STUFF(_draw_primitive_pcollector.start()); + + GraphicsStateGuardian::begin_draw_primitives(vertex_data); + + const qpGeomVertexFormat *format = _vertex_data->get_format(); + + if (format == qpGeomVertexFormat::get_v3()) { + set_vertex_format(D3DFVF_XYZ); + } else if (format == qpGeomVertexFormat::get_v3n3()) { + set_vertex_format(D3DFVF_XYZ | D3DFVF_NORMAL); + } else if (format == qpGeomVertexFormat::get_v3t2()) { + set_vertex_format(D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0)); + } else if (format == qpGeomVertexFormat::get_v3n3t2()) { + set_vertex_format(D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0)); + } else if (format == qpGeomVertexFormat::get_v3cp() || + format == qpGeomVertexFormat::get_v3c4()) { + set_vertex_format(D3DFVF_XYZ | D3DFVF_DIFFUSE); + } else if (format == qpGeomVertexFormat::get_v3n3cp() || + format == qpGeomVertexFormat::get_v3n3c4()) { + set_vertex_format(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL); + } else if (format == qpGeomVertexFormat::get_v3cpt2() || + format == qpGeomVertexFormat::get_v3c4t2()) { + set_vertex_format(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0)); + } else if (format == qpGeomVertexFormat::get_v3n3cpt2() || + format == qpGeomVertexFormat::get_v3n3c4t2()) { + set_vertex_format(D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0)); + } else { + nassert_raise("Unexpected vertex format"); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: DXGraphicsStateGuardian8::draw_triangles +// Access: Public, Virtual +// Description: Draws a series of disconnected triangles. +//////////////////////////////////////////////////////////////////// +void DXGraphicsStateGuardian8:: +draw_triangles(qpGeomTriangles *primitive) { + HRESULT hr = _pD3DDevice->DrawIndexedPrimitiveUP + (D3DPT_TRIANGLELIST, + primitive->get_min_vertex(), + primitive->get_max_vertex() - primitive->get_min_vertex() + 1, + primitive->get_num_primitives(), + primitive->get_vertices(), + D3DFMT_INDEX16, + vertex_data->get_array_data(0), + vertex_data->get_format()->get_array_format(0)->get_stride()); + + TestDrawPrimFailure(DrawPrim,hr,_pD3DDevice,nPrims,0); +} + +//////////////////////////////////////////////////////////////////// +// Function: DXGraphicsStateGuardian8::end_draw_primitives() +// Access: Public, Virtual +// Description: Called after a sequence of draw_primitive() +// functions are called, this should do whatever cleanup +// is appropriate. +//////////////////////////////////////////////////////////////////// +void DXGraphicsStateGuardian8:: +end_draw_primitives() { + DO_PSTATS_STUFF(_draw_primitive_pcollector.stop()); +} + //////////////////////////////////////////////////////////////////// // Function: DXGraphicsStateGuardian8::prepare_texture // Access: Public, Virtual diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.h b/panda/src/dxgsg8/dxGraphicsStateGuardian8.h index 60f4c9b930..1430e93e06 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.h +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.h @@ -89,6 +89,10 @@ public: virtual void draw_trifan(GeomTrifan *geom, GeomContext *gc); virtual void draw_sphere(GeomSphere *geom, GeomContext *gc); + virtual void begin_draw_primitives(const qpGeomVertexData *vertex_data); + virtual void draw_triangles(qpGeomTriangles *primitive); + virtual void end_draw_primitives(); + virtual TextureContext *prepare_texture(Texture *tex); virtual void apply_texture(TextureContext *tc); virtual void release_texture(TextureContext *tc); diff --git a/panda/src/egg2pg/computedVerticesMaker.cxx b/panda/src/egg2pg/computedVerticesMaker.cxx index 6b0aa0a9d9..41f56b68ec 100644 --- a/panda/src/egg2pg/computedVerticesMaker.cxx +++ b/panda/src/egg2pg/computedVerticesMaker.cxx @@ -26,7 +26,7 @@ #include "eggNode.h" #include "eggGroup.h" #include "eggVertex.h" -#include "texCoordName.h" +#include "internalName.h" #include @@ -257,7 +257,7 @@ add_normal(const Normald &normal, const EggMorphNormalList &morphs, // array. //////////////////////////////////////////////////////////////////// int ComputedVerticesMaker:: -add_texcoord(const TexCoordName *name, +add_texcoord(const InternalName *name, const TexCoordd &texcoord, const EggMorphTexCoordList &morphs, const LMatrix3d &transform) { TexCoordDef &def = _tdefmap[name]; @@ -389,7 +389,7 @@ make_computed_vertices(Character *character, CharacterMaker &char_maker) { // Temporary: the ComputedVertices object currently doesn't support // multitexture. - character->_cv._texcoords = _texcoords[TexCoordName::get_default()]; + character->_cv._texcoords = _texcoords[InternalName::get_texcoord()]; // Finally, add in all the morph definitions. Morphs::const_iterator mi; @@ -446,12 +446,12 @@ make_computed_vertices(Character *character, CharacterMaker &char_maker) { TexCoordMorphMap::const_iterator mmi; for (mmi = mlist._tmorphs.begin(); mmi != mlist._tmorphs.end(); ++mmi) { - const TexCoordName *name = (*mmi).first; + const InternalName *name = (*mmi).first; const TexCoordMorphList &tmorphs = (*mmi).second; // Temporary check: the ComputedVertices object currently // doesn't support multitexture. - if (name == TexCoordName::get_default()) { + if (name == InternalName::get_texcoord()) { comp_verts->_texcoord_morphs.push_back(ComputedVerticesMorphTexCoord()); ComputedVerticesMorphTexCoord &mv = comp_verts->_texcoord_morphs.back(); mv._slider_index = slider_index; diff --git a/panda/src/egg2pg/computedVerticesMaker.h b/panda/src/egg2pg/computedVerticesMaker.h index e90cd2f86a..e54a6e234e 100644 --- a/panda/src/egg2pg/computedVerticesMaker.h +++ b/panda/src/egg2pg/computedVerticesMaker.h @@ -40,7 +40,7 @@ class ComputedVertices; class CharacterMaker; class EggNode; class EggVertex; -class TexCoordName; +class InternalName; /////////////////////////////////////////////////////////////////// // Class : ComputedVerticesMaker @@ -74,7 +74,7 @@ public: const LMatrix4d &transform); int add_normal(const Normald &normal, const EggMorphNormalList &morphs, const LMatrix4d &transform); - int add_texcoord(const TexCoordName *name, + int add_texcoord(const InternalName *name, const TexCoordd &texcoord, const EggMorphTexCoordList &morphs, const LMatrix3d &transform); @@ -90,7 +90,7 @@ public: PTA_Normalf _norms; PTA_Colorf _colors; - typedef pmap TexCoords; + typedef pmap TexCoords; TexCoords _texcoords; protected: @@ -98,7 +98,7 @@ protected: typedef pmap NormalMorphList; typedef pmap TexCoordMorphList; typedef pmap ColorMorphList; - typedef pmap TexCoordMorphMap; + typedef pmap TexCoordMorphMap; class MorphList { public: VertexMorphList _vmorphs; @@ -120,7 +120,7 @@ protected: ComputedVerticesMakerTexCoordMap _tmap; }; - typedef pmap TexCoordDefMap; + typedef pmap TexCoordDefMap; TexCoordDefMap _tdefmap; ComputedVerticesMakerColorMap _cmap; diff --git a/panda/src/egg2pg/eggLoader.cxx b/panda/src/egg2pg/eggLoader.cxx index 67aac9230b..0420e9383f 100644 --- a/panda/src/egg2pg/eggLoader.cxx +++ b/panda/src/egg2pg/eggLoader.cxx @@ -320,11 +320,11 @@ make_nonindexed_primitive(EggPrimitive *egg_prim, PandaNode *parent, for (ui = egg_vert->uv_begin(); ui != egg_vert->uv_end(); ++ui) { EggVertexUV *uv_obj = (*ui); TexCoordd uv = uv_obj->get_uv(); - CPT(TexCoordName) uv_name; - if (uv_obj->has_name()) { - uv_name = TexCoordName::make(uv_obj->get_name()); + CPT(InternalName) uv_name; + if (uv_obj->has_name() && uv_obj->get_name() != string("default")) { + uv_name = InternalName::get_texcoord_name(uv_obj->get_name()); } else { - uv_name = TexCoordName::get_default(); + uv_name = InternalName::get_texcoord(); } BakeInUVs::const_iterator buv = bake_in_uvs.find(uv_name); @@ -453,11 +453,11 @@ make_indexed_primitive(EggPrimitive *egg_prim, PandaNode *parent, for (ui = egg_vert->uv_begin(); ui != egg_vert->uv_end(); ++ui) { EggVertexUV *uv_obj = (*ui); TexCoordd uv = uv_obj->get_uv(); - CPT(TexCoordName) uv_name; - if (uv_obj->has_name()) { - uv_name = TexCoordName::make(uv_obj->get_name()); + CPT(InternalName) uv_name; + if (uv_obj->has_name() && uv_obj->get_name() != string("default")) { + uv_name = InternalName::get_texcoord_name(uv_obj->get_name()); } else { - uv_name = TexCoordName::get_default(); + uv_name = InternalName::get_texcoord(); } LMatrix3d mat = LMatrix3d::ident_mat(); @@ -498,7 +498,7 @@ make_indexed_primitive(EggPrimitive *egg_prim, PandaNode *parent, for (tci = comp_verts_maker._texcoords.begin(); tci != comp_verts_maker._texcoords.end(); ++tci) { - const TexCoordName *name = (*tci).first; + const InternalName *name = (*tci).first; bucket.set_texcoords(name, (*tci).second); } @@ -1248,9 +1248,10 @@ make_texture_stage(const EggTexture *egg_tex) { } - if (egg_tex->has_uv_name() && !egg_tex->get_uv_name().empty()) { - CPT(TexCoordName) name = - TexCoordName::make(egg_tex->get_uv_name()); + if (egg_tex->has_uv_name() && !egg_tex->get_uv_name().empty() && + egg_tex->get_uv_name() != string("default")) { + CPT(InternalName) name = + InternalName::get_texcoord_name(egg_tex->get_uv_name()); stage->set_texcoord_name(name); } @@ -1461,11 +1462,11 @@ setup_bucket(BuilderBucket &bucket, EggLoader::BakeInUVs &bake_in_uvs, // if we can safely bake it into the UV's. (We need to get the // complete list of textures that share this same set of UV's // per each unique texture matrix. Whew!) - CPT(TexCoordName) uv_name; - if (egg_tex->has_uv_name()) { - uv_name = TexCoordName::make(egg_tex->get_uv_name()); + CPT(InternalName) uv_name; + if (egg_tex->has_uv_name() && egg_tex->get_uv_name() != string("default")) { + uv_name = InternalName::get_texcoord_name(egg_tex->get_uv_name()); } else { - uv_name = TexCoordName::get_default(); + uv_name = InternalName::get_texcoord(); } if (has_tex_gen) { @@ -1503,7 +1504,7 @@ setup_bucket(BuilderBucket &bucket, EggLoader::BakeInUVs &bake_in_uvs, // texture matrix. TexMats::const_iterator tmi; for (tmi = tex_mats.begin(); tmi != tex_mats.end(); ++tmi) { - const TexCoordName *uv_name = (*tmi).first; + const InternalName *uv_name = (*tmi).first; const TexMatTransforms &tmt = (*tmi).second; if (tmt.size() == 1 && !needs_tex_mat) { diff --git a/panda/src/egg2pg/eggLoader.h b/panda/src/egg2pg/eggLoader.h index 396242f2d2..cf5b4490c6 100644 --- a/panda/src/egg2pg/eggLoader.h +++ b/panda/src/egg2pg/eggLoader.h @@ -91,10 +91,10 @@ private: // This structure is used internally in setup_bucket(). typedef pvector TexMatTextures; typedef pmap TexMatTransforms; - typedef pmap TexMats; + typedef pmap TexMats; // This structure is returned by setup_bucket(). - typedef pmap BakeInUVs; + typedef pmap BakeInUVs; void make_nurbs_curve(EggNurbsCurve *egg_curve, PandaNode *parent, const LMatrix4d &mat); diff --git a/panda/src/express/numeric_types.h b/panda/src/express/numeric_types.h index 0ba0d07bd4..8c334809f8 100644 --- a/panda/src/express/numeric_types.h +++ b/panda/src/express/numeric_types.h @@ -44,6 +44,9 @@ typedef PRUint64 PN_uint64; typedef PRFloat64 PN_float64; +// NSPR doesn't define a float32. +typedef float PN_float32; + #else // HAVE_NSPR // Without NSPR, and without any other information, we need some @@ -66,6 +69,7 @@ typedef unsigned short PN_uint16; typedef unsigned long PN_uint32; typedef double PN_float64; +typedef float PN_float32; #endif // HAVE_NSPR diff --git a/panda/src/express/pointerToArray.I b/panda/src/express/pointerToArray.I index c4c17fd501..ca627f63f2 100644 --- a/panda/src/express/pointerToArray.I +++ b/panda/src/express/pointerToArray.I @@ -228,8 +228,11 @@ back() const { //////////////////////////////////////////////////////////////////// template INLINE TYPENAME PointerToArray::iterator PointerToArray:: -insert(iterator position, const Element &x) const { - nassertr((this->_void_ptr) != NULL, position); +insert(iterator position, const Element &x) { + if ((this->_void_ptr) == NULL) { + reassign(new RefCountObj >); + position = end(); + } nassertr(position >= ((To *)(this->_void_ptr))->begin() && position <= ((To *)(this->_void_ptr))->end(), position); return ((To *)(this->_void_ptr))->insert(position, x); @@ -242,8 +245,11 @@ insert(iterator position, const Element &x) const { //////////////////////////////////////////////////////////////////// template INLINE void PointerToArray:: -insert(iterator position, size_type n, const Element &x) const { - nassertv((this->_void_ptr) != NULL); +insert(iterator position, size_type n, const Element &x) { + if ((this->_void_ptr) == NULL) { + reassign(new RefCountObj >); + position = end(); + } nassertv(position >= ((To *)(this->_void_ptr))->begin() && position <= ((To *)(this->_void_ptr))->end()); ((To *)(this->_void_ptr))->insert(position, n, x); @@ -256,10 +262,8 @@ insert(iterator position, size_type n, const Element &x) const { //////////////////////////////////////////////////////////////////// template INLINE void PointerToArray:: -erase(iterator position) const { - nassertd((this->_void_ptr) != NULL) { - ((PointerToArray *)this)->reassign(new RefCountObj >); - } +erase(iterator position) { + nassertv((this->_void_ptr) != NULL); nassertv(position >= ((To *)(this->_void_ptr))->begin() && position <= ((To *)(this->_void_ptr))->end()); ((To *)(this->_void_ptr))->erase(position); @@ -272,10 +276,8 @@ erase(iterator position) const { //////////////////////////////////////////////////////////////////// template INLINE void PointerToArray:: -erase(iterator first, iterator last) const { - nassertd((this->_void_ptr) != NULL) { - ((PointerToArray *)this)->reassign(new RefCountObj >); - } +erase(iterator first, iterator last) { + nassertv((this->_void_ptr) != NULL); nassertv(first >= ((To *)(this->_void_ptr))->begin() && first <= ((To *)(this->_void_ptr))->end()); nassertv(last >= ((To *)(this->_void_ptr))->begin() && last <= ((To *)(this->_void_ptr))->end()); ((To *)(this->_void_ptr))->erase(first, last); diff --git a/panda/src/express/pointerToArray.h b/panda/src/express/pointerToArray.h index 2d98bf9a0e..5c207ea615 100644 --- a/panda/src/express/pointerToArray.h +++ b/panda/src/express/pointerToArray.h @@ -135,8 +135,8 @@ public: INLINE size_type capacity() const; INLINE reference front() const; INLINE reference back() const; - INLINE iterator insert(iterator position, const Element &x) const; - INLINE void insert(iterator position, size_type n, const Element &x) const; + INLINE iterator insert(iterator position, const Element &x); + INLINE void insert(iterator position, size_type n, const Element &x); // We don't define the insert() method that accepts a pair of // iterators to copy from. That's problematic because of the whole @@ -145,8 +145,8 @@ public: // be exported from the DLL, you should use // insert_into_vector(pta.v(), ...). - INLINE void erase(iterator position) const; - INLINE void erase(iterator first, iterator last) const; + INLINE void erase(iterator position); + INLINE void erase(iterator first, iterator last); PUBLISHED: #if !defined(WIN32_VC) diff --git a/panda/src/framework/windowFramework.cxx b/panda/src/framework/windowFramework.cxx index b60b7db98f..0139198012 100644 --- a/panda/src/framework/windowFramework.cxx +++ b/panda/src/framework/windowFramework.cxx @@ -26,8 +26,15 @@ #include "loader.h" #include "keyboardButton.h" #include "geomTri.h" +#include "qpgeom.h" +#include "qpgeomTriangles.h" +#include "qpgeomTristrips.h" +#include "qpgeomVertexData.h" +#include "qpgeomVertexFormat.h" +#include "qpgeomVertexIterator.h" #include "texturePool.h" #include "textureAttrib.h" +#include "colorAttrib.h" #include "perspectiveLens.h" #include "orthographicLens.h" #include "auto_bind.h" @@ -603,31 +610,6 @@ load_model(const NodePath &parent, Filename filename) { //////////////////////////////////////////////////////////////////// NodePath WindowFramework:: load_default_model(const NodePath &parent) { - PTA_Vertexf coords; - PTA_TexCoordf uvs; - PTA_Normalf norms; - PTA_Colorf colors; - PTA_ushort cindex; - - coords.push_back(Vertexf::rfu(0.0, 0.0, 0.0)); - coords.push_back(Vertexf::rfu(1.0, 0.0, 0.0)); - coords.push_back(Vertexf::rfu(0.0, 0.0, 1.0)); - uvs.push_back(TexCoordf(0.0, 0.0)); - uvs.push_back(TexCoordf(1.0, 0.0)); - uvs.push_back(TexCoordf(0.0, 1.0)); - norms.push_back(Normalf::back()); - colors.push_back(Colorf(0.5, 0.5, 1.0, 1.0)); - cindex.push_back(0); - cindex.push_back(0); - cindex.push_back(0); - - PT(GeomTri) geom = new GeomTri; - geom->set_num_prims(1); - geom->set_coords(coords); - geom->set_texcoords(uvs, G_PER_VERTEX); - geom->set_normals(norms, G_PER_PRIM); - geom->set_colors(colors, G_PER_VERTEX, cindex); - CPT(RenderState) state = RenderState::make_empty(); // Get the default texture to apply to the triangle; it's compiled @@ -645,7 +627,70 @@ load_default_model(const NodePath &parent) { } GeomNode *geomnode = new GeomNode("tri"); - geomnode->add_geom(geom, state); + + if (use_qpgeom) { + // New, experimental Geom code. + PT(qpGeomVertexData) vdata = new qpGeomVertexData(qpGeomVertexFormat::get_v3n3cpt2()); + qpGeomVertexIterator vertex(vdata, InternalName::get_vertex()); + qpGeomVertexIterator normal(vdata, InternalName::get_normal()); + qpGeomVertexIterator color(vdata, InternalName::get_color()); + qpGeomVertexIterator texcoord(vdata, InternalName::get_texcoord()); + + vertex.set_data3(Vertexf::rfu(0.0, 0.0, 0.0)); + vertex.set_data3(Vertexf::rfu(1.0, 0.0, 0.0)); + vertex.set_data3(Vertexf::rfu(0.0, 0.0, 1.0)); + + normal.set_data3(Normalf::back()); + normal.set_data3(Normalf::back()); + normal.set_data3(Normalf::back()); + + color.set_data4(0.5, 0.5, 1.0, 1.0); + color.set_data4(0.5, 0.5, 1.0, 1.0); + color.set_data4(0.5, 0.5, 1.0, 1.0); + + texcoord.set_data2(0.0, 0.0); + texcoord.set_data2(1.0, 0.0); + texcoord.set_data2(0.0, 1.0); + + PT(qpGeomTriangles) tri = new qpGeomTriangles; + tri->add_consecutive_vertices(0, 3); + tri->close_primitive(); + + PT(qpGeom) geom = new qpGeom; + geom->set_vertex_data(vdata); + geom->add_primitive(tri); + + geomnode->add_geom(geom, state); + + } else { + // Original, tried-and-true Geom code. + PTA_Vertexf coords; + PTA_TexCoordf uvs; + PTA_Normalf norms; + PTA_Colorf colors; + PTA_ushort cindex; + + coords.push_back(Vertexf::rfu(0.0, 0.0, 0.0)); + coords.push_back(Vertexf::rfu(1.0, 0.0, 0.0)); + coords.push_back(Vertexf::rfu(0.0, 0.0, 1.0)); + uvs.push_back(TexCoordf(0.0, 0.0)); + uvs.push_back(TexCoordf(1.0, 0.0)); + uvs.push_back(TexCoordf(0.0, 1.0)); + norms.push_back(Normalf::back()); + colors.push_back(Colorf(0.5, 0.5, 1.0, 1.0)); + cindex.push_back(0); + cindex.push_back(0); + cindex.push_back(0); + + PT(GeomTri) geom = new GeomTri; + geom->set_num_prims(1); + geom->set_coords(coords); + geom->set_texcoords(uvs, G_PER_VERTEX); + geom->set_normals(norms, G_PER_PRIM); + geom->set_colors(colors, G_PER_VERTEX, cindex); + + geomnode->add_geom(geom, state); + } return parent.attach_new_node(geomnode); } @@ -995,7 +1040,6 @@ load_image_as_model(const Filename &filename) { tex->set_magfilter(Texture::FT_linear); // Ok, now make a polygon to show the texture. - PT(GeomNode) card_geode = new GeomNode("card"); // Choose the dimensions of the polygon appropriately. float left = -x_size / 2.0; @@ -1003,34 +1047,64 @@ load_image_as_model(const Filename &filename) { float bottom = -y_size / 2.0; float top = y_size / 2.0; - GeomTristrip *geoset = new GeomTristrip; - PTA_int lengths=PTA_int::empty_array(0); - lengths.push_back(4); - - PTA_Vertexf verts; - verts.push_back(Vertexf::rfu(left, 0.02f, top)); - verts.push_back(Vertexf::rfu(left, 0.02f, bottom)); - verts.push_back(Vertexf::rfu(right, 0.02f, top)); - verts.push_back(Vertexf::rfu(right, 0.02f, bottom)); - - geoset->set_num_prims(1); - geoset->set_lengths(lengths); - - geoset->set_coords(verts); - - PTA_TexCoordf uvs; - uvs.push_back(TexCoordf(0.0f, 1.0f)); - uvs.push_back(TexCoordf(0.0f, 0.0f)); - uvs.push_back(TexCoordf(1.0f, 1.0f)); - uvs.push_back(TexCoordf(1.0f, 0.0f)); - - geoset->set_texcoords(uvs, G_PER_VERTEX); - - card_geode->add_geom(geoset); - card_geode->set_attrib(TextureAttrib::make(tex)); + PT(GeomNode) card_node = new GeomNode("card"); + card_node->set_attrib(ColorAttrib::make_flat(Colorf(1.0f, 1.0f, 1.0f, 1.0f))); + card_node->set_attrib(TextureAttrib::make(tex)); if (has_alpha) { - card_geode->set_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha)); + card_node->set_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha)); } - return card_geode.p(); + if (use_qpgeom) { + PT(qpGeomVertexData) vdata = new qpGeomVertexData(qpGeomVertexFormat::get_v3t2()); + qpGeomVertexIterator vertex(vdata, InternalName::get_vertex()); + qpGeomVertexIterator texcoord(vdata, InternalName::get_texcoord()); + + vertex.set_data3(Vertexf::rfu(left, 0.02f, top)); + vertex.set_data3(Vertexf::rfu(left, 0.02f, bottom)); + vertex.set_data3(Vertexf::rfu(right, 0.02f, top)); + vertex.set_data3(Vertexf::rfu(right, 0.02f, bottom)); + + texcoord.set_data2(0.0f, 1.0f); + texcoord.set_data2(0.0f, 0.0f); + texcoord.set_data2(1.0f, 1.0f); + texcoord.set_data2(1.0f, 0.0f); + + PT(qpGeomTristrips) strip = new qpGeomTristrips; + strip->add_consecutive_vertices(0, 4); + strip->close_primitive(); + + PT(qpGeom) geom = new qpGeom; + geom->set_vertex_data(vdata); + geom->add_primitive(strip); + + card_node->add_geom(geom); + + } else { + GeomTristrip *geom = new GeomTristrip; + PTA_int lengths=PTA_int::empty_array(0); + lengths.push_back(4); + + PTA_Vertexf verts; + verts.push_back(Vertexf::rfu(left, 0.02f, top)); + verts.push_back(Vertexf::rfu(left, 0.02f, bottom)); + verts.push_back(Vertexf::rfu(right, 0.02f, top)); + verts.push_back(Vertexf::rfu(right, 0.02f, bottom)); + + geom->set_num_prims(1); + geom->set_lengths(lengths); + + geom->set_coords(verts); + + PTA_TexCoordf uvs; + uvs.push_back(TexCoordf(0.0f, 1.0f)); + uvs.push_back(TexCoordf(0.0f, 0.0f)); + uvs.push_back(TexCoordf(1.0f, 1.0f)); + uvs.push_back(TexCoordf(1.0f, 0.0f)); + + geom->set_texcoords(uvs, G_PER_VERTEX); + + card_node->add_geom(geom); + } + + return card_node.p(); } diff --git a/panda/src/glstuff/Sources.pp b/panda/src/glstuff/Sources.pp index 6a37fdd24e..6de45c86cb 100644 --- a/panda/src/glstuff/Sources.pp +++ b/panda/src/glstuff/Sources.pp @@ -22,6 +22,9 @@ glGeomContext_src.cxx \ glGeomContext_src.I \ glGeomContext_src.h \ + glGeomMunger_src.cxx \ + glGeomMunger_src.I \ + glGeomMunger_src.h \ glGraphicsStateGuardian_src.cxx \ glGraphicsStateGuardian_src.I \ glGraphicsStateGuardian_src.h \ diff --git a/panda/src/glstuff/glGeomMunger_src.I b/panda/src/glstuff/glGeomMunger_src.I new file mode 100644 index 0000000000..6c53a1621f --- /dev/null +++ b/panda/src/glstuff/glGeomMunger_src.I @@ -0,0 +1,27 @@ +// Filename: glGeomMunger_src.I +// Created by: drose (10Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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: CLP(GeomMunger)::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE CLP(GeomMunger):: +CLP(GeomMunger)() { +} diff --git a/panda/src/glstuff/glGeomMunger_src.cxx b/panda/src/glstuff/glGeomMunger_src.cxx new file mode 100644 index 0000000000..ab9dc6c6b5 --- /dev/null +++ b/panda/src/glstuff/glGeomMunger_src.cxx @@ -0,0 +1,52 @@ +// Filename: glGeomMunger_src.cxx +// Created by: drose (10Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 . +// +//////////////////////////////////////////////////////////////////// + +TypeHandle CLP(GeomMunger)::_type_handle; + + +//////////////////////////////////////////////////////////////////// +// Function: CLP(GeomMunger)::munge_format_impl +// Access: Protected, Virtual +// Description: Given a source GeomVertexFormat, converts it if +// necessary to the appropriate format for rendering. +//////////////////////////////////////////////////////////////////// +CPT(qpGeomVertexFormat) CLP(GeomMunger):: +munge_format_impl(const qpGeomVertexFormat *orig) { + CPT(qpGeomVertexFormat) format = orig; + + const qpGeomVertexDataType *color_type = + format->get_data_type(InternalName::get_color()); + if (color_type != (qpGeomVertexDataType *)NULL && + color_type->get_numeric_type() == qpGeomVertexDataType::NT_packed_argb) { + // We need to convert the color format; OpenGL doesn't support the + // byte order of DirectX's packed_argb format. + int color_array = format->get_array_with(InternalName::get_color()); + + PT(qpGeomVertexFormat) new_format = new qpGeomVertexFormat(*format); + PT(qpGeomVertexArrayFormat) new_array_format = new_format->modify_array(color_array); + + // Replace the existing color format with the new format. + new_array_format->add_data_type + (InternalName::get_color(), 4, qpGeomVertexDataType::NT_uint8, + color_type->get_start()); + + format = qpGeomVertexFormat::register_format(new_format); + } + + return format; +} diff --git a/panda/src/glstuff/glGeomMunger_src.h b/panda/src/glstuff/glGeomMunger_src.h new file mode 100644 index 0000000000..f4a7908e30 --- /dev/null +++ b/panda/src/glstuff/glGeomMunger_src.h @@ -0,0 +1,54 @@ +// Filename: glGeomMunger_src.h +// Created by: drose (10Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "pandabase.h" +#include "qpgeomMunger.h" + +//////////////////////////////////////////////////////////////////// +// Class : GLGeomMunger +// Description : This specialization on GeomMunger finesses vertices +// for OpenGL rendering. In particular, it makes sure +// colors aren't stored in DirectX's packed_argb format. +//////////////////////////////////////////////////////////////////// +class EXPCL_GL CLP(GeomMunger) : public qpGeomMunger { +public: + INLINE CLP(GeomMunger)(); + +protected: + virtual CPT(qpGeomVertexFormat) munge_format_impl(const qpGeomVertexFormat *orig); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + qpGeomMunger::init_type(); + register_type(_type_handle, CLASSPREFIX_QUOTED "GeomMunger", + qpGeomMunger::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 "glGeomMunger_src.I" + diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 49f856dcac..e10eb1f1c8 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -21,6 +21,10 @@ #include "renderBuffer.h" #include "geom.h" #include "geomIssuer.h" +#include "qpgeomVertexData.h" +#include "qpgeomTriangles.h" +#include "qpgeomTristrips.h" +#include "qpgeomTrifans.h" #include "graphicsWindow.h" #include "lens.h" #include "perspectiveLens.h" @@ -128,6 +132,14 @@ issue_scaled_color_gl(const Geom *geom, Geom::ColorIterator &citerator, // defined by the GL, just so it will always be safe to call the // extension functions. +static void APIENTRY +null_glDrawRangeElements(GLenum mode, GLuint start, GLuint end, + GLsizei count, GLenum type, const GLvoid *indices) { + // If we don't support glDrawRangeElements(), just use the original + // glDrawElements() instead. + GLP(DrawElements)(mode, count, type, indices); +} + static void APIENTRY null_glActiveTexture(GLenum gl_texture_stage) { // If we don't support multitexture, we'd better not try to request @@ -346,6 +358,27 @@ reset() { get_extra_extensions(); report_extensions(); + if (is_at_least_version(1, 2)) { + _supports_draw_range_elements = true; + _glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC) + get_extension_func(GLPREFIX_QUOTED, "DrawRangeElements"); + + } else if (has_extension("EXT_draw_range_elements")) { + _supports_draw_range_elements = true; + _glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC) + get_extension_func(GLPREFIX_QUOTED, "DrawRangeElementsEXT"); + } + if (_supports_draw_range_elements) { + if (_glDrawRangeElements == NULL) { + GLCAT.warning() + << "glDrawRangeElements advertised as supported by OpenGL runtime, but could not get pointers to extension functions.\n"; + _supports_draw_range_elements = false; + } + } + if (!_supports_draw_range_elements) { + _glDrawRangeElements = null_glDrawRangeElements; + } + _supports_3d_texture = has_extension("GL_EXT_texture3D") || is_at_least_version(1, 2); @@ -1975,6 +2008,128 @@ draw_sphere(GeomSphere *geom, GeomContext *gc) { DO_PSTATS_STUFF(_draw_primitive_pcollector.stop()); } +//////////////////////////////////////////////////////////////////// +// Function: CLP(GraphicsStateGuardian)::begin_draw_primitives +// Access: Public, Virtual +// Description: Called before a sequence of draw_primitive() +// functions are called, this should prepare the vertex +// buffer if necessary. +//////////////////////////////////////////////////////////////////// +void CLP(GraphicsStateGuardian):: +begin_draw_primitives(const qpGeomVertexData *vertex_data) { + DO_PSTATS_STUFF(_draw_primitive_pcollector.start()); + + GraphicsStateGuardian::begin_draw_primitives(vertex_data); + + CPTA_uchar array_data; + int num_components; + qpGeomVertexDataType::NumericType numeric_type; + int start; + int stride; + + if (_vertex_data->get_array_info(InternalName::get_vertex(), + array_data, num_components, numeric_type, + start, stride)) { + GLP(VertexPointer)(num_components, get_numeric_type(numeric_type), + stride, array_data + start); + GLP(EnableClientState)(GL_VERTEX_ARRAY); + } else { + GLP(DisableClientState)(GL_VERTEX_ARRAY); + } + + bool has_normals = false; + if (wants_normals() && + _vertex_data->get_array_info(InternalName::get_normal(), + array_data, num_components, numeric_type, + start, stride)) { + GLP(NormalPointer)(get_numeric_type(numeric_type), stride, + array_data + start); + GLP(EnableClientState)(GL_NORMAL_ARRAY); + has_normals = true; + } else { + GLP(DisableClientState)(GL_NORMAL_ARRAY); + } + + bool has_colors = false; + if (wants_colors()) { + if (_vertex_data->get_array_info(InternalName::get_color(), + array_data, num_components, numeric_type, + start, stride)) { + if (numeric_type == qpGeomVertexDataType::NT_packed_argb) { + // Temporary hack--this will probably reverse r and b. + GLP(ColorPointer)(4, GL_UNSIGNED_BYTE, stride, array_data + start); + + } else { + GLP(ColorPointer)(num_components, get_numeric_type(numeric_type), + stride, array_data + start); + } + GLP(EnableClientState)(GL_COLOR_ARRAY); + has_colors = true; + + } else { + // We wanted colors, but the geom didn't have any; just issue + // white. + GLP(Color4f)(1.0f, 1.0f, 1.0f, 1.0f); + GLP(DisableClientState)(GL_COLOR_ARRAY); + } + } else { + GLP(DisableClientState)(GL_COLOR_ARRAY); + } + + if (wants_texcoords() && + _vertex_data->get_array_info(InternalName::get_texcoord(), + array_data, num_components, numeric_type, + start, stride)) { + GLP(TexCoordPointer)(num_components, get_numeric_type(numeric_type), + stride, array_data + start); + GLP(EnableClientState)(GL_TEXTURE_COORD_ARRAY); + } else { + GLP(DisableClientState)(GL_TEXTURE_COORD_ARRAY); + } + + // If we have per-vertex colors or normals, we need smooth shading. + // Otherwise we want flat shading for performance reasons. + if (has_colors || has_normals) { + GLP(ShadeModel)(GL_SMOOTH); + } else { + GLP(ShadeModel)(GL_FLAT); + } + + issue_scene_graph_color(); +} + +//////////////////////////////////////////////////////////////////// +// Function: CLP(GraphicsStateGuardian)::draw_triangles +// Access: Public, Virtual +// Description: Draws a series of disconnected triangles. +//////////////////////////////////////////////////////////////////// +void CLP(GraphicsStateGuardian):: +draw_triangles(qpGeomTriangles *primitive) { + setup_antialias_polygon(); + + _glDrawRangeElements(GL_TRIANGLES, + primitive->get_min_vertex(), + primitive->get_max_vertex(), + primitive->get_num_vertices(), + GL_UNSIGNED_SHORT, primitive->get_vertices()); + + report_my_gl_errors(); +} + +//////////////////////////////////////////////////////////////////// +// Function: CLP(GraphicsStateGuardian)::end_draw_primitives() +// Access: Public, Virtual +// Description: Called after a sequence of draw_primitive() +// functions are called, this should do whatever cleanup +// is appropriate. +//////////////////////////////////////////////////////////////////// +void CLP(GraphicsStateGuardian):: +end_draw_primitives() { + GLP(DisableClientState)(GL_VERTEX_ARRAY); + + DO_PSTATS_STUFF(_draw_primitive_pcollector.stop()); +} + //////////////////////////////////////////////////////////////////// // Function: CLP(GraphicsStateGuardian)::prepare_texture // Access: Public, Virtual @@ -3762,6 +3917,30 @@ upload_texture_image(CLP(TextureContext) *gtc, } +//////////////////////////////////////////////////////////////////// +// Function: CLP(GraphicsStateGuardian)::get_numeric_type +// Access: Protected, Static +// Description: Maps from the Geom's internal numeric type symbols +// to GL's. +//////////////////////////////////////////////////////////////////// +GLenum CLP(GraphicsStateGuardian):: +get_numeric_type(qpGeomVertexDataType::NumericType numeric_type) { + switch (numeric_type) { + case qpGeomVertexDataType::NT_uint8: + return GL_UNSIGNED_BYTE; + + case qpGeomVertexDataType::NT_packed_argb: + return GL_UNSIGNED_INT; + + case qpGeomVertexDataType::NT_float: + return GL_FLOAT; + } + + GLCAT.error() + << "Invalid NumericType value (" << (int)numeric_type << ")\n"; + return GL_UNSIGNED_BYTE; +} + //////////////////////////////////////////////////////////////////// // Function: CLP(GraphicsStateGuardian)::get_texture_target // Access: Protected @@ -4843,6 +5022,19 @@ finish_modify_state() { } } +//////////////////////////////////////////////////////////////////// +// Function: CLP(GraphicsStateGuardian)::setup_geom_munger +// Access: Protected, Virtual +// Description: Called after finish_modify_state has completed, this +// method sets up the GeomMunger for rendering with the +// current state. +//////////////////////////////////////////////////////////////////// +void CLP(GraphicsStateGuardian):: +setup_geom_munger(PT(qpGeomMunger) munger) { + munger = new CLP(GeomMunger); + GraphicsStateGuardian::setup_geom_munger(munger); +} + //////////////////////////////////////////////////////////////////// // Function: CLP(GraphicsStateGuardian)::free_pointers // Access: Protected, Virtual diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index 0b82f7cafd..ee0ca93b83 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -20,6 +20,7 @@ #include "graphicsStateGuardian.h" #include "geomprimitives.h" +#include "qpgeomVertexDataType.h" #include "texture.h" #include "displayRegion.h" #include "material.h" @@ -48,6 +49,7 @@ class Light; // system GL version matches or exceeds the GL version in which these // functions are defined, and the system gl.h sometimes doesn't // declare these typedefs. +typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); typedef void (APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture); @@ -87,6 +89,10 @@ public: virtual void draw_trifan(GeomTrifan *geom, GeomContext *gc); virtual void draw_sphere(GeomSphere *geom, GeomContext *gc); + virtual void begin_draw_primitives(const qpGeomVertexData *vertex_data); + virtual void draw_triangles(qpGeomTriangles *primitive); + virtual void end_draw_primitives(); + INLINE bool draw_display_list(GeomContext *gc); virtual TextureContext *prepare_texture(Texture *tex); @@ -174,6 +180,7 @@ protected: virtual void set_blend_mode(); virtual void finish_modify_state(); + virtual void setup_geom_munger(PT(qpGeomMunger) munger); virtual void free_pointers(); @@ -212,6 +219,7 @@ protected: GLint external_format, GLenum component_type, const unsigned char *image); + static GLenum get_numeric_type(qpGeomVertexDataType::NumericType numeric_type); GLenum get_texture_target(Texture::TextureType texture_type) const; GLenum get_texture_wrap_mode(Texture::WrapMode wm); static GLenum get_texture_filter_type(Texture::FilterType ft, bool ignore_mipmaps); @@ -296,6 +304,9 @@ protected: pset _extensions; public: + bool _supports_draw_range_elements; + PFNGLDRAWRANGEELEMENTSPROC _glDrawRangeElements; + bool _supports_3d_texture; PFNGLTEXIMAGE3DPROC _glTexImage3D; PFNGLTEXSUBIMAGE3DPROC _glTexSubImage3D; diff --git a/panda/src/glstuff/glstuff_src.cxx b/panda/src/glstuff/glstuff_src.cxx index e99a634d66..1ab571e7e9 100644 --- a/panda/src/glstuff/glstuff_src.cxx +++ b/panda/src/glstuff/glstuff_src.cxx @@ -24,6 +24,7 @@ #include "glmisc_src.cxx" #include "glTextureContext_src.cxx" #include "glGeomContext_src.cxx" +#include "glGeomMunger_src.cxx" #include "glCgShaderContext_src.cxx" #include "glGraphicsStateGuardian_src.cxx" diff --git a/panda/src/glstuff/glstuff_src.h b/panda/src/glstuff/glstuff_src.h index 2c311d500a..b15c7c9f34 100644 --- a/panda/src/glstuff/glstuff_src.h +++ b/panda/src/glstuff/glstuff_src.h @@ -42,6 +42,7 @@ #include "glmisc_src.h" #include "glTextureContext_src.h" #include "glGeomContext_src.h" +#include "glGeomMunger_src.h" #include "glCgShaderContext_src.h" #include "glGraphicsStateGuardian_src.h" diff --git a/panda/src/gobj/Sources.pp b/panda/src/gobj/Sources.pp index da214ebe53..a2c79d74f9 100644 --- a/panda/src/gobj/Sources.pp +++ b/panda/src/gobj/Sources.pp @@ -17,6 +17,18 @@ geomLine.h geomLinestrip.h geomPoint.h geomPolygon.h \ geomQuad.h geomSphere.h geomSprite.I geomSprite.h geomTri.h \ geomTrifan.h geomTristrip.h \ + qpgeom.h qpgeom.I \ + qpgeomMunger.h qpgeomMunger.I \ + qpgeomPrimitive.h qpgeomPrimitive.I \ + qpgeomTriangles.h \ + qpgeomTristrips.h \ + qpgeomTrifans.h \ + qpgeomVertexArrayFormat.h qpgeomVertexArrayFormat.I \ + qpgeomVertexData.h qpgeomVertexData.I \ + qpgeomVertexDataType.h qpgeomVertexDataType.I \ + qpgeomVertexFormat.h qpgeomVertexFormat.I \ + qpgeomVertexIterator.h qpgeomVertexIterator.I \ + internalName.I internalName.h \ material.I material.h materialPool.I materialPool.h \ matrixLens.I matrixLens.h \ orthographicLens.I orthographicLens.h perspectiveLens.I \ @@ -27,7 +39,6 @@ texture.I texture.h \ textureContext.I textureContext.h \ texturePool.I texturePool.h \ - texCoordName.I texCoordName.h \ textureStage.I textureStage.h #define INCLUDED_SOURCES \ @@ -36,13 +47,26 @@ geomContext.cxx \ geomLine.cxx geomLinestrip.cxx geomPoint.cxx geomPolygon.cxx \ geomQuad.cxx geomSphere.cxx geomSprite.cxx geomTri.cxx \ - geomTrifan.cxx geomTristrip.cxx material.cxx \ + geomTrifan.cxx geomTristrip.cxx \ + qpgeom.cxx \ + qpgeomMunger.cxx \ + qpgeomPrimitive.cxx \ + qpgeomTriangles.cxx \ + qpgeomTristrips.cxx \ + qpgeomTrifans.cxx \ + qpgeomVertexArrayFormat.cxx \ + qpgeomVertexData.cxx \ + qpgeomVertexDataType.cxx \ + qpgeomVertexFormat.cxx \ + qpgeomVertexIterator.cxx \ + material.cxx \ + internalName.cxx \ materialPool.cxx matrixLens.cxx orthographicLens.cxx \ perspectiveLens.cxx \ preparedGraphicsObjects.cxx \ lens.cxx \ savedContext.cxx texture.cxx textureContext.cxx texturePool.cxx \ - texCoordName.cxx textureStage.cxx + textureStage.cxx #define INSTALL_HEADERS \ boundedObject.I boundedObject.h \ @@ -52,7 +76,9 @@ geomLine.h \ geomLinestrip.h geomPoint.h geomPolygon.h geomQuad.h geomSphere.h \ geomSprite.I geomSprite.h geomTri.h geomTrifan.h geomTristrip.h \ - geomprimitives.h material.I material.h \ + geomprimitives.h \ + internalName.I internalName.h \ + material.I material.h \ materialPool.I materialPool.h matrixLens.I matrixLens.h \ orthographicLens.I orthographicLens.h perspectiveLens.I \ perspectiveLens.h \ @@ -62,7 +88,6 @@ texture.I texture.h \ textureContext.I textureContext.h \ texturePool.I texturePool.h \ - texCoordName.I texCoordName.h \ textureStage.I textureStage.h #define IGATESCAN all diff --git a/panda/src/gobj/config_gobj.cxx b/panda/src/gobj/config_gobj.cxx index daad368bd3..90adae9c72 100644 --- a/panda/src/gobj/config_gobj.cxx +++ b/panda/src/gobj/config_gobj.cxx @@ -22,6 +22,15 @@ #include "drawable.h" #include "geom.h" #include "geomprimitives.h" +#include "qpgeom.h" +#include "qpgeomMunger.h" +#include "qpgeomPrimitive.h" +#include "qpgeomTriangles.h" +#include "qpgeomTristrips.h" +#include "qpgeomTrifans.h" +#include "qpgeomVertexArrayFormat.h" +#include "qpgeomVertexData.h" +#include "qpgeomVertexFormat.h" #include "material.h" #include "orthographicLens.h" #include "matrixLens.h" @@ -29,7 +38,7 @@ #include "lens.h" #include "texture.h" #include "textureStage.h" -#include "texCoordName.h" +#include "internalName.h" #include "dconfig.h" #include "string_utils.h" @@ -72,6 +81,12 @@ ConfigVariableBool retained_mode "GSG. Set it false to use only immediate mode, which sends the " "vertices to the GSG every frame.")); +ConfigVariableBool use_qpgeom +("use-qpgeom", false, + PRC_DESC("A temporary variable while the experimental Geom rewrite is " + "underway. Set this true if you want to use the experimental " + "code. You don't really want to set this true.")); + ConfigVariableEnum bam_texture_mode ("bam-texture-mode", BTM_relative, @@ -133,6 +148,15 @@ ConfigureFn(config_gobj) { GeomTri::init_type(); GeomTrifan::init_type(); GeomTristrip::init_type(); + qpGeom::init_type(); + qpGeomMunger::init_type(); + qpGeomPrimitive::init_type(); + qpGeomTriangles::init_type(); + qpGeomTristrips::init_type(); + qpGeomTrifans::init_type(); + qpGeomVertexArrayFormat::init_type(); + qpGeomVertexData::init_type(); + qpGeomVertexFormat::init_type(); Material::init_type(); OrthographicLens::init_type(); MatrixLens::init_type(); @@ -141,7 +165,7 @@ ConfigureFn(config_gobj) { Texture::init_type(); dDrawable::init_type(); TextureStage::init_type(); - TexCoordName::init_type(); + InternalName::init_type(); //Registration of writeable object's creation //functions with BamReader's factory @@ -155,13 +179,20 @@ ConfigureFn(config_gobj) { GeomTristrip::register_with_read_factory(); GeomTrifan::register_with_read_factory(); GeomSphere::register_with_read_factory(); + qpGeom::register_with_read_factory(); + qpGeomTriangles::register_with_read_factory(); + qpGeomTristrips::register_with_read_factory(); + qpGeomTrifans::register_with_read_factory(); + qpGeomVertexArrayFormat::register_with_read_factory(); + qpGeomVertexData::register_with_read_factory(); + qpGeomVertexFormat::register_with_read_factory(); Material::register_with_read_factory(); OrthographicLens::register_with_read_factory(); MatrixLens::register_with_read_factory(); PerspectiveLens::register_with_read_factory(); Texture::register_with_read_factory(); TextureStage::register_with_read_factory(); - TexCoordName::register_with_read_factory(); + InternalName::register_with_read_factory(); } ostream & diff --git a/panda/src/gobj/config_gobj.h b/panda/src/gobj/config_gobj.h index f530d9eed9..10662f7274 100644 --- a/panda/src/gobj/config_gobj.h +++ b/panda/src/gobj/config_gobj.h @@ -52,6 +52,8 @@ extern EXPCL_PANDA ConfigVariableBool keep_texture_ram; extern EXPCL_PANDA ConfigVariableBool keep_geom_ram; extern EXPCL_PANDA ConfigVariableBool retained_mode; +extern EXPCL_PANDA ConfigVariableBool use_qpgeom; + extern EXPCL_PANDA ConfigVariableEnum bam_texture_mode; extern EXPCL_PANDA ConfigVariableEnum textures_power_2; extern EXPCL_PANDA ConfigVariableEnum textures_square; diff --git a/panda/src/gobj/geom.I b/panda/src/gobj/geom.I index 89a442e791..ee25ea48b0 100644 --- a/panda/src/gobj/geom.I +++ b/panda/src/gobj/geom.I @@ -48,7 +48,7 @@ has_any_texcoords() const { // name, or false otherwise. //////////////////////////////////////////////////////////////////// INLINE bool Geom:: -has_texcoords(const TexCoordName *name) const { +has_texcoords(const InternalName *name) const { TexCoordsByName::const_iterator tci = _texcoords_by_name.find(name); return (tci != _texcoords_by_name.end()); } @@ -106,11 +106,11 @@ get_colors_array() const { // returns the default texture coordinates only. In the // presence of multitexturing, use the version of // get_texcoords_array() method that takes a -// TexCoordName parameter. +// InternalName parameter. //////////////////////////////////////////////////////////////////// INLINE PTA_TexCoordf Geom:: get_texcoords_array() const { - return get_texcoords_array(TexCoordName::get_default()); + return get_texcoords_array(InternalName::get_texcoord()); } //////////////////////////////////////////////////////////////////// @@ -123,7 +123,7 @@ get_texcoords_array() const { // texture coordinates with the indicated name. //////////////////////////////////////////////////////////////////// INLINE PTA_TexCoordf Geom:: -get_texcoords_array(const TexCoordName *name) const { +get_texcoords_array(const InternalName *name) const { TexCoordsByName::const_iterator tci = _texcoords_by_name.find(name); if (tci != _texcoords_by_name.end()) { return (*tci).second._texcoords; @@ -174,11 +174,11 @@ get_colors_index() const { // returns the default texture coordinates only. In the // presence of multitexturing, use the version of // get_texcoords_array() method that takes a -// TexCoordName parameter. +// InternalName parameter. //////////////////////////////////////////////////////////////////// INLINE PTA_ushort Geom:: get_texcoords_index() const { - return get_texcoords_index(TexCoordName::get_default()); + return get_texcoords_index(InternalName::get_texcoord()); } //////////////////////////////////////////////////////////////////// @@ -192,7 +192,7 @@ get_texcoords_index() const { // the geom does not use indexed texcoords. //////////////////////////////////////////////////////////////////// INLINE PTA_ushort Geom:: -get_texcoords_index(const TexCoordName *name) const { +get_texcoords_index(const InternalName *name) const { TexCoordsByName::const_iterator tci = _texcoords_by_name.find(name); if (tci != _texcoords_by_name.end()) { return (*tci).second._tindex; @@ -368,7 +368,7 @@ get_next_normal(NormalIterator &niterator) const { //////////////////////////////////////////////////////////////////// INLINE Geom::TexCoordIterator Geom:: make_texcoord_iterator() const { - return make_texcoord_iterator(TexCoordName::get_default()); + return make_texcoord_iterator(InternalName::get_texcoord()); } //////////////////////////////////////////////////////////////////// @@ -377,7 +377,7 @@ make_texcoord_iterator() const { // Description: //////////////////////////////////////////////////////////////////// INLINE Geom::TexCoordIterator Geom:: -make_texcoord_iterator(const TexCoordName *texcoord_name) const { +make_texcoord_iterator(const InternalName *texcoord_name) const { check_config(); TexCoordIterator i; diff --git a/panda/src/gobj/geom.cxx b/panda/src/gobj/geom.cxx index f90aaa42e4..68b7672635 100644 --- a/panda/src/gobj/geom.cxx +++ b/panda/src/gobj/geom.cxx @@ -392,7 +392,7 @@ set_colors(const PTA_Colorf &colors, GeomBindType bind, // Access: Published // Description: This single-texturing version of set_texcoords() only // changes the default texcoords name. Use the version -// of set_texcoords() that takes a TexCoordName +// of set_texcoords() that takes a InternalName // parameter to set up different texture coordinates for // different stages of a multitexture pipeline. //////////////////////////////////////////////////////////////////// @@ -402,9 +402,9 @@ set_texcoords(const PTA_TexCoordf &texcoords, GeomBindType bind, nassertv(bind == G_PER_VERTEX || bind == G_OFF); if (bind == G_OFF) { - remove_texcoords(TexCoordName::get_default()); + remove_texcoords(InternalName::get_texcoord()); } else { - set_texcoords(TexCoordName::get_default(), texcoords, tindex); + set_texcoords(InternalName::get_texcoord(), texcoords, tindex); } } @@ -417,9 +417,9 @@ set_texcoords(const PTA_TexCoordf &texcoords, GeomBindType bind, // remove_texcoords(). //////////////////////////////////////////////////////////////////// void Geom:: -set_texcoords(const TexCoordName *name, const PTA_TexCoordf &texcoords, +set_texcoords(const InternalName *name, const PTA_TexCoordf &texcoords, const PTA_ushort &tindex) { - nassertv(name != (TexCoordName *)NULL); + nassertv(name != (InternalName *)NULL); #ifndef NDEBUG // All of the texture coordinates must be either nonindexed, or all @@ -438,7 +438,7 @@ set_texcoords(const TexCoordName *name, const PTA_TexCoordf &texcoords, def._texcoords = texcoords; def._tindex = tindex; - if (name == TexCoordName::get_default()) { + if (name == InternalName::get_texcoord()) { _bind[G_TEXCOORD] = G_PER_VERTEX; } @@ -454,10 +454,10 @@ set_texcoords(const TexCoordName *name, const PTA_TexCoordf &texcoords, // set_texcoords(). //////////////////////////////////////////////////////////////////// void Geom:: -remove_texcoords(const TexCoordName *name) { +remove_texcoords(const InternalName *name) { _texcoords_by_name.erase(name); - if (name == TexCoordName::get_default()) { + if (name == InternalName::get_texcoord()) { _bind[G_TEXCOORD] = G_OFF; } @@ -529,7 +529,7 @@ void Geom:: get_texcoords(PTA_TexCoordf &texcoords, GeomBindType &bind, PTA_ushort &tindex) const { TexCoordsByName::const_iterator tci = - _texcoords_by_name.find(TexCoordName::get_default()); + _texcoords_by_name.find(InternalName::get_texcoord()); if (tci != _texcoords_by_name.end()) { const TexCoordDef &def = (*tci).second; texcoords = def._texcoords; @@ -573,6 +573,46 @@ prepare(PreparedGraphicsObjects *prepared_objects) { prepared_objects->enqueue_geom(this); } +//////////////////////////////////////////////////////////////////// +// Function: Geom::get_num_vertices_per_prim +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +int Geom:: +get_num_vertices_per_prim() const { + return 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: Geom::get_num_more_vertices_than_components +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +int Geom:: +get_num_more_vertices_than_components() const { + return 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: Geom::uses_components +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +bool Geom:: +uses_components() const { + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: Geom::get_length +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +int Geom:: +get_length(int) const { + return 0; +} + //////////////////////////////////////////////////////////////////// // Function: Geom::explode // Access: Published, Virtual @@ -721,7 +761,7 @@ write_verbose(ostream &out, int indent_level) const { for (tci = _texcoords_by_name.begin(); tci != _texcoords_by_name.end(); ++tci) { - const TexCoordName *name = (*tci).first; + const InternalName *name = (*tci).first; const TexCoordDef &def = (*tci).second; if (def._tindex != (ushort *)NULL) { indent(out, indent_level) @@ -762,7 +802,7 @@ setup_multitexcoord_iterator(MultiTexCoordIterator &iterator, if (no_texcoords.find(stage) == no_texcoords.end()) { // This stage is not one of the stages that doesn't need // texcoords issued for it. - const TexCoordName *name = stage->get_texcoord_name(); + const InternalName *name = stage->get_texcoord_name(); TexCoordsByName::const_iterator tci = _texcoords_by_name.find(name); if (tci != _texcoords_by_name.end()) { // This Geom does have texcoords for this stage. @@ -952,6 +992,24 @@ config() { } } +//////////////////////////////////////////////////////////////////// +// Function: Geom::draw_immediate +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void Geom:: +draw_immediate(GraphicsStateGuardianBase *, GeomContext *) { +} + +//////////////////////////////////////////////////////////////////// +// Function: Geom::print_draw_immediate +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void Geom:: +print_draw_immediate() const { +} + //////////////////////////////////////////////////////////////////// // Function: Geom::calc_tight_bounds // Access: Public @@ -1118,7 +1176,7 @@ write_datagram(BamWriter *manager, Datagram &me) { // write the TexCoordsByName pointers if any TexCoordsByName::const_iterator tci; for (tci = _texcoords_by_name.begin(); tci != _texcoords_by_name.end(); ++tci) { - CPT(TexCoordName) tc = (*tci).first; + CPT(InternalName) tc = (*tci).first; manager->write_pointer(me, tc); WRITE_PTA(manager, me, IPD_TexCoordf::write_datagram, (*tci).second._texcoords); WRITE_PTA(manager, me, IPD_ushort::write_datagram, (*tci).second._tindex); @@ -1160,16 +1218,16 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) { for (ci = _temp_texcoord_set.begin(); ci != _temp_texcoord_set.end(); ++ci) { - CPT(TexCoordName) tc = DCAST(TexCoordName, p_list[pi++]); + CPT(InternalName) tc = DCAST(InternalName, p_list[pi++]); TexCoordDef *def = (*ci); _texcoords_by_name[tc] = *def; /* - cerr << "TexCoordName from Geom " << (void *)this + cerr << "InternalName from Geom " << (void *)this << " complete pointers " << tc << " " << *tc << " = " << def->_texcoords << " and " << def->_tindex << "\n"; */ delete def; - if (tc == TexCoordName::get_default()) { + if (tc == InternalName::get_texcoord()) { _bind[G_TEXCOORD] = G_PER_VERTEX; } } diff --git a/panda/src/gobj/geom.h b/panda/src/gobj/geom.h index 65726928ce..3c67f7bc00 100644 --- a/panda/src/gobj/geom.h +++ b/panda/src/gobj/geom.h @@ -34,7 +34,7 @@ #include "pta_TexCoordf.h" #include "pta_ushort.h" #include "pta_int.h" -#include "texCoordName.h" +#include "internalName.h" #include "textureStage.h" #include "pset.h" @@ -146,9 +146,9 @@ PUBLISHED: const PTA_ushort &cindex = PTA_ushort()); void set_texcoords(const PTA_TexCoordf &texcoords, GeomBindType bind, const PTA_ushort &tindex = PTA_ushort()); - void set_texcoords(const TexCoordName *name, const PTA_TexCoordf &texcoords, + void set_texcoords(const InternalName *name, const PTA_TexCoordf &texcoords, const PTA_ushort &tindex = PTA_ushort()); - void remove_texcoords(const TexCoordName *name); + void remove_texcoords(const InternalName *name); public: // These can't be published because of the pass-by-reference @@ -171,19 +171,19 @@ PUBLISHED: INLINE GeomBindType get_binding(int attr) const; INLINE bool has_any_texcoords() const; - INLINE bool has_texcoords(const TexCoordName *name) const; + INLINE bool has_texcoords(const InternalName *name) const; INLINE PTA_Vertexf get_coords_array() const; INLINE PTA_Normalf get_normals_array() const; INLINE PTA_Colorf get_colors_array() const; INLINE PTA_TexCoordf get_texcoords_array() const; - INLINE PTA_TexCoordf get_texcoords_array(const TexCoordName *name) const; + INLINE PTA_TexCoordf get_texcoords_array(const InternalName *name) const; INLINE PTA_ushort get_coords_index() const; INLINE PTA_ushort get_normals_index() const; INLINE PTA_ushort get_colors_index() const; INLINE PTA_ushort get_texcoords_index() const; - INLINE PTA_ushort get_texcoords_index(const TexCoordName *name) const; + INLINE PTA_ushort get_texcoords_index(const InternalName *name) const; INLINE bool are_texcoords_indexed() const; void prepare(PreparedGraphicsObjects *prepared_objects); @@ -194,16 +194,16 @@ PUBLISHED: INLINE void set_lengths(const PTA_int &lengths); INLINE PTA_int get_lengths() const; - virtual int get_num_vertices_per_prim() const=0; - virtual int get_num_more_vertices_than_components() const=0; - virtual bool uses_components() const=0; + virtual int get_num_vertices_per_prim() const; + virtual int get_num_more_vertices_than_components() const; + virtual bool uses_components() const; INLINE int get_num_vertices() const; // Returns the length of the indicated primitive. Often this is the // same for all primitives in the Geom. However, geoms which use // the lengths array will redefine this appropriately. - virtual int get_length(int prim) const=0; + virtual int get_length(int prim) const; virtual Geom *explode() const; virtual PTA_ushort get_tris() const; @@ -223,7 +223,7 @@ public: INLINE const Normalf &get_next_normal(NormalIterator &niterator) const; INLINE TexCoordIterator make_texcoord_iterator() const; - INLINE TexCoordIterator make_texcoord_iterator(const TexCoordName *texcoord_name) const; + INLINE TexCoordIterator make_texcoord_iterator(const InternalName *texcoord_name) const; INLINE const TexCoordf &get_next_texcoord(TexCoordIterator &tciterator) const; void setup_multitexcoord_iterator(MultiTexCoordIterator &iterator, const ActiveTextureStages &active_stages, @@ -245,8 +245,8 @@ public: virtual void config(); // Immediate mode drawing functions - issue graphics commands - virtual void draw_immediate(GraphicsStateGuardianBase *gsg, GeomContext *gc) = 0; - virtual void print_draw_immediate() const = 0; + virtual void draw_immediate(GraphicsStateGuardianBase *gsg, GeomContext *gc); + virtual void print_draw_immediate() const; void calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point, bool &found_any) const; @@ -277,7 +277,7 @@ protected: // A pmap, not a phash_map, to save space because it will probably // have only one element. - typedef pmap TexCoordsByName; + typedef pmap TexCoordsByName; TexCoordsByName _texcoords_by_name; // Functions to extract component values, one at a time. @@ -286,7 +286,7 @@ protected: GetNextColor *_get_color; GetNextTexCoord *_get_texcoord; - // temporary storage until complete_pointers fills in _texcoords_by_name's TexCoordName * + // temporary storage until complete_pointers fills in _texcoords_by_name's InternalName * typedef pvector TexCoordDefSet; TexCoordDefSet _temp_texcoord_set; diff --git a/panda/src/gobj/gobj_composite1.cxx b/panda/src/gobj/gobj_composite1.cxx index a6a2c7e2cd..8586ecb5dd 100644 --- a/panda/src/gobj/gobj_composite1.cxx +++ b/panda/src/gobj/gobj_composite1.cxx @@ -11,4 +11,14 @@ #include "geomTri.cxx" #include "geomTrifan.cxx" #include "geomTristrip.cxx" - +#include "qpgeom.cxx" +#include "qpgeomMunger.cxx" +#include "qpgeomPrimitive.cxx" +#include "qpgeomTriangles.cxx" +#include "qpgeomTristrips.cxx" +#include "qpgeomTrifans.cxx" +#include "qpgeomVertexArrayFormat.cxx" +#include "qpgeomVertexData.cxx" +#include "qpgeomVertexDataType.cxx" +#include "qpgeomVertexFormat.cxx" +#include "qpgeomVertexIterator.cxx" diff --git a/panda/src/gobj/gobj_composite2.cxx b/panda/src/gobj/gobj_composite2.cxx index 5315e38495..c8f210dbd5 100644 --- a/panda/src/gobj/gobj_composite2.cxx +++ b/panda/src/gobj/gobj_composite2.cxx @@ -2,6 +2,7 @@ #include "config_gobj.cxx" #include "drawable.cxx" #include "geomContext.cxx" +#include "internalName.cxx" #include "material.cxx" #include "materialPool.cxx" #include "orthographicLens.cxx" @@ -13,5 +14,4 @@ #include "texture.cxx" #include "textureContext.cxx" #include "texturePool.cxx" -#include "texCoordName.cxx" #include "textureStage.cxx" diff --git a/panda/src/gobj/internalName.I b/panda/src/gobj/internalName.I new file mode 100644 index 0000000000..0f9ab8e32b --- /dev/null +++ b/panda/src/gobj/internalName.I @@ -0,0 +1,185 @@ +// Filename: internalName.I +// Created by: masad (15Jul04) +// +//////////////////////////////////////////////////////////////////// +// +// 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: InternalName::make +// Access: Published, Static +// Description: The public interface for constructing an InternalName +// pointer. This will return a new InternalName +// representing the indicated name, if this is the first +// time the particular name has been requested; if the +// name is already in use, it will return the existing +// pointer. +// +// If the string contains the '.' character, the string +// will be divided at the dots and the so-defined +// hierarchy of names will be registered. This is +// handled transparently. +//////////////////////////////////////////////////////////////////// +INLINE PT(InternalName) InternalName:: +make(const string &name) { + return get_root()->append(name); +} + +//////////////////////////////////////////////////////////////////// +// Function: InternalName::get_parent +// Access: Published +// Description: Return the parent of this InternalName. All names +// have a parent, except the root name. +//////////////////////////////////////////////////////////////////// +INLINE InternalName *InternalName:: +get_parent() const { + return _parent; +} + +//////////////////////////////////////////////////////////////////// +// Function: InternalName::get_basename +// Access: Published +// Description: Return the name represented by just this particular +// InternalName object, ignoring its parents names. +// This is everything after the rightmost dot. +//////////////////////////////////////////////////////////////////// +INLINE const string &InternalName:: +get_basename() const { + return _basename; +} + +//////////////////////////////////////////////////////////////////// +// Function: InternalName::get_root +// Access: Published, Static +// Description: Returns the standard root InternalName. This is the +// root of all other InternalNames. It has no name +// itself, and it is the only InternalName with no +// parent. +//////////////////////////////////////////////////////////////////// +INLINE PT(InternalName) InternalName:: +get_root() { + if (_root == (InternalName *)NULL) { + _root = new InternalName(NULL, ""); + } + return _root; +} + +//////////////////////////////////////////////////////////////////// +// Function: InternalName::get_error +// Access: Published, Static +// Description: Returns the standard InternalName "error". +//////////////////////////////////////////////////////////////////// +INLINE PT(InternalName) InternalName:: +get_error() { + if (_error == (InternalName *)NULL) { + _error = InternalName::make("error"); + } + return _error; +} + +//////////////////////////////////////////////////////////////////// +// Function: InternalName::get_vertex +// Access: Published, Static +// Description: Returns the standard InternalName "vertex". +//////////////////////////////////////////////////////////////////// +INLINE PT(InternalName) InternalName:: +get_vertex() { + if (_vertex == (InternalName *)NULL) { + _vertex = InternalName::make("vertex"); + } + return _vertex; +} + +//////////////////////////////////////////////////////////////////// +// Function: InternalName::get_normal +// Access: Published, Static +// Description: Returns the standard InternalName "normal". +//////////////////////////////////////////////////////////////////// +INLINE PT(InternalName) InternalName:: +get_normal() { + if (_normal == (InternalName *)NULL) { + _normal = InternalName::make("normal"); + } + return _normal; +} + +//////////////////////////////////////////////////////////////////// +// Function: InternalName::get_tangent +// Access: Published, Static +// Description: Returns the standard InternalName "tangent". +//////////////////////////////////////////////////////////////////// +INLINE PT(InternalName) InternalName:: +get_tangent() { + if (_tangent == (InternalName *)NULL) { + _tangent = InternalName::make("tangent"); + } + return _tangent; +} + +//////////////////////////////////////////////////////////////////// +// Function: InternalName::get_binormal +// Access: Published, Static +// Description: Returns the standard InternalName "binormal". +//////////////////////////////////////////////////////////////////// +INLINE PT(InternalName) InternalName:: +get_binormal() { + if (_binormal == (InternalName *)NULL) { + _binormal = InternalName::make("binormal"); + } + return _binormal; +} + +//////////////////////////////////////////////////////////////////// +// Function: InternalName::get_texcoord +// Access: Published, Static +// Description: Returns the standard InternalName "texcoord". +//////////////////////////////////////////////////////////////////// +INLINE PT(InternalName) InternalName:: +get_texcoord() { + if (_texcoord == (InternalName *)NULL) { + _texcoord = InternalName::make("texcoord"); + } + return _texcoord; +} + +//////////////////////////////////////////////////////////////////// +// Function: InternalName::get_texcoord_name +// Access: Published, Static +// Description: Returns the InternalName "texcoord.name", where name +// is the supplied string. This, by convention, +// represents the named texture coordinate set. +//////////////////////////////////////////////////////////////////// +INLINE PT(InternalName) InternalName:: +get_texcoord_name(const string &name) { + return get_texcoord()->append(name); +} + +//////////////////////////////////////////////////////////////////// +// Function: InternalName::get_color +// Access: Published, Static +// Description: Returns the standard InternalName "color". +//////////////////////////////////////////////////////////////////// +INLINE PT(InternalName) InternalName:: +get_color() { + if (_color == (InternalName *)NULL) { + _color = InternalName::make("color"); + } + return _color; +} + +INLINE ostream & +operator << (ostream &out, const InternalName &tcn) { + tcn.output(out); + return out; +} diff --git a/panda/src/gobj/internalName.cxx b/panda/src/gobj/internalName.cxx new file mode 100644 index 0000000000..4159ff1672 --- /dev/null +++ b/panda/src/gobj/internalName.cxx @@ -0,0 +1,231 @@ +// Filename: internalName.cxx +// Created by: masad (15Jul04) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "pandabase.h" +#include "internalName.h" +#include "datagram.h" +#include "datagramIterator.h" +#include "bamReader.h" +#include "preparedGraphicsObjects.h" + +PT(InternalName) InternalName::_root; +PT(InternalName) InternalName::_error; +PT(InternalName) InternalName::_default; +PT(InternalName) InternalName::_vertex; +PT(InternalName) InternalName::_normal; +PT(InternalName) InternalName::_tangent; +PT(InternalName) InternalName::_binormal; +PT(InternalName) InternalName::_texcoord; +PT(InternalName) InternalName::_color; + +TypeHandle InternalName::_type_handle; +TypeHandle InternalName::_texcoord_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: InternalName::Constructor +// Access: Private +// Description: Use make() to make a new InternalName instance. +//////////////////////////////////////////////////////////////////// +InternalName:: +InternalName(InternalName *parent, const string &basename) : + _parent(parent), + _basename(basename) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: InternalName::Destructor +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +InternalName:: +~InternalName() { + if (_parent != (const InternalName *)NULL) { + NameTable::iterator ni = _parent->_name_table.find(_basename); + nassertv(ni != _parent->_name_table.end()); + _parent->_name_table.erase(ni); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: InternalName::append +// Access: Published +// Description: Constructs a new InternalName based on this name, +// with the indicated string following it. This is a +// cheaper way to construct a hierarchical name than +// InternalName::make(parent->get_name() + ".basename"). +//////////////////////////////////////////////////////////////////// +PT(InternalName) InternalName:: +append(const string &name) { + if (name.empty()) { + return this; + } + + size_t dot = name.rfind('.'); + if (dot != string::npos) { + return append(name.substr(0, dot))->append(name.substr(dot + 1)); + } + + NameTable::iterator ni = _name_table.find(name); + if (ni != _name_table.end()) { + return (*ni).second; + } + + PT(InternalName) internal_name = new InternalName(this, name); + _name_table[name] = internal_name; + return internal_name; +} + +//////////////////////////////////////////////////////////////////// +// Function: InternalName::get_name +// Access: Published +// Description: Returns the complete name represented by the +// InternalName and all of its parents. +//////////////////////////////////////////////////////////////////// +string InternalName:: +get_name() const { + if (_parent == get_root()) { + return _basename; + + } else if (_parent == (InternalName *)NULL) { + return string(); + + } else { + return _parent->get_name() + "." + _basename; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: InternalName::output +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void InternalName:: +output(ostream &out) const { + if (_parent == get_root()) { + out << _basename; + + } else if (_parent == (InternalName *)NULL) { + out << "(root)"; + + } else { + _parent->output(out); + out << '.' << _basename; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: InternalName::register_with_read_factory +// Access: Public, Static +// Description: Factory method to generate a InternalName object +//////////////////////////////////////////////////////////////////// +void InternalName:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); + BamReader::get_factory()->register_factory(_texcoord_type_handle, make_texcoord_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: InternalName::finalize +// Access: Public, Virtual +// Description: Method to ensure that any necessary clean up tasks +// that have to be performed by this object are performed +//////////////////////////////////////////////////////////////////// +void InternalName:: +finalize() { + // Unref the pointer that we explicitly reffed in make_from_bam(). + unref(); + + // We should never get back to zero after unreffing our own count, + // because we expect to have been stored in a pointer somewhere. If + // we do get to zero, it's a memory leak; the way to avoid this is + // to call unref_delete() above instead of unref(), but this is + // dangerous to do from within a virtual function. + nassertv(get_ref_count() != 0); +} + +//////////////////////////////////////////////////////////////////// +// Function: InternalName::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type InternalName is encountered +// in the Bam file. It should create the InternalName +// and extract its information from the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *InternalName:: +make_from_bam(const FactoryParams ¶ms) { + // The process of making a InternalName is slightly + // different than making other Writable objects. + // That is because all creation of InternalNames should + // be done through the make() constructor. + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + + // The name is the only thing written to the data stream. + string name = scan.get_string(); + + // Make a new InternalName with that name (or get the previous one + // if there is one already). + PT(InternalName) me = make(name); + + // But now we have a problem, since we have to hold the reference + // count and there's no way to return a TypedWritable while still + // holding the reference count! We work around this by explicitly + // upping the count, and also setting a finalize() callback to down + // it later. + me->ref(); + manager->register_finalize(me); + + return me.p(); +} + +//////////////////////////////////////////////////////////////////// +// Function: InternalName::make_texcoord_from_bam +// Access: Protected, Static +// Description: This is a temporary method; it exists only to support +// old bam files (4.11 through 4.17) generated before we +// renamed this class from TexCoordName to InternalName. +//////////////////////////////////////////////////////////////////// +TypedWritable *InternalName:: +make_texcoord_from_bam(const FactoryParams ¶ms) { + DatagramIterator scan; + BamReader *manager; + parse_params(params, scan, manager); + + string name = scan.get_string(); + PT(InternalName) me = get_texcoord_name(name); + + me->ref(); + manager->register_finalize(me); + + return me.p(); +} + +//////////////////////////////////////////////////////////////////// +// Function: InternalName::write_datagram +// Access: Public +// Description: Function to write the important information in +// the particular object to a Datagram +//////////////////////////////////////////////////////////////////// +void InternalName:: +write_datagram(BamWriter *manager, Datagram &me) { + me.add_string(get_name()); +} + diff --git a/panda/src/gobj/internalName.h b/panda/src/gobj/internalName.h new file mode 100644 index 0000000000..2626344dcc --- /dev/null +++ b/panda/src/gobj/internalName.h @@ -0,0 +1,129 @@ +// Filename: internalName.h +// Created by: drose (15Jul04) +// +//////////////////////////////////////////////////////////////////// +// +// 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 INTERNALNAME_H +#define INTERNALNAME_H + +#include "pandabase.h" + +#include "typedWritableReferenceCount.h" +#include "pointerTo.h" +#include "pmap.h" + +class FactoryParams; + +//////////////////////////////////////////////////////////////////// +// Class : InternalName +// Description : Encodes a string name in a hash table, mapping it to +// a pointer. This is used to tokenify names so they +// may be used efficiently in low-level Panda +// structures, for instance to differentiate the +// multiple sets of texture coordinates that might be +// stored on a Geom. +// +// InternalNames are hierarchical, with the '.' used by +// convention as a separator character. You can +// construct a single InternalName as a composition of +// one or more other names, or by giving it a source +// string directly. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA InternalName : public TypedWritableReferenceCount { +private: + InternalName(InternalName *parent, const string &basename); + +PUBLISHED: + virtual ~InternalName(); + INLINE static PT(InternalName) make(const string &name); + PT(InternalName) append(const string &basename); + + INLINE InternalName *get_parent() const; + string get_name() const; + INLINE const string &get_basename() const; + + void output(ostream &out) const; + + // Some predefined built-in names. + INLINE static PT(InternalName) get_root(); + INLINE static PT(InternalName) get_error(); + INLINE static PT(InternalName) get_vertex(); + INLINE static PT(InternalName) get_normal(); + INLINE static PT(InternalName) get_tangent(); + INLINE static PT(InternalName) get_binormal(); + INLINE static PT(InternalName) get_texcoord(); + INLINE static PT(InternalName) get_texcoord_name(const string &name); + INLINE static PT(InternalName) get_color(); + +private: + PT(InternalName) _parent; + string _basename; + + typedef phash_map NameTable; + NameTable _name_table; + + static PT(InternalName) _root; + static PT(InternalName) _error; + static PT(InternalName) _default; + static PT(InternalName) _vertex; + static PT(InternalName) _normal; + static PT(InternalName) _tangent; + static PT(InternalName) _binormal; + static PT(InternalName) _texcoord; + static PT(InternalName) _color; + +public: + // Datagram stuff + static void register_with_read_factory(); + virtual void write_datagram(BamWriter *manager, Datagram &me); + + virtual void finalize(); + +protected: + static TypedWritable *make_from_bam(const FactoryParams ¶ms); + static TypedWritable *make_texcoord_from_bam(const FactoryParams ¶ms); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + TypedWritableReferenceCount::init_type(); + register_type(_type_handle, "InternalName", + TypedWritableReferenceCount::get_class_type()); + // The _texcoord_type_handle is defined only to support older bam + // files, generated before we renamed the type to InternalName. + register_type(_texcoord_type_handle, "TexCoordName", + TypedWritableReferenceCount::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; + static TypeHandle _texcoord_type_handle; +}; + +INLINE ostream &operator << (ostream &out, const InternalName &tcn); + +#include "internalName.I" + +#endif + + + diff --git a/panda/src/gobj/qpgeom.I b/panda/src/gobj/qpgeom.I new file mode 100644 index 0000000000..d322ed3aef --- /dev/null +++ b/panda/src/gobj/qpgeom.I @@ -0,0 +1,114 @@ +// Filename: qpgeom.I +// Created by: drose (06Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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: qpGeom::get_vertex_data +// Access: Published +// Description: Returns a const pointer to the GeomVertexData, +// for application code to directly examine (but not +// modify) the geom's underlying data. +//////////////////////////////////////////////////////////////////// +INLINE CPT(qpGeomVertexData) qpGeom:: +get_vertex_data() const { + CDReader cdata(_cycler); + return cdata->_data; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeom::get_num_primitives +// Access: Published +// Description: Returns the number of GeomPrimitive objects stored +// within the Geom, each of which represents a number of +// primitives of a particular type. +//////////////////////////////////////////////////////////////////// +INLINE int qpGeom:: +get_num_primitives() const { + CDReader cdata(_cycler); + return cdata->_primitives.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeom::get_primitive +// Access: Published +// Description: Returns a const pointer to the ith GeomPrimitive +// object stored within the Geom. Use this call only to +// inspect the ith object; use modify_primitive() or +// set_primitive() if you want to modify it. +//////////////////////////////////////////////////////////////////// +INLINE const qpGeomPrimitive *qpGeom:: +get_primitive(int i) const { + CDReader cdata(_cycler); + nassertr(i >= 0 && i < (int)cdata->_primitives.size(), NULL); + return cdata->_primitives[i]; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeom::modify_primitive +// Access: Published +// Description: Returns a modifiable pointer to the ith GeomPrimitive +// object stored within the Geom, so application code +// can directly manipulate the properties of this +// primitive. +//////////////////////////////////////////////////////////////////// +INLINE qpGeomPrimitive *qpGeom:: +modify_primitive(int i) { + CDWriter cdata(_cycler); + nassertr(i >= 0 && i < (int)cdata->_primitives.size(), NULL); + return cdata->_primitives[i]; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeom::set_primitive +// Access: Published +// Description: Replaces the ith GeomPrimitive object stored within +// the Geom with the new object. +//////////////////////////////////////////////////////////////////// +INLINE void qpGeom:: +set_primitive(int i, qpGeomPrimitive *primitive) { + CDWriter cdata(_cycler); + nassertv(i >= 0 && i < (int)cdata->_primitives.size()); + cdata->_primitives[i] = primitive; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeom::CData::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE qpGeom::CData:: +CData() { +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeom::CData::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE qpGeom::CData:: +CData(const qpGeom::CData ©) : + _data(copy._data), + _primitives(copy._primitives) +{ +} + +INLINE ostream & +operator << (ostream &out, const qpGeom &obj) { + obj.output(out); + return out; +} diff --git a/panda/src/gobj/qpgeom.cxx b/panda/src/gobj/qpgeom.cxx new file mode 100644 index 0000000000..64db170eef --- /dev/null +++ b/panda/src/gobj/qpgeom.cxx @@ -0,0 +1,395 @@ +// Filename: qpgeom.cxx +// Created by: drose (06Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "qpgeom.h" +#include "bamReader.h" +#include "bamWriter.h" + +TypeHandle qpGeom::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: qpGeom::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +qpGeom:: +qpGeom() { +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeom::Copy Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +qpGeom:: +qpGeom(const qpGeom ©) : + /* + TypedWritableReferenceCount(copy), + BoundedObject(copy), + */ + Geom(copy), + _cycler(copy._cycler) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeom::Copy Assignment Operator +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void qpGeom:: +operator = (const qpGeom ©) { + /* + TypedWritableReferenceCount::operator = (copy); + BoundedObject::operator = (copy); + */ + Geom::operator = (copy); + _cycler = copy._cycler; + mark_bound_stale(); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeom::Destructor +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +qpGeom:: +~qpGeom() { +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeom::make_copy +// Access: Published, Virtual +// Description: Temporarily redefined from Geom base class. +//////////////////////////////////////////////////////////////////// +Geom *qpGeom:: +make_copy() const { + return new qpGeom(*this); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeom::modify_vertex_data +// Access: Published +// Description: Returns a modifiable pointer to the GeomVertexData, +// so that application code may directly maniuplate the +// geom's underlying data. +//////////////////////////////////////////////////////////////////// +PT(qpGeomVertexData) qpGeom:: +modify_vertex_data() { + // Perform copy-on-write: if the reference count on the vertex data + // is greater than 1, assume some other Geom has the same pointer, + // so make a copy of it first. + + CDWriter cdata(_cycler); + if (cdata->_data->get_ref_count() > 1) { + cdata->_data = new qpGeomVertexData(*cdata->_data); + } + mark_bound_stale(); + return cdata->_data; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeom::set_vertex_data +// Access: Published +// Description: Replaces the Geom's underlying vertex data table with +// a completely new table. +//////////////////////////////////////////////////////////////////// +void qpGeom:: +set_vertex_data(PT(qpGeomVertexData) data) { + CDWriter cdata(_cycler); + cdata->_data = data; + mark_bound_stale(); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeom::add_primitive +// Access: Published +// Description: Adds a new GeomPrimitive structure to the Geom +// object. This specifies a particular subset of +// vertices that are used to define geometric primitives +// of the indicated type. +//////////////////////////////////////////////////////////////////// +void qpGeom:: +add_primitive(qpGeomPrimitive *primitive) { + CDWriter cdata(_cycler); + cdata->_primitives.push_back(primitive); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeom::remove_primitive +// Access: Published +// Description: Removes the ith primitive from the list. +//////////////////////////////////////////////////////////////////// +void qpGeom:: +remove_primitive(int i) { + CDWriter cdata(_cycler); + nassertv(i >= 0 && i < (int)cdata->_primitives.size()); + cdata->_primitives.erase(cdata->_primitives.begin() + i); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeom::clear_primitives +// Access: Published +// Description: Removes all the primitives from the Geom object (but +// keeps the same table of vertices). You may then +// re-add primitives one at a time via calls to +// add_primitive(). +//////////////////////////////////////////////////////////////////// +void qpGeom:: +clear_primitives() { + CDWriter cdata(_cycler); + cdata->_primitives.clear(); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeom::output +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void qpGeom:: +output(ostream &out) const { + CDReader cdata(_cycler); + + // Get a list of the primitive types contained within this object. + pset types; + Primitives::const_iterator pi; + for (pi = cdata->_primitives.begin(); + pi != cdata->_primitives.end(); + ++pi) { + types.insert((*pi)->get_type()); + } + + out << "Geom ["; + pset::iterator ti; + for (ti = types.begin(); ti != types.end(); ++ti) { + out << " " << (*ti); + } + out << " ], " << cdata->_data->get_num_vertices() << " vertices."; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeom::write +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void qpGeom:: +write(ostream &out, int indent_level) const { + CDReader cdata(_cycler); + + // Get a list of the primitive types contained within this object. + Primitives::const_iterator pi; + for (pi = cdata->_primitives.begin(); + pi != cdata->_primitives.end(); + ++pi) { + (*pi)->write(out, cdata->_data, indent_level); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeom::draw +// Access: Public +// Description: Actually draws the Geom with the indicated GSG. +//////////////////////////////////////////////////////////////////// +void qpGeom:: +draw(GraphicsStateGuardianBase *gsg) const { + // PreparedGraphicsObjects *prepared_objects = gsg->get_prepared_objects(); + CDReader cdata(_cycler); + + gsg->begin_draw_primitives(cdata->_data); + + Primitives::const_iterator pi; + for (pi = cdata->_primitives.begin(); + pi != cdata->_primitives.end(); + ++pi) { + (*pi)->draw(gsg); + } + + gsg->end_draw_primitives(); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeom::recompute_bound +// Access: Protected, Virtual +// Description: Recomputes the dynamic bounding volume for this Geom. +// This includes all of the vertices. +//////////////////////////////////////////////////////////////////// +BoundingVolume *qpGeom:: +recompute_bound() { + // First, get ourselves a fresh, empty bounding volume. + BoundingVolume *bound = BoundedObject::recompute_bound(); + nassertr(bound != (BoundingVolume*)0L, bound); + + GeometricBoundingVolume *gbv = DCAST(GeometricBoundingVolume, bound); + + // Now actually compute the bounding volume by putting it around all + // of our vertices. + CDReader cdata(_cycler); + + const qpGeomVertexFormat *format = cdata->_data->get_format(); + + int array_index = format->get_array_with(InternalName::get_vertex()); + if (array_index < 0) { + // No vertex data. + return bound; + } + + const qpGeomVertexArrayFormat *array_format = format->get_array(array_index); + const qpGeomVertexDataType *data_type = + array_format->get_data_type(InternalName::get_vertex()); + + int stride = array_format->get_stride(); + int start = data_type->get_start(); + int num_components = data_type->get_num_components(); + + CPTA_uchar array_data = cdata->_data->get_array_data(array_index); + + if (stride == 3 * sizeof(PN_float32) && start == 0 && num_components == 3 && + (array_data.size() % stride) == 0) { + // Here's an easy special case: it's a standalone table of vertex + // positions, with nothing else in the middle, so we can use + // directly as an array of LPoint3f's. + const LPoint3f *vertices_begin = (const LPoint3f *)&array_data[0]; + const LPoint3f *vertices_end = (const LPoint3f *)&array_data[array_data.size()]; + gbv->around(vertices_begin, vertices_end); + + } else { + // Otherwise, we have to copy the vertex positions out one at time. + pvector vertices; + + size_t p = start; + while (p + stride <= array_data.size()) { + const PN_float32 *v = (const PN_float32 *)&array_data[p]; + + LPoint3f vertex; + qpGeomVertexData::to_vec3(vertex, v, num_components); + + vertices.push_back(vertex); + p += stride; + } + + const LPoint3f *vertices_begin = &vertices[0]; + const LPoint3f *vertices_end = vertices_begin + vertices.size(); + + gbv->around(vertices_begin, vertices_end); + } + + return bound; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeom::register_with_read_factory +// Access: Public, Static +// Description: Tells the BamReader how to create objects of type +// qpGeom. +//////////////////////////////////////////////////////////////////// +void qpGeom:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeom::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void qpGeom:: +write_datagram(BamWriter *manager, Datagram &dg) { + TypedWritable::write_datagram(manager, dg); + + manager->write_cdata(dg, _cycler); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeom::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type qpGeom is encountered +// in the Bam file. It should create the qpGeom +// and extract its information from the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *qpGeom:: +make_from_bam(const FactoryParams ¶ms) { + qpGeom *object = new qpGeom; + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + object->fillin(scan, manager); + + return object; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeom::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 qpGeom. +//////////////////////////////////////////////////////////////////// +void qpGeom:: +fillin(DatagramIterator &scan, BamReader *manager) { + TypedWritable::fillin(scan, manager); + + manager->read_cdata(scan, _cycler); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeom::CData::make_copy +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +CycleData *qpGeom::CData:: +make_copy() const { + return new CData(*this); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeom::CData::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void qpGeom::CData:: +write_datagram(BamWriter *manager, Datagram &dg) const { +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeom::CData::complete_pointers +// Access: Public, Virtual +// Description: Receives an array of pointers, one for each time +// manager->read_pointer() was called in fillin(). +// Returns the number of pointers processed. +//////////////////////////////////////////////////////////////////// +int qpGeom::CData:: +complete_pointers(TypedWritable **p_list, BamReader *manager) { + int pi = CycleData::complete_pointers(p_list, manager); + + return pi; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeom::CData::fillin +// Access: Public, Virtual +// Description: This internal function is called by make_from_bam to +// read in all of the relevant data from the BamFile for +// the new qpGeom. +//////////////////////////////////////////////////////////////////// +void qpGeom::CData:: +fillin(DatagramIterator &scan, BamReader *manager) { +} diff --git a/panda/src/gobj/qpgeom.h b/panda/src/gobj/qpgeom.h new file mode 100644 index 0000000000..ee75758b7f --- /dev/null +++ b/panda/src/gobj/qpgeom.h @@ -0,0 +1,139 @@ +// Filename: qpgeom.h +// Created by: drose (06Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 qpGEOM_H +#define qpGEOM_H + +#include "pandabase.h" +#include "typedWritableReferenceCount.h" +#include "boundedObject.h" +#include "cycleData.h" +#include "cycleDataReader.h" +#include "cycleDataWriter.h" +#include "pipelineCycler.h" +#include "qpgeomVertexData.h" +#include "qpgeomPrimitive.h" +#include "pointerTo.h" +#include "geom.h" + +//////////////////////////////////////////////////////////////////// +// Class : qpGeom +// Description : A container for geometry primitives. This class +// associates one or more GeomPrimitive objects with a +// table of vertices defined by a GeomVertexData object. +// All of the primitives stored in a particular Geom are +// drawn from the same set of vertices (each primitive +// uses a subset of all of the vertices in the table), +// and all of them must be rendered at the same time, in +// the same graphics state. +// +// This is part of the experimental Geom rewrite. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA qpGeom /* : public TypedWritableReferenceCount, public BoundedObject */ +// We temporarily inherit from Geom, merely so we can store this +// pointer where a Geom should go, while we have both implementations +// in the codebase. We pick up some additional cruft from Geom that +// we're not really using. + : public Geom +{ +PUBLISHED: + qpGeom(); + qpGeom(const qpGeom ©); + void operator = (const qpGeom ©); + virtual ~qpGeom(); + + // Temporary. + virtual Geom *make_copy() const; + + INLINE CPT(qpGeomVertexData) get_vertex_data() const; + PT(qpGeomVertexData) modify_vertex_data(); + void set_vertex_data(PT(qpGeomVertexData) data); + + INLINE int get_num_primitives() const; + INLINE const qpGeomPrimitive *get_primitive(int i) const; + INLINE qpGeomPrimitive *modify_primitive(int i); + INLINE void set_primitive(int i, qpGeomPrimitive *primitive); + void add_primitive(qpGeomPrimitive *primitive); + void remove_primitive(int i); + void clear_primitives(); + + void output(ostream &out) const; + void write(ostream &out, int indent_level = 0) const; + +public: + void draw(GraphicsStateGuardianBase *gsg) const; + +protected: + virtual BoundingVolume *recompute_bound(); + +private: + typedef pvector Primitives; + + // This is the data that must be cycled between pipeline stages. + class EXPCL_PANDA CData : public CycleData { + public: + INLINE CData(); + INLINE CData(const CData ©); + virtual CycleData *make_copy() const; + virtual void write_datagram(BamWriter *manager, Datagram &dg) const; + virtual int complete_pointers(TypedWritable **plist, BamReader *manager); + virtual void fillin(DatagramIterator &scan, BamReader *manager); + + PT(qpGeomVertexData) _data; + Primitives _primitives; + }; + + PipelineCycler _cycler; + typedef CycleDataReader CDReader; + typedef CycleDataWriter CDWriter; + +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() { + /*TypedWritableReferenceCount::init_type(); + BoundedObject::init_type();*/ + Geom::init_type(); + register_type(_type_handle, "qpGeom", + Geom::get_class_type() + /*TypedWritableReferenceCount::get_class_type(), + BoundedObject::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; +}; + +INLINE ostream &operator << (ostream &out, const qpGeom &obj); + +#include "qpgeom.I" + +#endif diff --git a/panda/src/gobj/qpgeomMunger.I b/panda/src/gobj/qpgeomMunger.I new file mode 100644 index 0000000000..75fbcf6510 --- /dev/null +++ b/panda/src/gobj/qpgeomMunger.I @@ -0,0 +1,113 @@ +// Filename: qpgeomMunger.I +// Created by: drose (10Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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: qpGeomMunger::is_registered +// Access: Published +// Description: Returns true if this munger has been registered, +// false if it has not. It may not be used for a Geom +// until it has been registered, but once registered, it +// may no longer be modified. +//////////////////////////////////////////////////////////////////// +INLINE bool qpGeomMunger:: +is_registered() const { + return _is_registered; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomMunger::register_munger +// Access: Published, Static +// Description: Adds the indicated munger to the registry, if there +// is not an equivalent munger already there; in either +// case, returns the pointer to the equivalent munger +// now in the registry. +// +// This must be called before a munger may be used in a +// Geom. After this call, you should discard the +// original pointer you passed in (which may or may not +// now be invalid) and let its reference count decrement +// normally; you should use only the returned value from +// this point on. +//////////////////////////////////////////////////////////////////// +INLINE CPT(qpGeomMunger) qpGeomMunger:: +register_munger(qpGeomMunger *munger) { + return get_registry()->register_munger(munger); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomMunger::compare_to +// Access: Public +// Description: Provides an arbitrary ordering among all unique +// GeomMungers, so we can store the essentially +// different ones in a big set and throw away the rest. +//////////////////////////////////////////////////////////////////// +INLINE int qpGeomMunger:: +compare_to(const qpGeomMunger &other) const { + // First, we compare the types; if they are of different types then + // they sort differently. + TypeHandle type = get_type(); + TypeHandle other_type = other.get_type(); + if (type != other_type) { + return type.get_index() - other_type.get_index(); + } + + // We only call compare_to_impl() if they have the same type. + return compare_to_impl(&other); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomMunger::munge_data +// Access: Public +// Description: Given a source GeomVertexData, converts it if +// necessary to the appropriate data for rendering. +//////////////////////////////////////////////////////////////////// +INLINE CPT(qpGeomVertexData) qpGeomMunger:: +munge_data(const qpGeomVertexData *data) const { + // We cast away the const pointer, because do_munge_data() needs to + // update caches and stuff, but we trust it not to change any + // user-definable parameters. + return ((qpGeomMunger *)this)->do_munge_data(data); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomMunger::munge_format +// Access: Public +// Description: Given a source GeomVertexFormat, converts it if +// necessary to the appropriate format for rendering. +//////////////////////////////////////////////////////////////////// +INLINE CPT(qpGeomVertexFormat) qpGeomMunger:: +munge_format(const qpGeomVertexFormat *format) const { + // We cast away the const pointer, because do_munge_format() needs + // to update caches and stuff, but we trust it not to change any + // user-definable parameters. + return ((qpGeomMunger *)this)->do_munge_format(format); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomMunger::get_registry +// Access: Private +// Description: Returns the global registry object. +//////////////////////////////////////////////////////////////////// +INLINE qpGeomMunger::Registry *qpGeomMunger:: +get_registry() { + if (_registry == (Registry *)NULL) { + make_registry(); + } + return _registry; +} diff --git a/panda/src/gobj/qpgeomMunger.cxx b/panda/src/gobj/qpgeomMunger.cxx new file mode 100644 index 0000000000..223bbb2a14 --- /dev/null +++ b/panda/src/gobj/qpgeomMunger.cxx @@ -0,0 +1,282 @@ +// Filename: qpgeomMunger.cxx +// Created by: drose (10Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "qpgeomMunger.h" + +qpGeomMunger::Registry *qpGeomMunger::_registry = NULL; +TypeHandle qpGeomMunger::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomMunger::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomMunger:: +qpGeomMunger() : + _is_registered(false) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomMunger::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomMunger:: +~qpGeomMunger() { + if (is_registered()) { + get_registry()->unregister_munger(this); + } + nassertv(_formats.empty()); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomMunger::remove_format +// Access: Public +// Description: Removes a prepared GeomVertexFormat from the cache. +//////////////////////////////////////////////////////////////////// +void qpGeomMunger:: +remove_format(const qpGeomVertexFormat *format) { + // If this assertion is triggered, maybe we accidentally deleted a + // GeomVertexFormat while we were in the process of unregistering, + // causing a recursive re-entry. + nassertv(_is_registered); + + Formats::iterator fi; + fi = _formats.find(format); + nassertv(fi != _formats.end()); + + CPT(qpGeomVertexFormat) derived_format = (*fi).second; + _formats.erase(fi); + + // We need to unref the derived format, if we reffed it earlier. + if (derived_format != format) { + derived_format->unref(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomMunger::remove_data +// Access: Public +// Description: Removes a prepared GeomVertexData from the cache. +//////////////////////////////////////////////////////////////////// +void qpGeomMunger:: +remove_data(const qpGeomVertexData *data) { + // If this assertion is triggered, maybe we accidentally deleted a + // GeomVertexData while we were in the process of unregistering, + // causing a recursive re-entry. + nassertv(_is_registered); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomMunger::do_munge_data +// Access: Protected +// Description: The protected implementation of munge_data(). This +// exists just to cast away the const pointer. +//////////////////////////////////////////////////////////////////// +CPT(qpGeomVertexData) qpGeomMunger:: +do_munge_data(const qpGeomVertexData *data) { + nassertr(_is_registered, NULL); + + CPT(qpGeomVertexFormat) orig_format = data->get_format(); + CPT(qpGeomVertexFormat) new_format = munge_format(orig_format); + + if (new_format == orig_format) { + // Trivial case. + return data; + } + + return data->convert_to(new_format); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomMunger::do_munge_format +// Access: Protected +// Description: The protected implementation of munge_format(). This +// exists just to cast away the const pointer. +//////////////////////////////////////////////////////////////////// +CPT(qpGeomVertexFormat) qpGeomMunger:: +do_munge_format(const qpGeomVertexFormat *format) { + nassertr(_is_registered, NULL); + nassertr(format->is_registered(), NULL); + + Formats::iterator fi; + fi = _formats.find(format); + if (fi != _formats.end()) { + // This format was previously munged, so the answer will be the + // same. + return (*fi).second; + } + + // We have to munge this format for the first time. + CPT(qpGeomVertexFormat) derived_format = munge_format_impl(format); + nassertr(derived_format->is_registered(), NULL); + + // Store the answer in the map, so we can quickly get it next time. + bool inserted = _formats.insert(Formats::value_type(format, derived_format)).second; + nassertr(inserted, NULL); + + // Tell the source format that we have its pointer. + inserted = ((qpGeomVertexFormat *)format)->_mungers.insert(this).second; + nassertr(inserted, NULL); + + // We also want to keep a reference count on the derived format, but + // only if it is actually a different pointer from the original + // format--otherwise it would cause a self-referential reference + // count. + if (derived_format != format) { + derived_format->ref(); + } + + return derived_format; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomMunger::munge_format_impl +// Access: Protected, Virtual +// Description: Given a source GeomVertexFormat, converts it if +// necessary to the appropriate format for rendering. +//////////////////////////////////////////////////////////////////// +CPT(qpGeomVertexFormat) qpGeomMunger:: +munge_format_impl(const qpGeomVertexFormat *orig) { + return orig; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomMunger::compare_to_impl +// Access: Protected, Virtual +// Description: Called to compare two GeomMungers who are known to be +// of the same type, for an apples-to-apples comparison. +// This will never be called on two pointers of a +// different type. +//////////////////////////////////////////////////////////////////// +int qpGeomMunger:: +compare_to_impl(const qpGeomMunger *other) const { + return 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomMunger::make_registry +// Access: Private +// Description: Returns the global registry object. +//////////////////////////////////////////////////////////////////// +void qpGeomMunger:: +make_registry() { + if (_registry == (Registry *)NULL) { + _registry = new Registry; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomMunger::do_register +// Access: Private +// Description: Called internally when the munger is registered. +//////////////////////////////////////////////////////////////////// +void qpGeomMunger:: +do_register() { + nassertv(!_is_registered); + nassertv(_formats.empty()); + + _is_registered = true; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomMunger::do_unregister +// Access: Private +// Description: Called internally when the munger is unregistered. +//////////////////////////////////////////////////////////////////// +void qpGeomMunger:: +do_unregister() { + nassertv(_is_registered); + _is_registered = false; + + // Unregistering means we should blow away the cache. + Formats::iterator fi; + for (fi = _formats.begin(); fi != _formats.end(); ++fi) { + const qpGeomVertexFormat *format = (*fi).first; + CPT(qpGeomVertexFormat) derived_format = (*fi).second; + + size_t num_erased = ((qpGeomVertexFormat *)format)->_mungers.erase(this); + nassertv(num_erased == 1); + + if (derived_format != format) { + derived_format->unref(); + } + } + _formats.clear(); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomMunger::Registry::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomMunger::Registry:: +Registry() { +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomMunger::Registry::register_munger +// Access: Public +// Description: Adds the indicated munger to the registry, if there +// is not an equivalent munger already there; in either +// case, returns the pointer to the equivalent munger +// now in the registry. +// +// This must be called before a munger may be used in a +// Geom. After this call, you should discard the +// original pointer you passed in (which may or may not +// now be invalid) and let its reference count decrement +// normally; you should use only the returned value from +// this point on. +//////////////////////////////////////////////////////////////////// +CPT(qpGeomMunger) qpGeomMunger::Registry:: +register_munger(qpGeomMunger *munger) { + if (munger->is_registered()) { + return munger; + } + + // Save the incoming pointer in a local PointerTo, so that if it has + // a zero reference count and is not added into the map below, it + // will be automatically deleted when this function returns. + PT(qpGeomMunger) pt_munger = munger; + + Mungers::iterator mi = _mungers.insert(munger).first; + qpGeomMunger *new_munger = (*mi); + if (!new_munger->is_registered()) { + new_munger->do_register(); + } + + return new_munger; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomMunger::Registry::unregister_munger +// Access: Public +// Description: Removes the indicated munger from the registry. +// Normally this should not be done until the munger is +// destructing. +//////////////////////////////////////////////////////////////////// +void qpGeomMunger::Registry:: +unregister_munger(qpGeomMunger *munger) { + nassertv(munger->is_registered()); + Mungers::iterator mi = _mungers.find(munger); + nassertv(mi != _mungers.end()); + _mungers.erase(mi); + munger->do_unregister(); +} diff --git a/panda/src/gobj/qpgeomMunger.h b/panda/src/gobj/qpgeomMunger.h new file mode 100644 index 0000000000..943ff6393e --- /dev/null +++ b/panda/src/gobj/qpgeomMunger.h @@ -0,0 +1,121 @@ +// Filename: qpgeomMunger.h +// Created by: drose (10Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 qpGEOMMUNGER_H +#define qpGEOMMUNGER_H + +#include "pandabase.h" +#include "typedReferenceCount.h" +#include "qpgeomVertexFormat.h" +#include "indirectCompareTo.h" +#include "pmap.h" +#include "pset.h" + +//////////////////////////////////////////////////////////////////// +// Class : qpGeomMunger +// Description : Objects of this class are used to convert vertex data +// from a Geom into a format suitable for passing to the +// rendering backend. Typically, the rendering backend +// will create a specialization of this class to handle +// its particular needs (e.g. DXGeomMunger). This class +// is necessary because DirectX and OpenGL have somewhat +// different requirements for vertex format. +// +// This also performs runtime application of state +// changes to the vertex data; for instance, by scaling +// all of the color values in response to a +// ColorScaleAttrib. +// +// A GeomMunger must be registered before it can be +// used, and once registered, the object is constant and +// cannot be changed. All registered GeomMungers that +// perform the same operation will have the same +// pointer. +// +// This is part of the experimental Geom rewrite. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA qpGeomMunger : public TypedReferenceCount { +public: + qpGeomMunger(); + virtual ~qpGeomMunger(); + + INLINE bool is_registered() const; + INLINE static CPT(qpGeomMunger) register_munger(qpGeomMunger *munger); + + INLINE CPT(qpGeomVertexFormat) munge_format(const qpGeomVertexFormat *format) const; + void remove_format(const qpGeomVertexFormat *format); + + INLINE CPT(qpGeomVertexData) munge_data(const qpGeomVertexData *data) const; + void remove_data(const qpGeomVertexData *data); + +public: + INLINE int compare_to(const qpGeomMunger &other) const; + +protected: + CPT(qpGeomVertexFormat) do_munge_format(const qpGeomVertexFormat *format); + CPT(qpGeomVertexData) do_munge_data(const qpGeomVertexData *data); + + virtual CPT(qpGeomVertexFormat) munge_format_impl(const qpGeomVertexFormat *orig); + virtual int compare_to_impl(const qpGeomMunger *other) const; + +private: + class Registry; + INLINE static Registry *get_registry(); + static void make_registry(); + + void do_register(); + void do_unregister(); + + typedef pmap Formats; + Formats _formats; + + bool _is_registered; + typedef pset > Mungers; + class Registry { + public: + Registry(); + CPT(qpGeomMunger) register_munger(qpGeomMunger *munger); + void unregister_munger(qpGeomMunger *munger); + + Mungers _mungers; + }; + + static Registry *_registry; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + TypedReferenceCount::init_type(); + register_type(_type_handle, "qpGeomMunger", + TypedReferenceCount::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 "qpgeomMunger.I" + +#endif + diff --git a/panda/src/gobj/qpgeomPrimitive.I b/panda/src/gobj/qpgeomPrimitive.I new file mode 100644 index 0000000000..de69f0fc6c --- /dev/null +++ b/panda/src/gobj/qpgeomPrimitive.I @@ -0,0 +1,132 @@ +// Filename: qpgeomPrimitive.I +// Created by: drose (06Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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: qpGeomPrimitive::get_num_vertices +// Access: Published +// Description: Returns the number of vertex vertices used by all the +// primitives in this object. +//////////////////////////////////////////////////////////////////// +INLINE int qpGeomPrimitive:: +get_num_vertices() const { + CDReader cdata(_cycler); + return cdata->_vertices.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::get_vertex +// Access: Published +// Description: Returns the ith vertex index in the table. +//////////////////////////////////////////////////////////////////// +INLINE int qpGeomPrimitive:: +get_vertex(int i) const { + CDReader cdata(_cycler); + nassertr(i >= 0 && i < (int)cdata->_vertices.size(), -1); + return cdata->_vertices[i]; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::get_vertices +// Access: Published +// Description: Returns a const pointer to the vertex index array so +// application code can read it directly. Do not +// attempt to modify the returned array; use +// modify_vertices() or set_vertices() for this. +//////////////////////////////////////////////////////////////////// +INLINE CPTA_ushort qpGeomPrimitive:: +get_vertices() const { + CDReader cdata(_cycler); + return cdata->_vertices; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::get_vertices +// Access: Published +// Description: Returns a const pointer to the primitive lengths +// array so application code can read it directly. Do +// not attempt to modify the returned array; use +// modify_lengths() or set_lengths() for this. +// +// Note that simple primitive types, like triangles, do +// not have a lengths array: since all the primitives +// have the same number of vertices, it is not needed. +//////////////////////////////////////////////////////////////////// +INLINE CPTA_int qpGeomPrimitive:: +get_lengths() const { + CDReader cdata(_cycler); + return cdata->_lengths; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::get_min_vertex +// Access: Published +// Description: Returns the minimum vertex index number used by the +// primitives in this object. +//////////////////////////////////////////////////////////////////// +INLINE int qpGeomPrimitive:: +get_min_vertex() const { + CDReader cdata(_cycler); + if (!cdata->_got_minmax) { + ((qpGeomPrimitive *)this)->recompute_minmax(); + } + return cdata->_min_vertex; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::get_max_vertex +// Access: Published +// Description: Returns the maximum vertex index number used by the +// primitives in this object. +//////////////////////////////////////////////////////////////////// +INLINE int qpGeomPrimitive:: +get_max_vertex() const { + CDReader cdata(_cycler); + if (!cdata->_got_minmax) { + ((qpGeomPrimitive *)this)->recompute_minmax(); + } + return cdata->_max_vertex; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::CData::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE qpGeomPrimitive::CData:: +CData() : + _got_minmax(true), + _min_vertex(0), + _max_vertex(0) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::CData::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE qpGeomPrimitive::CData:: +CData(const qpGeomPrimitive::CData ©) : + _vertices(copy._vertices), + _lengths(copy._lengths), + _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 new file mode 100644 index 0000000000..6c50341ed0 --- /dev/null +++ b/panda/src/gobj/qpgeomPrimitive.cxx @@ -0,0 +1,520 @@ +// Filename: qpgeomPrimitive.cxx +// Created by: drose (06Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "qpgeomPrimitive.h" +#include "qpgeomVertexData.h" +#include "qpgeomVertexArrayFormat.h" +#include "qpgeomVertexDataType.h" +#include "internalName.h" +#include "bamReader.h" +#include "bamWriter.h" +#include "indent.h" + +TypeHandle qpGeomPrimitive::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomPrimitive:: +qpGeomPrimitive() { +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::Copy Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomPrimitive:: +qpGeomPrimitive(const qpGeomPrimitive ©) : + TypedWritableReferenceCount(copy), + _cycler(copy._cycler) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::Destructor +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomPrimitive:: +~qpGeomPrimitive() { +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::add_vertex +// Access: Published +// Description: Adds the indicated vertex to the list of vertex +// indices used by the graphics primitive type. To +// define primitive, you must call add_vertex() for each +// vertex of the new primitve, and then call +// close_primitive() after you have specified the last +// vertex of each primitive. +//////////////////////////////////////////////////////////////////// +void qpGeomPrimitive:: +add_vertex(int vertex) { + unsigned short short_vertex = vertex; + nassertv((int)short_vertex == vertex); + + CDWriter cdata(_cycler); + cdata->_vertices.push_back(short_vertex); + + if (cdata->_got_minmax) { + cdata->_min_vertex = min(cdata->_min_vertex, short_vertex); + cdata->_max_vertex = max(cdata->_min_vertex, short_vertex); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::add_consecutive_vertices +// Access: Published +// Description: Adds a consecutive sequence of vertices, beginning at +// start, to the primitive. +//////////////////////////////////////////////////////////////////// +void qpGeomPrimitive:: +add_consecutive_vertices(int start, int num_vertices) { + int end = (start + num_vertices) - 1; + unsigned short short_start = start; + unsigned short short_end = end; + nassertv((int)short_start == start && (int)short_end == end); + + CDWriter cdata(_cycler); + for (unsigned short v = short_start; v <= short_end; ++v) { + cdata->_vertices.push_back(v); + } + + if (cdata->_got_minmax) { + cdata->_min_vertex = min(cdata->_min_vertex, short_start); + cdata->_max_vertex = max(cdata->_min_vertex, short_end); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::close_primitive +// Access: Published +// Description: Indicates that the previous n calls to add_vertex(), +// since the last call to close_primitive(), have fully +// defined a new primitive. +//////////////////////////////////////////////////////////////////// +void qpGeomPrimitive:: +close_primitive() { + int num_vertices_per_primitive = get_num_vertices_per_primitive(); + + CDWriter cdata(_cycler); + 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.back() != (int)cdata->_vertices.size()) { + cdata->_lengths.push_back((int)cdata->_vertices.size()); + } + + } else { + // This is a simple primitive type like a triangle: each primitive + // uses the same number of vertices. Assert that we added the + // correct number of vertices. + nassertv((int)cdata->_vertices.size() % num_vertices_per_primitive == 0); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::clear_vertices +// Access: Published +// Description: Removes all of the vertices and primitives from the +// object, so they can be re-added. +//////////////////////////////////////////////////////////////////// +void qpGeomPrimitive:: +clear_vertices() { + CDWriter cdata(_cycler); + cdata->_vertices.clear(); + cdata->_lengths.clear(); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::modify_vertices +// Access: Published +// Description: Returns a modifiable pointer to the vertex index +// list, 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. +//////////////////////////////////////////////////////////////////// +PTA_ushort qpGeomPrimitive:: +modify_vertices() { + CDWriter cdata(_cycler); + return cdata->_vertices; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::set_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. +//////////////////////////////////////////////////////////////////// +void qpGeomPrimitive:: +set_vertices(PTA_ushort vertices) { + CDWriter cdata(_cycler); + cdata->_vertices = vertices; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::modify_lengths +// Access: Published +// Description: Returns a modifiable pointer to the primitive lengths +// 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 +// have the same number of vertices, it is not needed. +//////////////////////////////////////////////////////////////////// +PTA_int qpGeomPrimitive:: +modify_lengths() { + CDWriter cdata(_cycler); + return cdata->_lengths; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::set_lengths +// Access: Published +// Description: Completely replaces the primitive lengths 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 +// have the same number of vertices, it is not needed. +//////////////////////////////////////////////////////////////////// +void qpGeomPrimitive:: +set_lengths(PTA_int lengths) { + CDWriter cdata(_cycler); + cdata->_lengths = lengths; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::get_num_vertices_per_primitive +// Access: Published, Virtual +// Description: If the primitive type is a simple type in which all +// primitives have the same number of vertices, like +// triangles, returns the number of vertices per +// primitive. If the primitive type is a more complex +// type in which different primitives might have +// different numbers of vertices, for instance a +// triangle strip, returns 0. +//////////////////////////////////////////////////////////////////// +int qpGeomPrimitive:: +get_num_vertices_per_primitive() const { + return 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::get_num_primitives +// Access: Published +// Description: Returns the number of individual primitives stored +// within this object. All primitives are the same +// type. +//////////////////////////////////////////////////////////////////// +int qpGeomPrimitive:: +get_num_primitives() const { + int num_vertices_per_primitive = get_num_vertices_per_primitive(); + + CDReader cdata(_cycler); + 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(); + + } else { + // This is a simple primitive type like a triangle: each primitive + // uses the same number of vertices. + return ((int)cdata->_vertices.size() / num_vertices_per_primitive); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::get_primitive_start +// Access: Published +// Description: Returns the element within the _vertices list at which +// the ith primitive starts. +// +// If i is one more than the highest valid primitive +// vertex, the return value will be one more than the +// last valid vertex. Thus, it is always true that the +// vertices used by a particular primitive i are the set +// get_primitive_start(i) <= vi < get_primitive_start(i +// + 1). +//////////////////////////////////////////////////////////////////// +int qpGeomPrimitive:: +get_primitive_start(int i) const { + int num_vertices_per_primitive = get_num_vertices_per_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. + CDReader cdata(_cycler); + nassertr(i >= 0 && i <= (int)cdata->_lengths.size(), -1); + if (i == 0) { + return 0; + } else { + return cdata->_lengths[i - 1]; + } + + } else { + // This is a simple primitive type like a triangle: each primitive + // uses the same number of vertices. + return i * num_vertices_per_primitive; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::get_primitive_num_vertices +// Access: Published +// Description: Returns the number of vertices used by the ith +// primitive. +//////////////////////////////////////////////////////////////////// +int qpGeomPrimitive:: +get_primitive_num_vertices(int i) const { + int num_vertices_per_primitive = get_num_vertices_per_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. + CDReader cdata(_cycler); + nassertr(i >= 0 && i < (int)cdata->_lengths.size(), 0); + return cdata->_lengths[i]; + + } else { + // This is a simple primitive type like a triangle: each primitive + // uses the same number of vertices. + return num_vertices_per_primitive; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::decompose +// Access: Published, Virtual +// Description: Decomposes a complex primitive type into a simpler +// primitive type, for instance triangle strips to +// triangles, and returns a pointer to the new primitive +// definition. If the decomposition cannot be +// performed, this might return the original object. +// +// This method is useful for application code that wants +// to iterate through the set of triangles on the +// primitive without having to write handlers for each +// possible kind of primitive type. +//////////////////////////////////////////////////////////////////// +PT(qpGeomPrimitive) qpGeomPrimitive:: +decompose(const qpGeomVertexData *vertex_data) { + return this; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::output +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void qpGeomPrimitive:: +output(ostream &out, const qpGeomVertexData *vertex_data) const { + out << get_type() << ", " << get_num_primitives() + << ", " << get_num_vertices(); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::write +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void qpGeomPrimitive:: +write(ostream &out, const qpGeomVertexData *vertex_data, + int indent_level) const { + indent(out, indent_level) + << get_type() << ":\n"; + int num_primitives = get_num_primitives(); + for (int i = 0; i < num_primitives; i++) { + indent(out, indent_level + 2) + << "["; + int begin = get_primitive_start(i); + int end = get_primitive_start(i + 1); + for (int vi = begin; vi < end; vi++) { + out << " " << get_vertex(vi); + } + out << " ]\n"; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::calc_tight_bounds +// Access: Public, Virtual +// Description: Expands min_point and max_point to include all of the +// vertices in the Geom, if any. found_any is set true +// if any points are found. It is the caller's +// responsibility to initialize min_point, max_point, +// and found_any before calling this function. +//////////////////////////////////////////////////////////////////// +void qpGeomPrimitive:: +calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point, + bool &found_any, + const qpGeomVertexData *vertex_data) const { + CDReader cdata(_cycler); + + const qpGeomVertexFormat *format = vertex_data->get_format(); + + int array_index = format->get_array_with(InternalName::get_vertex()); + if (array_index < 0) { + // No vertex data. + return; + } + + const qpGeomVertexArrayFormat *array_format = format->get_array(array_index); + const qpGeomVertexDataType *data_type = + array_format->get_data_type(InternalName::get_vertex()); + + int stride = array_format->get_stride(); + int start = data_type->get_start(); + int num_components = data_type->get_num_components(); + + CPTA_uchar array_data = vertex_data->get_array_data(array_index); + + PTA_ushort::const_iterator ii; + for (ii = cdata->_vertices.begin(); ii != cdata->_vertices.end(); ++ii) { + int index = (int)(*ii); + const PN_float32 *v = (const PN_float32 *)&array_data[start + index * stride]; + + LPoint3f vertex; + qpGeomVertexData::to_vec3(vertex, v, num_components); + + if (found_any) { + min_point.set(min(min_point[0], vertex[0]), + min(min_point[1], vertex[1]), + min(min_point[2], vertex[2])); + max_point.set(max(max_point[0], vertex[0]), + max(max_point[1], vertex[1]), + max(max_point[2], vertex[2])); + } else { + min_point = vertex; + max_point = vertex; + found_any = true; + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::recompute_minmax +// Access: Private +// Description: Recomputes the _min_vertex and _max_vertex values if +// necessary. +//////////////////////////////////////////////////////////////////// +void qpGeomPrimitive:: +recompute_minmax() { + CDWriter cdata(_cycler); + + if (cdata->_vertices.empty()) { + cdata->_min_vertex = 0; + cdata->_max_vertex = 0; + } else { + PTA_ushort::const_iterator ii = cdata->_vertices.begin(); + cdata->_min_vertex = (*ii); + cdata->_max_vertex = (*ii); + + ++ii; + while (ii != cdata->_vertices.end()) { + cdata->_min_vertex = min(cdata->_min_vertex, (*ii)); + cdata->_max_vertex = max(cdata->_min_vertex, (*ii)); + + ++ii; + } + } + + cdata->_got_minmax = true; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void qpGeomPrimitive:: +write_datagram(BamWriter *manager, Datagram &dg) { + TypedWritable::write_datagram(manager, dg); + + manager->write_cdata(dg, _cycler); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::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 qpGeomPrimitive. +//////////////////////////////////////////////////////////////////// +void qpGeomPrimitive:: +fillin(DatagramIterator &scan, BamReader *manager) { + TypedWritable::fillin(scan, manager); + + manager->read_cdata(scan, _cycler); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::CData::make_copy +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +CycleData *qpGeomPrimitive::CData:: +make_copy() const { + return new CData(*this); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::CData::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void qpGeomPrimitive::CData:: +write_datagram(BamWriter *manager, Datagram &dg) const { +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::CData::complete_pointers +// Access: Public, Virtual +// Description: Receives an array of pointers, one for each time +// manager->read_pointer() was called in fillin(). +// Returns the number of pointers processed. +//////////////////////////////////////////////////////////////////// +int qpGeomPrimitive::CData:: +complete_pointers(TypedWritable **p_list, BamReader *manager) { + int pi = CycleData::complete_pointers(p_list, manager); + + return pi; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::CData::fillin +// Access: Public, Virtual +// Description: This internal function is called by make_from_bam to +// read in all of the relevant data from the BamFile for +// the new qpGeomPrimitive. +//////////////////////////////////////////////////////////////////// +void qpGeomPrimitive::CData:: +fillin(DatagramIterator &scan, BamReader *manager) { +} diff --git a/panda/src/gobj/qpgeomPrimitive.h b/panda/src/gobj/qpgeomPrimitive.h new file mode 100644 index 0000000000..f7a78975b4 --- /dev/null +++ b/panda/src/gobj/qpgeomPrimitive.h @@ -0,0 +1,156 @@ +// Filename: qpgeomPrimitive.h +// Created by: drose (06Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 qpGEOMPRIMITIVE_H +#define qpGEOMPRIMITIVE_H + +#include "pandabase.h" +#include "typedWritableReferenceCount.h" +#include "luse.h" +#include "pointerTo.h" +#include "pta_ushort.h" +#include "pta_int.h" +#include "cycleData.h" +#include "cycleDataReader.h" +#include "cycleDataWriter.h" +#include "pipelineCycler.h" + +class qpGeomVertexData; +class GraphicsStateGuardianBase; +class GeomContext; +class FactoryParams; + +//////////////////////////////////////////////////////////////////// +// Class : qpGeomPrimitive +// Description : This is an abstract base class for a family of +// classes that represent the fundamental geometry +// primitives that may be stored in a Geom. +// +// They all have in common the fact that they are +// defined by tables of vertex data stored in a +// GeomVertexData object. Each GeomPrimitive object +// contains an ordered list of integers, which index +// into the vertex array defined by the GeomVertexData +// and define the particular vertices of the +// GeomVertexData that are used for this primitive. +// +// The meaning of a given arrangement of vertices is +// defined by each individual primitive type; for +// instance, a GeomTriangle renders a triangle from each +// three consecutive vertices, while a GeomTriangleStrip +// renders a strip of (n - 2) connected triangles from +// each sequence of n vertices. +// +// This is part of the experimental Geom rewrite. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA qpGeomPrimitive : public TypedWritableReferenceCount { +PUBLISHED: + qpGeomPrimitive(); + qpGeomPrimitive(const qpGeomPrimitive ©); + virtual ~qpGeomPrimitive(); + + INLINE int get_num_vertices() const; + INLINE int get_vertex(int i) const; + void add_vertex(int vertex); + void add_consecutive_vertices(int start, int num_vertices); + void close_primitive(); + void clear_vertices(); + + INLINE CPTA_ushort get_vertices() const; + 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 int get_min_vertex() const; + INLINE int get_max_vertex() const; + + virtual int get_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; + + virtual PT(qpGeomPrimitive) decompose(const qpGeomVertexData *vertex_data); + + virtual void output(ostream &out, const qpGeomVertexData *vertex_data) const; + virtual void write(ostream &out, const qpGeomVertexData *vertex_data, + int indent_level) const; + +public: + virtual void draw(GraphicsStateGuardianBase *gsg)=0; + + virtual void calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point, + bool &found_any, + const qpGeomVertexData *vertex_data) const; + +private: + // This is the data that must be cycled between pipeline stages. + class EXPCL_PANDA CData : public CycleData { + public: + INLINE CData(); + INLINE CData(const CData ©); + virtual CycleData *make_copy() const; + virtual void write_datagram(BamWriter *manager, Datagram &dg) const; + virtual int complete_pointers(TypedWritable **plist, BamReader *manager); + virtual void fillin(DatagramIterator &scan, BamReader *manager); + + PTA_ushort _vertices; + PTA_int _lengths; + + bool _got_minmax; + unsigned short _min_vertex; + unsigned short _max_vertex; + }; + + PipelineCycler _cycler; + typedef CycleDataReader CDReader; + typedef CycleDataWriter CDWriter; + + void recompute_minmax(); + +public: + virtual void write_datagram(BamWriter *manager, Datagram &dg); + +protected: + void fillin(DatagramIterator &scan, BamReader *manager); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + TypedWritableReferenceCount::init_type(); + register_type(_type_handle, "qpGeomPrimitive", + TypedWritableReferenceCount::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; + + friend class qpGeom; +}; + +#include "qpgeomPrimitive.I" + +#endif diff --git a/panda/src/gobj/qpgeomTriangles.cxx b/panda/src/gobj/qpgeomTriangles.cxx new file mode 100644 index 0000000000..857b377a1e --- /dev/null +++ b/panda/src/gobj/qpgeomTriangles.cxx @@ -0,0 +1,110 @@ +// Filename: qpgeomTriangles.cxx +// Created by: drose (06Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "qpgeomTriangles.h" +#include "bamReader.h" +#include "bamWriter.h" + +TypeHandle qpGeomTriangles::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomTriangles::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomTriangles:: +qpGeomTriangles() { +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomTriangles::Copy Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomTriangles:: +qpGeomTriangles(const qpGeomTriangles ©) : + qpGeomPrimitive(copy) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomTriangles::Destructor +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomTriangles:: +~qpGeomTriangles() { +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomTriangles::get_num_vertices_per_primitive +// Access: Published, Virtual +// Description: If the primitive type is a simple type in which all +// primitives have the same number of vertices, like +// triangles, returns the number of vertices per +// primitive. If the primitive type is a more complex +// type in which different primitives might have +// different numbers of vertices, for instance a +// triangle strip, returns 0. +//////////////////////////////////////////////////////////////////// +int qpGeomTriangles:: +get_num_vertices_per_primitive() const { + return 3; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomTriangles::draw +// Access: Public, Virtual +// Description: Calls the appropriate method on the GSG to draw the +// primitive. +//////////////////////////////////////////////////////////////////// +void qpGeomTriangles:: +draw(GraphicsStateGuardianBase *gsg) { + gsg->draw_triangles(this); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomTriangles::register_with_read_factory +// Access: Public, Static +// Description: Tells the BamReader how to create objects of type +// qpGeom. +//////////////////////////////////////////////////////////////////// +void qpGeomTriangles:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomTriangles::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type qpGeom is encountered +// in the Bam file. It should create the qpGeom +// and extract its information from the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *qpGeomTriangles:: +make_from_bam(const FactoryParams ¶ms) { + qpGeomTriangles *object = new qpGeomTriangles; + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + object->fillin(scan, manager); + + return object; +} diff --git a/panda/src/gobj/qpgeomTriangles.h b/panda/src/gobj/qpgeomTriangles.h new file mode 100644 index 0000000000..c1bcb391a3 --- /dev/null +++ b/panda/src/gobj/qpgeomTriangles.h @@ -0,0 +1,68 @@ +// Filename: qpgeomTriangles.h +// Created by: drose (06Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 qpGEOMTRIANGLES_H +#define qpGEOMTRIANGLES_H + +#include "pandabase.h" +#include "qpgeomPrimitive.h" + +//////////////////////////////////////////////////////////////////// +// Class : qpGeomTriangles +// Description : Defines a series of disconnected triangles. +// +// This is part of the experimental Geom rewrite. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA qpGeomTriangles : public qpGeomPrimitive { +PUBLISHED: + qpGeomTriangles(); + qpGeomTriangles(const qpGeomTriangles ©); + virtual ~qpGeomTriangles(); + + virtual int get_num_vertices_per_primitive() const; + +public: + virtual void draw(GraphicsStateGuardianBase *gsg); + +public: + static void register_with_read_factory(); + +protected: + static TypedWritable *make_from_bam(const FactoryParams ¶ms); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + qpGeomPrimitive::init_type(); + register_type(_type_handle, "qpGeomTriangles", + qpGeomPrimitive::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; + + friend class qpGeom; +}; + +#endif diff --git a/panda/src/gobj/qpgeomTrifans.cxx b/panda/src/gobj/qpgeomTrifans.cxx new file mode 100644 index 0000000000..9a19bedaad --- /dev/null +++ b/panda/src/gobj/qpgeomTrifans.cxx @@ -0,0 +1,138 @@ +// Filename: qpgeomTrifans.cxx +// Created by: drose (08Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "qpgeomTrifans.h" +#include "qpgeomTriangles.h" +#include "bamReader.h" +#include "bamWriter.h" + +TypeHandle qpGeomTrifans::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomTrifans::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomTrifans:: +qpGeomTrifans() { +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomTrifans::Copy Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomTrifans:: +qpGeomTrifans(const qpGeomTrifans ©) : + qpGeomPrimitive(copy) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomTrifans::Destructor +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomTrifans:: +~qpGeomTrifans() { +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomTrifans::decompose +// Access: Published, Virtual +// Description: Decomposes a complex primitive type into a simpler +// primitive type, for instance triangle strips to +// triangles, and returns a pointer to the new primitive +// definition. If the decomposition cannot be +// performed, this might return the original object. +// +// This method is useful for application code that wants +// to iterate through the set of triangles on the +// primitive without having to write handlers for each +// possible kind of primitive type. +//////////////////////////////////////////////////////////////////// +PT(qpGeomPrimitive) qpGeomTrifans:: +decompose(const qpGeomVertexData *) { + PT(qpGeomTriangles) triangles = new qpGeomTriangles; + CPTA_ushort vertices = get_vertices(); + CPTA_int lengths = get_lengths(); + + 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); + ++vi; + int v1 = (*vi); + ++vi; + for (int i = 2; i < length; i++) { + triangles->add_vertex(v0); + triangles->add_vertex(v1); + triangles->add_vertex(*vi); + triangles->close_primitive(); + ++vi; + } + } + + return triangles.p(); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomTrifans::draw +// Access: Public, Virtual +// Description: Calls the appropriate method on the GSG to draw the +// primitive. +//////////////////////////////////////////////////////////////////// +void qpGeomTrifans:: +draw(GraphicsStateGuardianBase *gsg) { + gsg->draw_trifans(this); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomTrifans::register_with_read_factory +// Access: Public, Static +// Description: Tells the BamReader how to create objects of type +// qpGeom. +//////////////////////////////////////////////////////////////////// +void qpGeomTrifans:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomTrifans::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type qpGeom is encountered +// in the Bam file. It should create the qpGeom +// and extract its information from the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *qpGeomTrifans:: +make_from_bam(const FactoryParams ¶ms) { + qpGeomTrifans *object = new qpGeomTrifans; + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + object->fillin(scan, manager); + + return object; +} diff --git a/panda/src/gobj/qpgeomTrifans.h b/panda/src/gobj/qpgeomTrifans.h new file mode 100644 index 0000000000..1cb707cc7c --- /dev/null +++ b/panda/src/gobj/qpgeomTrifans.h @@ -0,0 +1,68 @@ +// Filename: qpgeomTrifans.h +// Created by: drose (08Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 qpGEOMTRIFANS_H +#define qpGEOMTRIFANS_H + +#include "pandabase.h" +#include "qpgeomPrimitive.h" + +//////////////////////////////////////////////////////////////////// +// Class : qpGeomTrifans +// Description : Defines a series of triangle fans. +// +// This is part of the experimental Geom rewrite. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA qpGeomTrifans : public qpGeomPrimitive { +PUBLISHED: + qpGeomTrifans(); + qpGeomTrifans(const qpGeomTrifans ©); + virtual ~qpGeomTrifans(); + + virtual PT(qpGeomPrimitive) decompose(const qpGeomVertexData *vertex_data); + +public: + virtual void draw(GraphicsStateGuardianBase *gsg); + +public: + static void register_with_read_factory(); + +protected: + static TypedWritable *make_from_bam(const FactoryParams ¶ms); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + qpGeomPrimitive::init_type(); + register_type(_type_handle, "qpGeomTrifans", + qpGeomPrimitive::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; + + friend class qpGeom; +}; + +#endif diff --git a/panda/src/gobj/qpgeomTristrips.cxx b/panda/src/gobj/qpgeomTristrips.cxx new file mode 100644 index 0000000000..964085d607 --- /dev/null +++ b/panda/src/gobj/qpgeomTristrips.cxx @@ -0,0 +1,148 @@ +// Filename: qpgeomTristrips.cxx +// Created by: drose (08Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "qpgeomTristrips.h" +#include "qpgeomTriangles.h" +#include "bamReader.h" +#include "bamWriter.h" + +TypeHandle qpGeomTristrips::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomTristrips::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomTristrips:: +qpGeomTristrips() { +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomTristrips::Copy Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomTristrips:: +qpGeomTristrips(const qpGeomTristrips ©) : + qpGeomPrimitive(copy) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomTristrips::Destructor +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomTristrips:: +~qpGeomTristrips() { +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomTristrips::decompose +// Access: Published, Virtual +// Description: Decomposes a complex primitive type into a simpler +// primitive type, for instance triangle strips to +// triangles, and returns a pointer to the new primitive +// definition. If the decomposition cannot be +// performed, this might return the original object. +// +// This method is useful for application code that wants +// to iterate through the set of triangles on the +// primitive without having to write handlers for each +// possible kind of primitive type. +//////////////////////////////////////////////////////////////////// +PT(qpGeomPrimitive) qpGeomTristrips:: +decompose(const qpGeomVertexData *) { + PT(qpGeomTriangles) triangles = new qpGeomTriangles; + CPTA_ushort vertices = get_vertices(); + CPTA_int lengths = get_lengths(); + + 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); + ++vi; + int v1 = (*vi); + ++vi; + bool reversed = false; + for (int i = 2; i < length; i++) { + if (reversed) { + triangles->add_vertex(v1); + triangles->add_vertex(v0); + reversed = false; + } else { + triangles->add_vertex(v0); + triangles->add_vertex(v1); + reversed = true; + } + triangles->add_vertex(*vi); + v0 = v1; + v1 = *vi; + triangles->close_primitive(); + ++vi; + } + } + + return triangles.p(); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomTristrips::draw +// Access: Public, Virtual +// Description: Calls the appropriate method on the GSG to draw the +// primitive. +//////////////////////////////////////////////////////////////////// +void qpGeomTristrips:: +draw(GraphicsStateGuardianBase *gsg) { + gsg->draw_tristrips(this); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomTristrips::register_with_read_factory +// Access: Public, Static +// Description: Tells the BamReader how to create objects of type +// qpGeom. +//////////////////////////////////////////////////////////////////// +void qpGeomTristrips:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomTristrips::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type qpGeom is encountered +// in the Bam file. It should create the qpGeom +// and extract its information from the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *qpGeomTristrips:: +make_from_bam(const FactoryParams ¶ms) { + qpGeomTristrips *object = new qpGeomTristrips; + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + object->fillin(scan, manager); + + return object; +} diff --git a/panda/src/gobj/qpgeomTristrips.h b/panda/src/gobj/qpgeomTristrips.h new file mode 100644 index 0000000000..a532c0c8b4 --- /dev/null +++ b/panda/src/gobj/qpgeomTristrips.h @@ -0,0 +1,68 @@ +// Filename: qpgeomTristrips.h +// Created by: drose (08Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 qpGEOMTRISTRIPS_H +#define qpGEOMTRISTRIPS_H + +#include "pandabase.h" +#include "qpgeomPrimitive.h" + +//////////////////////////////////////////////////////////////////// +// Class : qpGeomTristrips +// Description : Defines a series of triangle strips. +// +// This is part of the experimental Geom rewrite. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA qpGeomTristrips : public qpGeomPrimitive { +PUBLISHED: + qpGeomTristrips(); + qpGeomTristrips(const qpGeomTristrips ©); + virtual ~qpGeomTristrips(); + + virtual PT(qpGeomPrimitive) decompose(const qpGeomVertexData *vertex_data); + +public: + virtual void draw(GraphicsStateGuardianBase *gsg); + +public: + static void register_with_read_factory(); + +protected: + static TypedWritable *make_from_bam(const FactoryParams ¶ms); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + qpGeomPrimitive::init_type(); + register_type(_type_handle, "qpGeomTristrips", + qpGeomPrimitive::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; + + friend class qpGeom; +}; + +#endif diff --git a/panda/src/gobj/qpgeomVertexArrayFormat.I b/panda/src/gobj/qpgeomVertexArrayFormat.I new file mode 100644 index 0000000000..fea157b1f7 --- /dev/null +++ b/panda/src/gobj/qpgeomVertexArrayFormat.I @@ -0,0 +1,121 @@ +// Filename: qpgeomVertexArrayFormat.I +// Created by: drose (06Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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: qpGeomVertexArrayFormat::is_registered +// Access: Published +// Description: Returns true if this format has been registered, +// false if it has not. It may not be used for a Geom +// until it has been registered, but once registered, it +// may no longer be modified. +//////////////////////////////////////////////////////////////////// +INLINE bool qpGeomVertexArrayFormat:: +is_registered() const { + return _is_registered; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::get_stride +// Access: Published +// Description: Returns the total number of bytes reserved in the +// array for each vertex. +//////////////////////////////////////////////////////////////////// +INLINE int qpGeomVertexArrayFormat:: +get_stride() const { + return _stride; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::set_stride +// Access: Published +// Description: Changes the total number of bytes reserved in the +// array for each vertex. +//////////////////////////////////////////////////////////////////// +INLINE void qpGeomVertexArrayFormat:: +set_stride(int stride) { + nassertv(!_is_registered); + _stride = stride; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::get_total_bytes +// Access: Published +// Description: Returns the total number of bytes used by the data +// types within the format, including gaps between +// elements. +//////////////////////////////////////////////////////////////////// +INLINE int qpGeomVertexArrayFormat:: +get_total_bytes() const { + return _total_bytes; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::get_pad_to +// Access: Published +// Description: Returns the byte divisor to which the data record +// must be padded to meet hardware limitations. For +// instance, if this is 4, the stride will be +// automatically rounded up to the next multiple of 4 +// bytes. +//////////////////////////////////////////////////////////////////// +INLINE int qpGeomVertexArrayFormat:: +get_pad_to() const { + return _pad_to; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::get_num_data_types +// Access: Published +// Description: Returns the number of different data types in the +// specification. +//////////////////////////////////////////////////////////////////// +INLINE int qpGeomVertexArrayFormat:: +get_num_data_types() const { + return (int)_data_types.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::get_data_type +// Access: Published +// Description: Returns the ith data types of the specification. +//////////////////////////////////////////////////////////////////// +INLINE const qpGeomVertexDataType *qpGeomVertexArrayFormat:: +get_data_type(int i) const { + nassertr(i >= 0 && i < (int)_data_types.size(), NULL); + consider_sort_data_types(); + return _data_types[i]; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::consider_sort_data_types +// Access: Private +// Description: Resorts the _data_types vector if necessary. +//////////////////////////////////////////////////////////////////// +INLINE void qpGeomVertexArrayFormat:: +consider_sort_data_types() const { + if (_data_types_unsorted) { + ((qpGeomVertexArrayFormat *)this)->sort_data_types(); + } +} + +INLINE ostream & +operator << (ostream &out, const qpGeomVertexArrayFormat &obj) { + obj.output(out); + return out; +} diff --git a/panda/src/gobj/qpgeomVertexArrayFormat.cxx b/panda/src/gobj/qpgeomVertexArrayFormat.cxx new file mode 100644 index 0000000000..733a8b31eb --- /dev/null +++ b/panda/src/gobj/qpgeomVertexArrayFormat.cxx @@ -0,0 +1,556 @@ +// Filename: qpgeomVertexArrayFormat.cxx +// Created by: drose (06Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "qpgeomVertexFormat.h" +#include "qpgeomVertexDataType.h" +#include "qpgeomVertexData.h" +#include "indent.h" +#include "bamReader.h" +#include "bamWriter.h" +#include "indirectLess.h" + +TypeHandle qpGeomVertexArrayFormat::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomVertexArrayFormat:: +qpGeomVertexArrayFormat() : + _is_registered(false), + _stride(0), + _total_bytes(0), + _pad_to(1), + _data_types_unsorted(false) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomVertexArrayFormat:: +qpGeomVertexArrayFormat(const InternalName *name0, int num_components0, + qpGeomVertexDataType::NumericType numeric_type0) : + _is_registered(false), + _stride(0), + _total_bytes(0), + _pad_to(1), + _data_types_unsorted(false) +{ + add_data_type(name0, num_components0, numeric_type0); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomVertexArrayFormat:: +qpGeomVertexArrayFormat(const InternalName *name0, int num_components0, + qpGeomVertexDataType::NumericType numeric_type0, + const InternalName *name1, int num_components1, + qpGeomVertexDataType::NumericType numeric_type1) : + _is_registered(false), + _stride(0), + _total_bytes(0), + _pad_to(1), + _data_types_unsorted(false) +{ + add_data_type(name0, num_components0, numeric_type0); + add_data_type(name1, num_components1, numeric_type1); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomVertexArrayFormat:: +qpGeomVertexArrayFormat(const InternalName *name0, int num_components0, + qpGeomVertexDataType::NumericType numeric_type0, + const InternalName *name1, int num_components1, + qpGeomVertexDataType::NumericType numeric_type1, + const InternalName *name2, int num_components2, + qpGeomVertexDataType::NumericType numeric_type2) : + _is_registered(false), + _stride(0), + _total_bytes(0), + _pad_to(1), + _data_types_unsorted(false) +{ + add_data_type(name0, num_components0, numeric_type0); + add_data_type(name1, num_components1, numeric_type1); + add_data_type(name2, num_components2, numeric_type2); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomVertexArrayFormat:: +qpGeomVertexArrayFormat(const InternalName *name0, int num_components0, + qpGeomVertexDataType::NumericType numeric_type0, + const InternalName *name1, int num_components1, + qpGeomVertexDataType::NumericType numeric_type1, + const InternalName *name2, int num_components2, + qpGeomVertexDataType::NumericType numeric_type2, + const InternalName *name3, int num_components3, + qpGeomVertexDataType::NumericType numeric_type3) : + _is_registered(false), + _stride(0), + _total_bytes(0), + _pad_to(1), + _data_types_unsorted(false) +{ + add_data_type(name0, num_components0, numeric_type0); + add_data_type(name1, num_components1, numeric_type1); + add_data_type(name2, num_components2, numeric_type2); + add_data_type(name3, num_components3, numeric_type3); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::Copy Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomVertexArrayFormat:: +qpGeomVertexArrayFormat(const qpGeomVertexArrayFormat ©) : + _is_registered(false), + _stride(copy._stride), + _total_bytes(copy._total_bytes), + _pad_to(copy._pad_to), + _data_types_unsorted(copy._data_types_unsorted) +{ + DataTypes::const_iterator dti; + for (dti = copy._data_types.begin(); dti != copy._data_types.end(); ++dti) { + add_data_type(*(*dti)); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::Copy Assignment Operator +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void qpGeomVertexArrayFormat:: +operator = (const qpGeomVertexArrayFormat ©) { + nassertv(!_is_registered); + _stride = copy._stride; + _total_bytes = copy._total_bytes; + _pad_to = copy._pad_to; + + _data_types.clear(); + _data_types_by_name.clear(); + _data_types_unsorted = false; + DataTypes::const_iterator dti; + for (dti = copy._data_types.begin(); dti != copy._data_types.end(); ++dti) { + add_data_type(*(*dti)); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::Destructor +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomVertexArrayFormat:: +~qpGeomVertexArrayFormat() { + // Once registered, these things should not be deallocated. + nassertv(!_is_registered); + + DataTypes::iterator dti; + for (dti = _data_types.begin(); dti != _data_types.end(); ++dti) { + delete (*dti); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::add_data_type +// Access: Published +// Description: Adds a new data type to the specification. This is a +// table of per-vertex floating-point numbers such as +// "vertex" or "normal"; you must specify where in each +// record the table starts, and how many components +// (dimensions) exist per vertex. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexArrayFormat:: +add_data_type(const InternalName *name, int num_components, + qpGeomVertexDataType::NumericType numeric_type, int start) { + if (start < 0) { + start = _total_bytes; + + qpGeomVertexDataType temp_data_type(name, num_components, numeric_type, 0); + int pad_to = temp_data_type.get_component_bytes(); + start = ((start + pad_to - 1) / pad_to) * pad_to; + } + + add_data_type(qpGeomVertexDataType(name, num_components, + numeric_type, start)); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::add_data_type +// Access: Published +// Description: Adds a new data type to the specification. This is a +// table of per-vertex floating-point numbers such as +// "vertex" or "normal"; you must specify where in each +// record the table starts, and how many components +// (dimensions) exist per vertex. +// +// Adding a data type with the same name as a previous +// type, or that overlaps with one or more previous +// types, quietly removes the previous type(s). +//////////////////////////////////////////////////////////////////// +void qpGeomVertexArrayFormat:: +add_data_type(const qpGeomVertexDataType &data_type) { + nassertv(!_is_registered); + + // Make sure there isn't already a data type with this name. + remove_data_type(data_type.get_name()); + + // Also make sure there aren't any data types that overlap with this + // one. + const qpGeomVertexDataType *orig_data_type = get_data_type(data_type.get_start(), data_type.get_total_bytes()); + while (orig_data_type != (const qpGeomVertexDataType *)NULL) { + remove_data_type(orig_data_type->get_name()); + orig_data_type = get_data_type(data_type.get_start(), data_type.get_total_bytes()); + } + + _total_bytes = max(_total_bytes, data_type.get_start() + data_type.get_total_bytes()); + _pad_to = max(_pad_to, data_type.get_component_bytes()); + _stride = max(_stride, ((_total_bytes + _pad_to - 1) / _pad_to) * _pad_to); + + qpGeomVertexDataType *new_data_type = new qpGeomVertexDataType(data_type); + + if (!_data_types.empty() && *new_data_type < *_data_types.back()) { + _data_types_unsorted = true; + } + + _data_types.push_back(new_data_type); + _data_types_by_name.insert(DataTypesByName::value_type(new_data_type->get_name(), new_data_type)); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::remove_data_type +// Access: Published +// Description: Removes the data type with the indicated name, if +// any. This leaves a gap in the byte structure. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexArrayFormat:: +remove_data_type(const InternalName *name) { + nassertv(!_is_registered); + DataTypesByName::iterator ni; + ni = _data_types_by_name.find(name); + if (ni != _data_types_by_name.end()) { + qpGeomVertexDataType *data_type = (*ni).second; + _data_types_by_name.erase(ni); + + DataTypes::iterator dti; + dti = find(_data_types.begin(), _data_types.end(), data_type); + nassertv(dti != _data_types.end()); + _data_types.erase(dti); + + delete data_type; + + // Maybe we just removed the tail data_type. If that's so, we + // should recompute _total_bytes to reflect the new tail. + if (_data_types.empty()) { + _total_bytes = 0; + } else { + consider_sort_data_types(); + qpGeomVertexDataType *last = _data_types.back(); + _total_bytes = last->get_start() + last->get_total_bytes(); + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::clear_data_types +// Access: Published +// Description: Removes all data types previously added, sets the +// stride to zero, and prepares to start over. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexArrayFormat:: +clear_data_types() { + _data_types.clear(); + _data_types_by_name.clear(); + _data_types_unsorted = false; + _stride = 0; + _total_bytes = 0; + _pad_to = 1; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::get_data_type +// Access: Published +// Description: Returns the specification with the indicated name, or +// NULL if the name is not used. +//////////////////////////////////////////////////////////////////// +const qpGeomVertexDataType *qpGeomVertexArrayFormat:: +get_data_type(const InternalName *name) const { + DataTypesByName::const_iterator ni; + ni = _data_types_by_name.find(name); + if (ni != _data_types_by_name.end()) { + return (*ni).second; + } + return NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::get_data_type +// Access: Published +// Description: Returns the first specification that overlaps with +// any of the indicated bytes in the range, or NULL if +// none do. +//////////////////////////////////////////////////////////////////// +const qpGeomVertexDataType *qpGeomVertexArrayFormat:: +get_data_type(int start_byte, int num_bytes) const { + consider_sort_data_types(); + DataTypes::const_iterator dti; + for (dti = _data_types.begin(); dti != _data_types.end(); ++dti) { + const qpGeomVertexDataType *data_type = (*dti); + if (data_type->overlaps_with(start_byte, num_bytes)) { + return data_type; + } + } + + return NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::is_data_subset_of +// Access: Published +// Description: Returns true if all of the fields in this array +// format are also present and equivalent in the other +// array format, and in the same byte positions, and the +// stride is the same. That is, true if this format can +// share the same data pointer as the other format (with +// possibly some unused gaps). +//////////////////////////////////////////////////////////////////// +bool qpGeomVertexArrayFormat:: +is_data_subset_of(const qpGeomVertexArrayFormat &other) const { + if (_data_types.size() > other._data_types.size() || + get_stride() != other.get_stride()) { + return false; + } + + consider_sort_data_types(); + other.consider_sort_data_types(); + size_t i = 0; + size_t j = 0; + while (i < _data_types.size() && j < other._data_types.size()) { + if (*_data_types[i] == *other._data_types[j]) { + ++i; + } + ++j; + } + + // If we reached the end of our list, all fields matched. + return (i == _data_types.size()); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::output +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void qpGeomVertexArrayFormat:: +output(ostream &out) const { + DataTypes::const_iterator dti; + out << "["; + for (dti = _data_types.begin(); dti != _data_types.end(); ++dti) { + const qpGeomVertexDataType *data_type = (*dti); + out << " " << *data_type; + } + out << " ]"; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::write +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void qpGeomVertexArrayFormat:: +write(ostream &out, int indent_level) const { + indent(out, indent_level) + << "Array format (stride = " << get_stride() << "):\n"; + consider_sort_data_types(); + DataTypes::const_iterator dti; + for (dti = _data_types.begin(); dti != _data_types.end(); ++dti) { + const qpGeomVertexDataType *data_type = (*dti); + indent(out, indent_level + 2) + << *data_type << " start at " << data_type->get_start() << "\n"; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::write_with_data +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void qpGeomVertexArrayFormat:: +write_with_data(ostream &out, int indent_level, + const qpGeomVertexData *data, int array_index) const { + consider_sort_data_types(); + int num_vertices = data->get_num_vertices(); + for (int i = 0; i < num_vertices; i++) { + indent(out, indent_level) + << "vertex index " << i << ":\n"; + DataTypes::const_iterator dti; + for (dti = _data_types.begin(); dti != _data_types.end(); ++dti) { + const qpGeomVertexDataType *data_type = (*dti); + int num_values = min(data_type->get_num_values(), 4); + float data_values[4]; + data->get_data(array_index, data_type, i, data_values, num_values); + + indent(out, indent_level + 2) + << *data_type->get_name(); + for (int v = 0; v < num_values; v++) { + out << " " << data_values[v]; + } + out << "\n"; + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::compare_to +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +int qpGeomVertexArrayFormat:: +compare_to(const qpGeomVertexArrayFormat &other) const { + if (_stride != other._stride) { + return _stride - other._stride; + } + if (_total_bytes != other._total_bytes) { + return _total_bytes - other._total_bytes; + } + if (_pad_to != other._pad_to) { + return _pad_to - other._pad_to; + } + if (_data_types.size() != other._data_types.size()) { + return (int)_data_types.size() - (int)other._data_types.size(); + } + consider_sort_data_types(); + other.consider_sort_data_types(); + for (size_t i = 0; i < _data_types.size(); i++) { + int compare = _data_types[i]->compare_to(*other._data_types[i]); + if (compare != 0) { + return compare; + } + } + + return 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::sort_data_types +// Access: Private +// Description: Resorts the _data_types vector so that the data types +// are listed in the same order they appear in the +// record. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexArrayFormat:: +sort_data_types() { + sort(_data_types.begin(), _data_types.end(), IndirectLess()); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::do_register +// Access: Private +// Description: Called internally when the format is registered. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexArrayFormat:: +do_register() { + nassertv(!_is_registered); + _is_registered = true; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::register_with_read_factory +// Access: Public, Static +// Description: Tells the BamReader how to create objects of type +// qpGeomVertexArrayFormat. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexArrayFormat:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexArrayFormat:: +write_datagram(BamWriter *manager, Datagram &dg) { + TypedWritableReferenceCount::write_datagram(manager, dg); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::complete_pointers +// Access: Public, Virtual +// Description: Receives an array of pointers, one for each time +// manager->read_pointer() was called in fillin(). +// Returns the number of pointers processed. +//////////////////////////////////////////////////////////////////// +int qpGeomVertexArrayFormat:: +complete_pointers(TypedWritable **p_list, BamReader *manager) { + int pi = TypedWritableReferenceCount::complete_pointers(p_list, manager); + + return pi; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type qpGeomVertexArrayFormat is +// encountered in the Bam file. It should create the +// qpGeomVertexArrayFormat and extract its information from +// the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *qpGeomVertexArrayFormat:: +make_from_bam(const FactoryParams ¶ms) { + qpGeomVertexArrayFormat *object = new qpGeomVertexArrayFormat; + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + object->fillin(scan, manager); + + return object; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::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 qpGeomVertexArrayFormat. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexArrayFormat:: +fillin(DatagramIterator &scan, BamReader *manager) { + TypedWritableReferenceCount::fillin(scan, manager); +} diff --git a/panda/src/gobj/qpgeomVertexArrayFormat.h b/panda/src/gobj/qpgeomVertexArrayFormat.h new file mode 100644 index 0000000000..e3b1f98973 --- /dev/null +++ b/panda/src/gobj/qpgeomVertexArrayFormat.h @@ -0,0 +1,162 @@ +// Filename: qpgeomVertexArrayFormat.h +// Created by: drose (06Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 qpGEOMVERTEXARRAYFORMAT_H +#define qpGEOMVERTEXARRAYFORMAT_H + +#include "pandabase.h" +#include "typedWritableReferenceCount.h" +#include "qpgeomVertexDataType.h" +#include "pvector.h" +#include "pmap.h" + +class qpGeomVertexFormat; +class qpGeomVertexData; +class InternalName; +class FactoryParams; + +//////////////////////////////////////////////////////////////////// +// Class : qpGeomVertexArrayFormat +// Description : This describes the structure of a single array within +// a Geom data. See GeomVertexFormat for the parent +// class which collects together all of the individual +// GeomVertexArrayFormat objects. +// +// A particular array may include any number of standard +// or user-defined data types. All data types consist +// of a sequence of one or more floating-point numbers; +// the semantic meaning of the data type is implicit +// from its name. The standard array types are named +// "vertex", "normal", "texcoord", "color", "tangent", +// and "binormal"; other data may be stored simply by +// choosing a different name. +// +// This is part of the experimental Geom rewrite. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA qpGeomVertexArrayFormat : public TypedWritableReferenceCount { +PUBLISHED: + qpGeomVertexArrayFormat(); + qpGeomVertexArrayFormat(const qpGeomVertexArrayFormat ©); + qpGeomVertexArrayFormat(const InternalName *name0, int num_components0, + qpGeomVertexDataType::NumericType numeric_type0); + qpGeomVertexArrayFormat(const InternalName *name0, int num_components0, + qpGeomVertexDataType::NumericType numeric_type0, + const InternalName *name1, int num_components1, + qpGeomVertexDataType::NumericType numeric_type1); + qpGeomVertexArrayFormat(const InternalName *name0, int num_components0, + qpGeomVertexDataType::NumericType numeric_type0, + const InternalName *name1, int num_components1, + qpGeomVertexDataType::NumericType numeric_type1, + const InternalName *name2, int num_components2, + qpGeomVertexDataType::NumericType numeric_type2); + qpGeomVertexArrayFormat(const InternalName *name0, int num_components0, + qpGeomVertexDataType::NumericType numeric_type0, + const InternalName *name1, int num_components1, + qpGeomVertexDataType::NumericType numeric_type1, + const InternalName *name2, int num_components2, + qpGeomVertexDataType::NumericType numeric_type2, + const InternalName *name3, int num_components3, + qpGeomVertexDataType::NumericType numeric_type3); + void operator = (const qpGeomVertexArrayFormat ©); + ~qpGeomVertexArrayFormat(); + + INLINE bool is_registered() const; + + INLINE int get_stride() const; + INLINE void set_stride(int stride); + + INLINE int get_total_bytes() const; + INLINE int get_pad_to() const; + + void add_data_type(const InternalName *name, int num_components, + qpGeomVertexDataType::NumericType numeric_type, + int start = -1); + void add_data_type(const qpGeomVertexDataType &data_type); + void remove_data_type(const InternalName *name); + void clear_data_types(); + + INLINE int get_num_data_types() const; + INLINE const qpGeomVertexDataType *get_data_type(int i) const; + + const qpGeomVertexDataType *get_data_type(const InternalName *name) const; + const qpGeomVertexDataType *get_data_type(int start_byte, int num_bytes) const; + + bool is_data_subset_of(const qpGeomVertexArrayFormat &other) const; + + void output(ostream &out) const; + void write(ostream &out, int indent_level = 0) const; + void write_with_data(ostream &out, int indent_level, + const qpGeomVertexData *data, int array_index) const; + +public: + int compare_to(const qpGeomVertexArrayFormat &other) const; + +private: + INLINE void consider_sort_data_types() const; + void sort_data_types(); + void do_register(); + + bool _is_registered; + const qpGeomVertexFormat *_root_format; + const qpGeomVertexFormat *_parent_format; + + int _stride; + int _total_bytes; + int _pad_to; + + typedef pvector DataTypes; + DataTypes _data_types; + bool _data_types_unsorted; + + typedef pmap DataTypesByName; + DataTypesByName _data_types_by_name; + +public: + static void register_with_read_factory(); + virtual void write_datagram(BamWriter *manager, Datagram &dg); + virtual int complete_pointers(TypedWritable **plist, BamReader *manager); + +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() { + TypedWritableReferenceCount::init_type(); + register_type(_type_handle, "qpGeomVertexArrayFormat", + TypedWritableReferenceCount::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; + + friend class qpGeomVertexFormat; +}; + +INLINE ostream &operator << (ostream &out, const qpGeomVertexArrayFormat &obj); + +#include "qpgeomVertexArrayFormat.I" + +#endif diff --git a/panda/src/gobj/qpgeomVertexData.I b/panda/src/gobj/qpgeomVertexData.I new file mode 100644 index 0000000000..8c748b540e --- /dev/null +++ b/panda/src/gobj/qpgeomVertexData.I @@ -0,0 +1,82 @@ +// Filename: qpgeomVertexData.I +// Created by: drose (06Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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: qpGeomVertexData::get_format +// Access: Published +// Description: Returns a pointer to the GeomVertexFormat structure +// that defines this data. +//////////////////////////////////////////////////////////////////// +INLINE const qpGeomVertexFormat *qpGeomVertexData:: +get_format() const { + return _format; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::get_num_arrays +// Access: Published +// Description: Returns the number of individual arrays stored within +// the data. This must match +// get_format()->get_num_arrays(). +//////////////////////////////////////////////////////////////////// +INLINE int qpGeomVertexData:: +get_num_arrays() const { + CDReader cdata(_cycler); + return cdata->_arrays.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::get_array_data +// Access: Published +// Description: Returns a const pointer to the vertex data for the +// indicated array, for application code to directly +// examine (but not modify) the underlying vertex data. +//////////////////////////////////////////////////////////////////// +INLINE CPTA_uchar qpGeomVertexData:: +get_array_data(int array) const { + CDReader cdata(_cycler); + nassertr(array >= 0 && array < (int)cdata->_arrays.size(), CPTA_uchar()); + return cdata->_arrays[array]; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::CData::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE qpGeomVertexData::CData:: +CData() { +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::CData::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE qpGeomVertexData::CData:: +CData(const qpGeomVertexData::CData ©) : + _arrays(copy._arrays) +{ +} + +INLINE ostream & +operator << (ostream &out, const qpGeomVertexData &obj) { + obj.output(out); + return out; +} diff --git a/panda/src/gobj/qpgeomVertexData.cxx b/panda/src/gobj/qpgeomVertexData.cxx new file mode 100644 index 0000000000..2a08851232 --- /dev/null +++ b/panda/src/gobj/qpgeomVertexData.cxx @@ -0,0 +1,650 @@ +// Filename: qpgeomVertexData.cxx +// Created by: drose (06Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "qpgeomVertexData.h" +#include "bamReader.h" +#include "bamWriter.h" +#include "pset.h" + +TypeHandle qpGeomVertexData::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::Default Constructor +// Access: Private +// Description: Constructs an invalid object. This is only used when +// reading from the bam file. +//////////////////////////////////////////////////////////////////// +qpGeomVertexData:: +qpGeomVertexData() { +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomVertexData:: +qpGeomVertexData(const qpGeomVertexFormat *format) : + _format(format) +{ + nassertv(_format->is_registered()); + + // Create some empty arrays as required by the format. + CDWriter cdata(_cycler); + cdata->_arrays.insert(cdata->_arrays.end(), _format->get_num_arrays(), + PTA_uchar()); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::Copy Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomVertexData:: +qpGeomVertexData(const qpGeomVertexData ©) : + TypedWritableReferenceCount(copy), + _format(copy._format), + _cycler(copy._cycler) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::Copy Assignment Operator +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void qpGeomVertexData:: +operator = (const qpGeomVertexData ©) { + TypedWritableReferenceCount::operator = (copy); + _format = copy._format; + _cycler = copy._cycler; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::Destructor +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomVertexData:: +~qpGeomVertexData() { +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::get_num_vertices +// Access: Published +// Description: Returns the number of vertices stored within all the +// arrays. All arrays store data for the same n +// vertices. +//////////////////////////////////////////////////////////////////// +int qpGeomVertexData:: +get_num_vertices() const { + CDReader cdata(_cycler); + nassertr(_format->get_num_arrays() == (int)cdata->_arrays.size(), 0); + if (_format->get_num_arrays() == 0) { + // No arrays means no vertices. Weird but legal. + return 0; + } + + // Look up the answer on the first array (since any array will do). + int stride = _format->get_array(0)->get_stride(); + return cdata->_arrays[0].size() / stride; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::set_num_vertices +// Access: Published +// Description: Sets the length of the array to n vertices in all of +// the various arrays (presumably by adding vertices). +// The new vertex data is uninitialized. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexData:: +set_num_vertices(int n) { + CDWriter cdata(_cycler); + nassertv(_format->get_num_arrays() == (int)cdata->_arrays.size()); + + for (size_t i = 0; i < cdata->_arrays.size(); i++) { + int stride = _format->get_array(i)->get_stride(); + int delta = n - (cdata->_arrays[i].size() / stride); + + if (delta != 0) { + if (cdata->_arrays[i].get_ref_count() > 1) { + // Copy-on-write: the array is already reffed somewhere else, + // so we're just going to make a copy. + PTA_uchar new_array; + new_array.reserve(n * stride); + new_array.insert(new_array.end(), n * stride, uchar()); + memcpy(new_array, cdata->_arrays[i], + min((size_t)(n * stride), cdata->_arrays[i].size())); + cdata->_arrays[i] = new_array; + + } else { + // We've got the only reference to the array, so we can change + // it directly. + if (delta > 0) { + cdata->_arrays[i].insert(cdata->_arrays[i].end(), delta * stride, uchar()); + + } else { + cdata->_arrays[i].erase(cdata->_arrays[i].begin() + n * stride, + cdata->_arrays[i].end()); + } + } + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::clear_vertices +// Access: Published +// Description: Removes all of the vertices from the arrays; +// functionally equivalent to set_num_vertices(0) (but +// faster). +//////////////////////////////////////////////////////////////////// +void qpGeomVertexData:: +clear_vertices() { + CDWriter cdata(_cycler); + nassertv(_format->get_num_arrays() == (int)cdata->_arrays.size()); + + Arrays::iterator ai; + for (ai = cdata->_arrays.begin(); + ai != cdata->_arrays.end(); + ++ai) { + (*ai).clear(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::modify_array_data +// Access: Published +// Description: Returns a modifiable pointer to the indicated vertex +// array, so that application code may directly +// manipulate the vertices. You should avoid changing +// the length of this array, since all of the arrays +// should be kept in sync--use add_vertices() instead. +//////////////////////////////////////////////////////////////////// +PTA_uchar qpGeomVertexData:: +modify_array_data(int array) { + // Perform copy-on-write: if the reference count on the vertex data + // is greater than 1, assume some other GeomVertexData has the same + // pointer, so make a copy of it first. + + CDWriter cdata(_cycler); + nassertr(array >= 0 && array < (int)cdata->_arrays.size(), PTA_uchar()); + + if (cdata->_arrays[array].get_ref_count() > 1) { + PTA_uchar orig_data = cdata->_arrays[array]; + cdata->_arrays[array] = PTA_uchar(); + cdata->_arrays[array].v() = orig_data.v(); + } + return cdata->_arrays[array]; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::set_array_data +// Access: Published +// Description: Replaces the indicated vertex data array with +// a completely new array. You should be careful that +// the new array has the same length as the old one, +// unless you know what you are doing. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexData:: +set_array_data(int array, PTA_uchar array_data) { + CDWriter cdata(_cycler); + nassertv(array >= 0 && array < (int)cdata->_arrays.size()); + cdata->_arrays[array] = array_data; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::set_data +// Access: Published +// Description: Sets the nth vertex to a particular value. Query the +// format to get the array index and data_type +// parameters for the particular data type you want to +// set. +// +// This flavor of set_data() accepts a generic float +// array and a specific number of dimensions. The new +// data will be copied from the num_values elements +// of data. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexData:: +set_data(int array, const qpGeomVertexDataType *data_type, + int vertex, const float *data, int num_values) { + int stride = _format->get_array(array)->get_stride(); + int element = vertex * stride + data_type->get_start(); + + { + CDReader cdata(_cycler); + int array_size = (int)cdata->_arrays[array].size(); + if (element + data_type->get_total_bytes() > array_size) { + // Whoops, we need more vertices! + set_num_vertices(vertex + 1); + } + } + + PTA_uchar array_data = modify_array_data(array); + nassertv(element >= 0 && element + data_type->get_total_bytes() <= (int)array_data.size()); + + switch (data_type->get_numeric_type()) { + case qpGeomVertexDataType::NT_uint8: + { + nassertv(num_values <= data_type->get_num_values()); + for (int i = 0; i < num_values; i++) { + int value = (int)(data[i] * 255.0f); + *(unsigned char *)&array_data[element] = value; + element += 1; + } + } + break; + + case qpGeomVertexDataType::NT_packed_argb: + { + nassertv(num_values == 4); + *(PN_uint32 *)&array_data[element] = pack_argb(data); + } + break; + + case qpGeomVertexDataType::NT_float: + nassertv(num_values == data_type->get_num_values()); + memcpy(&array_data[element], data, data_type->get_total_bytes()); + break; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::get_data +// Access: Published +// Description: Returns the data associated with the nth vertex for a +// particular value. Query the format to get the array +// index and data_type parameters for the particular +// data type you want to get. +// +// This flavor of get_data() copies its data into a +// generic float array. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexData:: +get_data(int array, const qpGeomVertexDataType *data_type, + int vertex, float *data, int num_values) const { + CPTA_uchar array_data = get_array_data(array); + int stride = _format->get_array(array)->get_stride(); + int element = vertex * stride + data_type->get_start(); + nassertv(element >= 0 && element + data_type->get_total_bytes() <= (int)array_data.size()); + + switch (data_type->get_numeric_type()) { + case qpGeomVertexDataType::NT_uint8: + { + nassertv(num_values <= data_type->get_num_values()); + for (int i = 0; i < num_values; i++) { + int value = *(unsigned char *)&array_data[element]; + element += 1; + data[i] = (float)value / 255.0f; + } + } + break; + + case qpGeomVertexDataType::NT_packed_argb: + { + nassertv(num_values == 4); + unpack_argb(data, *(PN_uint32 *)&array_data[element]); + } + break; + + case qpGeomVertexDataType::NT_float: + nassertv(num_values <= data_type->get_num_values()); + memcpy(data, &array_data[element], num_values * sizeof(PN_float32)); + break; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::convert_to +// Access: Published +// Description: Matches up the data types of this format with the +// data types of the other format by name, and copies +// the data vertex-by-vertex to a new set of data arrays +// in the new format. +//////////////////////////////////////////////////////////////////// +PT(qpGeomVertexData) qpGeomVertexData:: +convert_to(const qpGeomVertexFormat *new_format) const { + int num_vertices = get_num_vertices(); + + PT(qpGeomVertexData) new_data = new qpGeomVertexData(new_format); + + pset done_arrays; + + int num_arrays = _format->get_num_arrays(); + int array; + + // First, check to see if any arrays can be simply appropriated for + // the new format, without changing the data. + for (array = 0; array < num_arrays; ++array) { + const qpGeomVertexArrayFormat *array_format = + _format->get_array(array); + + bool array_done = false; + + int new_num_arrays = new_format->get_num_arrays(); + for (int new_array = 0; + new_array < new_num_arrays && !array_done; + ++new_array) { + const qpGeomVertexArrayFormat *new_array_format = + new_format->get_array(new_array); + if (new_array_format->is_data_subset_of(*array_format)) { + // Great! Just use the same data for this one. + new_data->set_array_data(new_array, (PTA_uchar &)get_array_data(array)); + array_done = true; + + done_arrays.insert(new_array); + } + } + } + + // Now make sure the arrays we didn't share are all filled in. + new_data->set_num_vertices(num_vertices); + + // Now go back through and copy any data that's left over. + for (array = 0; array < num_arrays; ++array) { + CPTA_uchar array_data = get_array_data(array); + const qpGeomVertexArrayFormat *array_format = + _format->get_array(array); + int num_data_types = array_format->get_num_data_types(); + for (int di = 0; di < num_data_types; ++di) { + const qpGeomVertexDataType *data_type = array_format->get_data_type(di); + + int new_array = new_format->get_array_with(data_type->get_name()); + if (new_array >= 0 && done_arrays.count(new_array) == 0) { + // The data type exists in the new format; we have to copy it. + PTA_uchar new_array_data = new_data->modify_array_data(new_array); + const qpGeomVertexArrayFormat *new_array_format = + new_format->get_array(new_array); + const qpGeomVertexDataType *new_data_type = + new_array_format->get_data_type(data_type->get_name()); + + new_data_type->copy_records + (new_array_data + new_data_type->get_start(), + new_array_format->get_stride(), + array_data + data_type->get_start(), array_format->get_stride(), + data_type, num_vertices); + } + } + } + + return new_data; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::output +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void qpGeomVertexData:: +output(ostream &out) const { + out << get_num_vertices() << ": " << *get_format(); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::write +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void qpGeomVertexData:: +write(ostream &out, int indent_level) const { + _format->write_with_data(out, indent_level, this); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::get_array_info +// Access: Public +// Description: A convenience function to collect together the +// important parts of the array data for rendering. +// Given the name of a data type, fills in the start of +// the array, the number of floats for each vertex, the +// starting bytes number, and the number of bytes to +// increment for each consecutive vertex. +// +// The return value is true if the named array data +// exists in this record, or false if it does not (in +// which case none of the output parameters are valid). +//////////////////////////////////////////////////////////////////// +bool qpGeomVertexData:: +get_array_info(const InternalName *name, CPTA_uchar &array_data, + int &num_components, + qpGeomVertexDataType::NumericType &numeric_type, + int &start, int &stride) const { + int array_index; + const qpGeomVertexDataType *data_type; + if (_format->get_array_info(name, array_index, data_type)) { + CDReader cdata(_cycler); + array_data = cdata->_arrays[array_index]; + num_components = data_type->get_num_components(); + numeric_type = data_type->get_numeric_type(); + start = data_type->get_start(); + stride = _format->get_array(array_index)->get_stride(); + return true; + } + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::to_vec2 +// Access: Public, Static +// Description: Converts a data element of arbitrary number of +// dimensions (1 - 4) into a vec2 in a sensible way. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexData:: +to_vec2(LVecBase2f &vec, const float *data, int num_values) { + switch (num_values) { + case 1: + vec.set(data[0], 0.0f); + break; + + case 2: + case 3: + vec.set(data[0], data[1]); + break; + + default: // 4 or more. + vec.set(data[0] / data[3], data[1] / data[3]); + break; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::to_vec3 +// Access: Public, Static +// Description: Converts a data element of arbitrary number of +// dimensions (1 - 4) into a vec3 in a sensible way. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexData:: +to_vec3(LVecBase3f &vec, const float *data, int num_values) { + switch (num_values) { + case 1: + vec.set(data[0], 0.0f, 0.0f); + break; + + case 2: + vec.set(data[0], data[1], 0.0f); + break; + + case 3: + vec.set(data[0], data[1], data[2]); + break; + + default: // 4 or more. + vec.set(data[0] / data[3], data[1] / data[3], data[2] / data[3]); + break; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::to_vec4 +// Access: Public, Static +// Description: Converts a data element of arbitrary number of +// dimensions (1 - 4) into a vec4 in a sensible way. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexData:: +to_vec4(LVecBase4f &vec, const float *data, int num_values) { + switch (num_values) { + case 1: + vec.set(data[0], 0.0f, 0.0f, 1.0f); + break; + + case 2: + vec.set(data[0], data[1], 0.0f, 1.0f); + break; + + case 3: + vec.set(data[0], data[1], data[2], 1.0f); + break; + + default: // 4 or more. + vec.set(data[0], data[1], data[2], data[3]); + break; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::pack_argb +// Access: Public, Static +// Description: Packs four floats, stored R, G, B, A, into a +// packed_argb value. +//////////////////////////////////////////////////////////////////// +unsigned int qpGeomVertexData:: +pack_argb(const float data[4]) { + unsigned int r = ((unsigned int)(data[0] * 255.0f)) & 0xff; + unsigned int g = ((unsigned int)(data[1] * 255.0f)) & 0xff; + unsigned int b = ((unsigned int)(data[2] * 255.0f)) & 0xff; + unsigned int a = ((unsigned int)(data[3] * 255.0f)) & 0xff; + return ((a << 24) | (r << 16) | (g << 8) | b); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::unpack_argb +// Access: Public, Static +// Description: Unpacks a packed_argb value into four floats, stored +// R, G, B, A. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexData:: +unpack_argb(float data[4], unsigned int packed_argb) { + data[0] = (float)((packed_argb >> 16) & 0xff) / 255.0f; + data[1] = (float)((packed_argb >> 8) & 0xff) / 255.0f; + data[2] = (float)(packed_argb & 0xff) / 255.0f; + data[3] = (float)((packed_argb >> 24) & 0xff) / 255.0f; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::register_with_read_factory +// Access: Public, Static +// Description: Tells the BamReader how to create objects of type +// qpGeomVertexData. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexData:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexData:: +write_datagram(BamWriter *manager, Datagram &dg) { + TypedWritable::write_datagram(manager, dg); + + manager->write_cdata(dg, _cycler); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type qpGeomVertexData is encountered +// in the Bam file. It should create the qpGeomVertexData +// and extract its information from the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *qpGeomVertexData:: +make_from_bam(const FactoryParams ¶ms) { + qpGeomVertexData *object = new qpGeomVertexData; + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + object->fillin(scan, manager); + + return object; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::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 qpGeomVertexData. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexData:: +fillin(DatagramIterator &scan, BamReader *manager) { + TypedWritable::fillin(scan, manager); + + manager->read_cdata(scan, _cycler); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::CData::make_copy +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +CycleData *qpGeomVertexData::CData:: +make_copy() const { + return new CData(*this); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::CData::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexData::CData:: +write_datagram(BamWriter *manager, Datagram &dg) const { +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::CData::complete_pointers +// Access: Public, Virtual +// Description: Receives an array of pointers, one for each time +// manager->read_pointer() was called in fillin(). +// Returns the number of pointers processed. +//////////////////////////////////////////////////////////////////// +int qpGeomVertexData::CData:: +complete_pointers(TypedWritable **p_list, BamReader *manager) { + int pi = CycleData::complete_pointers(p_list, manager); + + return pi; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::CData::fillin +// Access: Public, Virtual +// Description: This internal function is called by make_from_bam to +// read in all of the relevant data from the BamFile for +// the new qpGeomVertexData. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexData::CData:: +fillin(DatagramIterator &scan, BamReader *manager) { +} diff --git a/panda/src/gobj/qpgeomVertexData.h b/panda/src/gobj/qpgeomVertexData.h new file mode 100644 index 0000000000..48336dc112 --- /dev/null +++ b/panda/src/gobj/qpgeomVertexData.h @@ -0,0 +1,155 @@ +// Filename: qpgeomVertexData.h +// Created by: drose (06Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 qpGEOMVERTEXDATA_H +#define qpGEOMVERTEXDATA_H + +#include "pandabase.h" +#include "typedWritableReferenceCount.h" +#include "qpgeomVertexFormat.h" +#include "qpgeomVertexDataType.h" +#include "internalName.h" +#include "cycleData.h" +#include "cycleDataReader.h" +#include "cycleDataWriter.h" +#include "pipelineCycler.h" +#include "pointerTo.h" +#include "pmap.h" +#include "pvector.h" +#include "pta_uchar.h" + +class FactoryParams; +class qpGeomVertexDataType; + +//////////////////////////////////////////////////////////////////// +// Class : qpGeomVertexData +// Description : This defines the actual numeric vertex data stored in +// a Geom, in the structure defined by a particular +// GeomVertexFormat object. +// +// The data consists of one or more arrays of floats. +// Typically, there will be only one array per Geom, and +// the various data types defined in the +// GeomVertexFormat will be interleaved throughout that +// array. However, it is possible to have multiple +// different arrays, with different combinations of data +// types through each one. +// +// However the data is distributed, the effect is of a +// table of vertices, with a value for each of the +// GeomVertexFormat's data types, stored for each +// vertex. +// +// This is part of the experimental Geom rewrite. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA qpGeomVertexData : public TypedWritableReferenceCount { +private: + qpGeomVertexData(); +PUBLISHED: + qpGeomVertexData(const qpGeomVertexFormat *format); + qpGeomVertexData(const qpGeomVertexData ©); + void operator = (const qpGeomVertexData ©); + virtual ~qpGeomVertexData(); + + INLINE const qpGeomVertexFormat *get_format() const; + + int get_num_vertices() const; + void set_num_vertices(int n); + void clear_vertices(); + + INLINE int get_num_arrays() const; + INLINE CPTA_uchar get_array_data(int array) const; + PTA_uchar modify_array_data(int array); + void set_array_data(int array, PTA_uchar array_data); + + void set_data(int array, const qpGeomVertexDataType *data_type, + int vertex, const float *data, int num_values); + void get_data(int array, const qpGeomVertexDataType *data_type, + int vertex, float *data, int num_values) const; + + PT(qpGeomVertexData) convert_to(const qpGeomVertexFormat *new_format) const; + + void output(ostream &out) const; + void write(ostream &out, int indent_level = 0) const; + +public: + bool get_array_info(const InternalName *name, CPTA_uchar &array_data, + int &num_components, + qpGeomVertexDataType::NumericType &numeric_type, + int &start, int &stride) const; + + static void to_vec2(LVecBase2f &vec, const float *data, int num_values); + static void to_vec3(LVecBase3f &vec, const float *data, int num_values); + static void to_vec4(LVecBase4f &vec, const float *data, int num_values); + + static unsigned int pack_argb(const float data[4]); + static void unpack_argb(float data[4], unsigned int packed_argb); + +private: + typedef pvector Arrays; + + CPT(qpGeomVertexFormat) _format; + + // This is the data that must be cycled between pipeline stages. + class EXPCL_PANDA CData : public CycleData { + public: + INLINE CData(); + INLINE CData(const CData ©); + virtual CycleData *make_copy() const; + virtual void write_datagram(BamWriter *manager, Datagram &dg) const; + virtual int complete_pointers(TypedWritable **plist, BamReader *manager); + virtual void fillin(DatagramIterator &scan, BamReader *manager); + + Arrays _arrays; + }; + + PipelineCycler _cycler; + typedef CycleDataReader CDReader; + typedef CycleDataWriter CDWriter; + +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() { + TypedWritableReferenceCount::init_type(); + register_type(_type_handle, "qpGeomVertexData", + TypedWritableReferenceCount::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; +}; + +INLINE ostream &operator << (ostream &out, const qpGeomVertexData &obj); + +#include "qpgeomVertexData.I" + +#endif diff --git a/panda/src/gobj/qpgeomVertexDataType.I b/panda/src/gobj/qpgeomVertexDataType.I new file mode 100644 index 0000000000..2d1e3351ac --- /dev/null +++ b/panda/src/gobj/qpgeomVertexDataType.I @@ -0,0 +1,221 @@ +// Filename: qpgeomVertexDataType.I +// Created by: drose (06Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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: qpGeomVertexDataType::Copy Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE qpGeomVertexDataType:: +qpGeomVertexDataType(const qpGeomVertexDataType ©) : + _name(copy._name), + _num_components(copy._num_components), + _num_values(copy._num_values), + _numeric_type(copy._numeric_type), + _start(copy._start), + _component_bytes(copy._component_bytes), + _total_bytes(copy._total_bytes) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexDataType::Copy Assignment Operator +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void qpGeomVertexDataType:: +operator = (const qpGeomVertexDataType ©) { + _name = copy._name; + _num_components = copy._num_components; + _num_values = copy._num_values; + _numeric_type = copy._numeric_type; + _start = copy._start; + _component_bytes = copy._component_bytes; + _total_bytes = copy._total_bytes; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexDataType::get_name +// Access: Published +// Description: Returns the name of this particular data field, +// e.g. "vertex" or "normal". The name may be a +// user-defined string, or it may be one of the standard +// system-defined field types. Only the system-defined +// field types are used for the actual rendering. +//////////////////////////////////////////////////////////////////// +INLINE const InternalName *qpGeomVertexDataType:: +get_name() const { + return _name; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexDataType::get_num_components +// Access: Published +// Description: Returns the number of components of each data type: +// the number of instances of the NumericType in each +// element. This is usually, but not always, the same +// thing as get_num_values(). +//////////////////////////////////////////////////////////////////// +INLINE int qpGeomVertexDataType:: +get_num_components() const { + return _num_components; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexDataType::get_num_values +// Access: Published +// Description: Returns the number of numeric values of each data +// type: the number of distinct numeric values that go +// into each element. This is usually, but not always, +// the same thing as get_num_components(); the +// difference is in the case of a composite numeric type +// like NT_packed_argb, which has four numeric values +// per component. +//////////////////////////////////////////////////////////////////// +INLINE int qpGeomVertexDataType:: +get_num_values() const { + return _num_values; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexDataType::get_numeric_type +// Access: Published +// Description: Returns the token representing the numeric type of +// the data storage. +//////////////////////////////////////////////////////////////////// +INLINE qpGeomVertexDataType::NumericType qpGeomVertexDataType:: +get_numeric_type() const { + return _numeric_type; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexDataType::get_start +// Access: Published +// Description: Returns the byte within the array record at which +// this data type starts. This can be set to non-zero +// to implement interleaved arrays. +//////////////////////////////////////////////////////////////////// +INLINE int qpGeomVertexDataType:: +get_start() const { + return _start; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexDataType::get_component_bytes +// Access: Published +// Description: Returns the number of bytes used by each component +// (that is, by one element of the numeric type). +//////////////////////////////////////////////////////////////////// +INLINE int qpGeomVertexDataType:: +get_component_bytes() const { + return _component_bytes; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexDataType::get_total_bytes +// Access: Published +// Description: Returns the number of bytes used by the data type: +// component_bytes * num_components. +//////////////////////////////////////////////////////////////////// +INLINE int qpGeomVertexDataType:: +get_total_bytes() const { + return _total_bytes; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexDataType::overlaps_with +// Access: Published +// Description: Returns true if this data type overlaps with any of +// the bytes in the indicated range, false if it does +// not. +//////////////////////////////////////////////////////////////////// +INLINE bool qpGeomVertexDataType:: +overlaps_with(int start_byte, int num_bytes) const { + return (_start < start_byte + num_bytes && + _start + _total_bytes > start_byte); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexDataType::compare_to +// Access: Public +// Description: This is used to unquify data types, and hence +// formats, for the GeomVertexFormat registry. +//////////////////////////////////////////////////////////////////// +INLINE int qpGeomVertexDataType:: +compare_to(const qpGeomVertexDataType &other) const { + if (_name != other._name) { + return _name < other._name ? -1 : 1; + } + if (_num_components != other._num_components) { + return _num_components - other._num_components; + } + if (_numeric_type != other._numeric_type) { + return (int)_numeric_type - (int)other._numeric_type; + } + if (_start != other._start) { + return _start - other._start; + } + return 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexDataType::operator == +// Access: Public +// Description: Returns true if the two data types are exactly +// equivalent, false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool qpGeomVertexDataType:: +operator == (const qpGeomVertexDataType &other) const { + return compare_to(other) == 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexDataType::operator != +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool qpGeomVertexDataType:: +operator != (const qpGeomVertexDataType &other) const { + return compare_to(other) != 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexDataType::operator < +// Access: Public +// Description: This is used to put data types in order within a +// particular GeomVertexArrayFormat. Note that it is +// *not* in the same space as operator == and operator +// !=. +//////////////////////////////////////////////////////////////////// +INLINE bool qpGeomVertexDataType:: +operator < (const qpGeomVertexDataType &other) const { + if (_start != other._start) { + return _start < other._start; + } + if (_total_bytes < other._total_bytes) { + return _total_bytes < other._total_bytes; + } + return 0; +} + +INLINE ostream & +operator << (ostream &out, const qpGeomVertexDataType &obj) { + obj.output(out); + return out; +} diff --git a/panda/src/gobj/qpgeomVertexDataType.cxx b/panda/src/gobj/qpgeomVertexDataType.cxx new file mode 100644 index 0000000000..a732dcb814 --- /dev/null +++ b/panda/src/gobj/qpgeomVertexDataType.cxx @@ -0,0 +1,309 @@ +// Filename: qpgeomVertexDataType.cxx +// Created by: drose (06Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "qpgeomVertexDataType.h" + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexDataType::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomVertexDataType:: +qpGeomVertexDataType(const InternalName *name, int num_components, + NumericType numeric_type, int start) : + _name(name), + _num_components(num_components), + _num_values(num_components), + _numeric_type(numeric_type), + _start(start) +{ + nassertv(num_components > 0 && start >= 0); + + switch (numeric_type) { + case NT_uint8: + _component_bytes = 1; + break; + + case NT_packed_argb: + _component_bytes = 4; // sizeof(PN_uint32) + _num_values *= 4; + break; + + case NT_float: + _component_bytes = 4; // sizeof(PN_float32) + break; + } + + _total_bytes = _component_bytes * _num_components; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexDataType::error named constructor +// Access: Published +// Description: Returns a data type specifically to represent an +// error condition. +//////////////////////////////////////////////////////////////////// +const qpGeomVertexDataType &qpGeomVertexDataType:: +error() { + static qpGeomVertexDataType error_result + (InternalName::get_error(), 1, NT_uint8, 0); + return error_result; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexDataType::output +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void qpGeomVertexDataType:: +output(ostream &out) const { + out << *get_name() << "(" << get_num_components() << ")"; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexDataType::copy_records +// Access: Published +// Description: Copies and converts from one data type to another. +// Copies the num_records records from the "from" +// buffer, encoded with from_type, to the "to" buffer, +// encoded with this current type, converting each one +// as necessary. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexDataType:: +copy_records(unsigned char *to, int to_stride, + const unsigned char *from, int from_stride, + const qpGeomVertexDataType *from_type, + int num_records) const { + // Temp for debugging. + static ConfigVariableBool do_copy_generic("copy-generic", false); + if (do_copy_generic) { + copy_generic(to, to_stride, from, from_stride, from_type, num_records); + return; + } + + if (get_numeric_type() == from_type->get_numeric_type() && + get_num_values() == from_type->get_num_values()) { + // An easy case. + copy_no_convert(to, to_stride, from, from_stride, from_type, num_records); + + } else if (get_numeric_type() == NT_uint8 && from_type->get_numeric_type() == NT_packed_argb && + get_num_values() == from_type->get_num_values()) { + copy_argb_to_uint8(to, to_stride, from, from_stride, from_type, num_records); + } else if (get_numeric_type() == NT_packed_argb && from_type->get_numeric_type() == NT_uint8 && + get_num_values() == from_type->get_num_values()) { + copy_uint8_to_argb(to, to_stride, from, from_stride, from_type, num_records); + } else { + copy_generic(to, to_stride, from, from_stride, from_type, num_records); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexDataType::copy_no_convert +// Access: Private +// Description: Quickly copies data without the need to convert it. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexDataType:: +copy_no_convert(unsigned char *to, int to_stride, + const unsigned char *from, int from_stride, + const qpGeomVertexDataType *from_type, + int num_records) const { + if (to_stride == _total_bytes && from_stride == _total_bytes) { + // Fantastic! It's just a linear array of this one data type. + // Copy the whole thing all at once. + memcpy(to, from, num_records * _total_bytes); + + } else { + // Ok, it's interleaved in with other data. Copy them one record + // at a time. + while (num_records > 0) { + memcpy(to, from, _total_bytes); + to += to_stride; + from += from_stride; + num_records--; + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexDataType::copy_argb_to_uint8 +// Access: Private +// Description: Converts packed_argb to uint8-based r, g, b, a. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexDataType:: +copy_argb_to_uint8(unsigned char *to, int to_stride, + const unsigned char *from, int from_stride, + const qpGeomVertexDataType *from_type, + int num_records) const { + while (num_records > 0) { + PN_uint32 packed_argb = *(const PN_uint32 *)from; + to[0] = ((packed_argb >> 16) & 0xff); + to[1] = ((packed_argb >> 8) & 0xff); + to[2] = (packed_argb & 0xff); + to[3] = ((packed_argb >> 24) & 0xff); + + to += to_stride; + from += from_stride; + num_records--; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexDataType::copy_uint8_to_argb +// Access: Private +// Description: Converts uint8-based r, g, b, a to packed_argb. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexDataType:: +copy_uint8_to_argb(unsigned char *to, int to_stride, + const unsigned char *from, int from_stride, + const qpGeomVertexDataType *from_type, + int num_records) const { + while (num_records > 0) { + PN_uint32 packed_argb = ((from[3] << 24) | (from[0] << 16) | (from[1] << 8) | from[2]); + *(PN_uint32 *)to = packed_argb; + + to += to_stride; + from += from_stride; + num_records--; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexDataType::copy_generic +// Access: Private +// Description: A more general anything-to-anything copy (somewhat +// more expensive than the above). +//////////////////////////////////////////////////////////////////// +void qpGeomVertexDataType:: +copy_generic(unsigned char *to, int to_stride, + const unsigned char *from, int from_stride, + const qpGeomVertexDataType *from_type, + int num_records) const { + int num_values_to_copy = min(get_num_values(), from_type->get_num_values()); + int num_values_to_fill = get_num_values() - num_values_to_copy; + + while (num_records > 0) { + int vi = 0; + while (vi < num_values_to_copy) { + float value = from_type->get_value(from, vi); + set_value(to, vi, value); + ++vi; + } + while (vi < num_values_to_fill) { + set_value(to, vi, 0.0f); + ++vi; + } + + to += to_stride; + from += from_stride; + num_records--; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexDataType::get_value +// Access: Private +// Description: Returns the nth value of the data type, expressed as +// a float. +//////////////////////////////////////////////////////////////////// +float qpGeomVertexDataType:: +get_value(const unsigned char *data, int n) const { + switch (get_numeric_type()) { + case NT_uint8: + return (float)data[n] / 255.0f; + + case qpGeomVertexDataType::NT_packed_argb: + { + int element = n / 4; + const PN_uint32 *int_array = (const PN_uint32 *)data; + + PN_uint32 packed_argb = int_array[element]; + switch (n % 4) { + case 0: + return (float)((packed_argb >> 16) & 0xff) / 255.0f; + case 1: + return (float)((packed_argb >> 8) & 0xff) / 255.0f; + case 2: + return (float)(packed_argb & 0xff) / 255.0f; + case 3: + return (float)((packed_argb >> 24) & 0xff) / 255.0f; + } + } + break; + + case qpGeomVertexDataType::NT_float: + { + const PN_float32 *float_array = (const PN_float32 *)data; + return float_array[n]; + } + } + + return 0.0f; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexDataType::set_value +// Access: Private +// Description: Modifies the nth value of the data type. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexDataType:: +set_value(unsigned char *data, int n, float value) const { + switch (get_numeric_type()) { + case NT_uint8: + data[n] = (int)(value * 255.0f); + break; + + case qpGeomVertexDataType::NT_packed_argb: + { + int element = n / 4; + + union { + PN_uint32 _packed_argb; + struct { + unsigned char _a; + unsigned char _r; + unsigned char _g; + unsigned char _b; + } _argb; + } color; + + PN_uint32 *int_array = (PN_uint32 *)data; + color._packed_argb = int_array[element]; + switch (n % 4) { + case 0: + color._argb._r = (int)(value * 255.0f); + break; + case 1: + color._argb._g = (int)(value * 255.0f); + break; + case 2: + color._argb._b = (int)(value * 255.0f); + break; + case 3: + color._argb._a = (int)(value * 255.0f); + break; + } + int_array[element] = color._packed_argb; + } + break; + + case qpGeomVertexDataType::NT_float: + PN_float32 *float_array = (PN_float32 *)data; + float_array[n] = value; + break; + } +} diff --git a/panda/src/gobj/qpgeomVertexDataType.h b/panda/src/gobj/qpgeomVertexDataType.h new file mode 100644 index 0000000000..28be593950 --- /dev/null +++ b/panda/src/gobj/qpgeomVertexDataType.h @@ -0,0 +1,109 @@ +// Filename: qpgeomVertexDataType.h +// Created by: drose (06Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 qpGEOMVERTEXDATATYPE_H +#define qpGEOMVERTEXDATATYPE_H + +#include "pandabase.h" +#include "internalName.h" +#include "pointerTo.h" + +//////////////////////////////////////////////////////////////////// +// Class : qpGeomVertexDataType +// Description : This defines how a single data type is interleaved +// within a vertex array stored within a Geom. The +// GeomVertexArrayFormat class maintains a list of these +// to completely define a particular array structure. +// +// This is part of the experimental Geom rewrite. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA qpGeomVertexDataType { +PUBLISHED: + enum NumericType { + NT_uint8, + NT_packed_argb, // DirectX style + NT_float, + }; + + INLINE qpGeomVertexDataType(const InternalName *name, int num_components, + NumericType numeric_type, int start); + INLINE qpGeomVertexDataType(const qpGeomVertexDataType ©); + INLINE void operator = (const qpGeomVertexDataType ©); + + static const qpGeomVertexDataType &error(); + + INLINE const InternalName *get_name() const; + INLINE int get_num_components() const; + INLINE int get_num_values() const; + INLINE NumericType get_numeric_type() const; + INLINE int get_start() const; + INLINE int get_component_bytes() const; + INLINE int get_total_bytes() const; + + INLINE bool overlaps_with(int start_byte, int num_bytes) const; + + void output(ostream &out) const; + +public: + INLINE int compare_to(const qpGeomVertexDataType &other) const; + INLINE bool operator == (const qpGeomVertexDataType &other) const; + INLINE bool operator != (const qpGeomVertexDataType &other) const; + INLINE bool operator < (const qpGeomVertexDataType &other) const; + + void copy_records(unsigned char *to, int to_stride, + const unsigned char *from, int from_stride, + const qpGeomVertexDataType *from_type, + int num_records) const; + +private: + void copy_no_convert(unsigned char *to, int to_stride, + const unsigned char *from, int from_stride, + const qpGeomVertexDataType *from_type, + int num_records) const; + void copy_argb_to_uint8(unsigned char *to, int to_stride, + const unsigned char *from, int from_stride, + const qpGeomVertexDataType *from_type, + int num_records) const; + void copy_uint8_to_argb(unsigned char *to, int to_stride, + const unsigned char *from, int from_stride, + const qpGeomVertexDataType *from_type, + int num_records) const; + + void copy_generic(unsigned char *to, int to_stride, + const unsigned char *from, int from_stride, + const qpGeomVertexDataType *from_type, + int num_records) const; + + float get_value(const unsigned char *data, int n) const; + void set_value(unsigned char *data, int n, float value) const; + +private: + CPT(InternalName) _name; + int _num_components; + int _num_values; + NumericType _numeric_type; + int _start; + int _component_bytes; + int _total_bytes; +}; + +INLINE ostream &operator << (ostream &out, const qpGeomVertexDataType &obj); + +#include "qpgeomVertexDataType.I" + +#endif diff --git a/panda/src/gobj/qpgeomVertexFormat.I b/panda/src/gobj/qpgeomVertexFormat.I new file mode 100644 index 0000000000..834b84bc03 --- /dev/null +++ b/panda/src/gobj/qpgeomVertexFormat.I @@ -0,0 +1,260 @@ +// Filename: qpgeomVertexFormat.I +// Created by: drose (07Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 . +// +//////////////////////////////////////////////////////////////////// + + +INLINE ostream & +operator << (ostream &out, const qpGeomVertexFormat &obj) { + obj.output(out); + return out; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::is_registered +// Access: Published +// Description: Returns true if this format has been registered, +// false if it has not. It may not be used for a Geom +// until it has been registered, but once registered, it +// may no longer be modified. +//////////////////////////////////////////////////////////////////// +INLINE bool qpGeomVertexFormat:: +is_registered() const { + return _is_registered; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::register_format +// Access: Published, Static +// Description: Adds the indicated format to the registry, if there +// is not an equivalent format already there; in either +// case, returns the pointer to the equivalent format +// now in the registry. +// +// This must be called before a format may be used in a +// Geom. After this call, you should discard the +// original pointer you passed in (which may or may not +// now be invalid) and let its reference count decrement +// normally; you should use only the returned value from +// this point on. +//////////////////////////////////////////////////////////////////// +INLINE CPT(qpGeomVertexFormat) qpGeomVertexFormat:: +register_format(qpGeomVertexFormat *format) { + return get_registry()->register_format(format); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::register_format +// Access: Published, Static +// Description: This flavor of register_format() implicitly creates a +// one-array vertex format from the array definition. +//////////////////////////////////////////////////////////////////// +INLINE CPT(qpGeomVertexFormat) qpGeomVertexFormat:: +register_format(qpGeomVertexArrayFormat *format) { + return get_registry()->register_format(format); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::get_num_arrays +// Access: Published +// Description: Returns the number of individual arrays required by +// the format. If the array data is completely +// interleaved, this will be 1; if it is completely +// parallel, this will be the same as the number of data +// types. +//////////////////////////////////////////////////////////////////// +INLINE int qpGeomVertexFormat:: +get_num_arrays() const { + return _arrays.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::get_array +// Access: Published +// Description: Returns the description of the nth array used by the +// format. +//////////////////////////////////////////////////////////////////// +INLINE const qpGeomVertexArrayFormat *qpGeomVertexFormat:: +get_array(int array) const { + nassertr(array >= 0 && array < (int)_arrays.size(), NULL); + return _arrays[array]; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::get_v3 +// Access: Published, Static +// Description: Returns a standard vertex format with just a +// 3-component vertex position. +//////////////////////////////////////////////////////////////////// +INLINE const qpGeomVertexFormat *qpGeomVertexFormat:: +get_v3() { + return get_registry()->_v3; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::get_v3n3 +// Access: Published, Static +// Description: Returns a standard vertex format with a 3-component +// normal and a 3-component vertex position. +//////////////////////////////////////////////////////////////////// +INLINE const qpGeomVertexFormat *qpGeomVertexFormat:: +get_v3n3() { + return get_registry()->_v3n3; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::get_v3t2 +// Access: Published, Static +// Description: Returns a standard vertex format with a 2-component +// texture coordinate pair and a 3-component vertex +// position. +//////////////////////////////////////////////////////////////////// +INLINE const qpGeomVertexFormat *qpGeomVertexFormat:: +get_v3t2() { + return get_registry()->_v3t2; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::get_v3n3t2 +// Access: Published, Static +// Description: Returns a standard vertex format with a 2-component +// texture coordinate pair, a 3-component normal, and a +// 3-component vertex position. +//////////////////////////////////////////////////////////////////// +INLINE const qpGeomVertexFormat *qpGeomVertexFormat:: +get_v3n3t2() { + return get_registry()->_v3n3t2; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::get_v3cp +// Access: Published, Static +// Description: Returns a standard vertex format with a packed +// color and a 3-component vertex position. +//////////////////////////////////////////////////////////////////// +INLINE const qpGeomVertexFormat *qpGeomVertexFormat:: +get_v3cp() { + return get_registry()->_v3cp; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::get_v3n3cp +// Access: Published, Static +// Description: Returns a standard vertex format with a packed +// color, a 3-component normal, and a 3-component vertex +// position. +//////////////////////////////////////////////////////////////////// +INLINE const qpGeomVertexFormat *qpGeomVertexFormat:: +get_v3n3cp() { + return get_registry()->_v3n3cp; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::get_v3cpt2 +// Access: Published, Static +// Description: Returns a standard vertex format with a 2-component +// texture coordinate pair, a packed color, and a +// 3-component vertex position. +//////////////////////////////////////////////////////////////////// +INLINE const qpGeomVertexFormat *qpGeomVertexFormat:: +get_v3cpt2() { + return get_registry()->_v3cpt2; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::get_v3n3cpt2 +// Access: Published, Static +// Description: Returns a standard vertex format with a 2-component +// texture coordinate pair, a packed color, a +// 3-component normal, and a 3-component vertex +// position. +//////////////////////////////////////////////////////////////////// +INLINE const qpGeomVertexFormat *qpGeomVertexFormat:: +get_v3n3cpt2() { + return get_registry()->_v3n3cpt2; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::get_v3c4 +// Access: Published, Static +// Description: Returns a standard vertex format with a 4-component +// color and a 3-component vertex position. +//////////////////////////////////////////////////////////////////// +INLINE const qpGeomVertexFormat *qpGeomVertexFormat:: +get_v3c4() { + return get_registry()->_v3c4; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::get_v3n3c4 +// Access: Published, Static +// Description: Returns a standard vertex format with a 4-component +// color, a 3-component normal, and a 3-component vertex +// position. +//////////////////////////////////////////////////////////////////// +INLINE const qpGeomVertexFormat *qpGeomVertexFormat:: +get_v3n3c4() { + return get_registry()->_v3n3c4; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::get_v3c4t2 +// Access: Published, Static +// Description: Returns a standard vertex format with a 2-component +// texture coordinate pair, a 4-component color, and a +// 3-component vertex position. +//////////////////////////////////////////////////////////////////// +INLINE const qpGeomVertexFormat *qpGeomVertexFormat:: +get_v3c4t2() { + return get_registry()->_v3c4t2; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::get_v3n3c4t2 +// Access: Published, Static +// Description: Returns a standard vertex format with a 2-component +// texture coordinate pair, a 4-component color, a +// 3-component normal, and a 3-component vertex +// position. +//////////////////////////////////////////////////////////////////// +INLINE const qpGeomVertexFormat *qpGeomVertexFormat:: +get_v3n3c4t2() { + return get_registry()->_v3n3c4t2; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::get_registry +// Access: Private +// Description: Returns the global registry object. +//////////////////////////////////////////////////////////////////// +INLINE qpGeomVertexFormat::Registry *qpGeomVertexFormat:: +get_registry() { + if (_registry == (Registry *)NULL) { + make_registry(); + } + return _registry; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::Registry::register_format +// Access: Public +// Description: This flavor of register_format() implicitly creates a +// one-array vertex format from the array definition. +//////////////////////////////////////////////////////////////////// +INLINE CPT(qpGeomVertexFormat) qpGeomVertexFormat::Registry:: +register_format(qpGeomVertexArrayFormat *format) { + return register_format(new qpGeomVertexFormat(format)); +} diff --git a/panda/src/gobj/qpgeomVertexFormat.cxx b/panda/src/gobj/qpgeomVertexFormat.cxx new file mode 100644 index 0000000000..19d4d60799 --- /dev/null +++ b/panda/src/gobj/qpgeomVertexFormat.cxx @@ -0,0 +1,632 @@ +// Filename: qpgeomVertexFormat.cxx +// Created by: drose (07Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "qpgeomVertexFormat.h" +#include "qpgeomVertexData.h" +#include "qpgeomMunger.h" +#include "indent.h" +#include "bamReader.h" +#include "bamWriter.h" + +qpGeomVertexFormat::Registry *qpGeomVertexFormat::_registry = NULL; +TypeHandle qpGeomVertexFormat::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomVertexFormat:: +qpGeomVertexFormat() : + _is_registered(false) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomVertexFormat:: +qpGeomVertexFormat(qpGeomVertexArrayFormat *array_format) : + _is_registered(false) +{ + add_array(array_format); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::Copy Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomVertexFormat:: +qpGeomVertexFormat(const qpGeomVertexFormat ©) : + _is_registered(false), + _arrays(copy._arrays) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::Copy Assignment Operator +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void qpGeomVertexFormat:: +operator = (const qpGeomVertexFormat ©) { + nassertv(!_is_registered); + + _arrays = copy._arrays; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::Destructor +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomVertexFormat:: +~qpGeomVertexFormat() { + if (is_registered()) { + get_registry()->unregister_format(this); + } + nassertv(_mungers.empty()); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::modify_array +// Access: Published +// Description: Returns a modifiable pointer to the indicated array. +// This means duplicating it if it is shared or +// registered. +//////////////////////////////////////////////////////////////////// +qpGeomVertexArrayFormat *qpGeomVertexFormat:: +modify_array(int array) { + nassertr(!_is_registered, NULL); + nassertr(array >= 0 && array < (int)_arrays.size(), NULL); + + if (_arrays[array]->is_registered() || + _arrays[array]->get_ref_count() > 1) { + _arrays[array] = new qpGeomVertexArrayFormat(*_arrays[array]); + } + + return _arrays[array]; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::set_array +// Access: Published +// Description: Replaces the definition of the indicated array. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexFormat:: +set_array(int array, qpGeomVertexArrayFormat *format) { + nassertv(!_is_registered); + nassertv(array >= 0 && array < (int)_arrays.size()); + _arrays[array] = format; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::remove_array +// Access: Published +// Description: Removes the nth array from the format. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexFormat:: +remove_array(int array) { + nassertv(!_is_registered); + + nassertv(array >= 0 && array < (int)_arrays.size()); + _arrays.erase(_arrays.begin() + array); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::add_array +// Access: Published +// Description: Adds the indicated array definition to the list of +// arrays included within this vertex format definition. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexFormat:: +add_array(qpGeomVertexArrayFormat *array_format) { + nassertv(!_is_registered); + + _arrays.push_back(array_format); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::clear_arrays +// Access: Published +// Description: Removes all of the array definitions from the format +// and starts over. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexFormat:: +clear_arrays() { + nassertv(!_is_registered); + + _arrays.clear(); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::get_num_data_types +// Access: Published +// Description: Returns the total number of different data types in +// the specification, across all arrays. +//////////////////////////////////////////////////////////////////// +int qpGeomVertexFormat:: +get_num_data_types() const { + int num_data_types = 0; + Arrays::const_iterator ai; + for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) { + num_data_types += (*ai)->get_num_data_types(); + } + return num_data_types; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::get_data_type +// Access: Published +// Description: Returns the ith data type of the specification, +// across all arrays. +//////////////////////////////////////////////////////////////////// +const qpGeomVertexDataType *qpGeomVertexFormat:: +get_data_type(int i) const { + Arrays::const_iterator ai; + for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) { + if (i < (*ai)->get_num_data_types()) { + return (*ai)->get_data_type(i); + } + i -= (*ai)->get_num_data_types(); + } + + return NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::get_array_with +// Access: Published +// Description: Returns the index number of the array with the +// ith data type. +// +// The return value can be passed to get_array_format() +// to get the format of the array. It may also be +// passed to GeomVertexData::get_array_data() or +// get_data() or set_data() to manipulate the actual +// array data. +//////////////////////////////////////////////////////////////////// +int qpGeomVertexFormat:: +get_array_with(int i) const { + int array_index = 0; + for (array_index = 0; array_index < (int)_arrays.size(); array_index++) { + if (i < _arrays[array_index]->get_num_data_types()) { + return array_index; + } + i -= _arrays[array_index]->get_num_data_types(); + } + + return -1; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::get_array_with +// Access: Published +// Description: Returns the index number of the array with the +// indicated data type, or -1 if no arrays contained +// that name. +// +// The return value can be passed to get_array_format() +// to get the format of the array. It may also be +// passed to GeomVertexData::get_array_data() or +// get_data() or set_data() to manipulate the actual +// array data. +// +// This may only be called after the format has been +// registered. +//////////////////////////////////////////////////////////////////// +int qpGeomVertexFormat:: +get_array_with(const InternalName *name) const { + nassertr(_is_registered, -1); + + DataTypesByName::const_iterator ai; + ai = _data_types_by_name.find(name); + if (ai != _data_types_by_name.end()) { + return (*ai).second._array_index; + } + return -1; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::get_data_type +// Access: Published +// Description: Returns the specification with the indicated name, or +// NULL if the name is not used. Use get_array_with() +// to determine which array this data type is associated +// with. +// +// This may only be called after the format has been +// registered. +//////////////////////////////////////////////////////////////////// +const qpGeomVertexDataType *qpGeomVertexFormat:: +get_data_type(const InternalName *name) const { + nassertr(_is_registered, NULL); + + DataTypesByName::const_iterator ai; + ai = _data_types_by_name.find(name); + if (ai != _data_types_by_name.end()) { + int array_index = (*ai).second._array_index; + int data_type_index = (*ai).second._data_type_index; + + nassertr(array_index >= 0 && array_index < (int)_arrays.size(), NULL); + return _arrays[array_index]->get_data_type(data_type_index); + } + return NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::output +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void qpGeomVertexFormat:: +output(ostream &out) const { + if (_arrays.empty()) { + out << "(empty)"; + + } else { + Arrays::const_iterator ai; + ai = _arrays.begin(); + out << *(*ai); + ++ai; + while (ai != _arrays.end()) { + out << ", " << *(*ai); + ++ai; + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::write +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void qpGeomVertexFormat:: +write(ostream &out, int indent_level) const { + for (size_t i = 0; i < _arrays.size(); i++) { + indent(out, indent_level) + << "Array " << i << ":\n"; + _arrays[i]->write(out, indent_level + 2); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::write_with_data +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void qpGeomVertexFormat:: +write_with_data(ostream &out, int indent_level, + const qpGeomVertexData *data) const { + indent(out, indent_level) + << data->get_num_vertices() << " vertices.\n"; + for (size_t i = 0; i < _arrays.size(); i++) { + CPTA_uchar array_data = data->get_array_data(i); + indent(out, indent_level) + << "Array " << i << " (" << (void *)array_data.p() << "):\n"; + _arrays[i]->write_with_data(out, indent_level + 2, data, i); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::get_array_info +// Access: Public +// Description: Quickly looks up the indicated data type within all +// of the nested arrays and sets array_index and +// data_type appropriately. Returns true if the data +// type exists in this format, false if it does not. +// +// This may only be called after the format has been +// registered. +//////////////////////////////////////////////////////////////////// +bool qpGeomVertexFormat:: +get_array_info(const InternalName *name, int &array_index, + const qpGeomVertexDataType *&data_type) const { + nassertr(_is_registered, false); + + DataTypesByName::const_iterator ai; + ai = _data_types_by_name.find(name); + if (ai != _data_types_by_name.end()) { + array_index = (*ai).second._array_index; + data_type = _arrays[array_index]->get_data_type((*ai).second._data_type_index); + return true; + } + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::compare_to +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +int qpGeomVertexFormat:: +compare_to(const qpGeomVertexFormat &other) const { + if (_arrays.size() != other._arrays.size()) { + return (int)_arrays.size() - (int)other._arrays.size(); + } + + for (size_t i = 0; i < _arrays.size(); i++) { + int compare = _arrays[i]->compare_to(*other._arrays[i]); + if (compare != 0) { + return compare; + } + } + + return 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::make_registry +// Access: Private +// Description: Returns the global registry object. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexFormat:: +make_registry() { + if (_registry == (Registry *)NULL) { + _registry = new Registry; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::do_register +// Access: Private +// Description: Called internally when the format is registered. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexFormat:: +do_register() { + nassertv(!_is_registered); + nassertv(_data_types_by_name.empty()); + nassertv(_mungers.empty()); + + int array = 0; + for (array = 0; array < (int)_arrays.size(); ++array) { + const qpGeomVertexArrayFormat *array_format = _arrays[array]; + if (!array_format->is_registered()) { + ((qpGeomVertexArrayFormat *)array_format)->do_register(); + } + + // Now add the names to the index. + int num_data_types = array_format->get_num_data_types(); + for (int i = 0; i < num_data_types; i++) { + const qpGeomVertexDataType *data_type = array_format->get_data_type(i); + pair result; + result = _data_types_by_name.insert(DataTypesByName::value_type(data_type->get_name(), DataTypeRecord())); + if (!result.second) { + gobj_cat.warning() + << "Data type " << data_type->get_name() << " repeated in format.\n"; + } else { + DataTypeRecord &record = (*result.first).second; + record._array_index = array; + record._data_type_index = i; + } + } + } + + _is_registered = true; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::do_unregister +// Access: Private +// Description: Called internally when the format is unregistered. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexFormat:: +do_unregister() { + nassertv(_is_registered); + _is_registered = false; + + _data_types_by_name.clear(); + + Mungers::iterator mi; + for (mi = _mungers.begin(); mi != _mungers.end(); ++mi) { + (*mi)->remove_format(this); + } + _mungers.clear(); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::register_with_read_factory +// Access: Public, Static +// Description: Tells the BamReader how to create objects of type +// qpGeomVertexFormat. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexFormat:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexFormat:: +write_datagram(BamWriter *manager, Datagram &dg) { + TypedWritableReferenceCount::write_datagram(manager, dg); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::complete_pointers +// Access: Public, Virtual +// Description: Receives an array of pointers, one for each time +// manager->read_pointer() was called in fillin(). +// Returns the number of pointers processed. +//////////////////////////////////////////////////////////////////// +int qpGeomVertexFormat:: +complete_pointers(TypedWritable **p_list, BamReader *manager) { + int pi = TypedWritableReferenceCount::complete_pointers(p_list, manager); + + return pi; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type qpGeomVertexFormat is +// encountered in the Bam file. It should create the +// qpGeomVertexFormat and extract its information from +// the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *qpGeomVertexFormat:: +make_from_bam(const FactoryParams ¶ms) { + qpGeomVertexFormat *object = new qpGeomVertexFormat; + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + object->fillin(scan, manager); + + return object; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::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 qpGeomVertexFormat. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexFormat:: +fillin(DatagramIterator &scan, BamReader *manager) { + TypedWritableReferenceCount::fillin(scan, manager); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::Registry::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomVertexFormat::Registry:: +Registry() { + _v3 = register_format(new qpGeomVertexArrayFormat + (InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float)); + + _v3n3 = register_format(new qpGeomVertexArrayFormat + (InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float, + InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float)); + + _v3t2 = register_format(new qpGeomVertexArrayFormat + (InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float, + InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float)); + + _v3n3t2 = register_format(new qpGeomVertexArrayFormat + (InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float, + InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float, + InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float)); + + // Define the DirectX-style packed color formats + _v3cp = register_format(new qpGeomVertexArrayFormat + (InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float, + InternalName::get_color(), 1, qpGeomVertexDataType::NT_packed_argb)); + + _v3n3cp = register_format(new qpGeomVertexArrayFormat + (InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float, + InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float, + InternalName::get_color(), 1, qpGeomVertexDataType::NT_packed_argb)); + + _v3cpt2 = register_format(new qpGeomVertexArrayFormat + (InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float, + InternalName::get_color(), 1, qpGeomVertexDataType::NT_packed_argb, + InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float)); + + _v3n3cpt2 = register_format(new qpGeomVertexArrayFormat + (InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float, + InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float, + InternalName::get_color(), 1, qpGeomVertexDataType::NT_packed_argb, + InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float)); + + // Define the OpenGL-style per-byte color formats. This is not the + // same as a packed format, above, because the resulting byte order + // is endian-independent. + _v3c4 = register_format(new qpGeomVertexArrayFormat + (InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float, + InternalName::get_color(), 4, qpGeomVertexDataType::NT_uint8)); + + _v3n3c4 = register_format(new qpGeomVertexArrayFormat + (InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float, + InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float, + InternalName::get_color(), 4, qpGeomVertexDataType::NT_uint8)); + + _v3c4t2 = register_format(new qpGeomVertexArrayFormat + (InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float, + InternalName::get_color(), 4, qpGeomVertexDataType::NT_uint8, + InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float)); + + _v3n3c4t2 = register_format(new qpGeomVertexArrayFormat + (InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float, + InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float, + InternalName::get_color(), 4, qpGeomVertexDataType::NT_uint8, + InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float)); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::Registry::register_format +// Access: Public +// Description: Adds the indicated format to the registry, if there +// is not an equivalent format already there; in either +// case, returns the pointer to the equivalent format +// now in the registry. +// +// This must be called before a format may be used in a +// Geom. After this call, you should discard the +// original pointer you passed in (which may or may not +// now be invalid) and let its reference count decrement +// normally; you should use only the returned value from +// this point on. +//////////////////////////////////////////////////////////////////// +CPT(qpGeomVertexFormat) qpGeomVertexFormat::Registry:: +register_format(qpGeomVertexFormat *format) { + if (format->is_registered()) { + return format; + } + + // Save the incoming pointer in a local PointerTo, so that if it has + // a zero reference count and is not added into the map below, it + // will be automatically deleted when this function returns. + PT(qpGeomVertexFormat) pt_format = format; + + Formats::iterator fi = _formats.insert(format).first; + + qpGeomVertexFormat *new_format = (*fi); + if (!new_format->is_registered()) { + new_format->do_register(); + } + + return new_format; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::Registry::unregister_format +// Access: Public +// Description: Removes the indicated format from the registry. +// Normally this should not be done until the format is +// destructing. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexFormat::Registry:: +unregister_format(qpGeomVertexFormat *format) { + nassertv(format->is_registered()); + Formats::iterator fi = _formats.find(format); + nassertv(fi != _formats.end()); + _formats.erase(fi); + format->do_unregister(); +} diff --git a/panda/src/gobj/qpgeomVertexFormat.h b/panda/src/gobj/qpgeomVertexFormat.h new file mode 100644 index 0000000000..c06985642a --- /dev/null +++ b/panda/src/gobj/qpgeomVertexFormat.h @@ -0,0 +1,211 @@ +// Filename: qpgeomVertexFormat.h +// Created by: drose (07Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 qpGEOMVERTEXFORMAT_H +#define qpGEOMVERTEXFORMAT_H + +#include "pandabase.h" +#include "typedWritableReferenceCount.h" +#include "qpgeomVertexArrayFormat.h" +#include "internalName.h" +#include "luse.h" +#include "pointerTo.h" +#include "pmap.h" +#include "pset.h" +#include "pvector.h" +#include "pta_float.h" +#include "indirectCompareTo.h" + +class FactoryParams; +class qpGeomVertexData; +class qpGeomMunger; + +//////////////////////////////////////////////////////////////////// +// Class : qpGeomVertexFormat +// Description : This class defines the layout of the vertex data +// arrays stored within a Geom. The data within a Geom +// is typically stored within a single interleaved +// array, but it may also be distributed among multiple +// different arrays. Each array is described by a +// qpGeomVertexArrayFormat object, referenced within +// this object. +// +// There are a number of standard pre-defined +// GeomVertexFormat objects, or you may define your own +// as needed. You may also record any combination of +// standard and/or user-defined data types in your +// custom GeomVertexFormat constructions. +// +// This is part of the experimental Geom rewrite. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA qpGeomVertexFormat : public TypedWritableReferenceCount { +PUBLISHED: + qpGeomVertexFormat(); + qpGeomVertexFormat(qpGeomVertexArrayFormat *array_format); + qpGeomVertexFormat(const qpGeomVertexFormat ©); + void operator = (const qpGeomVertexFormat ©); + virtual ~qpGeomVertexFormat(); + + INLINE bool is_registered() const; + INLINE static CPT(qpGeomVertexFormat) register_format(qpGeomVertexFormat *format); + INLINE static CPT(qpGeomVertexFormat) register_format(qpGeomVertexArrayFormat *format); + + INLINE int get_num_arrays() const; + INLINE const qpGeomVertexArrayFormat *get_array(int array) const; + qpGeomVertexArrayFormat *modify_array(int array); + void set_array(int array, qpGeomVertexArrayFormat *format); + void remove_array(int array); + void add_array(qpGeomVertexArrayFormat *array_format); + void clear_arrays(); + + int get_num_data_types() const; + int get_array_with(int i) const; + const qpGeomVertexDataType *get_data_type(int i) const; + + int get_array_with(const InternalName *name) const; + const qpGeomVertexDataType *get_data_type(const InternalName *name) const; + + void output(ostream &out) const; + void write(ostream &out, int indent_level = 0) const; + void write_with_data(ostream &out, int indent_level, + const qpGeomVertexData *data) const; + + // Some standard vertex formats. No particular requirement to use + // one of these, but the DirectX renderers can use these formats + // directly, whereas any other format will have to be converted + // first. + INLINE static const qpGeomVertexFormat *get_v3(); + INLINE static const qpGeomVertexFormat *get_v3n3(); + INLINE static const qpGeomVertexFormat *get_v3t2(); + INLINE static const qpGeomVertexFormat *get_v3n3t2(); + + // These formats, with the DirectX-style packed color, are not + // supported directly by OpenGL. If you use them, the + // GLGraphicsStateGuardian will automatically convert to OpenGL + // form (with a small runtime overhead). + INLINE static const qpGeomVertexFormat *get_v3cp(); + INLINE static const qpGeomVertexFormat *get_v3cpt2(); + INLINE static const qpGeomVertexFormat *get_v3n3cp(); + INLINE static const qpGeomVertexFormat *get_v3n3cpt2(); + + // These formats, with an OpenGL-style four-byte color, are not + // supported directly by DirectX. If you use them, the + // DXGraphicsStateGuardian will automatically convert to DirectX + // form (with a larger runtime overhead, since DirectX8, and old + // DirectX9 drivers, require everything to be interleaved together). + INLINE static const qpGeomVertexFormat *get_v3c4(); + INLINE static const qpGeomVertexFormat *get_v3c4t2(); + INLINE static const qpGeomVertexFormat *get_v3n3c4(); + INLINE static const qpGeomVertexFormat *get_v3n3c4t2(); + +public: + bool get_array_info(const InternalName *name, + int &array_index, + const qpGeomVertexDataType *&data_type) const; + + int compare_to(const qpGeomVertexFormat &other) const; + +private: + class Registry; + INLINE static Registry *get_registry(); + static void make_registry(); + + void do_register(); + void do_unregister(); + + bool _is_registered; + + typedef pvector< PT(qpGeomVertexArrayFormat) > Arrays; + Arrays _arrays; + + class DataTypeRecord { + public: + int _array_index; + int _data_type_index; + }; + + typedef pmap DataTypesByName; + DataTypesByName _data_types_by_name; + + typedef pset Mungers; + Mungers _mungers; + + typedef pset > Formats; + class Registry { + public: + Registry(); + CPT(qpGeomVertexFormat) register_format(qpGeomVertexFormat *format); + INLINE CPT(qpGeomVertexFormat) register_format(qpGeomVertexArrayFormat *format); + void unregister_format(qpGeomVertexFormat *format); + + Formats _formats; + + CPT(qpGeomVertexFormat) _v3; + CPT(qpGeomVertexFormat) _v3n3; + CPT(qpGeomVertexFormat) _v3t2; + CPT(qpGeomVertexFormat) _v3n3t2; + + CPT(qpGeomVertexFormat) _v3cp; + CPT(qpGeomVertexFormat) _v3n3cp; + CPT(qpGeomVertexFormat) _v3cpt2; + CPT(qpGeomVertexFormat) _v3n3cpt2; + + CPT(qpGeomVertexFormat) _v3c4; + CPT(qpGeomVertexFormat) _v3n3c4; + CPT(qpGeomVertexFormat) _v3c4t2; + CPT(qpGeomVertexFormat) _v3n3c4t2; + }; + + static Registry *_registry; + + +public: + static void register_with_read_factory(); + virtual void write_datagram(BamWriter *manager, Datagram &dg); + virtual int complete_pointers(TypedWritable **plist, BamReader *manager); + +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() { + TypedWritableReferenceCount::init_type(); + register_type(_type_handle, "qpGeomVertexFormat", + TypedWritableReferenceCount::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; + + friend class qpGeomVertexFormat::Registry; + friend class qpGeomMunger; +}; + +INLINE ostream &operator << (ostream &out, const qpGeomVertexFormat &obj); + +#include "qpgeomVertexFormat.I" + +#endif diff --git a/panda/src/gobj/qpgeomVertexIterator.I b/panda/src/gobj/qpgeomVertexIterator.I new file mode 100644 index 0000000000..03ee9aab98 --- /dev/null +++ b/panda/src/gobj/qpgeomVertexIterator.I @@ -0,0 +1,380 @@ +// Filename: qpgeomVertexIterator.I +// Created by: drose (10Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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: qpGeomVertexIterator::Constructor +// Access: Published +// Description: Constructs a new iterator to process the vertices of +// the indicated data object. +//////////////////////////////////////////////////////////////////// +INLINE qpGeomVertexIterator:: +qpGeomVertexIterator(qpGeomVertexData *data) : + _data(data), + _array(0), + _data_type(NULL), + _start_vertex(0), + _read_vertex(0), + _write_vertex(0) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexIterator::Constructor +// Access: Published +// Description: Constructs a new iterator to process the vertices of +// the indicated data object. This flavor creates the +// iterator specifically to process the named data type. +//////////////////////////////////////////////////////////////////// +INLINE qpGeomVertexIterator:: +qpGeomVertexIterator(qpGeomVertexData *data, const string &name) : + _data(data), + _array(0), + _data_type(NULL), + _start_vertex(0), + _read_vertex(0), + _write_vertex(0) +{ + set_data_type(name); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexIterator::Constructor +// Access: Published +// Description: Constructs a new iterator to process the vertices of +// the indicated data object. This flavor creates the +// iterator specifically to process the named data type. +//////////////////////////////////////////////////////////////////// +INLINE qpGeomVertexIterator:: +qpGeomVertexIterator(qpGeomVertexData *data, const InternalName *name) : + _data(data), + _array(0), + _data_type(NULL), + _start_vertex(0), + _read_vertex(0), + _write_vertex(0) +{ + set_data_type(name); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexIterator::get_data +// Access: Published +// Description: Returns the current data object that the iterator is +// processing. +//////////////////////////////////////////////////////////////////// +INLINE qpGeomVertexData *qpGeomVertexIterator:: +get_data() const { + return _data; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexIterator::set_data_type +// Access: Published +// Description: Sets up the iterator to use the nth data type of the +// GeomVertexFormat, numbering from 0. +// +// This also resets the read and write vertex numbers to +// the start vertex (the same value passed to a previous +// call to set_vertex(), or 0 if set_vertex() was never +// called.) +//////////////////////////////////////////////////////////////////// +INLINE void qpGeomVertexIterator:: +set_data_type(int data_type) { + nassertv(_data->get_format()->get_array_with(data_type) >= 0); + set_data_type(_data->get_format()->get_array_with(data_type), + _data->get_format()->get_data_type(data_type)); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexIterator::set_data_type +// Access: Published +// Description: Sets up the iterator to use the data type with the +// indicated name. +// +// This also resets the read and write vertex numbers to +// the start vertex (the same value passed to a previous +// call to set_vertex(), or 0 if set_vertex() was never +// called.) +//////////////////////////////////////////////////////////////////// +INLINE void qpGeomVertexIterator:: +set_data_type(const string &name) { + set_data_type(InternalName::make(name)); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexIterator::set_data_type +// Access: Published +// Description: Sets up the iterator to use the data type with the +// indicated name. +// +// This also resets the read and write vertex numbers to +// the start vertex (the same value passed to a previous +// call to set_vertex(), or 0 if set_vertex() was never +// called.) +//////////////////////////////////////////////////////////////////// +INLINE void qpGeomVertexIterator:: +set_data_type(const InternalName *name) { + nassertv(_data->get_format()->get_array_with(name) >= 0); + set_data_type(_data->get_format()->get_array_with(name), + _data->get_format()->get_data_type(name)); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexIterator::set_data_type +// Access: Published +// Description: Sets up the iterator to use the indicated data_type +// description on the given array. +// +// This also resets the read and write vertex numbers to +// the start vertex (the same value passed to a previous +// call to set_vertex(), or 0 if set_vertex() was never +// called.) +//////////////////////////////////////////////////////////////////// +INLINE void qpGeomVertexIterator:: +set_data_type(int array, const qpGeomVertexDataType *data_type) { + nassertv(array >= 0 && array < _data->get_num_arrays()); + nassertv(data_type != (qpGeomVertexDataType *)NULL); + _array = array; + _data_type = data_type; + + _read_vertex = _start_vertex; + _write_vertex = _start_vertex; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexIterator::get_array +// Access: Published +// Description: Returns the array index containing the data type that +// the iterator is working on. +//////////////////////////////////////////////////////////////////// +INLINE int qpGeomVertexIterator:: +get_array() const { + return _array; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexIterator::get_data_type +// Access: Published +// Description: Returns the description of the data type that the +// iterator is working on. +//////////////////////////////////////////////////////////////////// +INLINE const qpGeomVertexDataType *qpGeomVertexIterator:: +get_data_type() const { + return _data_type; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexIterator::set_vertex +// Access: Published +// Description: Sets the start, read, and write index to the +// indicated value. The iterator will begin traversing +// from the given vertex. +//////////////////////////////////////////////////////////////////// +INLINE void qpGeomVertexIterator:: +set_vertex(int vertex) { + _start_vertex = vertex; + _read_vertex = vertex; + _write_vertex = vertex; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexIterator::get_start_vertex +// Access: Published +// Description: Returns the vertex index at which the iterator +// started. It will return to this vertex if you reset +// the current data_type. +//////////////////////////////////////////////////////////////////// +INLINE int qpGeomVertexIterator:: +get_start_vertex() const { + return _start_vertex; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexIterator::get_read_vertex +// Access: Published +// Description: Returns the current read vertex index of the +// iterator. This is the index whose value will be +// returned by the next call to get_vertex(). +//////////////////////////////////////////////////////////////////// +INLINE int qpGeomVertexIterator:: +get_read_vertex() const { + return _read_vertex; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexIterator::get_write_vertex +// Access: Published +// Description: Returns the current write vertex index of the +// iterator. This is the index whose value will be +// modified by the next call to set_vertex(). +//////////////////////////////////////////////////////////////////// +INLINE int qpGeomVertexIterator:: +get_write_vertex() const { + return _write_vertex; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexIterator::set_data1 +// Access: Published +// Description: Sets the write vertex to a particular 1-component +// value, and advances the write vertex. +//////////////////////////////////////////////////////////////////// +INLINE void qpGeomVertexIterator:: +set_data1(float data) { + _data->set_data(_array, _data_type, _write_vertex, &data, 1); + ++_write_vertex; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexIterator::set_data2 +// Access: Published +// Description: Sets the write vertex to a particular 2-component +// value, and advances the write vertex. +//////////////////////////////////////////////////////////////////// +INLINE void qpGeomVertexIterator:: +set_data2(float x, float y) { + set_data2(LVecBase2f(x, y)); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexIterator::set_data2 +// Access: Published +// Description: Sets the write vertex to a particular 2-component +// value, and advances the write vertex. +//////////////////////////////////////////////////////////////////// +INLINE void qpGeomVertexIterator:: +set_data2(const LVecBase2f &data) { + _data->set_data(_array, _data_type, _write_vertex, data.get_data(), 2); + ++_write_vertex; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexIterator::set_data3 +// Access: Published +// Description: Sets the write vertex to a particular 3-component +// value, and advances the write vertex. +//////////////////////////////////////////////////////////////////// +INLINE void qpGeomVertexIterator:: +set_data3(float x, float y, float z) { + set_data3(LVecBase3f(x, y, z)); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexIterator::set_data3 +// Access: Published +// Description: Sets the write vertex to a particular 3-component +// value, and advances the write vertex. +//////////////////////////////////////////////////////////////////// +INLINE void qpGeomVertexIterator:: +set_data3(const LVecBase3f &data) { + _data->set_data(_array, _data_type, _write_vertex, data.get_data(), 3); + ++_write_vertex; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexIterator::set_data4 +// Access: Published +// Description: Sets the write vertex to a particular 4-component +// value, and advances the write vertex. +//////////////////////////////////////////////////////////////////// +INLINE void qpGeomVertexIterator:: +set_data4(float x, float y, float z, float w) { + set_data4(LVecBase4f(x, y, z, w)); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexIterator::set_data4 +// Access: Published +// Description: Sets the write vertex to a particular 4-component +// value, and advances the write vertex. +//////////////////////////////////////////////////////////////////// +INLINE void qpGeomVertexIterator:: +set_data4(const LVecBase4f &data) { + _data->set_data(_array, _data_type, _write_vertex, data.get_data(), 4); + ++_write_vertex; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexIterator::get_data1 +// Access: Published +// Description: Returns the data associated with the read vertex, +// expressed as a 1-component value, and advances the +// read vertex. +//////////////////////////////////////////////////////////////////// +INLINE float qpGeomVertexIterator:: +get_data1() { + float data; + _data->get_data(_array, _data_type, _read_vertex, &data, 1); + ++_read_vertex; + return data; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexIterator::get_data2 +// Access: Published +// Description: Returns the data associated with the read vertex, +// expressed as a 2-component value, and advances the +// read vertex. +//////////////////////////////////////////////////////////////////// +INLINE LVecBase2f qpGeomVertexIterator:: +get_data2() { + float data[4]; + int num_values = min(_data_type->get_num_values(), 4); + _data->get_data(_array, _data_type, _read_vertex, data, num_values); + ++_read_vertex; + LVecBase2f result; + qpGeomVertexData::to_vec2(result, data, num_values); + return result; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexIterator::get_data3 +// Access: Published +// Description: Returns the data associated with the read vertex, +// expressed as a 3-component value, and advances the +// read vertex. +//////////////////////////////////////////////////////////////////// +INLINE LVecBase3f qpGeomVertexIterator:: +get_data3() { + float data[4]; + int num_values = min(_data_type->get_num_values(), 4); + _data->get_data(_array, _data_type, _read_vertex, data, num_values); + ++_read_vertex; + LVecBase3f result; + qpGeomVertexData::to_vec3(result, data, num_values); + return result; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexIterator::get_data4 +// Access: Published +// Description: Returns the data associated with the read vertex, +// expressed as a 4-component value, and advances the +// read vertex. +//////////////////////////////////////////////////////////////////// +INLINE LVecBase4f qpGeomVertexIterator:: +get_data4() { + float data[4]; + int num_values = min(_data_type->get_num_values(), 4); + _data->get_data(_array, _data_type, _read_vertex, data, num_values); + ++_read_vertex; + LVecBase4f result; + qpGeomVertexData::to_vec4(result, data, num_values); + return result; +} diff --git a/panda/src/gobj/qpgeomVertexIterator.cxx b/panda/src/gobj/qpgeomVertexIterator.cxx new file mode 100644 index 0000000000..26dee44baf --- /dev/null +++ b/panda/src/gobj/qpgeomVertexIterator.cxx @@ -0,0 +1,19 @@ +// Filename: qpgeomVertexIterator.cxx +// Created by: drose (10Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "qpgeomVertexIterator.h" diff --git a/panda/src/gobj/qpgeomVertexIterator.h b/panda/src/gobj/qpgeomVertexIterator.h new file mode 100644 index 0000000000..ed61e8f235 --- /dev/null +++ b/panda/src/gobj/qpgeomVertexIterator.h @@ -0,0 +1,86 @@ +// Filename: qpgeomVertexIterator.h +// Created by: drose (10Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 qpGEOMVERTEXITERATOR_H +#define qpGEOMVERTEXITERATOR_H + +#include "pandabase.h" +#include "qpgeomVertexData.h" +#include "qpgeomVertexDataType.h" +#include "internalName.h" +#include "luse.h" +#include "pointerTo.h" + +//////////////////////////////////////////////////////////////////// +// Class : qpGeomVertexIterator +// Description : This is used to read or write the vertices of a +// GeomVertexData structure, one vertex and data type at +// a time. +// +// This is part of the experimental Geom rewrite. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA qpGeomVertexIterator { +PUBLISHED: + INLINE qpGeomVertexIterator(qpGeomVertexData *data); + INLINE qpGeomVertexIterator(qpGeomVertexData *data, + const string &name); + INLINE qpGeomVertexIterator(qpGeomVertexData *data, + const InternalName *name); + + INLINE qpGeomVertexData *get_data() const; + + INLINE void set_data_type(int data_type); + INLINE void set_data_type(const string &name); + INLINE void set_data_type(const InternalName *name); + INLINE void set_data_type(int array, const qpGeomVertexDataType *data_type); + + INLINE int get_array() const; + INLINE const qpGeomVertexDataType *get_data_type() const; + + INLINE void set_vertex(int vertex); + + INLINE int get_start_vertex() const; + INLINE int get_read_vertex() const; + INLINE int get_write_vertex() const; + + INLINE void set_data1(float data); + INLINE void set_data2(float x, float y); + INLINE void set_data2(const LVecBase2f &data); + INLINE void set_data3(float x, float y, float z); + INLINE void set_data3(const LVecBase3f &data); + INLINE void set_data4(float x, float y, float z, float w); + INLINE void set_data4(const LVecBase4f &data); + + INLINE float get_data1(); + INLINE LVecBase2f get_data2(); + INLINE LVecBase3f get_data3(); + INLINE LVecBase4f get_data4(); + +private: + PT(qpGeomVertexData) _data; + int _array; + const qpGeomVertexDataType *_data_type; + + int _start_vertex; + int _read_vertex; + int _write_vertex; +}; + +#include "qpgeomVertexIterator.I" + +#endif diff --git a/panda/src/gobj/texCoordName.I b/panda/src/gobj/texCoordName.I deleted file mode 100755 index e73c97b543..0000000000 --- a/panda/src/gobj/texCoordName.I +++ /dev/null @@ -1,49 +0,0 @@ -// Filename: texCoordName.I -// Created by: masad (15Jul04) -// -//////////////////////////////////////////////////////////////////// -// -// 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: TexCoordName::get_name -// Access: Published -// Description: Return the name string of this texcoordname -//////////////////////////////////////////////////////////////////// -INLINE const string &TexCoordName:: -get_name() const { - return _name; -} - -//////////////////////////////////////////////////////////////////// -// Function: TexCoordName::get_default -// Access: Published, Static -// Description: Returns the default TexCoordName that will be used -// for all geometry that does not give a particular name -// for its UV's -//////////////////////////////////////////////////////////////////// -INLINE const TexCoordName *TexCoordName:: -get_default() { - if (_default_name == (TexCoordName *)NULL) { - _default_name = TexCoordName::make("default"); - } - return _default_name; -} - -INLINE ostream & -operator << (ostream &out, const TexCoordName &tcn) { - tcn.output(out); - return out; -} diff --git a/panda/src/gobj/texCoordName.cxx b/panda/src/gobj/texCoordName.cxx deleted file mode 100755 index 479502471d..0000000000 --- a/panda/src/gobj/texCoordName.cxx +++ /dev/null @@ -1,161 +0,0 @@ -// Filename: texCoordName.cxx -// Created by: masad (15Jul04) -// -//////////////////////////////////////////////////////////////////// -// -// 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 "pandabase.h" -#include "texCoordName.h" -#include "datagram.h" -#include "datagramIterator.h" -#include "bamReader.h" -#include "preparedGraphicsObjects.h" - -TexCoordName::TexCoordsByName TexCoordName::_texcoords_by_name; -CPT(TexCoordName) TexCoordName::_default_name; - -TypeHandle TexCoordName::_type_handle; - -//////////////////////////////////////////////////////////////////// -// Function: TexCoordName::Constructor -// Access: Private -// Description: Use make() to make a new TexCoordName instance. -//////////////////////////////////////////////////////////////////// -TexCoordName:: -TexCoordName(const string &name) { - _name = name; -} - -//////////////////////////////////////////////////////////////////// -// Function: TexCoordName::Destructor -// Access: Published, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -TexCoordName:: -~TexCoordName() { - TexCoordsByName::iterator ni = _texcoords_by_name.find(_name); - nassertv(ni != _texcoords_by_name.end()); - _texcoords_by_name.erase(ni); -} - -//////////////////////////////////////////////////////////////////// -// Function: TexCoordName::make -// Access: Published -// Description: The public interface for constructing a TexCoordName -// pointer. This will return a new TexCoordName -// associated with the indicated name, if this is the -// first time the particular name has been requested; if -// the name is already in use, it will return the -// existing pointer. -//////////////////////////////////////////////////////////////////// -const TexCoordName *TexCoordName:: -make(const string &name) { - TexCoordsByName::iterator ni = _texcoords_by_name.find(name); - if (ni != _texcoords_by_name.end()) { - return (*ni).second; - } - - TexCoordName *texcoord = new TexCoordName(name); - _texcoords_by_name[name] = texcoord; - return texcoord; -} - -//////////////////////////////////////////////////////////////////// -// Function: TexCoordName::output -// Access: Published -// Description: output the TexCoordName and its member data -//////////////////////////////////////////////////////////////////// -void TexCoordName:: -output(ostream &out) const { - out << get_name(); -} - -//////////////////////////////////////////////////////////////////// -// Function: TexCoordName::register_with_read_factory -// Access: Public, Static -// Description: Factory method to generate a TexCoordName object -//////////////////////////////////////////////////////////////////// -void TexCoordName:: -register_with_read_factory() { - BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); -} - -//////////////////////////////////////////////////////////////////// -// Function: TexCoordName::finalize -// Access: Public, Virtual -// Description: Method to ensure that any necessary clean up tasks -// that have to be performed by this object are performed -//////////////////////////////////////////////////////////////////// -void TexCoordName:: -finalize() { - // Unref the pointer that we explicitly reffed in make_from_bam(). - unref(); - - // We should never get back to zero after unreffing our own count, - // because we expect to have been stored in a pointer somewhere. If - // we do get to zero, it's a memory leak; the way to avoid this is - // to call unref_delete() above instead of unref(), but this is - // dangerous to do from within a virtual function. - nassertv(get_ref_count() != 0); -} - -//////////////////////////////////////////////////////////////////// -// Function: TexCoordName::make_from_bam -// Access: Protected, Static -// Description: This function is called by the BamReader's factory -// when a new object of type TexCoordName is encountered -// in the Bam file. It should create the TexCoordName -// and extract its information from the file. -//////////////////////////////////////////////////////////////////// -TypedWritable *TexCoordName:: -make_from_bam(const FactoryParams ¶ms) { - // The process of making a TexCoordName is slightly - // different than making other Writable objects. - // That is because all creation of TexCoordNames should - // be done through the make() constructor. - DatagramIterator scan; - BamReader *manager; - - parse_params(params, scan, manager); - - // The name is the only thing written to the data stream. - string name = scan.get_string(); - - // Make a new TexCoordName with that name (or get the previous one - // if there is one already). - PT(TexCoordName) me = (TexCoordName *)make(name); - - // But now we have a problem, since we have to hold the reference - // count and there's no way to return a TypedWritable while still - // holding the reference count! We work around this by explicitly - // upping the count, and also setting a finalize() callback to down - // it later. - me->ref(); - manager->register_finalize(me); - - return me.p(); -} - -//////////////////////////////////////////////////////////////////// -// Function: TexCoordName::write_datagram -// Access: Public -// Description: Function to write the important information in -// the particular object to a Datagram -//////////////////////////////////////////////////////////////////// -void TexCoordName:: -write_datagram(BamWriter *manager, Datagram &me) { - me.add_string(_name); -} - diff --git a/panda/src/gobj/texCoordName.h b/panda/src/gobj/texCoordName.h deleted file mode 100644 index 5afbd507a4..0000000000 --- a/panda/src/gobj/texCoordName.h +++ /dev/null @@ -1,92 +0,0 @@ -// Filename: texCoordName.h -// Created by: drose (15Jul04) -// -//////////////////////////////////////////////////////////////////// -// -// 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 TEXCOORDNAME_H -#define TEXCOORDNAME_H - -#include "pandabase.h" - -#include "typedWritableReferenceCount.h" - -class FactoryParams; - -//////////////////////////////////////////////////////////////////// -// Class : TexCoordName -// Description : Associates a name with a set of texture coordinates, -// for the purpose of storing within a Geom. This is -// used in conjunction with TextureStage to support -// multitexturing. -//////////////////////////////////////////////////////////////////// -class EXPCL_PANDA TexCoordName : public TypedWritableReferenceCount { -private: - TexCoordName(const string &name); - -PUBLISHED: - virtual ~TexCoordName(); - - static const TexCoordName *make(const string &name); - INLINE const string &get_name() const; - - void output(ostream &out) const; - - INLINE static const TexCoordName *get_default(); - -private: - string _name; - - typedef phash_map TexCoordsByName; - static TexCoordsByName _texcoords_by_name; - - static CPT(TexCoordName) _default_name; - -public: - // Datagram stuff - static void register_with_read_factory(); - virtual void write_datagram(BamWriter *manager, Datagram &me); - - virtual void finalize(); - -protected: - static TypedWritable *make_from_bam(const FactoryParams ¶ms); - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - TypedWritableReferenceCount::init_type(); - register_type(_type_handle, "TexCoordName", - TypedWritableReferenceCount::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; -}; - -INLINE ostream &operator << (ostream &out, const TexCoordName &tcn); - -#include "texCoordName.I" - -#endif - - - diff --git a/panda/src/gobj/textureStage.I b/panda/src/gobj/textureStage.I index 84e63227eb..d50b9e7534 100755 --- a/panda/src/gobj/textureStage.I +++ b/panda/src/gobj/textureStage.I @@ -136,7 +136,7 @@ operator < (const TextureStage &other) const { // sets, each of which must have a unique name. //////////////////////////////////////////////////////////////////// INLINE void TextureStage:: -set_texcoord_name(const TexCoordName *name) { +set_texcoord_name(const InternalName *name) { _texcoord_name = name; } @@ -149,15 +149,15 @@ set_texcoord_name(const TexCoordName *name) { //////////////////////////////////////////////////////////////////// INLINE void TextureStage:: set_texcoord_name(const string &name) { - _texcoord_name = TexCoordName::make(name); + _texcoord_name = InternalName::get_texcoord_name(name); } //////////////////////////////////////////////////////////////////// // Function: TextureStage::get_texcoord_name // Access: Published -// Description: Returns the TexCoordName +// Description: Returns the InternalName //////////////////////////////////////////////////////////////////// -INLINE const TexCoordName *TextureStage:: +INLINE const InternalName *TextureStage:: get_texcoord_name() const { return _texcoord_name; } diff --git a/panda/src/gobj/textureStage.cxx b/panda/src/gobj/textureStage.cxx index 54239e9f29..435aebdf82 100755 --- a/panda/src/gobj/textureStage.cxx +++ b/panda/src/gobj/textureStage.cxx @@ -17,7 +17,7 @@ //////////////////////////////////////////////////////////////////// #include "textureStage.h" -#include "texCoordName.h" +#include "internalName.h" PT(TextureStage) TextureStage::_default_stage; UpdateSeq TextureStage::_sort_seq; @@ -34,7 +34,7 @@ TextureStage(const string &name) { _name = name; _sort = 0; _priority = 0; - _texcoord_name = TexCoordName::get_default(); + _texcoord_name = InternalName::get_texcoord(); _mode = M_modulate; _color.set(0.0f, 0.0f, 0.0f, 1.0f); _rgb_scale = 1; @@ -319,7 +319,7 @@ int TextureStage:: complete_pointers(TypedWritable **p_list, BamReader *manager) { int pi = TypedWritableReferenceCount::complete_pointers(p_list, manager); - _texcoord_name = DCAST(TexCoordName, p_list[pi++]); + _texcoord_name = DCAST(InternalName, p_list[pi++]); return pi; } diff --git a/panda/src/gobj/textureStage.h b/panda/src/gobj/textureStage.h index 04520131c7..ceb15f4e84 100644 --- a/panda/src/gobj/textureStage.h +++ b/panda/src/gobj/textureStage.h @@ -21,7 +21,7 @@ #include "pandabase.h" -#include "texCoordName.h" +#include "internalName.h" #include "pointerTo.h" #include "typedWritableReferenceCount.h" #include "updateSeq.h" @@ -100,9 +100,9 @@ PUBLISHED: INLINE bool operator < (const TextureStage &other) const; - INLINE void set_texcoord_name(const TexCoordName *name); + INLINE void set_texcoord_name(const InternalName *name); INLINE void set_texcoord_name(const string &texcoord_name); - INLINE const TexCoordName *get_texcoord_name() const; + INLINE const InternalName *get_texcoord_name() const; INLINE void set_mode(Mode mode); INLINE Mode get_mode() const; @@ -170,7 +170,7 @@ private: string _name; int _sort; int _priority; - CPT(TexCoordName) _texcoord_name; + CPT(InternalName) _texcoord_name; Mode _mode; Colorf _color; int _rgb_scale; diff --git a/panda/src/grutil/multitexReducer.cxx b/panda/src/grutil/multitexReducer.cxx index 6aff78ae2e..0445f9b43d 100644 --- a/panda/src/grutil/multitexReducer.cxx +++ b/panda/src/grutil/multitexReducer.cxx @@ -116,7 +116,7 @@ scan(PandaNode *node, const RenderState *state, const TransformState *transform) //////////////////////////////////////////////////////////////////// // Function: MultitexReducer::set_target // Access: Published -// Description: Specifies the target TextureStage (and TexCoordName) +// Description: Specifies the target TextureStage (and InternalName) // that will be left on each multitexture node after the // flatten operation has completed. //////////////////////////////////////////////////////////////////// @@ -544,7 +544,7 @@ bool MultitexReducer:: determine_uv_range(TexCoordf &min_uv, TexCoordf &max_uv, const MultitexReducer::StageInfo &model_stage, const MultitexReducer::GeomList &geom_list) const { - const TexCoordName *model_name = model_stage._stage->get_texcoord_name(); + const InternalName *model_name = model_stage._stage->get_texcoord_name(); bool got_any = false; GeomList::const_iterator gi; @@ -799,7 +799,7 @@ make_texture_layer(const NodePath &render, // coordinates to the target set. //////////////////////////////////////////////////////////////////// void MultitexReducer:: -transfer_geom(GeomNode *geom_node, const TexCoordName *texcoord_name, +transfer_geom(GeomNode *geom_node, const InternalName *texcoord_name, const MultitexReducer::GeomList &geom_list, bool preserve_color) { GeomList::const_iterator gi; @@ -820,8 +820,8 @@ transfer_geom(GeomNode *geom_node, const TexCoordName *texcoord_name, } geom->set_coords(coords, geom->get_texcoords_index(_target_stage->get_texcoord_name())); - if (texcoord_name != (const TexCoordName *)NULL) { - geom->set_texcoords(TexCoordName::get_default(), + if (texcoord_name != (const InternalName *)NULL) { + geom->set_texcoords(InternalName::get_texcoord(), geom->get_texcoords_array(texcoord_name), geom->get_texcoords_index(texcoord_name)); } diff --git a/panda/src/grutil/multitexReducer.h b/panda/src/grutil/multitexReducer.h index f1a9de2794..304384b3f9 100644 --- a/panda/src/grutil/multitexReducer.h +++ b/panda/src/grutil/multitexReducer.h @@ -139,7 +139,7 @@ private: const StageInfo &stage_info, const GeomList &geom_list, bool force_use_geom); - void transfer_geom(GeomNode *geom_node, const TexCoordName *texcoord_name, + void transfer_geom(GeomNode *geom_node, const InternalName *texcoord_name, const GeomList &geom_list, bool preserve_color); void scan_color(const GeomList &geom_list, Colorf &geom_color, diff --git a/panda/src/gsgbase/graphicsStateGuardianBase.h b/panda/src/gsgbase/graphicsStateGuardianBase.h index 012451aaf5..b3c1376c79 100644 --- a/panda/src/gsgbase/graphicsStateGuardianBase.h +++ b/panda/src/gsgbase/graphicsStateGuardianBase.h @@ -43,6 +43,10 @@ class GeomTri; class GeomTristrip; class GeomTrifan; class GeomSphere; +class qpGeomVertexData; +class qpGeomTriangles; +class qpGeomTristrips; +class qpGeomTrifans; class PreparedGraphicsObjects; class GraphicsOutput; @@ -165,6 +169,12 @@ public: virtual void draw_trifan(GeomTrifan *geom, GeomContext *gc)=0; virtual void draw_sphere(GeomSphere *geom, GeomContext *gc)=0; + virtual void begin_draw_primitives(const qpGeomVertexData *vertex_data)=0; + virtual void draw_triangles(qpGeomTriangles *primitive)=0; + virtual void draw_tristrips(qpGeomTristrips *primitive)=0; + virtual void draw_trifans(qpGeomTrifans *primitive)=0; + virtual void end_draw_primitives()=0; + virtual void framebuffer_copy_to_texture (Texture *tex, int z, const DisplayRegion *dr, const RenderBuffer &rb)=0; virtual bool framebuffer_copy_to_ram diff --git a/panda/src/pgraph/geomNode.I b/panda/src/pgraph/geomNode.I index 9fafbaad1c..bbd6c565ba 100644 --- a/panda/src/pgraph/geomNode.I +++ b/panda/src/pgraph/geomNode.I @@ -182,10 +182,10 @@ get_default_collide_mask() { //////////////////////////////////////////////////////////////////// // Function: GeomNode::count_name // Access: Private -// Description: Increments the count for the indicated TexCoordName. +// Description: Increments the count for the indicated InternalName. //////////////////////////////////////////////////////////////////// INLINE void GeomNode:: -count_name(GeomNode::NameCount &name_count, const TexCoordName *name) { +count_name(GeomNode::NameCount &name_count, const InternalName *name) { pair result = name_count.insert(NameCount::value_type(name, 1)); if (!result.second) { @@ -196,10 +196,10 @@ count_name(GeomNode::NameCount &name_count, const TexCoordName *name) { //////////////////////////////////////////////////////////////////// // Function: GeomNode::get_name_count // Access: Private -// Description: Returns the count for the indicated TexCoordName. +// Description: Returns the count for the indicated InternalName. //////////////////////////////////////////////////////////////////// INLINE int GeomNode:: -get_name_count(const GeomNode::NameCount &name_count, const TexCoordName *name) { +get_name_count(const GeomNode::NameCount &name_count, const InternalName *name) { NameCount::const_iterator ni; ni = name_count.find(name); if (ni != name_count.end()) { diff --git a/panda/src/pgraph/geomNode.cxx b/panda/src/pgraph/geomNode.cxx index 8644f49c96..5bcbbff4c4 100644 --- a/panda/src/pgraph/geomNode.cxx +++ b/panda/src/pgraph/geomNode.cxx @@ -235,7 +235,7 @@ apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types, int num_on_stages = ta->get_num_on_stages(); for (int si = 0; si < num_on_stages; si++) { TextureStage *stage = ta->get_on_stage(si); - const TexCoordName *name = stage->get_texcoord_name(); + const InternalName *name = stage->get_texcoord_name(); count_name(name_count, name); } } @@ -248,7 +248,7 @@ apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types, int num_stages = tma->get_num_stages(); for (int i = 0; i < num_stages; i++) { TextureStage *stage = tma->get_stage(i); - const TexCoordName *name = stage->get_texcoord_name(); + const InternalName *name = stage->get_texcoord_name(); if (get_name_count(name_count, name) > 1) { // We can't transform these texcoords, since the name is // used by more than one active stage. diff --git a/panda/src/pgraph/geomNode.h b/panda/src/pgraph/geomNode.h index c6f8138e74..38f2daea68 100644 --- a/panda/src/pgraph/geomNode.h +++ b/panda/src/pgraph/geomNode.h @@ -92,10 +92,10 @@ public: private: typedef pvector Geoms; - typedef pmap NameCount; + typedef pmap NameCount; - INLINE void count_name(NameCount &name_count, const TexCoordName *name); - INLINE int get_name_count(const NameCount &name_count, const TexCoordName *name); + INLINE void count_name(NameCount &name_count, const InternalName *name); + INLINE int get_name_count(const NameCount &name_count, const InternalName *name); // This is the data that must be cycled between pipeline stages. class EXPCL_PANDA CData : public CycleData { diff --git a/panda/src/pgraph/geomTransformer.cxx b/panda/src/pgraph/geomTransformer.cxx index d5bfb0be66..770b8b553e 100644 --- a/panda/src/pgraph/geomTransformer.cxx +++ b/panda/src/pgraph/geomTransformer.cxx @@ -150,8 +150,8 @@ transform_vertices(GeomNode *node, const LMatrix4f &mat) { // Geom was changed, false otherwise. //////////////////////////////////////////////////////////////////// bool GeomTransformer:: -transform_texcoords(Geom *geom, const TexCoordName *from_name, - const TexCoordName *to_name, const LMatrix4f &mat) { +transform_texcoords(Geom *geom, const InternalName *from_name, + const InternalName *to_name, const LMatrix4f &mat) { bool transformed = false; nassertr(geom != (Geom *)NULL, false); @@ -201,8 +201,8 @@ transform_texcoords(Geom *geom, const TexCoordName *from_name, // false otherwise. //////////////////////////////////////////////////////////////////// bool GeomTransformer:: -transform_texcoords(GeomNode *node, const TexCoordName *from_name, - const TexCoordName *to_name, const LMatrix4f &mat) { +transform_texcoords(GeomNode *node, const InternalName *from_name, + const InternalName *to_name, const LMatrix4f &mat) { bool any_changed = false; GeomNode::CDWriter cdata(node->_cycler); diff --git a/panda/src/pgraph/geomTransformer.h b/panda/src/pgraph/geomTransformer.h index a25b9f3353..ac43b97457 100644 --- a/panda/src/pgraph/geomTransformer.h +++ b/panda/src/pgraph/geomTransformer.h @@ -26,7 +26,7 @@ class GeomNode; class RenderState; -class TexCoordName; +class InternalName; /////////////////////////////////////////////////////////////////// // Class : GeomTransformer @@ -52,11 +52,11 @@ public: bool transform_vertices(Geom *geom, const LMatrix4f &mat); bool transform_vertices(GeomNode *node, const LMatrix4f &mat); - bool transform_texcoords(Geom *geom, const TexCoordName *from_name, - const TexCoordName *to_name, + bool transform_texcoords(Geom *geom, const InternalName *from_name, + const InternalName *to_name, const LMatrix4f &mat); - bool transform_texcoords(GeomNode *node, const TexCoordName *from_name, - const TexCoordName *to_name, + bool transform_texcoords(GeomNode *node, const InternalName *from_name, + const InternalName *to_name, const LMatrix4f &mat); bool set_color(Geom *geom, const Colorf &color);