From bd820acd49ef58d60c5487f46424ff9d2bb9a948 Mon Sep 17 00:00:00 2001 From: David Rose Date: Thu, 24 Mar 2005 23:48:15 +0000 Subject: [PATCH] beginning vertex animation in qpgeom --- panda/src/dxgsg8/dxGeomMunger8.cxx | 6 +- panda/src/egg2pg/eggLoader.cxx | 14 +- panda/src/express/pointerToArray.I | 2 +- panda/src/framework/windowFramework.cxx | 40 +- panda/src/glstuff/glGeomMunger_src.I | 2 +- panda/src/glstuff/glGeomMunger_src.cxx | 2 +- .../glstuff/glGraphicsStateGuardian_src.cxx | 12 +- panda/src/gobj/Sources.pp | 21 +- panda/src/gobj/config_gobj.cxx | 11 + panda/src/gobj/gobj_composite2.cxx | 5 + panda/src/gobj/internalName.I | 13 + panda/src/gobj/internalName.cxx | 1 + panda/src/gobj/internalName.h | 2 + panda/src/gobj/qpgeom.cxx | 2 +- panda/src/gobj/qpgeomLines.cxx | 1 - panda/src/gobj/qpgeomLinestrips.cxx | 3 - panda/src/gobj/qpgeomVertexData.I | 35 ++ panda/src/gobj/qpgeomVertexData.cxx | 456 +++++++++++++++++- panda/src/gobj/qpgeomVertexData.h | 24 +- panda/src/gobj/qpgeomVertexDataType.cxx | 29 +- panda/src/gobj/qpgeomVertexDataType.h | 7 +- panda/src/gobj/qpgeomVertexFormat.cxx | 56 +-- panda/src/gobj/qpgeomVertexIterator.I | 78 ++- panda/src/gobj/qpgeomVertexIterator.h | 29 +- panda/src/gobj/transformBlend.I | 277 +++++++++++ panda/src/gobj/transformBlend.cxx | 287 +++++++++++ panda/src/gobj/transformBlend.h | 123 +++++ panda/src/gobj/transformBlendPalette.I | 80 +++ panda/src/gobj/transformBlendPalette.cxx | 269 +++++++++++ panda/src/gobj/transformBlendPalette.h | 141 ++++++ panda/src/gobj/transformPalette.I | 131 +++++ panda/src/gobj/transformPalette.cxx | 259 ++++++++++ panda/src/gobj/transformPalette.h | 127 +++++ panda/src/gobj/userVertexTransform.I | 63 +++ panda/src/gobj/userVertexTransform.cxx | 144 ++++++ panda/src/gobj/userVertexTransform.h | 96 ++++ panda/src/gobj/vertexTransform.I | 71 +++ panda/src/gobj/vertexTransform.cxx | 217 +++++++++ panda/src/gobj/vertexTransform.h | 118 +++++ panda/src/pgraph/cullableObject.cxx | 1 + 40 files changed, 3113 insertions(+), 142 deletions(-) create mode 100644 panda/src/gobj/transformBlend.I create mode 100644 panda/src/gobj/transformBlend.cxx create mode 100644 panda/src/gobj/transformBlend.h create mode 100644 panda/src/gobj/transformBlendPalette.I create mode 100644 panda/src/gobj/transformBlendPalette.cxx create mode 100644 panda/src/gobj/transformBlendPalette.h create mode 100644 panda/src/gobj/transformPalette.I create mode 100644 panda/src/gobj/transformPalette.cxx create mode 100644 panda/src/gobj/transformPalette.h create mode 100644 panda/src/gobj/userVertexTransform.I create mode 100644 panda/src/gobj/userVertexTransform.cxx create mode 100644 panda/src/gobj/userVertexTransform.h create mode 100644 panda/src/gobj/vertexTransform.I create mode 100644 panda/src/gobj/vertexTransform.cxx create mode 100644 panda/src/gobj/vertexTransform.h diff --git a/panda/src/dxgsg8/dxGeomMunger8.cxx b/panda/src/dxgsg8/dxGeomMunger8.cxx index 50b1b252a2..b134652ea1 100644 --- a/panda/src/dxgsg8/dxGeomMunger8.cxx +++ b/panda/src/dxgsg8/dxGeomMunger8.cxx @@ -45,7 +45,7 @@ munge_format_impl(const qpGeomVertexFormat *orig) { if (vertex_type != (const qpGeomVertexDataType *)NULL) { new_array_format->add_data_type - (InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float); + (InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float32); } else { // If we don't have a vertex type, not much we can do. return orig; @@ -53,7 +53,7 @@ munge_format_impl(const qpGeomVertexFormat *orig) { if (normal_type != (const qpGeomVertexDataType *)NULL) { new_array_format->add_data_type - (InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float); + (InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float32); } if (color_type != (const qpGeomVertexDataType *)NULL) { @@ -67,7 +67,7 @@ munge_format_impl(const qpGeomVertexFormat *orig) { if (texcoord_type != (const qpGeomVertexDataType *)NULL) { new_array_format->add_data_type (InternalName::get_texcoord(), texcoord_type->get_num_values(), - qpGeomVertexDataType::NT_float); + qpGeomVertexDataType::NT_float32); } PT(qpGeomVertexFormat) new_format = new qpGeomVertexFormat(new_array_format); diff --git a/panda/src/egg2pg/eggLoader.cxx b/panda/src/egg2pg/eggLoader.cxx index eebdf2ce43..345af6f81b 100644 --- a/panda/src/egg2pg/eggLoader.cxx +++ b/panda/src/egg2pg/eggLoader.cxx @@ -1904,11 +1904,11 @@ make_vertex_data(const EggRenderState *render_state, PT(qpGeomVertexArrayFormat) array_format = new qpGeomVertexArrayFormat; array_format->add_data_type (InternalName::get_vertex(), vertex_pool->get_num_dimensions(), - qpGeomVertexDataType::NT_float); + qpGeomVertexDataType::NT_float32); if (vertex_pool->has_normals()) { array_format->add_data_type - (InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float); + (InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float32); } if (vertex_pool->has_colors()) { @@ -1925,7 +1925,7 @@ make_vertex_data(const EggRenderState *render_state, name = string(); } PT(InternalName) iname = InternalName::get_texcoord_name(name); - array_format->add_data_type(iname, 2, qpGeomVertexDataType::NT_float); + array_format->add_data_type(iname, 2, qpGeomVertexDataType::NT_float32); } CPT(qpGeomVertexFormat) format = @@ -1943,16 +1943,16 @@ make_vertex_data(const EggRenderState *render_state, gvi.set_vertex(vertex->get_index()); gvi.set_data_type(InternalName::get_vertex()); - gvi.set_data4(LCAST(float, vertex->get_pos4() * transform)); + gvi.set_data4f(LCAST(float, vertex->get_pos4() * transform)); if (vertex->has_normal()) { gvi.set_data_type(InternalName::get_normal()); - gvi.set_data3(LCAST(float, vertex->get_normal() * transform)); + gvi.set_data3f(LCAST(float, vertex->get_normal() * transform)); } if (vertex->has_color()) { gvi.set_data_type(InternalName::get_color()); - gvi.set_data4(vertex->get_color()); + gvi.set_data4f(vertex->get_color()); } EggVertex::const_uv_iterator uvi; @@ -1973,7 +1973,7 @@ make_vertex_data(const EggRenderState *render_state, uv = uv * (*buv).second->get_transform(); } - gvi.set_data2(LCAST(float, uv)); + gvi.set_data2f(LCAST(float, uv)); } } diff --git a/panda/src/express/pointerToArray.I b/panda/src/express/pointerToArray.I index 6fe4c806d2..e16c27dc32 100644 --- a/panda/src/express/pointerToArray.I +++ b/panda/src/express/pointerToArray.I @@ -428,7 +428,7 @@ p() const { template INLINE pvector &PointerToArray:: v() const { - nassertd((this->_void_ptr) != NULL) { + if ((this->_void_ptr) == NULL) { ((PointerToArray *)this)->reassign(new RefCountObj >); } return *((To *)(this->_void_ptr)); diff --git a/panda/src/framework/windowFramework.cxx b/panda/src/framework/windowFramework.cxx index 46d7d243bf..99bb3dd57b 100644 --- a/panda/src/framework/windowFramework.cxx +++ b/panda/src/framework/windowFramework.cxx @@ -640,21 +640,21 @@ load_default_model(const NodePath &parent) { 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)); + vertex.set_data3f(Vertexf::rfu(0.0, 0.0, 0.0)); + vertex.set_data3f(Vertexf::rfu(1.0, 0.0, 0.0)); + vertex.set_data3f(Vertexf::rfu(0.0, 0.0, 1.0)); - normal.set_data3(Normalf::back()); - normal.set_data3(Normalf::back()); - normal.set_data3(Normalf::back()); + normal.set_data3f(Normalf::back()); + normal.set_data3f(Normalf::back()); + normal.set_data3f(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); + color.set_data4f(0.5, 0.5, 1.0, 1.0); + color.set_data4f(0.5, 0.5, 1.0, 1.0); + color.set_data4f(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); + texcoord.set_data2f(0.0, 0.0); + texcoord.set_data2f(1.0, 0.0); + texcoord.set_data2f(0.0, 1.0); PT(qpGeomTriangles) tri = new qpGeomTriangles(qpGeomUsageHint::UH_static); tri->add_consecutive_vertices(0, 3); @@ -1065,15 +1065,15 @@ load_image_as_model(const Filename &filename) { 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)); + vertex.set_data3f(Vertexf::rfu(left, 0.02f, top)); + vertex.set_data3f(Vertexf::rfu(left, 0.02f, bottom)); + vertex.set_data3f(Vertexf::rfu(right, 0.02f, top)); + vertex.set_data3f(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); + texcoord.set_data2f(0.0f, 1.0f); + texcoord.set_data2f(0.0f, 0.0f); + texcoord.set_data2f(1.0f, 1.0f); + texcoord.set_data2f(1.0f, 0.0f); PT(qpGeomTristrips) strip = new qpGeomTristrips(qpGeomUsageHint::UH_static); strip->add_consecutive_vertices(0, 4); diff --git a/panda/src/glstuff/glGeomMunger_src.I b/panda/src/glstuff/glGeomMunger_src.I index 3272943b32..88a5e55448 100644 --- a/panda/src/glstuff/glGeomMunger_src.I +++ b/panda/src/glstuff/glGeomMunger_src.I @@ -24,7 +24,7 @@ //////////////////////////////////////////////////////////////////// INLINE CLP(GeomMunger):: CLP(GeomMunger)(GraphicsStateGuardian *gsg, const RenderState *state) : - ColorMunger(gsg, state, 4, qpGeomVertexDataType::NT_uint8), + ColorMunger(gsg, state, 4, qpGeomVertexDataType::NT_ufloat8), _gsg(gsg), _texture(state->get_texture()), _tex_gen(state->get_tex_gen()) diff --git a/panda/src/glstuff/glGeomMunger_src.cxx b/panda/src/glstuff/glGeomMunger_src.cxx index 67bbe549ac..c9795f2291 100644 --- a/panda/src/glstuff/glGeomMunger_src.cxx +++ b/panda/src/glstuff/glGeomMunger_src.cxx @@ -60,7 +60,7 @@ munge_format_impl(const qpGeomVertexFormat *orig) { // Replace the existing color format with the new format. new_array_format->add_data_type - (InternalName::get_color(), 4, qpGeomVertexDataType::NT_uint8, + (InternalName::get_color(), 4, qpGeomVertexDataType::NT_ufloat8, color_type->get_start()); format = qpGeomVertexFormat::register_format(new_format); diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index a42a4632dd..0faaba8e91 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -2079,6 +2079,8 @@ begin_draw_primitives(const qpGeom *geom, const qpGeomMunger *munger, case qpGeomPrimitive::PT_lines: setup_antialias_line(); break; + case qpGeomPrimitive::PT_none: + break; } } @@ -4428,11 +4430,17 @@ upload_texture_image(CLP(TextureContext) *gtc, GLenum CLP(GraphicsStateGuardian):: get_numeric_type(qpGeomVertexDataType::NumericType numeric_type) { switch (numeric_type) { - case qpGeomVertexDataType::NT_uint8: + case qpGeomVertexDataType::NT_uint16: + return GL_UNSIGNED_SHORT; + + case qpGeomVertexDataType::NT_ufloat8: return GL_UNSIGNED_BYTE; - case qpGeomVertexDataType::NT_float: + case qpGeomVertexDataType::NT_float32: return GL_FLOAT; + + case qpGeomVertexDataType::NT_packed_argb: + break; } GLCAT.error() diff --git a/panda/src/gobj/Sources.pp b/panda/src/gobj/Sources.pp index 7afcbf8ae9..2aea51abe9 100644 --- a/panda/src/gobj/Sources.pp +++ b/panda/src/gobj/Sources.pp @@ -49,7 +49,12 @@ textureContext.I textureContext.h \ texturePool.I texturePool.h \ textureStage.I textureStage.h \ - vertexBufferContext.I vertexBufferContext.h + transformBlend.I transformBlend.h \ + transformBlendPalette.I transformBlendPalette.h \ + transformPalette.I transformPalette.h \ + userVertexTransform.I userVertexTransform.h \ + vertexBufferContext.I vertexBufferContext.h \ + vertexTransform.I vertexTransform.h #define INCLUDED_SOURCES \ boundedObject.cxx \ @@ -85,7 +90,12 @@ lens.cxx \ savedContext.cxx texture.cxx textureContext.cxx texturePool.cxx \ textureStage.cxx \ - vertexBufferContext.cxx + transformBlend.cxx \ + transformBlendPalette.cxx \ + transformPalette.cxx \ + userVertexTransform.cxx \ + vertexBufferContext.cxx \ + vertexTransform.cxx #define INSTALL_HEADERS \ boundedObject.I boundedObject.h \ @@ -127,7 +137,12 @@ textureContext.I textureContext.h \ texturePool.I texturePool.h \ textureStage.I textureStage.h \ - vertexBufferContext.I vertexBufferContext.h + transformBlend.I transformBlend.h \ + transformBlendPalette.I transformBlendPalette.h \ + transformPalette.I transformPalette.h \ + userVertexTransform.I userVertexTransform.h \ + vertexBufferContext.I vertexBufferContext.h \ + vertexTransform.I vertexTransform.h #define IGATESCAN all diff --git a/panda/src/gobj/config_gobj.cxx b/panda/src/gobj/config_gobj.cxx index 0946557bab..3746c0ac4a 100644 --- a/panda/src/gobj/config_gobj.cxx +++ b/panda/src/gobj/config_gobj.cxx @@ -43,6 +43,10 @@ #include "texture.h" #include "textureStage.h" #include "textureContext.h" +#include "transformBlendPalette.h" +#include "transformPalette.h" +#include "userVertexTransform.h" +#include "vertexTransform.h" #include "geomContext.h" #include "vertexBufferContext.h" #include "indexBufferContext.h" @@ -211,6 +215,10 @@ ConfigureFn(config_gobj) { Texture::init_type(); dDrawable::init_type(); TextureStage::init_type(); + TransformBlendPalette::init_type(); + TransformPalette::init_type(); + UserVertexTransform::init_type(); + VertexTransform::init_type(); InternalName::init_type(); //Registration of writeable object's creation @@ -242,6 +250,9 @@ ConfigureFn(config_gobj) { PerspectiveLens::register_with_read_factory(); Texture::register_with_read_factory(); TextureStage::register_with_read_factory(); + TransformBlendPalette::register_with_read_factory(); + TransformPalette::register_with_read_factory(); + UserVertexTransform::register_with_read_factory(); InternalName::register_with_read_factory(); } diff --git a/panda/src/gobj/gobj_composite2.cxx b/panda/src/gobj/gobj_composite2.cxx index c86de9bd1d..dd24bdce72 100644 --- a/panda/src/gobj/gobj_composite2.cxx +++ b/panda/src/gobj/gobj_composite2.cxx @@ -16,4 +16,9 @@ #include "textureContext.cxx" #include "texturePool.cxx" #include "textureStage.cxx" +#include "transformBlend.cxx" +#include "transformBlendPalette.cxx" +#include "transformPalette.cxx" +#include "userVertexTransform.cxx" #include "vertexBufferContext.cxx" +#include "vertexTransform.cxx" diff --git a/panda/src/gobj/internalName.I b/panda/src/gobj/internalName.I index 0f9ab8e32b..fc734dad56 100644 --- a/panda/src/gobj/internalName.I +++ b/panda/src/gobj/internalName.I @@ -178,6 +178,19 @@ get_color() { return _color; } +//////////////////////////////////////////////////////////////////// +// Function: InternalName::get_transform_blend +// Access: Published, Static +// Description: Returns the standard InternalName "transform_blend". +//////////////////////////////////////////////////////////////////// +INLINE PT(InternalName) InternalName:: +get_transform_blend() { + if (_transform_blend == (InternalName *)NULL) { + _transform_blend = InternalName::make("transform_blend"); + } + return _transform_blend; +} + INLINE ostream & operator << (ostream &out, const InternalName &tcn) { tcn.output(out); diff --git a/panda/src/gobj/internalName.cxx b/panda/src/gobj/internalName.cxx index 69b6ce11a0..8813c77db9 100644 --- a/panda/src/gobj/internalName.cxx +++ b/panda/src/gobj/internalName.cxx @@ -32,6 +32,7 @@ PT(InternalName) InternalName::_tangent; PT(InternalName) InternalName::_binormal; PT(InternalName) InternalName::_texcoord; PT(InternalName) InternalName::_color; +PT(InternalName) InternalName::_transform_blend; TypeHandle InternalName::_type_handle; TypeHandle InternalName::_texcoord_type_handle; diff --git a/panda/src/gobj/internalName.h b/panda/src/gobj/internalName.h index 2626344dcc..d789eb3ba2 100644 --- a/panda/src/gobj/internalName.h +++ b/panda/src/gobj/internalName.h @@ -67,6 +67,7 @@ PUBLISHED: INLINE static PT(InternalName) get_texcoord(); INLINE static PT(InternalName) get_texcoord_name(const string &name); INLINE static PT(InternalName) get_color(); + INLINE static PT(InternalName) get_transform_blend(); private: PT(InternalName) _parent; @@ -84,6 +85,7 @@ private: static PT(InternalName) _binormal; static PT(InternalName) _texcoord; static PT(InternalName) _color; + static PT(InternalName) _transform_blend; public: // Datagram stuff diff --git a/panda/src/gobj/qpgeom.cxx b/panda/src/gobj/qpgeom.cxx index e1716f3581..07b933ef1b 100644 --- a/panda/src/gobj/qpgeom.cxx +++ b/panda/src/gobj/qpgeom.cxx @@ -397,7 +397,7 @@ draw(GraphicsStateGuardianBase *gsg, const qpGeomMunger *munger, //////////////////////////////////////////////////////////////////// // Function: qpGeom::get_next_modified -// Access: Public +// Access: Public, Static // Description: Returns a monotonically increasing sequence. Each // time this is called, a new sequence number is // returned, higher than the previous value. diff --git a/panda/src/gobj/qpgeomLines.cxx b/panda/src/gobj/qpgeomLines.cxx index f327e0f260..55eaa89d0b 100644 --- a/panda/src/gobj/qpgeomLines.cxx +++ b/panda/src/gobj/qpgeomLines.cxx @@ -114,7 +114,6 @@ CPTA_ushort qpGeomLines:: rotate_impl() const { // To rotate lines, we just move reverse the pairs of vertices. CPTA_ushort vertices = get_vertices(); - ShadeModel shade_model = get_shade_model(); PTA_ushort new_vertices; new_vertices.reserve(vertices.size()); diff --git a/panda/src/gobj/qpgeomLinestrips.cxx b/panda/src/gobj/qpgeomLinestrips.cxx index 4978981e3f..3ae551fe21 100644 --- a/panda/src/gobj/qpgeomLinestrips.cxx +++ b/panda/src/gobj/qpgeomLinestrips.cxx @@ -151,12 +151,9 @@ rotate_impl() const { CPTA_int::const_iterator ei; for (ei = ends.begin(); ei != ends.end(); ++ei) { int end = (*ei); - int num_vertices = end - begin; - for (int vi = end - 1; vi >= begin; --vi) { new_vertices.push_back(vertices[vi]); } - begin = end; } nassertr(new_vertices.size() == vertices.size(), vertices); diff --git a/panda/src/gobj/qpgeomVertexData.I b/panda/src/gobj/qpgeomVertexData.I index cdb774d546..8a770a650a 100644 --- a/panda/src/gobj/qpgeomVertexData.I +++ b/panda/src/gobj/qpgeomVertexData.I @@ -91,6 +91,38 @@ get_array(int i) const { return cdata->_arrays[i]; } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::get_transform_blend_palette +// Access: Published +// Description: Returns a const pointer to the TransformBlendPalette +// assigned to this data. Vertices within the table +// will index into this palette to indicate their +// dynamic skinning information; this table is used when +// the vertex animation is to be performed by the CPU +// (but also see get_transform_palette()). +// +// This will return NULL if the vertex data does not +// have a TransformBlendPalette assigned (which implies +// the vertices will not be animated by the CPU). +//////////////////////////////////////////////////////////////////// +INLINE const TransformBlendPalette *qpGeomVertexData:: +get_transform_blend_palette() const { + CDReader cdata(_cycler); + return cdata->_transform_blend_palette; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::clear_transform_blend_palette +// Access: Published +// Description: Sets the TransformBlendPalette pointer to NULL, +// removing the palette from the vertex data. This +// disables CPU-driven vertex animation. +//////////////////////////////////////////////////////////////////// +INLINE void qpGeomVertexData:: +clear_transform_blend_palette() { + set_transform_blend_palette(NULL); +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomVertexData::get_modified // Access: Published @@ -121,6 +153,9 @@ CData() { INLINE qpGeomVertexData::CData:: CData(const qpGeomVertexData::CData ©) : _arrays(copy._arrays), + _transform_blend_palette(copy._transform_blend_palette), + _computed_vertices(copy._computed_vertices), + _computed_vertices_modified(copy._computed_vertices_modified), _modified(copy._modified) { } diff --git a/panda/src/gobj/qpgeomVertexData.cxx b/panda/src/gobj/qpgeomVertexData.cxx index 1eef7e17b4..609272edd9 100644 --- a/panda/src/gobj/qpgeomVertexData.cxx +++ b/panda/src/gobj/qpgeomVertexData.cxx @@ -28,6 +28,7 @@ TypeHandle qpGeomVertexData::_type_handle; PStatCollector qpGeomVertexData::_convert_pcollector("Cull:Munge:Convert"); PStatCollector qpGeomVertexData::_scale_color_pcollector("Cull:Munge:Scale color"); PStatCollector qpGeomVertexData::_set_color_pcollector("Cull:Munge:Set color"); +PStatCollector qpGeomVertexData::_compute_vertices_pcollector("Cull:Compute vertices"); //////////////////////////////////////////////////////////////////// // Function: qpGeomVertexData::Default Constructor @@ -137,6 +138,7 @@ clear_vertices() { (*ai)->clear_vertices(); } cdata->_modified = qpGeom::get_next_modified(); + cdata->_computed_vertices.clear(); } //////////////////////////////////////////////////////////////////// @@ -160,6 +162,7 @@ modify_array(int i) { cdata->_arrays[i] = new qpGeomVertexArrayData(*cdata->_arrays[i]); } cdata->_modified = qpGeom::get_next_modified(); + cdata->_computed_vertices_modified = UpdateSeq(); return cdata->_arrays[i]; } @@ -178,6 +181,48 @@ set_array(int i, const qpGeomVertexArrayData *array) { nassertv(i >= 0 && i < (int)cdata->_arrays.size()); cdata->_arrays[i] = (qpGeomVertexArrayData *)array; cdata->_modified = qpGeom::get_next_modified(); + cdata->_computed_vertices_modified = UpdateSeq(); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::modify_transform_blend_palette +// Access: Published +// Description: Returns a modifiable pointer to the current +// TransformBlendPalette on this vertex data, if any, or +// NULL if there is not a TransformBlendPalette. See +// get_transform_blend_palette(). +//////////////////////////////////////////////////////////////////// +TransformBlendPalette *qpGeomVertexData:: +modify_transform_blend_palette() { + // Perform copy-on-write: if the reference count on the palette is + // greater than 1, assume some other GeomVertexData has the same + // pointer, so make a copy of it first. + CDWriter cdata(_cycler); + + if (cdata->_transform_blend_palette->get_ref_count() > 1) { + cdata->_transform_blend_palette = new TransformBlendPalette(*cdata->_transform_blend_palette); + } + cdata->_modified = qpGeom::get_next_modified(); + cdata->_computed_vertices_modified = UpdateSeq(); + + return cdata->_transform_blend_palette; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::set_transform_blend_palette +// Access: Published +// Description: Replaces the TransformBlendPalette on this vertex +// data with the indicated palette. The length of this +// palette should be consistent with the maximum palette +// index assigned to the vertices under the +// "transform_blend" name. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexData:: +set_transform_blend_palette(const TransformBlendPalette *palette) { + CDWriter cdata(_cycler); + cdata->_transform_blend_palette = (TransformBlendPalette *)palette; + cdata->_modified = qpGeom::get_next_modified(); + cdata->_computed_vertices_modified = UpdateSeq(); } //////////////////////////////////////////////////////////////////// @@ -226,6 +271,7 @@ convert_to(const qpGeomVertexFormat *new_format) const { PT(qpGeomVertexData) new_data = new qpGeomVertexData(new_format, get_usage_hint()); + new_data->set_transform_blend_palette(get_transform_blend_palette()); pset done_arrays; @@ -319,15 +365,16 @@ scale_color(const LVecBase4f &color_scale, int num_components, PStatTimer timer(_scale_color_pcollector); PT(qpGeomVertexData) new_data = replace_data_type - (InternalName::get_color(), num_components, numeric_type); + (InternalName::get_color(), num_components, numeric_type, + get_usage_hint(), true); // Now go through and apply the scale, copying it to the new data. qpGeomVertexIterator from(this, InternalName::get_color()); qpGeomVertexIterator to(new_data, InternalName::get_color()); for (int i = 0; i < num_vertices; i++) { - Colorf color = from.get_data4(); - to.set_data4(color[0] * color_scale[0], + Colorf color = from.get_data4f(); + to.set_data4f(color[0] * color_scale[0], color[1] * color_scale[1], color[2] * color_scale[2], color[3] * color_scale[3]); @@ -359,18 +406,62 @@ set_color(const Colorf &color, int num_components, PStatTimer timer(_set_color_pcollector); PT(qpGeomVertexData) new_data = replace_data_type - (InternalName::get_color(), num_components, numeric_type); + (InternalName::get_color(), num_components, numeric_type, + get_usage_hint(), true); // Now go through and set the new color value. qpGeomVertexIterator to(new_data, InternalName::get_color()); for (int i = 0; i < num_vertices; i++) { - to.set_data4(color); + to.set_data4f(color); } return new_data; } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::compute_vertices +// Access: Published +// Description: Returns a GeomVertexData that represents the results +// of computing the vertex animation on the CPU for this +// GeomVertexData. +// +// If there is no CPU-defined vertex animation on this +// object, this just returns the original object. +// +// If there is vertex animation, but the VertexTransform +// values have not changed since last time, this may +// return the same pointer it returned previously. Even +// if the VertexTransform values have changed, it may +// still return the same pointer, but with its contents +// modified (this is preferred, since it allows the +// graphics backend to update vertex buffers optimally). +//////////////////////////////////////////////////////////////////// +CPT(qpGeomVertexData) qpGeomVertexData:: +compute_vertices() const { + CDReader cdata(_cycler); + if (cdata->_transform_blend_palette == (TransformBlendPalette *)NULL) { + // No vertex animation. + return this; + } + + if (cdata->_computed_vertices == (qpGeomVertexData *)NULL) { + CDWriter cdataw(((qpGeomVertexData *)this)->_cycler, cdata); + ((qpGeomVertexData *)this)->make_computed_vertices(cdataw); + return cdataw->_computed_vertices; + } else { + UpdateSeq blend_modified = cdata->_transform_blend_palette->get_modified(); + if (cdata->_computed_vertices_modified == blend_modified) { + // No changes. + return cdata->_computed_vertices; + } + CDWriter cdataw(((qpGeomVertexData *)this)->_cycler, cdata); + cdataw->_computed_vertices_modified = blend_modified; + ((qpGeomVertexData *)this)->update_computed_vertices(cdataw); + return cdataw->_computed_vertices; + } +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomVertexData::replace_data_type // Access: Published @@ -380,10 +471,16 @@ set_color(const Colorf &color, int num_components, // new table will be added as a new array; if the old // table was interleaved with a previous array, the // previous array will not be repacked. +// +// If num_components is 0, the indicated name is simply +// removed from the type, without replacing it with +// anything else. //////////////////////////////////////////////////////////////////// PT(qpGeomVertexData) qpGeomVertexData:: replace_data_type(const InternalName *name, int num_components, - qpGeomVertexDataType::NumericType numeric_type) const { + qpGeomVertexDataType::NumericType numeric_type, + qpGeomUsageHint::UsageHint usage_hint, + bool keep_animation) const { PT(qpGeomVertexFormat) new_format = new qpGeomVertexFormat(*_format); // Remove the old description of the type from the format. @@ -405,13 +502,20 @@ replace_data_type(const InternalName *name, int num_components, } // Now define a new array to contain just the type. - PT(qpGeomVertexArrayFormat) type_array_format = - new qpGeomVertexArrayFormat(name, num_components, numeric_type); - int new_type_array = new_format->add_array(type_array_format); - + int new_type_array = -1; + if (num_components != 0) { + PT(qpGeomVertexArrayFormat) type_array_format = + new qpGeomVertexArrayFormat(name, num_components, numeric_type); + new_type_array = new_format->add_array(type_array_format); + } + PT(qpGeomVertexData) new_data = new qpGeomVertexData(qpGeomVertexFormat::register_format(new_format), - get_usage_hint()); + usage_hint); + if (keep_animation) { + new_data->set_transform_blend_palette(get_transform_blend_palette()); + } + int j = 0; int num_arrays = get_num_arrays(); @@ -431,14 +535,16 @@ replace_data_type(const InternalName *name, int num_components, } } - nassertr(j == new_type_array, new_data); + if (new_type_array != -1) { + nassertr(j == new_type_array, new_data); - // For the new type array, we set up a temporary array that has - // room for the right number of vertices. - PT(qpGeomVertexArrayData) new_array = new qpGeomVertexArrayData - (new_format->get_array(j), get_usage_hint()); - new_array->set_num_vertices(get_num_vertices()); - new_data->set_array(j, new_array); + // For the new type array, we set up a temporary array that has + // room for the right number of vertices. + PT(qpGeomVertexArrayData) new_array = new qpGeomVertexArrayData + (new_format->get_array(j), get_usage_hint()); + new_array->set_num_vertices(get_num_vertices()); + new_data->set_array(j, new_array); + } return new_data; } @@ -496,7 +602,26 @@ set_data(int array, const qpGeomVertexDataType *data_type, nassertv(element >= 0 && element + data_type->get_total_bytes() <= (int)array_data.size()); switch (data_type->get_numeric_type()) { - case qpGeomVertexDataType::NT_uint8: + case qpGeomVertexDataType::NT_uint16: + { + // Elevate or truncate to the right number of components. + int i = 0; + int min_values = min(num_values, data_type->get_num_values()); + while (i < min_values) { + *(PN_uint16 *)&array_data[element] = (int)data[i]; + element += sizeof(PN_uint16); + ++i; + } + while (i < data_type->get_num_values()) { + *(PN_uint16 *)&array_data[element] = 0; + element += sizeof(PN_uint16); + ++i; + } + } + + break; + + case qpGeomVertexDataType::NT_ufloat8: { int i = 0; int min_values = min(num_values, data_type->get_num_values()); @@ -528,7 +653,7 @@ set_data(int array, const qpGeomVertexDataType *data_type, } break; - case qpGeomVertexDataType::NT_float: + case qpGeomVertexDataType::NT_float32: if (num_values == 4 && sizeof(float) == sizeof(PN_float32)) { // The easy way: we can memcpy the data directly in. memcpy(&array_data[element], data, data_type->get_total_bytes()); @@ -577,7 +702,23 @@ get_data(int array, const qpGeomVertexDataType *data_type, nassertv(element >= 0 && element + data_type->get_total_bytes() <= (int)array_data.size()); switch (data_type->get_numeric_type()) { - case qpGeomVertexDataType::NT_uint8: + case qpGeomVertexDataType::NT_uint16: + { + int i = 0; + int min_values = min(num_values, data_type->get_num_values()); + while (i < min_values) { + data[i] = *(PN_uint16 *)&array_data[element]; + element += sizeof(PN_uint16); + ++i; + } + while (i < num_values) { + data[i] = 0; + ++i; + } + } + break; + + case qpGeomVertexDataType::NT_ufloat8: { int i = 0; int min_values = min(num_values, data_type->get_num_values()); @@ -607,7 +748,7 @@ get_data(int array, const qpGeomVertexDataType *data_type, } break; - case qpGeomVertexDataType::NT_float: + case qpGeomVertexDataType::NT_float32: if (num_values == data_type->get_num_values() && sizeof(float) == sizeof(PN_float32)) { memcpy(data, &array_data[element], num_values * sizeof(PN_float32)); @@ -628,7 +769,194 @@ get_data(int array, const qpGeomVertexDataType *data_type, ++i; } } + break; + } +} +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::set_data +// Access: Public +// 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 int *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]->get_data_size_bytes(); + if (element + data_type->get_total_bytes() > array_size) { + // Whoops, we need more vertices! + CDWriter cdataw(_cycler, cdata); + do_set_num_vertices(vertex + 1, cdataw); + } + } + + PTA_uchar array_data = modify_array(array)->modify_data(); + nassertv(element >= 0 && element + data_type->get_total_bytes() <= (int)array_data.size()); + + switch (data_type->get_numeric_type()) { + case qpGeomVertexDataType::NT_uint16: + { + // Elevate or truncate to the right number of components. + int i = 0; + int min_values = min(num_values, data_type->get_num_values()); + while (i < min_values) { + *(PN_uint16 *)&array_data[element] = data[i]; + element += sizeof(PN_uint16); + ++i; + } + while (i < data_type->get_num_values()) { + *(PN_uint16 *)&array_data[element] = 0; + element += sizeof(PN_uint16); + ++i; + } + } + + break; + + case qpGeomVertexDataType::NT_ufloat8: + { + int i = 0; + int min_values = min(num_values, data_type->get_num_values()); + while (i < min_values) { + array_data[element] = data[i]; + element += 1; + ++i; + } + while (i < data_type->get_num_values()) { + array_data[element] = 0; + element += 1; + ++i; + } + } + break; + + case qpGeomVertexDataType::NT_packed_argb: + { + if (num_values == 4) { + *(PN_uint32 *)&array_data[element] = pack_argb(data); + } else { + // Elevate (or truncate) to 4 components. + int data4[4]; + memset(data4, 0, 4 * sizeof(int)); + memcpy(data4, data, min(4, num_values) * sizeof(int)); + *(PN_uint32 *)&array_data[element] = pack_argb(data4); + } + } + break; + + case qpGeomVertexDataType::NT_float32: + { + // Elevate or truncate to the right number of components. + int i = 0; + int min_values = min(num_values, data_type->get_num_values()); + while (i < min_values) { + *(PN_float32 *)&array_data[element] = data[i]; + element += sizeof(PN_float32); + ++i; + } + while (i < data_type->get_num_values()) { + *(PN_float32 *)&array_data[element] = 0.0f; + element += sizeof(PN_float32); + ++i; + } + } + + break; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::get_data +// Access: Public +// 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, int *data, int num_values) const { + CPTA_uchar array_data = get_array(array)->get_data(); + 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_uint16: + { + int i = 0; + int min_values = min(num_values, data_type->get_num_values()); + while (i < min_values) { + data[i] = *(PN_uint16 *)&array_data[element]; + element += sizeof(PN_uint16); + ++i; + } + while (i < num_values) { + data[i] = 0; + ++i; + } + } + break; + + case qpGeomVertexDataType::NT_ufloat8: + { + int i = 0; + int min_values = min(num_values, data_type->get_num_values()); + while (i < min_values) { + int value = *(unsigned char *)&array_data[element]; + element += 1; + data[i] = value; + ++i; + } + while (i < num_values) { + data[i] = 0; + ++i; + } + } + break; + + case qpGeomVertexDataType::NT_packed_argb: + { + if (num_values == 4) { + unpack_argb(data, *(PN_uint32 *)&array_data[element]); + } else { + int data4[4]; + unpack_argb(data4, *(PN_uint32 *)&array_data[element]); + memset(data, 0, num_values * sizeof(int)); + memcpy(data, data4, min(num_values, 4) * sizeof(int)); + } + } + break; + + case qpGeomVertexDataType::NT_float32: + { + int i = 0; + int min_values = min(num_values, data_type->get_num_values()); + while (i < min_values) { + data[i] = (int)*(PN_float32 *)&array_data[element]; + element += sizeof(PN_float32); + ++i; + } + while (i < num_values) { + data[i] = 0; + ++i; + } + } break; } } @@ -774,6 +1102,35 @@ unpack_argb(float data[4], unsigned int packed_argb) { data[3] = (float)((packed_argb >> 24) & 0xff) / 255.0f; } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::pack_argb +// Access: Public, Static +// Description: Packs four ints, stored R, G, B, A, into a +// packed_argb value. +//////////////////////////////////////////////////////////////////// +unsigned int qpGeomVertexData:: +pack_argb(const int data[4]) { + unsigned int r = ((unsigned int)data[0]) & 0xff; + unsigned int g = ((unsigned int)data[1]) & 0xff; + unsigned int b = ((unsigned int)data[2]) & 0xff; + unsigned int a = ((unsigned int)data[3]) & 0xff; + return ((a << 24) | (r << 16) | (g << 8) | b); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::unpack_argb +// Access: Public, Static +// Description: Unpacks a packed_argb value into four ints, stored +// R, G, B, A. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexData:: +unpack_argb(int data[4], unsigned int packed_argb) { + data[0] = (int)((packed_argb >> 16) & 0xff); + data[1] = (int)((packed_argb >> 8) & 0xff); + data[2] = (int)(packed_argb & 0xff); + data[3] = (int)((packed_argb >> 24) & 0xff); +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomVertexData::do_set_num_vertices // Access: Private @@ -798,11 +1155,66 @@ do_set_num_vertices(int n, qpGeomVertexData::CDWriter &cdata) { if (any_changed) { cdata->_modified = qpGeom::get_next_modified(); + cdata->_computed_vertices.clear(); } return any_changed; } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::make_computed_vertices +// Access: Private +// Description: Creates the GeomVertexData that represents the +// results of computing the vertex animation on the CPU. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexData:: +make_computed_vertices(qpGeomVertexData::CDWriter &cdata) { + // First, make a new format that doesn't have the transform_blend + // array. + cdata->_computed_vertices = replace_data_type + (InternalName::get_transform_blend(), 0, qpGeomVertexDataType::NT_uint16, + qpGeomUsageHint::UH_dynamic, false); + + // Now fill it up with the appropriate data. + update_computed_vertices(cdata); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::update_computed_vertices +// Access: Private +// Description: Recomputes the results of computing the vertex +// animation on the CPU, and applies them to the +// existing computed_vertices object. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexData:: +update_computed_vertices(qpGeomVertexData::CDWriter &cdata) { + int num_vertices = get_num_vertices(); + + if (gobj_cat.is_debug()) { + gobj_cat.debug() + << "Computing " << num_vertices << " vertices.\n"; + } + PStatTimer timer(_compute_vertices_pcollector); + + CPT(TransformBlendPalette) palette = cdata->_transform_blend_palette; + nassertv(palette != (TransformBlendPalette *)NULL); + PT(qpGeomVertexData) new_data = cdata->_computed_vertices; + + // Now go through and apply the scale, copying it to the new data. + qpGeomVertexIterator from(this, InternalName::get_vertex()); + qpGeomVertexIterator blendi(this, InternalName::get_transform_blend()); + qpGeomVertexIterator to(new_data, InternalName::get_vertex()); + + for (int i = 0; i < num_vertices; i++) { + LPoint4f vertex = from.get_data4f(); + int bi = blendi.get_data1i(); + const TransformBlend &blend = palette->get_blend(bi); + blend.transform_point(vertex); + + to.set_data4f(vertex); + } +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomVertexData::register_with_read_factory // Access: Public, Static diff --git a/panda/src/gobj/qpgeomVertexData.h b/panda/src/gobj/qpgeomVertexData.h index f8d26e9f77..282922cbda 100644 --- a/panda/src/gobj/qpgeomVertexData.h +++ b/panda/src/gobj/qpgeomVertexData.h @@ -25,6 +25,7 @@ #include "qpgeomVertexDataType.h" #include "qpgeomVertexArrayData.h" #include "qpgeomUsageHint.h" +#include "transformBlendPalette.h" #include "internalName.h" #include "cycleData.h" #include "cycleDataReader.h" @@ -81,6 +82,11 @@ PUBLISHED: qpGeomVertexArrayData *modify_array(int i); void set_array(int i, const qpGeomVertexArrayData *array); + INLINE const TransformBlendPalette *get_transform_blend_palette() const; + TransformBlendPalette *modify_transform_blend_palette(); + void set_transform_blend_palette(const TransformBlendPalette *palette); + INLINE void clear_transform_blend_palette(); + int get_num_bytes() const; INLINE UpdateSeq get_modified() const; @@ -92,9 +98,13 @@ PUBLISHED: set_color(const Colorf &color, int num_components, qpGeomVertexDataType::NumericType numeric_type) const; + CPT(qpGeomVertexData) compute_vertices() const; + PT(qpGeomVertexData) replace_data_type(const InternalName *name, int num_components, - qpGeomVertexDataType::NumericType numeric_type) const; + qpGeomVertexDataType::NumericType numeric_type, + qpGeomUsageHint::UsageHint usage_hint, + bool keep_animation) const; void output(ostream &out) const; void write(ostream &out, int indent_level = 0) const; @@ -104,6 +114,10 @@ public: 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; + void set_data(int array, const qpGeomVertexDataType *data_type, + int vertex, const int *data, int num_values); + void get_data(int array, const qpGeomVertexDataType *data_type, + int vertex, int *data, int num_values) const; bool get_array_info(const InternalName *name, const qpGeomVertexArrayData *&array_data, @@ -117,6 +131,8 @@ public: static unsigned int pack_argb(const float data[4]); static void unpack_argb(float data[4], unsigned int packed_argb); + static unsigned int pack_argb(const int data[4]); + static void unpack_argb(int data[4], unsigned int packed_argb); private: CPT(qpGeomVertexFormat) _format; @@ -135,6 +151,9 @@ private: virtual void fillin(DatagramIterator &scan, BamReader *manager); Arrays _arrays; + PT(TransformBlendPalette) _transform_blend_palette; + PT(qpGeomVertexData) _computed_vertices; + UpdateSeq _computed_vertices_modified; UpdateSeq _modified; }; @@ -144,10 +163,13 @@ private: private: bool do_set_num_vertices(int n, CDWriter &cdata); + void make_computed_vertices(CDWriter &cdata); + void update_computed_vertices(CDWriter &cdata); static PStatCollector _convert_pcollector; static PStatCollector _scale_color_pcollector; static PStatCollector _set_color_pcollector; + static PStatCollector _compute_vertices_pcollector; public: static void register_with_read_factory(); diff --git a/panda/src/gobj/qpgeomVertexDataType.cxx b/panda/src/gobj/qpgeomVertexDataType.cxx index a732dcb814..561ac24d9c 100644 --- a/panda/src/gobj/qpgeomVertexDataType.cxx +++ b/panda/src/gobj/qpgeomVertexDataType.cxx @@ -35,7 +35,11 @@ qpGeomVertexDataType(const InternalName *name, int num_components, nassertv(num_components > 0 && start >= 0); switch (numeric_type) { - case NT_uint8: + case NT_uint16: + _component_bytes = 2; // sizeof(PN_uint16) + break; + + case NT_ufloat8: _component_bytes = 1; break; @@ -44,7 +48,7 @@ qpGeomVertexDataType(const InternalName *name, int num_components, _num_values *= 4; break; - case NT_float: + case NT_float32: _component_bytes = 4; // sizeof(PN_float32) break; } @@ -61,7 +65,7 @@ qpGeomVertexDataType(const InternalName *name, int num_components, const qpGeomVertexDataType &qpGeomVertexDataType:: error() { static qpGeomVertexDataType error_result - (InternalName::get_error(), 1, NT_uint8, 0); + (InternalName::get_error(), 1, NT_ufloat8, 0); return error_result; } @@ -101,10 +105,10 @@ copy_records(unsigned char *to, int to_stride, // 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 && + } else if (get_numeric_type() == NT_ufloat8 && 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 && + } else if (get_numeric_type() == NT_packed_argb && from_type->get_numeric_type() == NT_ufloat8 && get_num_values() == from_type->get_num_values()) { copy_uint8_to_argb(to, to_stride, from, from_stride, from_type, num_records); } else { @@ -223,7 +227,10 @@ copy_generic(unsigned char *to, int to_stride, float qpGeomVertexDataType:: get_value(const unsigned char *data, int n) const { switch (get_numeric_type()) { - case NT_uint8: + case NT_uint16: + return (float)data[n]; + + case NT_ufloat8: return (float)data[n] / 255.0f; case qpGeomVertexDataType::NT_packed_argb: @@ -245,7 +252,7 @@ get_value(const unsigned char *data, int n) const { } break; - case qpGeomVertexDataType::NT_float: + case qpGeomVertexDataType::NT_float32: { const PN_float32 *float_array = (const PN_float32 *)data; return float_array[n]; @@ -263,7 +270,11 @@ get_value(const unsigned char *data, int n) const { void qpGeomVertexDataType:: set_value(unsigned char *data, int n, float value) const { switch (get_numeric_type()) { - case NT_uint8: + case NT_uint16: + data[n] = (int)value; + break; + + case NT_ufloat8: data[n] = (int)(value * 255.0f); break; @@ -301,7 +312,7 @@ set_value(unsigned char *data, int n, float value) const { } break; - case qpGeomVertexDataType::NT_float: + case qpGeomVertexDataType::NT_float32: 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 index 28be593950..ccc8d398a9 100644 --- a/panda/src/gobj/qpgeomVertexDataType.h +++ b/panda/src/gobj/qpgeomVertexDataType.h @@ -35,9 +35,10 @@ class EXPCL_PANDA qpGeomVertexDataType { PUBLISHED: enum NumericType { - NT_uint8, - NT_packed_argb, // DirectX style - NT_float, + NT_uint16, // A short integer 0..65535 + NT_ufloat8, // A floating-point number 0..1 packed into a byte + NT_float32, // A true floating-point number + NT_packed_argb, // DirectX style color specification }; INLINE qpGeomVertexDataType(const InternalName *name, int num_components, diff --git a/panda/src/gobj/qpgeomVertexFormat.cxx b/panda/src/gobj/qpgeomVertexFormat.cxx index c460dff99b..2753136901 100644 --- a/panda/src/gobj/qpgeomVertexFormat.cxx +++ b/panda/src/gobj/qpgeomVertexFormat.cxx @@ -526,64 +526,64 @@ fillin(DatagramIterator &scan, BamReader *manager) { qpGeomVertexFormat::Registry:: Registry() { _v3 = register_format(new qpGeomVertexArrayFormat - (InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float)); + (InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float32)); _v3n3 = register_format(new qpGeomVertexArrayFormat - (InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float, - InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float)); + (InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float32, + InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float32)); _v3t2 = register_format(new qpGeomVertexArrayFormat - (InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float, - InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float)); + (InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float32, + InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float32)); _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)); + (InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float32, + InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float32, + InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float32)); // Define the DirectX-style packed color formats _v3cp = register_format(new qpGeomVertexArrayFormat - (InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float, + (InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float32, 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_vertex(), 3, qpGeomVertexDataType::NT_float32, + InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float32, InternalName::get_color(), 1, qpGeomVertexDataType::NT_packed_argb)); _v3cpt2 = register_format(new qpGeomVertexArrayFormat - (InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float, + (InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float32, InternalName::get_color(), 1, qpGeomVertexDataType::NT_packed_argb, - InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float)); + InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float32)); _v3n3cpt2 = register_format(new qpGeomVertexArrayFormat - (InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float, - InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float, + (InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float32, + InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float32, InternalName::get_color(), 1, qpGeomVertexDataType::NT_packed_argb, - InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float)); + InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float32)); // 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)); + (InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float32, + InternalName::get_color(), 4, qpGeomVertexDataType::NT_ufloat8)); _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)); + (InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float32, + InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float32, + InternalName::get_color(), 4, qpGeomVertexDataType::NT_ufloat8)); _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)); + (InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float32, + InternalName::get_color(), 4, qpGeomVertexDataType::NT_ufloat8, + InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float32)); _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)); + (InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float32, + InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float32, + InternalName::get_color(), 4, qpGeomVertexDataType::NT_ufloat8, + InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float32)); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/qpgeomVertexIterator.I b/panda/src/gobj/qpgeomVertexIterator.I index d3124179d3..6a1cd4b92b 100644 --- a/panda/src/gobj/qpgeomVertexIterator.I +++ b/panda/src/gobj/qpgeomVertexIterator.I @@ -291,99 +291,99 @@ get_write_vertex() const { } //////////////////////////////////////////////////////////////////// -// Function: qpGeomVertexIterator::set_data1 +// Function: qpGeomVertexIterator::set_data1f // 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) { +set_data1f(float data) { nassertv(!_const_data); _data->set_data(_array, _data_type, _write_vertex, &data, 1); ++_write_vertex; } //////////////////////////////////////////////////////////////////// -// Function: qpGeomVertexIterator::set_data2 +// Function: qpGeomVertexIterator::set_data2f // 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)); +set_data2f(float x, float y) { + set_data2f(LVecBase2f(x, y)); } //////////////////////////////////////////////////////////////////// -// Function: qpGeomVertexIterator::set_data2 +// Function: qpGeomVertexIterator::set_data2f // 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) { +set_data2f(const LVecBase2f &data) { nassertv(!_const_data); _data->set_data(_array, _data_type, _write_vertex, data.get_data(), 2); ++_write_vertex; } //////////////////////////////////////////////////////////////////// -// Function: qpGeomVertexIterator::set_data3 +// Function: qpGeomVertexIterator::set_data3f // 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)); +set_data3f(float x, float y, float z) { + set_data3f(LVecBase3f(x, y, z)); } //////////////////////////////////////////////////////////////////// -// Function: qpGeomVertexIterator::set_data3 +// Function: qpGeomVertexIterator::set_data3f // 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) { +set_data3f(const LVecBase3f &data) { nassertv(!_const_data); _data->set_data(_array, _data_type, _write_vertex, data.get_data(), 3); ++_write_vertex; } //////////////////////////////////////////////////////////////////// -// Function: qpGeomVertexIterator::set_data4 +// Function: qpGeomVertexIterator::set_data4f // 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)); +set_data4f(float x, float y, float z, float w) { + set_data4f(LVecBase4f(x, y, z, w)); } //////////////////////////////////////////////////////////////////// -// Function: qpGeomVertexIterator::set_data4 +// Function: qpGeomVertexIterator::set_data4f // 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) { +set_data4f(const LVecBase4f &data) { nassertv(!_const_data); _data->set_data(_array, _data_type, _write_vertex, data.get_data(), 4); ++_write_vertex; } //////////////////////////////////////////////////////////////////// -// Function: qpGeomVertexIterator::get_data1 +// Function: qpGeomVertexIterator::get_data1f // 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() { +get_data1f() { float data; _data->get_data(_array, _data_type, _read_vertex, &data, 1); ++_read_vertex; @@ -391,14 +391,14 @@ get_data1() { } //////////////////////////////////////////////////////////////////// -// Function: qpGeomVertexIterator::get_data2 +// Function: qpGeomVertexIterator::get_data2f // 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() { +get_data2f() { float data[4]; int num_values = min(_data_type->get_num_values(), 4); _data->get_data(_array, _data_type, _read_vertex, data, num_values); @@ -409,14 +409,14 @@ get_data2() { } //////////////////////////////////////////////////////////////////// -// Function: qpGeomVertexIterator::get_data3 +// Function: qpGeomVertexIterator::get_data3f // 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() { +get_data3f() { float data[4]; int num_values = min(_data_type->get_num_values(), 4); _data->get_data(_array, _data_type, _read_vertex, data, num_values); @@ -427,14 +427,14 @@ get_data3() { } //////////////////////////////////////////////////////////////////// -// Function: qpGeomVertexIterator::get_data4 +// Function: qpGeomVertexIterator::get_data4f // 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() { +get_data4f() { float data[4]; int num_values = min(_data_type->get_num_values(), 4); _data->get_data(_array, _data_type, _read_vertex, data, num_values); @@ -443,3 +443,31 @@ get_data4() { qpGeomVertexData::to_vec4(result, data, num_values); return result; } + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexIterator::set_data1i +// Access: Published +// Description: Sets the write vertex to a particular 1-component +// value, and advances the write vertex. +//////////////////////////////////////////////////////////////////// +INLINE void qpGeomVertexIterator:: +set_data1i(int data) { + nassertv(!_const_data); + _data->set_data(_array, _data_type, _write_vertex, &data, 1); + ++_write_vertex; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexIterator::get_data1i +// Access: Published +// Description: Returns the data associated with the read vertex, +// expressed as a 1-component value, and advances the +// read vertex. +//////////////////////////////////////////////////////////////////// +INLINE int qpGeomVertexIterator:: +get_data1i() { + int data; + _data->get_data(_array, _data_type, _read_vertex, &data, 1); + ++_read_vertex; + return data; +} diff --git a/panda/src/gobj/qpgeomVertexIterator.h b/panda/src/gobj/qpgeomVertexIterator.h index 03444d5360..4739241df9 100644 --- a/panda/src/gobj/qpgeomVertexIterator.h +++ b/panda/src/gobj/qpgeomVertexIterator.h @@ -41,12 +41,16 @@ PUBLISHED: const string &name); INLINE qpGeomVertexIterator(qpGeomVertexData *data, const InternalName *name); +public: + // These const variants are not published, since our Python layer + // doesn't know the difference between const and non-const anyway. INLINE qpGeomVertexIterator(const qpGeomVertexData *data); INLINE qpGeomVertexIterator(const qpGeomVertexData *data, const string &name); INLINE qpGeomVertexIterator(const qpGeomVertexData *data, const InternalName *name); +PUBLISHED: INLINE const qpGeomVertexData *get_data() const; INLINE void set_data_type(int data_type); @@ -63,18 +67,21 @@ PUBLISHED: 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 void set_data1f(float data); + INLINE void set_data2f(float x, float y); + INLINE void set_data2f(const LVecBase2f &data); + INLINE void set_data3f(float x, float y, float z); + INLINE void set_data3f(const LVecBase3f &data); + INLINE void set_data4f(float x, float y, float z, float w); + INLINE void set_data4f(const LVecBase4f &data); - INLINE float get_data1(); - INLINE LVecBase2f get_data2(); - INLINE LVecBase3f get_data3(); - INLINE LVecBase4f get_data4(); + INLINE float get_data1f(); + INLINE LVecBase2f get_data2f(); + INLINE LVecBase3f get_data3f(); + INLINE LVecBase4f get_data4f(); + + INLINE void set_data1i(int data); + INLINE int get_data1i(); private: PT(qpGeomVertexData) _data; diff --git a/panda/src/gobj/transformBlend.I b/panda/src/gobj/transformBlend.I new file mode 100644 index 0000000000..d0155cb9e1 --- /dev/null +++ b/panda/src/gobj/transformBlend.I @@ -0,0 +1,277 @@ +// Filename: transformBlend.I +// Created by: drose (24Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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: TransformBlend::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE TransformBlend:: +TransformBlend() { +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE TransformBlend:: +TransformBlend(const VertexTransform *transform0, float) { + add_transform(transform0, 1.0f); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE TransformBlend:: +TransformBlend(const VertexTransform *transform0, float weight0, + const VertexTransform *transform1, float weight1) { + add_transform(transform0, weight0); + add_transform(transform1, weight1); + normalize_weights(); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE TransformBlend:: +TransformBlend(const VertexTransform *transform0, float weight0, + const VertexTransform *transform1, float weight1, + const VertexTransform *transform2, float weight2) { + add_transform(transform0, weight0); + add_transform(transform1, weight1); + add_transform(transform2, weight2); + normalize_weights(); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE TransformBlend:: +TransformBlend(const VertexTransform *transform0, float weight0, + const VertexTransform *transform1, float weight1, + const VertexTransform *transform2, float weight2, + const VertexTransform *transform3, float weight3) { + add_transform(transform0, weight0); + add_transform(transform1, weight1); + add_transform(transform2, weight2); + add_transform(transform3, weight3); + normalize_weights(); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::Copy Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE TransformBlend:: +TransformBlend(const TransformBlend ©) : + _entries(copy._entries) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::Copy Assignment Operator +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void TransformBlend:: +operator = (const TransformBlend ©) { + _entries = copy._entries; + clear_result(); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::Destructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE TransformBlend:: +~TransformBlend() { +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::operator < +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool TransformBlend:: +operator < (const TransformBlend &other) const { + return compare_to(other) < 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::operator == +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool TransformBlend:: +operator == (const TransformBlend &other) const { + return compare_to(other) == 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::operator != +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool TransformBlend:: +operator != (const TransformBlend &other) const { + return compare_to(other) != 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::get_num_transforms +// Access: Published +// Description: Returns the number of transforms stored in the blend +// object. +//////////////////////////////////////////////////////////////////// +INLINE int TransformBlend:: +get_num_transforms() const { + return _entries.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::get_transform +// Access: Published +// Description: Returns the nth transform stored in the blend +// object. +//////////////////////////////////////////////////////////////////// +INLINE const VertexTransform *TransformBlend:: +get_transform(int n) const { + nassertr(n >= 0 && n < (int)_entries.size(), NULL); + return _entries[n]._transform; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::get_weight +// Access: Published +// Description: Returns the weight associated with the nth transform +// stored in the blend object. +//////////////////////////////////////////////////////////////////// +INLINE float TransformBlend:: +get_weight(int n) const { + nassertr(n >= 0 && n < (int)_entries.size(), 0.0f); + return _entries[n]._weight; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::get_blend +// Access: Published +// Description: Returns the current value of the blend, based on the +// current value of all of the nested transform objects +// and their associated weights. +//////////////////////////////////////////////////////////////////// +INLINE void TransformBlend:: +get_blend(LMatrix4f &result) const { + CDReader cdata(_cycler); + if (cdata->_global_modified != VertexTransform::get_global_modified()) { + CDWriter cdataw(((TransformBlend *)this)->_cycler, cdata); + ((TransformBlend *)this)->recompute_result(cdataw); + result = cdataw->_result; + } else { + result = cdata->_result; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::transform_point +// Access: Published +// Description: Transforms the indicated point by the blend matrix. +//////////////////////////////////////////////////////////////////// +INLINE void TransformBlend:: +transform_point(LPoint4f &point) const { + if (!_entries.empty()) { + CDReader cdata(_cycler); + if (cdata->_global_modified != VertexTransform::get_global_modified()) { + CDWriter cdataw(((TransformBlend *)this)->_cycler, cdata); + ((TransformBlend *)this)->recompute_result(cdataw); + point = point * cdataw->_result; + } else { + point = point * cdata->_result; + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::get_modified +// Access: Published +// Description: Returns a counter which is guaranteed to increment at +// least as often as the result of get_blend() changes. +//////////////////////////////////////////////////////////////////// +INLINE UpdateSeq TransformBlend:: +get_modified() const { + CDReader cdata(_cycler); + if (cdata->_global_modified != VertexTransform::get_global_modified()) { + CDWriter cdataw(((TransformBlend *)this)->_cycler, cdata); + ((TransformBlend *)this)->recompute_result(cdataw); + return cdataw->_modified; + } else { + return cdata->_modified; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::TransformEntry::operator < +// Access: Public +// Description: Provides an ordering of TransformEntries by the +// VertexTransform pointer only, so we can easily look +// up in the set to see if a particular transform +// exists. +//////////////////////////////////////////////////////////////////// +INLINE bool TransformBlend::TransformEntry:: +operator < (const TransformBlend::TransformEntry &other) const { + return _transform < other._transform; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::CData::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE TransformBlend::CData:: +CData() : + _result(LMatrix4f::ident_mat()) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::CData::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE TransformBlend::CData:: +CData(const TransformBlend::CData ©) : + _result(copy._result), + _modified(copy._modified), + _global_modified(copy._global_modified) +{ +} + +INLINE ostream & +operator << (ostream &out, const TransformBlend &obj) { + obj.output(out); + return out; +} diff --git a/panda/src/gobj/transformBlend.cxx b/panda/src/gobj/transformBlend.cxx new file mode 100644 index 0000000000..652062a790 --- /dev/null +++ b/panda/src/gobj/transformBlend.cxx @@ -0,0 +1,287 @@ +// Filename: transformBlend.cxx +// Created by: drose (24Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "transformBlend.h" +#include "indent.h" +#include "bamReader.h" +#include "bamWriter.h" + + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::compare_to +// Access: Published +// Description: Defines an arbitrary ordering for TransformBlend +// objects. +//////////////////////////////////////////////////////////////////// +int TransformBlend:: +compare_to(const TransformBlend &other) const { + if (_entries.size() != other._entries.size()) { + return (int)_entries.size() - (int)other._entries.size(); + } + + Entries::const_iterator ai, bi; + ai = _entries.begin(); + bi = other._entries.begin(); + while (ai != _entries.end() && bi != other._entries.end()) { + if ((*ai)._transform != (*bi)._transform) { + return (*ai)._transform < (*bi)._transform ? -1 : 1; + } + if (!IS_NEARLY_EQUAL((*ai)._weight, (*bi)._weight)) { + return (*ai)._weight < (*bi)._weight ? -1 : 1; + } + ++ai; + ++bi; + } + + return 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::add_transform +// Access: Published +// Description: Adds a new transform to the blend. If the transform +// already existed, increases its weight factor. +//////////////////////////////////////////////////////////////////// +void TransformBlend:: +add_transform(const VertexTransform *transform, float weight) { + if (!IS_NEARLY_ZERO(weight)) { + TransformEntry entry; + entry._transform = transform; + entry._weight = weight; + pair result = _entries.insert(entry); + if (!result.second) { + // If the new value was not inserted, it was already there; + // increment the existing weight factor. + Entries::iterator ei = result.first; + (*ei)._weight += weight; + if (IS_NEARLY_ZERO((*ei)._weight)) { + // If we have just zeroed out the weight, remove it. + _entries.erase(ei); + } + } + clear_result(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::remove_transform +// Access: Published +// Description: Removes the indicated transform to the blend. +//////////////////////////////////////////////////////////////////// +void TransformBlend:: +remove_transform(const VertexTransform *transform) { + TransformEntry entry; + entry._transform = transform; + entry._weight = 0.0f; + Entries::iterator ei = _entries.find(entry); + if (ei != _entries.end()) { + _entries.erase(ei); + } + clear_result(); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::normalize_weights +// Access: Published +// Description: Rescales all of the weights on the various transforms +// so that they sum to 1.0. It is generally a good idea +// to call this after adding or removing transforms from +// the blend. +//////////////////////////////////////////////////////////////////// +void TransformBlend:: +normalize_weights() { + float net_weight = 0.0f; + Entries::iterator ei; + for (ei = _entries.begin(); ei != _entries.end(); ++ei) { + net_weight += (*ei)._weight; + } + if (net_weight != 0.0f) { + for (ei = _entries.begin(); ei != _entries.end(); ++ei) { + (*ei)._weight /= net_weight; + } + } + clear_result(); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::has_transform +// Access: Published +// Description: Returns true if the blend has the indicated +// transform, false otherwise. +//////////////////////////////////////////////////////////////////// +bool TransformBlend:: +has_transform(const VertexTransform *transform) const { + TransformEntry entry; + entry._transform = transform; + entry._weight = 0.0f; + Entries::const_iterator ei = _entries.find(entry); + return (ei != _entries.end()); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::get_weight +// Access: Published +// Description: Returns the weight associated with the indicated +// transform, or 0 if there is no entry for the +// transform. +//////////////////////////////////////////////////////////////////// +float TransformBlend:: +get_weight(const VertexTransform *transform) const { + TransformEntry entry; + entry._transform = transform; + entry._weight = 0.0f; + Entries::const_iterator ei = _entries.find(entry); + if (ei != _entries.end()) { + return (*ei)._weight; + } + return 0.0f; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::output +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void TransformBlend:: +output(ostream &out) const { + if (_entries.empty()) { + out << "empty"; + } else { + Entries::const_iterator ei = _entries.begin(); + out << *(*ei)._transform << ":" << (*ei)._weight; + ++ei; + while (ei != _entries.end()) { + out << " " << *(*ei)._transform << ":" << (*ei)._weight; + ++ei; + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::write +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void TransformBlend:: +write(ostream &out, int indent_level) const { + Entries::const_iterator ei; + for (ei = _entries.begin(); ei != _entries.end(); ++ei) { + indent(out, indent_level) + << *(*ei)._transform << ":" << (*ei)._weight << "\n"; + LMatrix4f mat; + (*ei)._transform->get_matrix(mat); + mat.write(out, indent_level + 4); + } + LMatrix4f blend; + get_blend(blend); + indent(out, indent_level) + << "Blended result =\n"; + blend.write(out, indent_level + 2); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::recompute_result +// Access: Private +// Description: Recomputes the blend result from the various +// VertexTransform objects, if necessary. +//////////////////////////////////////////////////////////////////// +void TransformBlend:: +recompute_result(TransformBlend::CDWriter &cdata) { + // Update the global_modified sequence number first, to prevent race + // conditions. + cdata->_global_modified = VertexTransform::get_global_modified(); + + // Now see if we really need to recompute. + UpdateSeq seq; + Entries::const_iterator ei; + for (ei = _entries.begin(); ei != _entries.end(); ++ei) { + seq = max(seq, (*ei)._transform->get_modified()); + } + + if (cdata->_modified != seq) { + // We do need to recompute. + cdata->_modified = seq; + + cdata->_result.set(0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f); + for (ei = _entries.begin(); ei != _entries.end(); ++ei) { + (*ei)._transform->accumulate_matrix(cdata->_result, (*ei)._weight); + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::clear_result +// Access: Private +// Description: Removes the computed result to force it to be +// recomputed. +//////////////////////////////////////////////////////////////////// +void TransformBlend:: +clear_result() { + CDWriter cdata(_cycler); + cdata->_global_modified = UpdateSeq(); + if (cdata->_modified != UpdateSeq()) { + cdata->_modified = UpdateSeq(); + cdata->_result = LMatrix4f::ident_mat(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::write_datagram +// Access: Public +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void TransformBlend:: +write_datagram(BamWriter *manager, Datagram &dg) const { +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::complete_pointers +// Access: Public +// Description: Receives an array of pointers, one for each time +// manager->read_pointer() was called in fillin(). +// Returns the number of pointers processed. +//////////////////////////////////////////////////////////////////// +int TransformBlend:: +complete_pointers(TypedWritable **p_list, BamReader *manager) { + return 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::fillin +// Access: Public +// Description: This internal function is called by make_from_bam to +// read in all of the relevant data from the BamFile for +// the new PandaNode. +//////////////////////////////////////////////////////////////////// +void TransformBlend:: +fillin(DatagramIterator &scan, BamReader *manager) { +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlend::CData::make_copy +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +CycleData *TransformBlend::CData:: +make_copy() const { + return new CData(*this); +} diff --git a/panda/src/gobj/transformBlend.h b/panda/src/gobj/transformBlend.h new file mode 100644 index 0000000000..7363e4cf6a --- /dev/null +++ b/panda/src/gobj/transformBlend.h @@ -0,0 +1,123 @@ +// Filename: transformBlend.h +// Created by: drose (24Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 TRANSFORMBLEND_H +#define TRANSFORMBLEND_H + +#include "pandabase.h" +#include "vertexTransform.h" +#include "pointerTo.h" +#include "pvector.h" +#include "ordered_vector.h" +#include "cycleData.h" +#include "cycleDataReader.h" +#include "cycleDataWriter.h" +#include "pipelineCycler.h" + +//////////////////////////////////////////////////////////////////// +// Class : TransformBlend +// Description : This defines a single entry in a +// TransformBlendPalette. It represents a unique +// combination of VertexTransform pointers and blend +// amounts. +// +// This is part of the experimental Geom rewrite. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA TransformBlend { +PUBLISHED: + INLINE TransformBlend(); + INLINE TransformBlend(const VertexTransform *transform0, float weight0); + INLINE TransformBlend(const VertexTransform *transform0, float weight0, + const VertexTransform *transform1, float weight1); + INLINE TransformBlend(const VertexTransform *transform0, float weight0, + const VertexTransform *transform1, float weight1, + const VertexTransform *transform2, float weight2); + INLINE TransformBlend(const VertexTransform *transform0, float weight0, + const VertexTransform *transform1, float weight1, + const VertexTransform *transform2, float weight2, + const VertexTransform *transform3, float weight3); + INLINE TransformBlend(const TransformBlend ©); + INLINE void operator = (const TransformBlend ©); + INLINE ~TransformBlend(); + + int compare_to(const TransformBlend &other) const; + INLINE bool operator < (const TransformBlend &other) const; + INLINE bool operator == (const TransformBlend &other) const; + INLINE bool operator != (const TransformBlend &other) const; + + void add_transform(const VertexTransform *transform, float weight); + void remove_transform(const VertexTransform *transform); + void normalize_weights(); + bool has_transform(const VertexTransform *transform) const; + float get_weight(const VertexTransform *transform) const; + + INLINE int get_num_transforms() const; + INLINE const VertexTransform *get_transform(int n) const; + INLINE float get_weight(int n) const; + + INLINE void get_blend(LMatrix4f &result) const; + INLINE void transform_point(LPoint4f &point) const; + INLINE UpdateSeq get_modified() const; + + void output(ostream &out) const; + void write(ostream &out, int indent_level) const; + +private: + class TransformEntry { + public: + INLINE bool operator < (const TransformEntry &other) const; + + CPT(VertexTransform) _transform; + float _weight; + }; + typedef ov_set Entries; + Entries _entries; + + // This is the data that must be cycled between pipeline stages; it + // is just a local cache. + class EXPCL_PANDA CData : public CycleData { + public: + INLINE CData(); + INLINE CData(const CData ©); + virtual CycleData *make_copy() const; + + LMatrix4f _result; + UpdateSeq _modified; + UpdateSeq _global_modified; + }; + + PipelineCycler _cycler; + typedef CycleDataReader CDReader; + typedef CycleDataWriter CDWriter; + + void recompute_result(CDWriter &cdata); + void clear_result(); + +public: + void write_datagram(BamWriter *manager, Datagram &dg) const; + int complete_pointers(TypedWritable **plist, BamReader *manager); + void fillin(DatagramIterator &scan, BamReader *manager); + + friend class VertexTransform; +}; + +INLINE ostream &operator << (ostream &out, const TransformBlend &obj); + +#include "transformBlend.I" + +#endif diff --git a/panda/src/gobj/transformBlendPalette.I b/panda/src/gobj/transformBlendPalette.I new file mode 100644 index 0000000000..6b6644630a --- /dev/null +++ b/panda/src/gobj/transformBlendPalette.I @@ -0,0 +1,80 @@ +// Filename: transformBlendPalette.I +// Created by: drose (24Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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: TransformBlendPalette::get_num_blends +// Access: Published +// Description: Returns the total number of different blend +// combinations in the palette. +//////////////////////////////////////////////////////////////////// +INLINE int TransformBlendPalette:: +get_num_blends() const { + return _blends.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlendPalette::get_blend +// Access: Published +// Description: Returns the nth blend in the palette. +//////////////////////////////////////////////////////////////////// +INLINE const TransformBlend &TransformBlendPalette:: +get_blend(int n) const { + nassertr(n >= 0 && n < (int)_blends.size(), _blends[0]); + return _blends[n]; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlendPalette::get_modified +// Access: Published +// Description: Returns a counter which is guaranteed to increment at +// least when any TransformBlends within the palette +// have changed. +//////////////////////////////////////////////////////////////////// +INLINE UpdateSeq TransformBlendPalette:: +get_modified() const { + CDReader cdata(_cycler); + if (cdata->_global_modified != VertexTransform::get_global_modified()) { + CDWriter cdataw(((TransformBlendPalette *)this)->_cycler, cdata); + ((TransformBlendPalette *)this)->recompute_modified(cdataw); + return cdataw->_modified; + } else { + return cdata->_modified; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlendPalette::CData::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE TransformBlendPalette::CData:: +CData() { +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlendPalette::CData::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE TransformBlendPalette::CData:: +CData(const TransformBlendPalette::CData ©) : + _modified(copy._modified), + _global_modified(copy._global_modified) +{ +} diff --git a/panda/src/gobj/transformBlendPalette.cxx b/panda/src/gobj/transformBlendPalette.cxx new file mode 100644 index 0000000000..9a5599d40b --- /dev/null +++ b/panda/src/gobj/transformBlendPalette.cxx @@ -0,0 +1,269 @@ +// Filename: transformBlendPalette.cxx +// Created by: drose (24Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "transformBlendPalette.h" +#include "indent.h" +#include "bamReader.h" +#include "bamWriter.h" + +TypeHandle TransformBlendPalette::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlendPalette::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +TransformBlendPalette:: +TransformBlendPalette() { +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlendPalette::Copy Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +TransformBlendPalette:: +TransformBlendPalette(const TransformBlendPalette ©) : + _blends(copy._blends) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlendPalette::Copy Assignment Operator +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void TransformBlendPalette:: +operator = (const TransformBlendPalette ©) { + _blends = copy._blends; + clear_index(); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlendPalette::Destructor +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +TransformBlendPalette:: +~TransformBlendPalette() { +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlendPalette::set_blend +// Access: Published +// Description: Replaces the blend at the nth position with the +// indicated value. +//////////////////////////////////////////////////////////////////// +void TransformBlendPalette:: +set_blend(int n, const TransformBlend &blend) { + nassertv(n >= 0 && n < (int)_blends.size()); + _blends[n] = blend; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlendPalette::remove_blend +// Access: Published +// Description: Removes the blend at the nth position. +//////////////////////////////////////////////////////////////////// +void TransformBlendPalette:: +remove_blend(int n) { + nassertv(n >= 0 && n < (int)_blends.size()); + _blends.erase(_blends.begin() + n); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlendPalette::add_blend +// Access: Published +// Description: Adds a new blend to the palette, and returns its +// index number. If there is already an identical blend +// in the palette, simply returns that number instead. +//////////////////////////////////////////////////////////////////// +int TransformBlendPalette:: +add_blend(const TransformBlend &blend) { + if (_blend_index.empty()) { + rebuild_index(); + } + + BlendIndex::iterator bi; + bi = _blend_index.find(&blend); + if (bi != _blend_index.end()) { + // Already had it. + return (*bi).second; + } + + int new_position = (int)_blends.size(); + _blends.push_back(blend); + clear_index(); + + return new_position; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlendPalette::write +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void TransformBlendPalette:: +write(ostream &out) const { + for (int i = 0; i < (int)_blends.size(); i++) { + out << i << ". " << _blends[i] << "\n"; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlendPalette::clear_index +// Access: Private +// Description: Resets the index so that it will be rebuilt next time +// it is needed. +//////////////////////////////////////////////////////////////////// +void TransformBlendPalette:: +clear_index() { + _blend_index.clear(); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlendPalette::rebuild_index +// Access: Private +// Description: Rebuilds the index so that we can easily determine +// what blend combinations are already present in the +// palette. +//////////////////////////////////////////////////////////////////// +void TransformBlendPalette:: +rebuild_index() { + _blend_index.clear(); + + for (int i = 0; i < (int)_blends.size(); i++) { + _blend_index[&_blends[i]] = i; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlendPalette::recompute_modified +// Access: Private +// Description: Recomputes the modified stamp from the various +// TransformBlend objects, if necessary. +//////////////////////////////////////////////////////////////////// +void TransformBlendPalette:: +recompute_modified(TransformBlendPalette::CDWriter &cdata) { + // Update the global_modified sequence number first, to prevent race + // conditions. + cdata->_global_modified = VertexTransform::get_global_modified(); + + // Now get the local modified number. + UpdateSeq seq; + Blends::const_iterator bi; + for (bi = _blends.begin(); bi != _blends.end(); ++bi) { + seq = max(seq, (*bi).get_modified()); + } + + cdata->_modified = seq; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlendPalette::clear_modified +// Access: Private +// Description: Clears the modified stamp to force it to be +// recomputed. +//////////////////////////////////////////////////////////////////// +void TransformBlendPalette:: +clear_modified() { + CDWriter cdata(_cycler); + cdata->_global_modified = UpdateSeq(); + cdata->_modified = UpdateSeq(); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlendPalette::register_with_read_factory +// Access: Public, Static +// Description: Tells the BamReader how to create objects of type +// TransformBlendPalette. +//////////////////////////////////////////////////////////////////// +void TransformBlendPalette:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlendPalette::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void TransformBlendPalette:: +write_datagram(BamWriter *manager, Datagram &dg) { + TypedWritable::write_datagram(manager, dg); + + manager->write_cdata(dg, _cycler); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlendPalette::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 TransformBlendPalette:: +complete_pointers(TypedWritable **p_list, BamReader *manager) { + int pi = TypedWritable::complete_pointers(p_list, manager); + return pi; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlendPalette::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type TransformBlendPalette is encountered +// in the Bam file. It should create the TransformBlendPalette +// and extract its information from the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *TransformBlendPalette:: +make_from_bam(const FactoryParams ¶ms) { + TransformBlendPalette *object = new TransformBlendPalette; + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + object->fillin(scan, manager); + + return object; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlendPalette::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 TransformBlendPalette. +//////////////////////////////////////////////////////////////////// +void TransformBlendPalette:: +fillin(DatagramIterator &scan, BamReader *manager) { + TypedWritable::fillin(scan, manager); + + manager->read_cdata(scan, _cycler); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlendPalette::CData::make_copy +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +CycleData *TransformBlendPalette::CData:: +make_copy() const { + return new CData(*this); +} diff --git a/panda/src/gobj/transformBlendPalette.h b/panda/src/gobj/transformBlendPalette.h new file mode 100644 index 0000000000..3bcd9ad9f1 --- /dev/null +++ b/panda/src/gobj/transformBlendPalette.h @@ -0,0 +1,141 @@ +// Filename: transformBlendPalette.h +// Created by: drose (24Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 TRANSFORMBLENDPALETTE_H +#define TRANSFORMBLENDPALETTE_H + +#include "pandabase.h" +#include "transformBlend.h" +#include "vertexTransform.h" +#include "typedWritableReferenceCount.h" +#include "pointerTo.h" +#include "pvector.h" +#include "pmap.h" +#include "indirectLess.h" +#include "cycleData.h" +#include "cycleDataReader.h" +#include "cycleDataWriter.h" +#include "pipelineCycler.h" + +//////////////////////////////////////////////////////////////////// +// Class : TransformBlendPalette +// Description : This structure collects together the different +// combinations of transforms and blend amounts used by +// a GeomVertexData, to facilitate computing dynamic +// vertices on the CPU at runtime. Each vertex has a +// pointer to exactly one of entries in this palette, +// and each entry defines a number of transform/blend +// combinations. +// +// This structure is used for a GeomVertexData set up to +// compute its dynamic vertices on the CPU. See +// TransformPalette for one set up to compute its +// dynamic vertices on the graphics card. +// +// This is part of the experimental Geom rewrite. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA TransformBlendPalette : public TypedWritableReferenceCount { +PUBLISHED: + TransformBlendPalette(); + TransformBlendPalette(const TransformBlendPalette ©); + void operator = (const TransformBlendPalette ©); + virtual ~TransformBlendPalette(); + + INLINE int get_num_blends() const; + INLINE const TransformBlend &get_blend(int n) const; + INLINE UpdateSeq get_modified() const; + + void set_blend(int n, const TransformBlend &blend); + void remove_blend(int n); + int add_blend(const TransformBlend &blend); + + void write(ostream &out) const; + +private: + void clear_index(); + void rebuild_index(); + +private: + // We don't bother with registering the palette, or protecting its + // data in a CycleData structure--the interface on GeomVertexData + // guarantees that the pointer will be copied if we modify the + // palette. + typedef pvector Blends; + Blends _blends; + + // This map indexes directly into the above vector. That means any + // time we add or remove anything from the vector, we must + // completely rebuild the index (since the vector might reallocate, + // invalidating all the pointers into it). + typedef pmap > BlendIndex; + BlendIndex _blend_index; + + // Even though we don't store the actual blend palette data in a + // CycleData structure, we do need to keep a local cache of the + // relevant modified stamps there, so it can be updated per-thread. + class EXPCL_PANDA CData : public CycleData { + public: + INLINE CData(); + INLINE CData(const CData ©); + virtual CycleData *make_copy() const; + + UpdateSeq _modified; + UpdateSeq _global_modified; + }; + + PipelineCycler _cycler; + typedef CycleDataReader CDReader; + typedef CycleDataWriter CDWriter; + + void recompute_modified(CDWriter &cdata); + void clear_modified(); + +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, "TransformBlendPalette", + 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 VertexTransform; +}; + +INLINE ostream &operator << (ostream &out, const TransformBlendPalette &obj); + +#include "transformBlendPalette.I" + +#endif diff --git a/panda/src/gobj/transformPalette.I b/panda/src/gobj/transformPalette.I new file mode 100644 index 0000000000..20f0a79a2e --- /dev/null +++ b/panda/src/gobj/transformPalette.I @@ -0,0 +1,131 @@ +// Filename: transformPalette.I +// Created by: drose (23Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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: TransformPalette::is_registered +// Access: Published +// Description: Returns true if this palette has been registered. +// Once it has been registered, the set of transforms in +// a TransformPalette may not be further modified; but +// it must be registered before it can be assigned to a +// Geom. +//////////////////////////////////////////////////////////////////// +INLINE bool TransformPalette:: +is_registered() const { + return _is_registered; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformPalette::register_palette +// Access: Published, Static +// Description: Registers a TransformPalette for use. This is +// similar to GeomVertexFormat::register_format(). Once +// registered, a TransformPalette may no longer be +// modified (although the individual VertexTransform +// objects may modify their reported transforms). +// +// This must be called before a palette 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(TransformPalette) TransformPalette:: +register_palette(TransformPalette *palette) { + // We don't actually bother adding the palette object to a registry. + // This means there may be multiple copies of identical registered + // TransformPalettes. Big deal. We can always go back and make a + // registry later if we really need it. + if (palette->is_registered()) { + return palette; + } + + palette->do_register(); + return palette; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformPalette::get_num_transforms +// Access: Published +// Description: Returns the number of transforms in the palette. +//////////////////////////////////////////////////////////////////// +INLINE int TransformPalette:: +get_num_transforms() const { + return _transforms.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformPalette::get_transform +// Access: Published +// Description: Returns the nth transform in the palette. +//////////////////////////////////////////////////////////////////// +INLINE const VertexTransform *TransformPalette:: +get_transform(int n) const { + nassertr(n >= 0 && n < (int)_transforms.size(), NULL); + return _transforms[n]; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformPalette::get_modified +// Access: Published +// Description: Returns a sequence number that's guaranteed to change +// at least when any VertexTransforms in the palette +// change. (However, this is only true for a registered +// palette. An unregistered palette may or may not +// reflect an update here when a VertexTransform +// changes.) +//////////////////////////////////////////////////////////////////// +INLINE UpdateSeq TransformPalette:: +get_modified() const { + CDReader cdata(_cycler); + return cdata->_modified; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformPalette::update_modified +// Access: Private +// Description: Called internally whenever a nested VertexTransform +// reports that it has been modified. +//////////////////////////////////////////////////////////////////// +INLINE void TransformPalette:: +update_modified(UpdateSeq) { + CDWriter cdata(_cycler); + ++(cdata->_modified); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformPalette::CData::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE TransformPalette::CData:: +CData() { +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformPalette::CData::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE TransformPalette::CData:: +CData(const TransformPalette::CData ©) : + _modified(copy._modified) +{ +} diff --git a/panda/src/gobj/transformPalette.cxx b/panda/src/gobj/transformPalette.cxx new file mode 100644 index 0000000000..924a343a8c --- /dev/null +++ b/panda/src/gobj/transformPalette.cxx @@ -0,0 +1,259 @@ +// Filename: transformPalette.cxx +// Created by: drose (23Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "transformPalette.h" +#include "bamReader.h" +#include "bamWriter.h" + +TypeHandle TransformPalette::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: TransformPalette::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +TransformPalette:: +TransformPalette() : + _is_registered(false) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformPalette::Copy Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +TransformPalette:: +TransformPalette(const TransformPalette ©) : + _is_registered(false), + _transforms(copy._transforms) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformPalette::Copy Assignment Operator +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void TransformPalette:: +operator = (const TransformPalette ©) { + nassertv(!_is_registered); + _transforms = copy._transforms; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformPalette::Destructor +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +TransformPalette:: +~TransformPalette() { + if (_is_registered) { + do_unregister(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformPalette::set_transform +// Access: Published +// Description: Replaces the nth transform. Only valid for +// unregistered palettes. +//////////////////////////////////////////////////////////////////// +void TransformPalette:: +set_transform(int n, VertexTransform *transform) { + nassertv(!_is_registered); + nassertv(n >= 0 && n < (int)_transforms.size()); + _transforms[n] = transform; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformPalette::remove_transform +// Access: Published +// Description: Removes the nth transform. Only valid for +// unregistered palettes. +//////////////////////////////////////////////////////////////////// +void TransformPalette:: +remove_transform(int n) { + nassertv(!_is_registered); + nassertv(n >= 0 && n < (int)_transforms.size()); + _transforms.erase(_transforms.begin() + n); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformPalette::add_transform +// Access: Published +// Description: Adds a new transform to the palette and returns the +// index number of the new transform. Only valid for +// unregistered palettes. +//////////////////////////////////////////////////////////////////// +int TransformPalette:: +add_transform(VertexTransform *transform) { + nassertr(!_is_registered, -1); + int new_index = (int)_transforms.size(); + _transforms.push_back(transform); + return new_index; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformPalette::write +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void TransformPalette:: +write(ostream &out) const { + for (size_t i = 0; i < _transforms.size(); ++i) { + out << i << ". " << *_transforms[i] << "\n"; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformPalette::do_register +// Access: Private +// Description: Called internally when the palette is registered. +//////////////////////////////////////////////////////////////////// +void TransformPalette:: +do_register() { + nassertv(!_is_registered); + + Transforms::iterator ti; + for (ti = _transforms.begin(); ti != _transforms.end(); ++ti) { + bool inserted = (*ti)->_palettes.insert(this).second; + nassertv(inserted); + } + _is_registered = true; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformPalette::do_unregister +// Access: Private +// Description: Called internally when the palette is unregistered +// (i.e. right before destruction). +//////////////////////////////////////////////////////////////////// +void TransformPalette:: +do_unregister() { + nassertv(_is_registered); + + Transforms::iterator ti; + for (ti = _transforms.begin(); ti != _transforms.end(); ++ti) { + (*ti)->_palettes.erase(this); + } + _is_registered = false; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformPalette::register_with_read_factory +// Access: Public, Static +// Description: Tells the BamReader how to create objects of type +// TransformPalette. +//////////////////////////////////////////////////////////////////// +void TransformPalette:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformPalette::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void TransformPalette:: +write_datagram(BamWriter *manager, Datagram &dg) { + TypedWritable::write_datagram(manager, dg); + + manager->write_cdata(dg, _cycler); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformPalette::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type TransformPalette is encountered +// in the Bam file. It should create the TransformPalette +// and extract its information from the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *TransformPalette:: +make_from_bam(const FactoryParams ¶ms) { + TransformPalette *object = new TransformPalette; + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + object->fillin(scan, manager); + + return object; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformPalette::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 TransformPalette. +//////////////////////////////////////////////////////////////////// +void TransformPalette:: +fillin(DatagramIterator &scan, BamReader *manager) { + TypedWritable::fillin(scan, manager); + + manager->read_cdata(scan, _cycler); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformPalette::CData::make_copy +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +CycleData *TransformPalette::CData:: +make_copy() const { + return new CData(*this); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformPalette::CData::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void TransformPalette::CData:: +write_datagram(BamWriter *manager, Datagram &dg) const { +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformPalette::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 TransformPalette::CData:: +complete_pointers(TypedWritable **p_list, BamReader *manager) { + int pi = CycleData::complete_pointers(p_list, manager); + + return pi; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformPalette::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 TransformPalette. +//////////////////////////////////////////////////////////////////// +void TransformPalette::CData:: +fillin(DatagramIterator &scan, BamReader *manager) { +} diff --git a/panda/src/gobj/transformPalette.h b/panda/src/gobj/transformPalette.h new file mode 100644 index 0000000000..213bd9195c --- /dev/null +++ b/panda/src/gobj/transformPalette.h @@ -0,0 +1,127 @@ +// Filename: transformPalette.h +// Created by: drose (23Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 TRANSFORMPALETTE_H +#define TRANSFORMPALETTE_H + +#include "pandabase.h" +#include "vertexTransform.h" +#include "typedWritableReferenceCount.h" +#include "pointerTo.h" +#include "luse.h" +#include "pvector.h" +#include "cycleData.h" +#include "cycleDataReader.h" +#include "cycleDataWriter.h" +#include "pipelineCycler.h" + + +//////////////////////////////////////////////////////////////////// +// Class : TransformPalette +// Description : Stores the total set of VertexTransforms that the +// vertices in a particular GeomVertexData object might +// depend on. +// +// This structure is used for a GeomVertexData set up to +// compute its dynamic vertices on the graphics card. +// See TransformBlendPalette for one set up to compute +// its dynamic vertices on the CPU. +// +// This is part of the experimental Geom rewrite. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA TransformPalette : public TypedWritableReferenceCount { +PUBLISHED: + TransformPalette(); + TransformPalette(const TransformPalette ©); + void operator = (const TransformPalette ©); + virtual ~TransformPalette(); + + INLINE bool is_registered() const; + INLINE static CPT(TransformPalette) register_palette(TransformPalette *palette); + + INLINE int get_num_transforms() const; + INLINE const VertexTransform *get_transform(int n) const; + INLINE UpdateSeq get_modified() const; + + void set_transform(int n, VertexTransform *transform); + void remove_transform(int n); + int add_transform(VertexTransform *transform); + + void write(ostream &out) const; + +private: + void do_register(); + void do_unregister(); + INLINE void update_modified(UpdateSeq modified); + +private: + bool _is_registered; + + typedef pvector< PT(VertexTransform) > Transforms; + Transforms _transforms; + + // 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); + + UpdateSeq _modified; + }; + + 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, "TransformPalette", + 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 VertexTransform; +}; + +INLINE ostream &operator << (ostream &out, const TransformPalette &obj); + +#include "transformPalette.I" + +#endif diff --git a/panda/src/gobj/userVertexTransform.I b/panda/src/gobj/userVertexTransform.I new file mode 100644 index 0000000000..e974ee9b90 --- /dev/null +++ b/panda/src/gobj/userVertexTransform.I @@ -0,0 +1,63 @@ +// Filename: userVertexTransform.I +// Created by: drose (24Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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: UserVertexTransform::get_name +// Access: Published +// Description: Returns the name passed to the constructor. +// Completely arbitrary. +//////////////////////////////////////////////////////////////////// +INLINE const string &UserVertexTransform:: +get_name() const { + return _name; +} + +//////////////////////////////////////////////////////////////////// +// Function: UserVertexTransform::set_matrix +// Access: Published +// Description: Stores the indicated matrix. +//////////////////////////////////////////////////////////////////// +INLINE void UserVertexTransform:: +set_matrix(const LMatrix4f &matrix) { + CDWriter cdata(_cycler); + cdata->_matrix = matrix; + mark_modified(); +} + +//////////////////////////////////////////////////////////////////// +// Function: UserVertexTransform::CData::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE UserVertexTransform::CData:: +CData() : + _matrix(LMatrix4f::ident_mat()) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: UserVertexTransform::CData::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE UserVertexTransform::CData:: +CData(const UserVertexTransform::CData ©) : + _matrix(copy._matrix) +{ +} diff --git a/panda/src/gobj/userVertexTransform.cxx b/panda/src/gobj/userVertexTransform.cxx new file mode 100644 index 0000000000..c9db457407 --- /dev/null +++ b/panda/src/gobj/userVertexTransform.cxx @@ -0,0 +1,144 @@ +// Filename: userVertexTransform.cxx +// Created by: drose (24Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "userVertexTransform.h" +#include "bamReader.h" +#include "bamWriter.h" + +TypeHandle UserVertexTransform::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: UserVertexTransform::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +UserVertexTransform:: +UserVertexTransform(const string &name) : + _name(name) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: UserVertexTransform::get_matrix +// Access: Published, Virtual +// Description: Stores the transform's matrix in the indicated value. +//////////////////////////////////////////////////////////////////// +void UserVertexTransform:: +get_matrix(LMatrix4f &matrix) const { + CDReader cdata(_cycler); + matrix = cdata->_matrix; +} + +//////////////////////////////////////////////////////////////////// +// Function: UserVertexTransform::output +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void UserVertexTransform:: +output(ostream &out) const { + out << get_name(); +} + +//////////////////////////////////////////////////////////////////// +// Function: UserVertexTransform::CData::make_copy +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +CycleData *UserVertexTransform::CData:: +make_copy() const { + return new CData(*this); +} + +//////////////////////////////////////////////////////////////////// +// Function: UserVertexTransform::register_with_read_factory +// Access: Public, Static +// Description: Tells the BamReader how to create objects of type +// UserVertexTransform. +//////////////////////////////////////////////////////////////////// +void UserVertexTransform:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: UserVertexTransform::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void UserVertexTransform:: +write_datagram(BamWriter *manager, Datagram &dg) { + TypedWritable::write_datagram(manager, dg); + + manager->write_cdata(dg, _cycler); +} + +//////////////////////////////////////////////////////////////////// +// Function: UserVertexTransform::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type UserVertexTransform is encountered +// in the Bam file. It should create the UserVertexTransform +// and extract its information from the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *UserVertexTransform:: +make_from_bam(const FactoryParams ¶ms) { + UserVertexTransform *object = new UserVertexTransform(""); + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + object->fillin(scan, manager); + + return object; +} + +//////////////////////////////////////////////////////////////////// +// Function: UserVertexTransform::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 UserVertexTransform. +//////////////////////////////////////////////////////////////////// +void UserVertexTransform:: +fillin(DatagramIterator &scan, BamReader *manager) { + TypedWritable::fillin(scan, manager); + + manager->read_cdata(scan, _cycler); +} + +//////////////////////////////////////////////////////////////////// +// Function: UserVertexTransform::CData::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void UserVertexTransform::CData:: +write_datagram(BamWriter *manager, Datagram &dg) const { +} + +//////////////////////////////////////////////////////////////////// +// Function: UserVertexTransform::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 UserVertexTransform. +//////////////////////////////////////////////////////////////////// +void UserVertexTransform::CData:: +fillin(DatagramIterator &scan, BamReader *manager) { +} diff --git a/panda/src/gobj/userVertexTransform.h b/panda/src/gobj/userVertexTransform.h new file mode 100644 index 0000000000..1b9e013f6a --- /dev/null +++ b/panda/src/gobj/userVertexTransform.h @@ -0,0 +1,96 @@ +// Filename: userVertexTransform.h +// Created by: drose (24Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 USERVERTEXTRANSFORM_H +#define USERVERTEXTRANSFORM_H + +#include "pandabase.h" +#include "vertexTransform.h" +#include "cycleData.h" +#include "cycleDataReader.h" +#include "cycleDataWriter.h" +#include "pipelineCycler.h" + +//////////////////////////////////////////////////////////////////// +// Class : UserVertexTransform +// Description : This is a specialization on VertexTransform that +// allows the user to specify any arbitrary transform +// matrix he likes. This is rarely used except for +// testing. +// +// This is part of the experimental Geom rewrite. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA UserVertexTransform : public VertexTransform { +PUBLISHED: + UserVertexTransform(const string &name); + + INLINE const string &get_name() const; + + INLINE void set_matrix(const LMatrix4f &matrix); + virtual void get_matrix(LMatrix4f &matrix) const; + + virtual void output(ostream &out) const; + +private: + string _name; + + // 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 void fillin(DatagramIterator &scan, BamReader *manager); + + LMatrix4f _matrix; + }; + + 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() { + VertexTransform::init_type(); + register_type(_type_handle, "UserVertexTransform", + VertexTransform::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 "userVertexTransform.I" + +#endif diff --git a/panda/src/gobj/vertexTransform.I b/panda/src/gobj/vertexTransform.I new file mode 100644 index 0000000000..4960f75261 --- /dev/null +++ b/panda/src/gobj/vertexTransform.I @@ -0,0 +1,71 @@ +// Filename: vertexTransform.I +// Created by: drose (23Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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: VertexTransform::get_modified +// Access: Published +// Description: Returns a sequence number that's guaranteed to change +// at least every time the value reported by +// get_matrix() changes. +//////////////////////////////////////////////////////////////////// +INLINE UpdateSeq VertexTransform:: +get_modified() const { + CDReader cdata(_cycler); + return cdata->_modified; +} + +//////////////////////////////////////////////////////////////////// +// Function: VertexTransform::get_global_modified +// Access: Published, Static +// Description: Returns the currently highest +// VertexTransform::get_modified() value in the world. +// This can be used as a quick way to determine if any +// VertexTransforms have changed value recently. +//////////////////////////////////////////////////////////////////// +INLINE UpdateSeq VertexTransform:: +get_global_modified() { + CDReader cdata(_global_cycler); + return cdata->_modified; +} + +//////////////////////////////////////////////////////////////////// +// Function: VertexTransform::CData::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE VertexTransform::CData:: +CData() { +} + +//////////////////////////////////////////////////////////////////// +// Function: VertexTransform::CData::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE VertexTransform::CData:: +CData(const VertexTransform::CData ©) : + _modified(copy._modified) +{ +} + +INLINE ostream & +operator << (ostream &out, const VertexTransform &obj) { + obj.output(out); + return out; +} diff --git a/panda/src/gobj/vertexTransform.cxx b/panda/src/gobj/vertexTransform.cxx new file mode 100644 index 0000000000..639b2979d0 --- /dev/null +++ b/panda/src/gobj/vertexTransform.cxx @@ -0,0 +1,217 @@ +// Filename: vertexTransform.cxx +// Created by: drose (23Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "vertexTransform.h" +#include "bamReader.h" +#include "bamWriter.h" +#include "indent.h" + +PipelineCycler VertexTransform::_global_cycler; +UpdateSeq VertexTransform::_next_modified; + +TypeHandle VertexTransform::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: VertexTransform::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +VertexTransform:: +VertexTransform() { +} + +//////////////////////////////////////////////////////////////////// +// Function: VertexTransform::Destructor +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +VertexTransform:: +~VertexTransform() { + // We shouldn't destruct while any TransformPalettes are holding our + // pointer. + nassertv(_palettes.empty()); +} + +//////////////////////////////////////////////////////////////////// +// Function: VertexTransform::accumulate_matrix +// Access: Published, Virtual +// Description: Adds the value of this transform's matrix, modified +// by the indicated weight, into the indicated +// accumulation matrix. This is used to compute the +// result of several blended transforms. +//////////////////////////////////////////////////////////////////// +void VertexTransform:: +accumulate_matrix(LMatrix4f &accum, float weight) const { + LMatrix4f me; + get_matrix(me); + + accum._m.m._00 += me._m.m._00 * weight; + accum._m.m._01 += me._m.m._01 * weight; + accum._m.m._02 += me._m.m._02 * weight; + accum._m.m._03 += me._m.m._03 * weight; + + accum._m.m._10 += me._m.m._10 * weight; + accum._m.m._11 += me._m.m._11 * weight; + accum._m.m._12 += me._m.m._12 * weight; + accum._m.m._13 += me._m.m._13 * weight; + + accum._m.m._20 += me._m.m._20 * weight; + accum._m.m._21 += me._m.m._21 * weight; + accum._m.m._22 += me._m.m._22 * weight; + accum._m.m._23 += me._m.m._23 * weight; + + accum._m.m._30 += me._m.m._30 * weight; + accum._m.m._31 += me._m.m._31 * weight; + accum._m.m._32 += me._m.m._32 * weight; + accum._m.m._33 += me._m.m._33 * weight; +} + +//////////////////////////////////////////////////////////////////// +// Function: VertexTransform::output +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void VertexTransform:: +output(ostream &out) const { + out << get_type(); +} + +//////////////////////////////////////////////////////////////////// +// Function: VertexTransform::write +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void VertexTransform:: +write(ostream &out, int indent_level) const { + indent(out, indent_level) + << *this << ":\n"; + LMatrix4f mat; + get_matrix(mat); + mat.write(out, indent_level + 2); +} + +//////////////////////////////////////////////////////////////////// +// Function: VertexTransform::get_next_modified +// Access: Public, Static +// Description: Returns a monotonically increasing sequence. Each +// time this is called, a new sequence number is +// returned, higher than the previous value. +// +// This is used to ensure that all +// VertexTransform::get_modified() calls return an +// increasing number in the same space, so that +// TransformBlend::get_modified() is easy to determine. +// It is similar to Geom::get_modified(), but it is in a +// different space. +//////////////////////////////////////////////////////////////////// +UpdateSeq VertexTransform:: +get_next_modified() { + ++_next_modified; + + CDWriter cdatag(_global_cycler); + cdatag->_modified = _next_modified; + + return _next_modified; +} + +//////////////////////////////////////////////////////////////////// +// Function: VertexTransform::mark_modified +// Access: Protected +// Description: Intended to be called by a derived class whenever the +// reported transform might have changed. Without +// calling this method, changes to get_matrix() may not +// be propagated through the system. +//////////////////////////////////////////////////////////////////// +void VertexTransform:: +mark_modified() { + CDWriter cdata(_cycler); + cdata->_modified = get_next_modified(); + + Palettes::iterator pi; + for (pi = _palettes.begin(); pi != _palettes.end(); ++pi) { + (*pi)->update_modified(cdata->_modified); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: VertexTransform::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void VertexTransform:: +write_datagram(BamWriter *manager, Datagram &dg) { + TypedWritable::write_datagram(manager, dg); +} + +//////////////////////////////////////////////////////////////////// +// Function: VertexTransform::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 VertexTransform. +//////////////////////////////////////////////////////////////////// +void VertexTransform:: +fillin(DatagramIterator &scan, BamReader *manager) { + TypedWritable::fillin(scan, manager); +} + +//////////////////////////////////////////////////////////////////// +// Function: VertexTransform::CData::make_copy +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +CycleData *VertexTransform::CData:: +make_copy() const { + return new CData(*this); +} + +//////////////////////////////////////////////////////////////////// +// Function: VertexTransform::CData::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void VertexTransform::CData:: +write_datagram(BamWriter *manager, Datagram &dg) const { +} + +//////////////////////////////////////////////////////////////////// +// Function: VertexTransform::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 VertexTransform::CData:: +complete_pointers(TypedWritable **p_list, BamReader *manager) { + int pi = CycleData::complete_pointers(p_list, manager); + + return pi; +} + +//////////////////////////////////////////////////////////////////// +// Function: VertexTransform::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 VertexTransform. +//////////////////////////////////////////////////////////////////// +void VertexTransform::CData:: +fillin(DatagramIterator &scan, BamReader *manager) { +} diff --git a/panda/src/gobj/vertexTransform.h b/panda/src/gobj/vertexTransform.h new file mode 100644 index 0000000000..b37e89d1f9 --- /dev/null +++ b/panda/src/gobj/vertexTransform.h @@ -0,0 +1,118 @@ +// Filename: vertexTransform.h +// Created by: drose (23Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 VERTEXTRANSFORM_H +#define VERTEXTRANSFORM_H + +#include "pandabase.h" +#include "typedWritableReferenceCount.h" +#include "updateSeq.h" +#include "luse.h" +#include "pset.h" +#include "cycleData.h" +#include "cycleDataReader.h" +#include "cycleDataWriter.h" +#include "pipelineCycler.h" + +class TransformPalette; + +//////////////////////////////////////////////////////////////////// +// Class : VertexTransform +// Description : This is an abstract base class that holds a pointer +// to some transform, computed in some arbitrary way, +// that is to be applied to vertices during rendering. +// This is used to implement soft-skinned and animated +// vertices. Derived classes will define how the +// transform is actually computed. +// +// This is part of the experimental Geom rewrite. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA VertexTransform : public TypedWritableReferenceCount { +PUBLISHED: + VertexTransform(); + virtual ~VertexTransform(); + + virtual void get_matrix(LMatrix4f &matrix) const=0; + virtual void accumulate_matrix(LMatrix4f &accum, float weight) const; + + INLINE UpdateSeq get_modified() const; + + virtual void output(ostream &out) const; + virtual void write(ostream &out, int indent_level) const; + + static UpdateSeq get_next_modified(); + INLINE static UpdateSeq get_global_modified(); + +protected: + void mark_modified(); + +private: + typedef pset Palettes; + Palettes _palettes; + + // 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); + + UpdateSeq _modified; + }; + + PipelineCycler _cycler; + typedef CycleDataReader CDReader; + typedef CycleDataWriter CDWriter; + + static PipelineCycler _global_cycler; + static UpdateSeq _next_modified; + +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, "VertexTransform", + 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 TransformPalette; +}; + +INLINE ostream &operator << (ostream &out, const VertexTransform &obj); + +#include "vertexTransform.I" + +#endif diff --git a/panda/src/pgraph/cullableObject.cxx b/panda/src/pgraph/cullableObject.cxx index eaeb2f4b05..5eb86e20b4 100644 --- a/panda/src/pgraph/cullableObject.cxx +++ b/panda/src/pgraph/cullableObject.cxx @@ -38,6 +38,7 @@ munge_geom(const qpGeomMunger *munger) { _munger = munger; CPT(qpGeom) qpgeom = DCAST(qpGeom, _geom); qpgeom->munge_geom(munger, qpgeom, _munged_data); + _munged_data = _munged_data->compute_vertices(); _geom = qpgeom; } }