From 19ef896a9b7ee70a8a61f90b183d7d83f69496c3 Mon Sep 17 00:00:00 2001 From: David Rose Date: Mon, 28 Mar 2005 22:24:04 +0000 Subject: [PATCH] beginning morph animations --- panda/src/glstuff/glGeomMunger_src.cxx | 5 +- .../glstuff/glGraphicsStateGuardian_src.cxx | 2 +- panda/src/gobj/Sources.pp | 12 +- panda/src/gobj/config_gobj.cxx | 8 + panda/src/gobj/gobj_composite2.cxx | 3 + panda/src/gobj/internalName.cxx | 68 +++ panda/src/gobj/internalName.h | 4 + panda/src/gobj/qpgeomVertexData.I | 29 + panda/src/gobj/qpgeomVertexData.cxx | 511 ++++++++++++------ panda/src/gobj/qpgeomVertexData.h | 10 +- panda/src/gobj/qpgeomVertexDataType.I | 24 + panda/src/gobj/qpgeomVertexDataType.h | 2 + panda/src/gobj/qpgeomVertexFormat.I | 75 +++ panda/src/gobj/qpgeomVertexFormat.cxx | 36 ++ panda/src/gobj/qpgeomVertexFormat.h | 14 + panda/src/gobj/sliderTable.I | 126 +++++ panda/src/gobj/sliderTable.cxx | 249 +++++++++ panda/src/gobj/sliderTable.h | 126 +++++ panda/src/gobj/transformPalette.I | 4 +- panda/src/gobj/userVertexSlider.I | 52 ++ panda/src/gobj/userVertexSlider.cxx | 145 +++++ panda/src/gobj/userVertexSlider.h | 91 ++++ panda/src/gobj/userVertexTransform.cxx | 2 +- panda/src/gobj/vertexSlider.I | 70 +++ panda/src/gobj/vertexSlider.cxx | 154 ++++++ panda/src/gobj/vertexSlider.h | 119 ++++ 26 files changed, 1757 insertions(+), 184 deletions(-) create mode 100644 panda/src/gobj/sliderTable.I create mode 100644 panda/src/gobj/sliderTable.cxx create mode 100644 panda/src/gobj/sliderTable.h create mode 100644 panda/src/gobj/userVertexSlider.I create mode 100644 panda/src/gobj/userVertexSlider.cxx create mode 100644 panda/src/gobj/userVertexSlider.h create mode 100644 panda/src/gobj/vertexSlider.I create mode 100644 panda/src/gobj/vertexSlider.cxx create mode 100644 panda/src/gobj/vertexSlider.h diff --git a/panda/src/glstuff/glGeomMunger_src.cxx b/panda/src/glstuff/glGeomMunger_src.cxx index a22dbe7209..99e5ef89e9 100644 --- a/panda/src/glstuff/glGeomMunger_src.cxx +++ b/panda/src/glstuff/glGeomMunger_src.cxx @@ -50,9 +50,10 @@ munge_format_impl(const qpGeomVertexFormat *orig) { const qpGeomVertexDataType *color_type = format->get_data_type(InternalName::get_color()); if (color_type != (qpGeomVertexDataType *)NULL && - color_type->get_numeric_type() == qpGeomVertexDataType::NT_packed_8888) { + (color_type->get_numeric_type() == qpGeomVertexDataType::NT_packed_8888 || + color_type->get_contents() != qpGeomVertexDataType::NT_rgba)) { // We need to convert the color format; OpenGL doesn't support the - // byte order of DirectX's packed_argb format. + // byte order of DirectX's packed ARGB format. int color_array = format->get_array_with(InternalName::get_color()); PT(qpGeomVertexFormat) new_format = new qpGeomVertexFormat(*format); diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 83bc71947b..60c2ff393e 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -2676,7 +2676,7 @@ prepare_index_buffer(qpGeomPrimitive *data) { if (GLCAT.is_debug()) { GLCAT.debug() - << "creating vertex buffer " << gibc->_index << "\n"; + << "creating index buffer " << gibc->_index << "\n"; } report_my_gl_errors(); diff --git a/panda/src/gobj/Sources.pp b/panda/src/gobj/Sources.pp index 14be2e667e..ebbdf0b57a 100644 --- a/panda/src/gobj/Sources.pp +++ b/panda/src/gobj/Sources.pp @@ -47,6 +47,7 @@ preparedGraphicsObjects.I preparedGraphicsObjects.h \ lens.h lens.I \ savedContext.I savedContext.h \ + sliderTable.I sliderTable.h \ texture.I texture.h \ textureContext.I textureContext.h \ texturePool.I texturePool.h \ @@ -54,8 +55,10 @@ transformBlend.I transformBlend.h \ transformBlendPalette.I transformBlendPalette.h \ transformPalette.I transformPalette.h \ + userVertexSlider.I userVertexSlider.h \ userVertexTransform.I userVertexTransform.h \ vertexBufferContext.I vertexBufferContext.h \ + vertexSlider.I vertexSlider.h \ vertexTransform.I vertexTransform.h #define INCLUDED_SOURCES \ @@ -92,13 +95,17 @@ perspectiveLens.cxx \ preparedGraphicsObjects.cxx \ lens.cxx \ - savedContext.cxx texture.cxx textureContext.cxx texturePool.cxx \ + savedContext.cxx \ + sliderTable.cxx \ + texture.cxx textureContext.cxx texturePool.cxx \ textureStage.cxx \ transformBlend.cxx \ transformBlendPalette.cxx \ transformPalette.cxx \ + userVertexSlider.cxx \ userVertexTransform.cxx \ vertexBufferContext.cxx \ + vertexSlider.cxx \ vertexTransform.cxx #define INSTALL_HEADERS \ @@ -139,6 +146,7 @@ preparedGraphicsObjects.I preparedGraphicsObjects.h \ lens.h lens.I \ savedContext.I savedContext.h \ + sliderTable.I sliderTable.h \ texture.I texture.h \ textureContext.I textureContext.h \ texturePool.I texturePool.h \ @@ -146,8 +154,10 @@ transformBlend.I transformBlend.h \ transformBlendPalette.I transformBlendPalette.h \ transformPalette.I transformPalette.h \ + userVertexSlider.I userVertexSlider.h \ userVertexTransform.I userVertexTransform.h \ vertexBufferContext.I vertexBufferContext.h \ + vertexSlider.I vertexSlider.h \ vertexTransform.I vertexTransform.h diff --git a/panda/src/gobj/config_gobj.cxx b/panda/src/gobj/config_gobj.cxx index 3746c0ac4a..25876a4027 100644 --- a/panda/src/gobj/config_gobj.cxx +++ b/panda/src/gobj/config_gobj.cxx @@ -40,13 +40,16 @@ #include "matrixLens.h" #include "perspectiveLens.h" #include "lens.h" +#include "sliderTable.h" #include "texture.h" #include "textureStage.h" #include "textureContext.h" #include "transformBlendPalette.h" #include "transformPalette.h" +#include "userVertexSlider.h" #include "userVertexTransform.h" #include "vertexTransform.h" +#include "vertexSlider.h" #include "geomContext.h" #include "vertexBufferContext.h" #include "indexBufferContext.h" @@ -212,13 +215,16 @@ ConfigureFn(config_gobj) { MatrixLens::init_type(); PerspectiveLens::init_type(); Lens::init_type(); + SliderTable::init_type(); Texture::init_type(); dDrawable::init_type(); TextureStage::init_type(); TransformBlendPalette::init_type(); TransformPalette::init_type(); + UserVertexSlider::init_type(); UserVertexTransform::init_type(); VertexTransform::init_type(); + VertexSlider::init_type(); InternalName::init_type(); //Registration of writeable object's creation @@ -248,10 +254,12 @@ ConfigureFn(config_gobj) { OrthographicLens::register_with_read_factory(); MatrixLens::register_with_read_factory(); PerspectiveLens::register_with_read_factory(); + SliderTable::register_with_read_factory(); Texture::register_with_read_factory(); TextureStage::register_with_read_factory(); TransformBlendPalette::register_with_read_factory(); TransformPalette::register_with_read_factory(); + UserVertexSlider::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 dd24bdce72..3b3a0ed3b3 100644 --- a/panda/src/gobj/gobj_composite2.cxx +++ b/panda/src/gobj/gobj_composite2.cxx @@ -12,6 +12,7 @@ #include "perspectiveLens.cxx" #include "preparedGraphicsObjects.cxx" #include "savedContext.cxx" +#include "sliderTable.cxx" #include "texture.cxx" #include "textureContext.cxx" #include "texturePool.cxx" @@ -19,6 +20,8 @@ #include "transformBlend.cxx" #include "transformBlendPalette.cxx" #include "transformPalette.cxx" +#include "userVertexSlider.cxx" #include "userVertexTransform.cxx" #include "vertexBufferContext.cxx" +#include "vertexSlider.cxx" #include "vertexTransform.cxx" diff --git a/panda/src/gobj/internalName.cxx b/panda/src/gobj/internalName.cxx index 8813c77db9..d907483bea 100644 --- a/panda/src/gobj/internalName.cxx +++ b/panda/src/gobj/internalName.cxx @@ -111,6 +111,74 @@ get_name() const { } } +//////////////////////////////////////////////////////////////////// +// Function: InternalName::find_ancestor +// Access: Published +// Description: Returns the index of the ancestor with the indicated +// basename, or -1 if no ancestor has that basename. +// Returns 0 if this name has the basename. +// +// This index value may be passed to get_ancestor() or +// get_net_basename() to retrieve more information about +// the indicated name. +//////////////////////////////////////////////////////////////////// +int InternalName:: +find_ancestor(const string &basename) const { + if (_basename == basename) { + return 0; + + } else if (_parent != (InternalName *)NULL) { + int index = _parent->find_ancestor(basename); + if (index >= 0) { + return index + 1; + } + } + + return -1; +} + +//////////////////////////////////////////////////////////////////// +// Function: InternalName::get_ancestor +// Access: Published +// Description: Returns the ancestor with the indicated index number. +// 0 is this name itself, 1 is the name's parent, 2 is +// the parent's parent, and so on. If there are not +// enough ancestors, returns the root InternalName. +//////////////////////////////////////////////////////////////////// +const InternalName *InternalName:: +get_ancestor(int n) const { + if (n == 0) { + return this; + + } else if (_parent != (InternalName *)NULL) { + return _parent->get_ancestor(n - 1); + + } else { + return get_root(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: InternalName::get_net_basename +// Access: Published +// Description: Returns the basename of this name prefixed by the +// indicated number of ancestors. 0 is this name's +// basename, 1 is parent.basename, 2 is +// grandparent.parent.basename, and so on. +//////////////////////////////////////////////////////////////////// +string InternalName:: +get_net_basename(int n) const { + if (n == 0) { + return _basename; + + } else if (_parent != (InternalName *)NULL && _parent != get_root()) { + return _parent->get_net_basename(n - 1) + "." + _basename; + + } else { + return _basename; + } +} + //////////////////////////////////////////////////////////////////// // Function: InternalName::output // Access: Published diff --git a/panda/src/gobj/internalName.h b/panda/src/gobj/internalName.h index d789eb3ba2..dc48136e07 100644 --- a/panda/src/gobj/internalName.h +++ b/panda/src/gobj/internalName.h @@ -55,6 +55,10 @@ PUBLISHED: string get_name() const; INLINE const string &get_basename() const; + int find_ancestor(const string &basename) const; + const InternalName *get_ancestor(int n) const; + string get_net_basename(int n) const; + void output(ostream &out) const; // Some predefined built-in names. diff --git a/panda/src/gobj/qpgeomVertexData.I b/panda/src/gobj/qpgeomVertexData.I index 04c6f6718f..f2df2fe8a9 100644 --- a/panda/src/gobj/qpgeomVertexData.I +++ b/panda/src/gobj/qpgeomVertexData.I @@ -150,6 +150,35 @@ clear_transform_blend_palette() { set_transform_blend_palette(NULL); } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::get_slider_table +// Access: Published +// Description: Returns a const pointer to the SliderTable +// assigned to this data. Vertices within the vertex +// data will look up their morph offsets, if any, within +// this table. +// +// This will return NULL if the vertex data does not +// have a SliderTable assigned. +//////////////////////////////////////////////////////////////////// +INLINE const SliderTable *qpGeomVertexData:: +get_slider_table() const { + CDReader cdata(_cycler); + return cdata->_slider_table; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::clear_slider_table +// Access: Published +// Description: Sets the SliderTable pointer to NULL, +// removing the table from the vertex data. This +// disables morph (blend shape) animation. +//////////////////////////////////////////////////////////////////// +INLINE void qpGeomVertexData:: +clear_slider_table() { + set_slider_table(NULL); +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomVertexData::get_modified // Access: Published diff --git a/panda/src/gobj/qpgeomVertexData.cxx b/panda/src/gobj/qpgeomVertexData.cxx index 14c5505a4b..7d5919ed3c 100644 --- a/panda/src/gobj/qpgeomVertexData.cxx +++ b/panda/src/gobj/qpgeomVertexData.cxx @@ -19,6 +19,7 @@ #include "qpgeomVertexData.h" #include "qpgeomVertexReader.h" #include "qpgeomVertexWriter.h" +#include "qpgeomVertexRewriter.h" #include "pStatTimer.h" #include "bamReader.h" #include "bamWriter.h" @@ -241,6 +242,51 @@ set_transform_blend_palette(const TransformBlendPalette *palette) { cdata->_animated_vertices_modified = UpdateSeq(); } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::modify_slider_table +// Access: Published +// Description: Returns a modifiable pointer to the current +// SliderTable on this vertex data, if any, or +// NULL if there is not a SliderTable. See +// get_slider_table(). +//////////////////////////////////////////////////////////////////// +SliderTable *qpGeomVertexData:: +modify_slider_table() { + // Perform copy-on-write: if the reference count on the table is + // greater than 1, assume some other GeomVertexData has the same + // pointer, so make a copy of it first. + CDWriter cdata(_cycler); + + if (cdata->_slider_table->get_ref_count() > 1) { + cdata->_slider_table = new SliderTable(*cdata->_slider_table); + } + cdata->_modified = qpGeom::get_next_modified(); + cdata->_animated_vertices_modified = UpdateSeq(); + + return cdata->_slider_table; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::set_slider_table +// Access: Published +// Description: Replaces the SliderTable on this vertex +// data with the indicated table. There should be an +// entry in this table for each kind of morph offset +// defined in the vertex data. +// +// The SliderTable object must have been registered +// prior to setting it on the GeomVertexData. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexData:: +set_slider_table(const SliderTable *table) { + nassertv(table == (SliderTable *)NULL || table->is_registered()); + + CDWriter cdata(_cycler); + cdata->_slider_table = (SliderTable *)table; + cdata->_modified = qpGeom::get_next_modified(); + cdata->_animated_vertices_modified = UpdateSeq(); +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomVertexData::get_num_bytes // Access: Published @@ -261,13 +307,149 @@ get_num_bytes() const { return num_bytes; } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::copy_from +// Access: Published +// Description: Copies all the data from the other array into the +// corresponding data types in this array, by matching +// data types name-by-name. +// +// keep_data_objects specifies what to do when one or +// more of the arrays can be copied without the need to +// apply any conversion operation. If it is true, the +// original GeomVertexArrayData objects in this object +// are retained, but their data arrays are copied +// pointerwise from the source; if it is false, then the +// GeomVertexArrayData objects themselves are copied +// pointerwise from the source. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexData:: +copy_from(const qpGeomVertexData &source, bool keep_data_objects) { + const qpGeomVertexFormat *source_format = source.get_format(); + const qpGeomVertexFormat *dest_format = get_format(); + + int num_vertices = source.get_num_vertices(); + int num_arrays = source_format->get_num_arrays(); + int source_i; + + // First, check to see if any arrays can be simply appropriated for + // the new format, without changing the data. + pset done_arrays; + + for (source_i = 0; source_i < num_arrays; ++source_i) { + const qpGeomVertexArrayFormat *source_array_format = + source_format->get_array(source_i); + + bool array_done = false; + + int dest_num_arrays = dest_format->get_num_arrays(); + for (int dest_i = 0; + dest_i < dest_num_arrays && !array_done; + ++dest_i) { + const qpGeomVertexArrayFormat *dest_array_format = + dest_format->get_array(dest_i); + if (dest_array_format->is_data_subset_of(*source_array_format)) { + // Great! Just use the same data for this one. + if (keep_data_objects) { + // Copy the data, but keep the same GeomVertexArrayData object. + + // Maybe it even has the same data pointer already. If so, + // avoid flipping the modified flag. + CPTA_uchar source_data = source.get_array(source_i)->get_data(); + if (get_array(dest_i)->get_data() != source_data) { + modify_array(dest_i)->set_data(source_data); + } + } else { + // Copy the GeomVertexArrayData object. + if (get_array(dest_i) != source.get_array(source_i)) { + set_array(dest_i, source.get_array(source_i)); + } + } + + array_done = true; + done_arrays.insert(dest_i); + } + } + } + + // Now make sure the arrays we didn't share are all filled in. + set_num_vertices(num_vertices); + + // Now go back through and copy any data that's left over. + for (source_i = 0; source_i < num_arrays; ++source_i) { + CPTA_uchar array_data = source.get_array(source_i)->get_data(); + const qpGeomVertexArrayFormat *source_array_format = source_format->get_array(source_i); + int num_data_types = source_array_format->get_num_data_types(); + for (int di = 0; di < num_data_types; ++di) { + const qpGeomVertexDataType *source_data_type = source_array_format->get_data_type(di); + + int dest_i = dest_format->get_array_with(source_data_type->get_name()); + if (dest_i >= 0 && done_arrays.count(dest_i) == 0) { + // The data type exists in the new format; we have to copy it. + const qpGeomVertexArrayFormat *dest_array_format = + dest_format->get_array(dest_i); + const qpGeomVertexDataType *dest_data_type = + dest_array_format->get_data_type(source_data_type->get_name()); + + if (dest_data_type->is_bytewise_equivalent(*source_data_type)) { + // We can do a quick bytewise copy. + PTA_uchar dest_array_data = modify_array(dest_i)->modify_data(); + + bytewise_copy(dest_array_data + dest_data_type->get_start(), + dest_array_format->get_stride(), + array_data + source_data_type->get_start(), source_array_format->get_stride(), + source_data_type, num_vertices); + + } else if (dest_data_type->is_packed_argb() && + source_data_type->is_uint8_rgba()) { + // A common special case: OpenGL color to DirectX color. + PTA_uchar dest_array_data = modify_array(dest_i)->modify_data(); + + uint8_rgba_to_packed_argb + (dest_array_data + dest_data_type->get_start(), + dest_array_format->get_stride(), + array_data + source_data_type->get_start(), source_array_format->get_stride(), + num_vertices); + + } else if (dest_data_type->is_uint8_rgba() && + source_data_type->is_packed_argb()) { + // Another common special case: DirectX color to OpenGL + // color. + PTA_uchar dest_array_data = modify_array(dest_i)->modify_data(); + + packed_argb_to_uint8_rgba + (dest_array_data + dest_data_type->get_start(), + dest_array_format->get_stride(), + array_data + source_data_type->get_start(), source_array_format->get_stride(), + num_vertices); + + } else { + // A generic copy. + if (gobj_cat.is_debug()) { + gobj_cat.debug() + << "generic copy " << *dest_data_type << " from " + << *source_data_type << "\n"; + } + qpGeomVertexWriter to(this); + to.set_data_type(dest_i, dest_data_type); + qpGeomVertexReader from(&source); + from.set_data_type(source_i, source_data_type); + + while (!from.is_at_end()) { + to.set_data4f(from.get_data4f()); + } + } + } + } + } +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomVertexData::convert_to // Access: Published -// Description: Matches up the data types of this format with the -// data types of the other format by name, and copies -// the data vertex-by-vertex to a new set of data arrays -// in the new format. +// Description: Returns a new GeomVertexData that represents the same +// contents as this one, with all data types matched up +// name-by-name to the indicated new format. //////////////////////////////////////////////////////////////////// CPT(qpGeomVertexData) qpGeomVertexData:: convert_to(const qpGeomVertexFormat *new_format) const { @@ -277,121 +459,18 @@ convert_to(const qpGeomVertexFormat *new_format) const { } // Okay, convert the data to the new format. - int num_vertices = get_num_vertices(); - if (gobj_cat.is_debug()) { gobj_cat.debug() - << "Converting " << num_vertices << " vertices.\n"; + << "Converting " << get_num_vertices() << " vertices.\n"; } PStatTimer timer(_convert_pcollector); PT(qpGeomVertexData) new_data = new qpGeomVertexData(get_name(), new_format, get_usage_hint()); new_data->set_transform_blend_palette(get_transform_blend_palette()); + new_data->set_slider_table(get_slider_table()); - pset done_arrays; - - int num_arrays = _format->get_num_arrays(); - int i; - - // First, check to see if any arrays can be simply appropriated for - // the new format, without changing the data. - for (i = 0; i < num_arrays; ++i) { - const qpGeomVertexArrayFormat *array_format = - _format->get_array(i); - - bool array_done = false; - - int new_num_arrays = new_format->get_num_arrays(); - for (int new_i = 0; - new_i < new_num_arrays && !array_done; - ++new_i) { - const qpGeomVertexArrayFormat *new_array_format = - new_format->get_array(new_i); - if (new_array_format->is_data_subset_of(*array_format)) { - // Great! Just use the same data for this one. - new_data->set_array(new_i, get_array(i)); - array_done = true; - - done_arrays.insert(new_i); - } - } - } - - // Now make sure the arrays we didn't share are all filled in. - new_data->set_num_vertices(num_vertices); - - // Now go back through and copy any data that's left over. - for (i = 0; i < num_arrays; ++i) { - CPTA_uchar array_data = get_array(i)->get_data(); - const qpGeomVertexArrayFormat *array_format = _format->get_array(i); - int num_data_types = array_format->get_num_data_types(); - for (int di = 0; di < num_data_types; ++di) { - const qpGeomVertexDataType *data_type = array_format->get_data_type(di); - - int new_i = new_format->get_array_with(data_type->get_name()); - if (new_i >= 0 && done_arrays.count(new_i) == 0) { - // The data type exists in the new format; we have to copy it. - const qpGeomVertexArrayFormat *new_array_format = - new_format->get_array(new_i); - const qpGeomVertexDataType *new_data_type = - new_array_format->get_data_type(data_type->get_name()); - - if (new_data_type->is_bytewise_equivalent(*data_type)) { - // We can do a quick bytewise copy. - PTA_uchar new_array_data = - new_data->modify_array(new_i)->modify_data(); - - bytewise_copy(new_array_data + new_data_type->get_start(), - new_array_format->get_stride(), - array_data + data_type->get_start(), array_format->get_stride(), - data_type, num_vertices); - - } else if (new_data_type->is_packed_argb() && - data_type->is_uint8_rgba()) { - // A common special case: OpenGL color to DirectX color. - PTA_uchar new_array_data = - new_data->modify_array(new_i)->modify_data(); - - uint8_rgba_to_packed_argb - (new_array_data + new_data_type->get_start(), - new_array_format->get_stride(), - array_data + data_type->get_start(), array_format->get_stride(), - num_vertices); - - } else if (new_data_type->is_uint8_rgba() && - data_type->is_packed_argb()) { - // Another common special case: DirectX color to OpenGL - // color. - PTA_uchar new_array_data = - new_data->modify_array(new_i)->modify_data(); - - packed_argb_to_uint8_rgba - (new_array_data + new_data_type->get_start(), - new_array_format->get_stride(), - array_data + data_type->get_start(), array_format->get_stride(), - num_vertices); - - } else { - // A generic copy. - if (gobj_cat.is_debug()) { - gobj_cat.debug() - << "generic copy " << *new_data_type << " from " - << *data_type << "\n"; - } - qpGeomVertexWriter to(new_data); - to.set_data_type(new_i, new_data_type); - qpGeomVertexReader from(this); - from.set_data_type(i, data_type); - - while (!from.is_at_end()) { - to.set_data4f(from.get_data4f()); - } - } - } - } - } - + new_data->copy_from(*this, false); return new_data; } @@ -542,6 +621,7 @@ replace_data_type(const InternalName *name, int num_components, new qpGeomVertexData(get_name(), format, usage_hint); if (keep_animation) { new_data->set_transform_blend_palette(get_transform_blend_palette()); + new_data->set_slider_table(get_slider_table()); } int j = 0; @@ -644,27 +724,35 @@ get_array_info(const InternalName *name, CPT(qpGeomVertexData) qpGeomVertexData:: do_animate_vertices(bool from_app) const { CDReader cdata(_cycler); - if (cdata->_transform_blend_palette == (TransformBlendPalette *)NULL) { - // No vertex animation. + + UpdateSeq modified; + if (cdata->_transform_blend_palette != (TransformBlendPalette *)NULL) { + if (cdata->_slider_table != (SliderTable *)NULL) { + modified = + max(cdata->_transform_blend_palette->get_modified(), + cdata->_slider_table->get_modified()); + } else { + modified = cdata->_transform_blend_palette->get_modified(); + } + + } else if (cdata->_slider_table != (SliderTable *)NULL) { + modified = cdata->_slider_table->get_modified(); + + } else { + // No transform blend palette or slider table--ergo, no vertex + // animation. return this; } - if (cdata->_animated_vertices == (qpGeomVertexData *)NULL) { - CDWriter cdataw(((qpGeomVertexData *)this)->_cycler, cdata); - ((qpGeomVertexData *)this)->make_animated_vertices(cdataw); - ((qpGeomVertexData *)this)->update_animated_vertices(cdataw, from_app); - return cdataw->_animated_vertices; - } else { - UpdateSeq blend_modified = cdata->_transform_blend_palette->get_modified(); - if (cdata->_animated_vertices_modified == blend_modified) { - // No changes. - return cdata->_animated_vertices; - } - CDWriter cdataw(((qpGeomVertexData *)this)->_cycler, cdata); - cdataw->_animated_vertices_modified = blend_modified; - ((qpGeomVertexData *)this)->update_animated_vertices(cdataw, from_app); - return cdataw->_animated_vertices; + if (cdata->_animated_vertices_modified == modified && + cdata->_animated_vertices != (qpGeomVertexData *)NULL) { + // No changes. + return cdata->_animated_vertices; } + CDWriter cdataw(((qpGeomVertexData *)this)->_cycler, cdata); + cdataw->_animated_vertices_modified = modified; + ((qpGeomVertexData *)this)->update_animated_vertices(cdataw, from_app); + return cdataw->_animated_vertices; } //////////////////////////////////////////////////////////////////// @@ -787,22 +875,6 @@ do_set_num_vertices(int n, qpGeomVertexData::CDWriter &cdata) { return any_changed; } -//////////////////////////////////////////////////////////////////// -// Function: qpGeomVertexData::make_animated_vertices -// Access: Private -// Description: Creates the GeomVertexData that represents the -// results of computing the vertex animation on the CPU. -//////////////////////////////////////////////////////////////////// -void qpGeomVertexData:: -make_animated_vertices(qpGeomVertexData::CDWriter &cdata) { - // First, make a new format that doesn't have the transform_blend - // array. - cdata->_animated_vertices = replace_data_type - (InternalName::get_transform_blend(), 0, qpGeomVertexDataType::NT_uint16, - qpGeomVertexDataType::C_index, - min(get_usage_hint(), qpGeomUsageHint::UH_dynamic), false); -} - //////////////////////////////////////////////////////////////////// // Function: qpGeomVertexData::update_animated_vertices // Access: Private @@ -825,46 +897,133 @@ update_animated_vertices(qpGeomVertexData::CDWriter &cdata, bool from_app) { PStatTimer timer(collector); #endif - CPT(TransformBlendPalette) palette = cdata->_transform_blend_palette; - nassertv(palette != (TransformBlendPalette *)NULL); - - // Recompute all the blends up front, so we don't have to test each - // one for staleness at each vertex. - int num_blends = palette->get_num_blends(); - int bi; - for (bi = 0; bi < num_blends; bi++) { - palette->get_blend(bi).update_blend(); + if (cdata->_animated_vertices == (qpGeomVertexData *)NULL) { + CPT(qpGeomVertexFormat) animated_format = get_post_animated_format(); + cdata->_animated_vertices = + new qpGeomVertexData(get_name(), animated_format, + min(get_usage_hint(), qpGeomUsageHint::UH_dynamic)); } - PT(qpGeomVertexData) new_data = cdata->_animated_vertices; - // Now go through and compute the animation. - qpGeomVertexWriter to(new_data, InternalName::get_vertex()); - qpGeomVertexReader from(this, InternalName::get_vertex()); - qpGeomVertexReader blendi(this, InternalName::get_transform_blend()); + // We have to make a complete copy of data first so we can modify + // it. If we were clever, we could maybe just figure out the subset + // of the data that might have changed since last frame, but that's + // too much trouble (and isn't obviously faster than just copying + // the whole thing). + new_data->copy_from(*this, true); - if (!blendi.has_data_type()) { - gobj_cat.warning() - << "Vertex data " << get_name() - << " has a transform_blend_palette, but no transform_blend data.\n"; - return; - } + // First, apply all of the morphs. + CPT(SliderTable) table = cdata->_slider_table; + if (table != (SliderTable *)NULL) { + int num_morphs = _format->get_num_morphs(); + for (int mi = 0; mi < num_morphs; mi++) { + CPT(InternalName) slider_name = _format->get_morph_slider(mi); + const VertexSlider *slider = table->get_slider(slider_name); + if (slider != (VertexSlider *)NULL) { + float slider_value = slider->get_slider(); + if (slider_value != 0.0f) { + CPT(InternalName) base_name = _format->get_morph_base(mi); + CPT(InternalName) delta_name = _format->get_morph_delta(mi); + + qpGeomVertexRewriter data(new_data, base_name); + qpGeomVertexReader delta(this, delta_name); - if (from.get_data_type()->get_num_values() == 4) { - for (int i = 0; i < num_vertices; i++) { - LPoint4f vertex = from.get_data4f(); - int bi = blendi.get_data1i(); - palette->get_blend(bi).transform_point(vertex); - to.set_data4f(vertex); - } - } else { - for (int i = 0; i < num_vertices; i++) { - LPoint3f vertex = from.get_data3f(); - int bi = blendi.get_data1i(); - palette->get_blend(bi).transform_point(vertex); - to.set_data3f(vertex); + if (data.get_data_type()->get_num_values() == 4) { + if (data.get_data_type()->has_homogeneous_coord()) { + for (int i = 0; i < num_vertices; i++) { + // Scale the delta by the homogeneous coordinate. + LPoint4f vertex = data.get_data4f(); + LPoint3f d = delta.get_data3f(); + d *= slider_value * vertex[3]; + data.set_data4f(vertex[0] + d[0], + vertex[1] + d[1], + vertex[2] + d[2], + vertex[3]); + } + } else { + // Just apply the four-component delta. + for (int i = 0; i < num_vertices; i++) { + const LPoint4f &vertex = data.get_data4f(); + LPoint4f d = delta.get_data4f(); + data.set_data4f(vertex + d * slider_value); + } + } + } else { + // 3-component or smaller values; don't worry about a + // homogeneous coordinate. + for (int i = 0; i < num_vertices; i++) { + const LPoint3f &vertex = data.get_data3f(); + LPoint3f d = delta.get_data3f(); + data.set_data3f(vertex + d * slider_value); + } + } + } + } } } + + // Then apply the transforms. + CPT(TransformBlendPalette) palette = cdata->_transform_blend_palette; + if (palette != (TransformBlendPalette *)NULL) { + + // Recompute all the blends up front, so we don't have to test + // each one for staleness at each vertex. + int num_blends = palette->get_num_blends(); + int bi; + for (bi = 0; bi < num_blends; bi++) { + palette->get_blend(bi).update_blend(); + } + + // Now go through and apply the transforms. + qpGeomVertexRewriter data(new_data, InternalName::get_vertex()); + qpGeomVertexReader blendi(this, InternalName::get_transform_blend()); + + if (!blendi.has_data_type()) { + gobj_cat.warning() + << "Vertex data " << get_name() + << " has a transform_blend_palette, but no transform_blend data.\n"; + return; + } + + if (data.get_data_type()->get_num_values() == 4) { + for (int i = 0; i < num_vertices; i++) { + LPoint4f vertex = data.get_data4f(); + int bi = blendi.get_data1i(); + palette->get_blend(bi).transform_point(vertex); + data.set_data4f(vertex); + } + } else { + for (int i = 0; i < num_vertices; i++) { + LPoint3f vertex = data.get_data3f(); + int bi = blendi.get_data1i(); + palette->get_blend(bi).transform_point(vertex); + data.set_data3f(vertex); + } + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::get_post_animated_format +// Access: Private +// Description: Returns a suitable vertex format for sending the +// animated vertices to the graphics backend. This is +// the same format as the source format, with the +// CPU-animation data elements removed. +//////////////////////////////////////////////////////////////////// +CPT(qpGeomVertexFormat) qpGeomVertexData:: +get_post_animated_format() const { + PT(qpGeomVertexFormat) new_format = new qpGeomVertexFormat(*_format); + + new_format->remove_data_type(InternalName::get_transform_blend()); + + int num_morphs = _format->get_num_morphs(); + for (int mi = 0; mi < num_morphs; mi++) { + CPT(InternalName) delta_name = _format->get_morph_delta(mi); + new_format->remove_data_type(delta_name); + } + + return qpGeomVertexFormat::register_format(new_format); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/qpgeomVertexData.h b/panda/src/gobj/qpgeomVertexData.h index 65650deae8..2d0609e05c 100644 --- a/panda/src/gobj/qpgeomVertexData.h +++ b/panda/src/gobj/qpgeomVertexData.h @@ -26,6 +26,7 @@ #include "qpgeomVertexArrayData.h" #include "qpgeomUsageHint.h" #include "transformBlendPalette.h" +#include "sliderTable.h" #include "internalName.h" #include "cycleData.h" #include "cycleDataReader.h" @@ -91,9 +92,15 @@ PUBLISHED: void set_transform_blend_palette(const TransformBlendPalette *palette); INLINE void clear_transform_blend_palette(); + INLINE const SliderTable *get_slider_table() const; + SliderTable *modify_slider_table(); + void set_slider_table(const SliderTable *palette); + INLINE void clear_slider_table(); + int get_num_bytes() const; INLINE UpdateSeq get_modified() const; + void copy_from(const qpGeomVertexData &source, bool keep_data_objects); CPT(qpGeomVertexData) convert_to(const qpGeomVertexFormat *new_format) const; CPT(qpGeomVertexData) scale_color(const LVecBase4f &color_scale, int num_components, @@ -167,6 +174,7 @@ private: Arrays _arrays; PT(TransformBlendPalette) _transform_blend_palette; + PT(SliderTable) _slider_table; PT(qpGeomVertexData) _animated_vertices; UpdateSeq _animated_vertices_modified; UpdateSeq _modified; @@ -178,8 +186,8 @@ private: private: bool do_set_num_vertices(int n, CDWriter &cdata); - void make_animated_vertices(CDWriter &cdata); void update_animated_vertices(CDWriter &cdata, bool from_app); + CPT(qpGeomVertexFormat) get_post_animated_format() const; static PStatCollector _convert_pcollector; static PStatCollector _scale_color_pcollector; diff --git a/panda/src/gobj/qpgeomVertexDataType.I b/panda/src/gobj/qpgeomVertexDataType.I index 2cbaf3a0ba..e1a25adb4e 100644 --- a/panda/src/gobj/qpgeomVertexDataType.I +++ b/panda/src/gobj/qpgeomVertexDataType.I @@ -151,6 +151,30 @@ get_total_bytes() const { return _total_bytes; } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexDataType::has_homogeneous_coord +// Access: Published +// Description: Returns true if this Contents type is one that +// includes a homogeneous coordinate in the fourth +// component, or false otherwise. If this is true, +// correct operation on the vertex data may require +// scaling by the homogeneous coordinate from time to +// time (but in general this is handled automatically if +// you use the 3-component or smaller forms of +// get_data() and set_data()). +//////////////////////////////////////////////////////////////////// +INLINE bool qpGeomVertexDataType:: +has_homogeneous_coord() const { + switch (_contents) { + case C_point: + case C_texcoord: + return true; + + default: + return false; + } +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomVertexDataType::overlaps_with // Access: Published diff --git a/panda/src/gobj/qpgeomVertexDataType.h b/panda/src/gobj/qpgeomVertexDataType.h index 1d0b3454c8..f7ef092d3b 100644 --- a/panda/src/gobj/qpgeomVertexDataType.h +++ b/panda/src/gobj/qpgeomVertexDataType.h @@ -49,6 +49,7 @@ PUBLISHED: C_rgba, // RGB or RGBA, OpenGL-style order C_argb, // RGBA, DirectX-style packed color C_index, // An index value into some other table + C_morph_delta, // A delta from some base value, defining a blend shape }; INLINE qpGeomVertexDataType(const InternalName *name, int num_components, @@ -67,6 +68,7 @@ PUBLISHED: INLINE int get_start() const; INLINE int get_component_bytes() const; INLINE int get_total_bytes() const; + INLINE bool has_homogeneous_coord() const; INLINE bool overlaps_with(int start_byte, int num_bytes) const; INLINE bool is_bytewise_equivalent(const qpGeomVertexDataType &other) const; diff --git a/panda/src/gobj/qpgeomVertexFormat.I b/panda/src/gobj/qpgeomVertexFormat.I index 834b84bc03..3ea6319df9 100644 --- a/panda/src/gobj/qpgeomVertexFormat.I +++ b/panda/src/gobj/qpgeomVertexFormat.I @@ -93,6 +93,81 @@ get_array(int array) const { return _arrays[array]; } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::get_num_morphs +// Access: Published +// Description: Returns the number of data types within the format +// that represent morph deltas. +// +// This may only be called after the format has been +// registered. +//////////////////////////////////////////////////////////////////// +INLINE int qpGeomVertexFormat:: +get_num_morphs() const { + nassertr(_is_registered, 0); + + return _morphs.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::get_morph_slider +// Access: Published +// Description: Returns the slider name associated with the nth morph +// data type. This is the name of the slider that will +// control the morph, and should be defined within the +// SliderTable associated with the GeomVertexData. +// +// This may only be called after the format has been +// registered. +//////////////////////////////////////////////////////////////////// +INLINE const InternalName *qpGeomVertexFormat:: +get_morph_slider(int n) const { + nassertr(_is_registered, NULL); + nassertr(n >= 0 && n < (int)_morphs.size(), NULL); + + return _morphs[n]._slider; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::get_morph_base +// Access: Published +// Description: Returns the name of the base data type that the nth +// morph modifies. This data type will also be defined +// within the format, and can be retrieved via +// get_array_with() and/or get_data_type(). +// +// This may only be called after the format has been +// registered. +//////////////////////////////////////////////////////////////////// +INLINE const InternalName *qpGeomVertexFormat:: +get_morph_base(int n) const { + nassertr(_is_registered, NULL); + nassertr(n >= 0 && n < (int)_morphs.size(), NULL); + + return _morphs[n]._base; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexFormat::get_morph_delta +// Access: Published +// Description: Returns the name of the data type that defines the +// nth morph. This contains the delta offsets that are +// to be applied to the data type defined by +// get_morph_base(). This data type will be defined +// within the format, and can be retrieved via +// get_array_with() and/or get_data_type(). +// +// This may only be called after the format has been +// registered. +//////////////////////////////////////////////////////////////////// +INLINE const InternalName *qpGeomVertexFormat:: +get_morph_delta(int n) const { + nassertr(_is_registered, NULL); + nassertr(n >= 0 && n < (int)_morphs.size(), NULL); + + return _morphs[n]._delta; +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomVertexFormat::get_v3 // Access: Published, Static diff --git a/panda/src/gobj/qpgeomVertexFormat.cxx b/panda/src/gobj/qpgeomVertexFormat.cxx index 47710b84ca..31af78611c 100644 --- a/panda/src/gobj/qpgeomVertexFormat.cxx +++ b/panda/src/gobj/qpgeomVertexFormat.cxx @@ -506,6 +506,42 @@ do_register() { } } + // Go back through the index now and look for morph descriptions. + DataTypesByName::iterator ni; + for (ni = _data_types_by_name.begin(); + ni != _data_types_by_name.end(); + ++ni) { + const DataTypeRecord &record = (*ni).second; + const qpGeomVertexDataType *data_type = _arrays[record._array_index]->get_data_type(record._data_type_index); + + // Is it a morph description? + if (data_type->get_contents() == qpGeomVertexDataType::C_morph_delta) { + MorphRecord morph; + morph._delta = data_type->get_name(); + + // The delta name must be of the form "basename.morph.slidername". + int n = morph._delta->find_ancestor("morph"); + if (n < 0) { + gobj_cat.warning() + << "vertex format defines " << *data_type->get_name() + << ", which is stored as a C_morph_delta, but its name does not include \"morph\".\n"; + } else { + morph._slider = InternalName::make(morph._delta->get_net_basename(n - 1)); + morph._base = morph._delta->get_ancestor(n + 1); + + if (_data_types_by_name.find(morph._base) == _data_types_by_name.end()) { + gobj_cat.warning() + << "vertex format defines " + << *data_type->get_name() << " but does not define " + << *morph._base << "\n"; + } else { + _morphs.push_back(morph); + } + } + } + } + + _is_registered = true; } diff --git a/panda/src/gobj/qpgeomVertexFormat.h b/panda/src/gobj/qpgeomVertexFormat.h index 0fd961f2bb..b8c26a88c0 100644 --- a/panda/src/gobj/qpgeomVertexFormat.h +++ b/panda/src/gobj/qpgeomVertexFormat.h @@ -84,6 +84,11 @@ PUBLISHED: void remove_data_type(const InternalName *name); + INLINE int get_num_morphs() const; + INLINE const InternalName *get_morph_slider(int n) const; + INLINE const InternalName *get_morph_base(int n) const; + INLINE const InternalName *get_morph_delta(int n) const; + void output(ostream &out) const; void write(ostream &out, int indent_level = 0) const; void write_with_data(ostream &out, int indent_level, @@ -146,6 +151,15 @@ private: typedef pmap DataTypesByName; DataTypesByName _data_types_by_name; + class MorphRecord { + public: + CPT(InternalName) _slider; + CPT(InternalName) _base; + CPT(InternalName) _delta; + }; + typedef pvector Morphs; + Morphs _morphs; + // This set keeps track of things that need to be told when we // destruct, and it is protected by the mutex. Mutex _cache_lock; diff --git a/panda/src/gobj/sliderTable.I b/panda/src/gobj/sliderTable.I new file mode 100644 index 0000000000..403705da5a --- /dev/null +++ b/panda/src/gobj/sliderTable.I @@ -0,0 +1,126 @@ +// Filename: sliderTable.I +// Created by: drose (28Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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: SliderTable::is_registered +// Access: Published +// Description: Returns true if this table has been registered. +// Once it has been registered, the set of sliders in +// a SliderTable may not be further modified; but +// it must be registered before it can be assigned to a +// Geom. +//////////////////////////////////////////////////////////////////// +INLINE bool SliderTable:: +is_registered() const { + return _is_registered; +} + +//////////////////////////////////////////////////////////////////// +// Function: SliderTable::register_table +// Access: Published, Static +// Description: Registers a SliderTable for use. This is +// similar to GeomVertexFormat::register_format(). Once +// registered, a SliderTable may no longer be +// modified (although the individual VertexSlider +// objects may modify their reported sliders). +// +// This must be called before a table 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(SliderTable) SliderTable:: +register_table(SliderTable *table) { + // We don't actually bother adding the table object to a registry. + // This means there may be multiple copies of identical registered + // SliderTables. Big deal. We can always go back and make a + // registry later if we really need it. + if (table->is_registered()) { + return table; + } + + table->do_register(); + return table; +} + +//////////////////////////////////////////////////////////////////// +// Function: SliderTable::get_slider +// Access: Published +// Description: Returns the slider with the indicated name, or NULL +// if no slider in the table has that name. +//////////////////////////////////////////////////////////////////// +INLINE const VertexSlider *SliderTable:: +get_slider(const InternalName *name) const { + Sliders::const_iterator si; + si = _sliders.find(name); + if (si != _sliders.end()) { + return (*si).second; + } + return NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: SliderTable::get_modified +// Access: Published +// Description: Returns a sequence number that's guaranteed to change +// at least when any VertexSliders in the table +// change. (However, this is only true for a registered +// table. An unregistered table may or may not +// reflect an update here when a VertexSlider +// changes.) +//////////////////////////////////////////////////////////////////// +INLINE UpdateSeq SliderTable:: +get_modified() const { + CDReader cdata(_cycler); + return cdata->_modified; +} + +//////////////////////////////////////////////////////////////////// +// Function: SliderTable::update_modified +// Access: Private +// Description: Called internally whenever a nested VertexSlider +// reports that it has been modified. +//////////////////////////////////////////////////////////////////// +INLINE void SliderTable:: +update_modified(UpdateSeq modified) { + CDWriter cdata(_cycler); + cdata->_modified = modified; +} + +//////////////////////////////////////////////////////////////////// +// Function: SliderTable::CData::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE SliderTable::CData:: +CData() { +} + +//////////////////////////////////////////////////////////////////// +// Function: SliderTable::CData::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE SliderTable::CData:: +CData(const SliderTable::CData ©) : + _modified(copy._modified) +{ +} diff --git a/panda/src/gobj/sliderTable.cxx b/panda/src/gobj/sliderTable.cxx new file mode 100644 index 0000000000..7b062fa425 --- /dev/null +++ b/panda/src/gobj/sliderTable.cxx @@ -0,0 +1,249 @@ +// Filename: sliderTable.cxx +// Created by: drose (28Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "sliderTable.h" +#include "bamReader.h" +#include "bamWriter.h" + +TypeHandle SliderTable::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: SliderTable::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +SliderTable:: +SliderTable() : + _is_registered(false) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: SliderTable::Copy Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +SliderTable:: +SliderTable(const SliderTable ©) : + _is_registered(false), + _sliders(copy._sliders) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: SliderTable::Copy Assignment Operator +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void SliderTable:: +operator = (const SliderTable ©) { + nassertv(!_is_registered); + _sliders = copy._sliders; +} + +//////////////////////////////////////////////////////////////////// +// Function: SliderTable::Destructor +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +SliderTable:: +~SliderTable() { + if (_is_registered) { + do_unregister(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: SliderTable::remove_slider +// Access: Published +// Description: Removes the named slider. Only valid for +// unregistered tables. +//////////////////////////////////////////////////////////////////// +void SliderTable:: +remove_slider(const InternalName *name) { + nassertv(!_is_registered); + + Sliders::iterator si = _sliders.find(name); + if (si != _sliders.end()) { + _sliders.erase(si); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: SliderTable::add_slider +// Access: Published +// Description: Adds a new slider to the table, or replaces an +// existing slider with the same name. Only valid for +// unregistered tables. +//////////////////////////////////////////////////////////////////// +void SliderTable:: +add_slider(VertexSlider *slider) { + nassertv(!_is_registered); + + _sliders[slider->get_name()] = slider; +} + +//////////////////////////////////////////////////////////////////// +// Function: SliderTable::write +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void SliderTable:: +write(ostream &out) const { + Sliders::const_iterator si; + for (si = _sliders.begin(); si != _sliders.end(); ++si) { + out << *(*si).second << "\n"; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: SliderTable::do_register +// Access: Private +// Description: Called internally when the table is registered. +//////////////////////////////////////////////////////////////////// +void SliderTable:: +do_register() { + nassertv(!_is_registered); + + Sliders::iterator si; + for (si = _sliders.begin(); si != _sliders.end(); ++si) { + bool inserted = (*si).second->_tables.insert(this).second; + nassertv(inserted); + } + _is_registered = true; +} + +//////////////////////////////////////////////////////////////////// +// Function: SliderTable::do_unregister +// Access: Private +// Description: Called internally when the table is unregistered +// (i.e. right before destruction). +//////////////////////////////////////////////////////////////////// +void SliderTable:: +do_unregister() { + nassertv(_is_registered); + + Sliders::iterator si; + for (si = _sliders.begin(); si != _sliders.end(); ++si) { + (*si).second->_tables.erase(this); + } + _is_registered = false; +} + +//////////////////////////////////////////////////////////////////// +// Function: SliderTable::register_with_read_factory +// Access: Public, Static +// Description: Tells the BamReader how to create objects of type +// SliderTable. +//////////////////////////////////////////////////////////////////// +void SliderTable:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: SliderTable::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void SliderTable:: +write_datagram(BamWriter *manager, Datagram &dg) { + TypedWritable::write_datagram(manager, dg); + + manager->write_cdata(dg, _cycler); +} + +//////////////////////////////////////////////////////////////////// +// Function: SliderTable::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type SliderTable is encountered +// in the Bam file. It should create the SliderTable +// and extract its information from the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *SliderTable:: +make_from_bam(const FactoryParams ¶ms) { + SliderTable *object = new SliderTable; + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + object->fillin(scan, manager); + + return object; +} + +//////////////////////////////////////////////////////////////////// +// Function: SliderTable::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 SliderTable. +//////////////////////////////////////////////////////////////////// +void SliderTable:: +fillin(DatagramIterator &scan, BamReader *manager) { + TypedWritable::fillin(scan, manager); + + manager->read_cdata(scan, _cycler); +} + +//////////////////////////////////////////////////////////////////// +// Function: SliderTable::CData::make_copy +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +CycleData *SliderTable::CData:: +make_copy() const { + return new CData(*this); +} + +//////////////////////////////////////////////////////////////////// +// Function: SliderTable::CData::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void SliderTable::CData:: +write_datagram(BamWriter *manager, Datagram &dg) const { +} + +//////////////////////////////////////////////////////////////////// +// Function: SliderTable::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 SliderTable::CData:: +complete_pointers(TypedWritable **p_list, BamReader *manager) { + int pi = CycleData::complete_pointers(p_list, manager); + + return pi; +} + +//////////////////////////////////////////////////////////////////// +// Function: SliderTable::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 SliderTable. +//////////////////////////////////////////////////////////////////// +void SliderTable::CData:: +fillin(DatagramIterator &scan, BamReader *manager) { +} diff --git a/panda/src/gobj/sliderTable.h b/panda/src/gobj/sliderTable.h new file mode 100644 index 0000000000..406fd841e4 --- /dev/null +++ b/panda/src/gobj/sliderTable.h @@ -0,0 +1,126 @@ +// Filename: sliderTable.h +// Created by: drose (28Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 SLIDERTABLE_H +#define SLIDERTABLE_H + +#include "pandabase.h" +#include "vertexSlider.h" +#include "typedWritableReferenceCount.h" +#include "pointerTo.h" +#include "pmap.h" +#include "cycleData.h" +#include "cycleDataReader.h" +#include "cycleDataWriter.h" +#include "pipelineCycler.h" + + +//////////////////////////////////////////////////////////////////// +// Class : SliderTable +// Description : Stores the total set of VertexSliders that the +// vertices in a particular GeomVertexData object might +// depend on. +// +// This is similar to a TransformPalette, but it stores +// VertexSliders instead of VertexTransforms, and it +// stores them by name instead of by index number. +// Also, it is only used when animating vertices on the +// CPU, since GPU's don't support morphs at this point +// in time. +// +// This is part of the experimental Geom rewrite. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA SliderTable : public TypedWritableReferenceCount { +PUBLISHED: + SliderTable(); + SliderTable(const SliderTable ©); + void operator = (const SliderTable ©); + virtual ~SliderTable(); + + INLINE bool is_registered() const; + INLINE static CPT(SliderTable) register_table(SliderTable *table); + + INLINE const VertexSlider *get_slider(const InternalName *name) const; + INLINE UpdateSeq get_modified() const; + + void remove_slider(const InternalName *name); + void add_slider(VertexSlider *slider); + + void write(ostream &out) const; + +private: + void do_register(); + void do_unregister(); + INLINE void update_modified(UpdateSeq modified); + +private: + bool _is_registered; + + typedef pmap< const InternalName *, PT(VertexSlider) > Sliders; + Sliders _sliders; + + // 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, "SliderTable", + 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 VertexSlider; +}; + +INLINE ostream &operator << (ostream &out, const SliderTable &obj); + +#include "sliderTable.I" + +#endif diff --git a/panda/src/gobj/transformPalette.I b/panda/src/gobj/transformPalette.I index 20f0a79a2e..a51d0566d1 100644 --- a/panda/src/gobj/transformPalette.I +++ b/panda/src/gobj/transformPalette.I @@ -105,9 +105,9 @@ get_modified() const { // reports that it has been modified. //////////////////////////////////////////////////////////////////// INLINE void TransformPalette:: -update_modified(UpdateSeq) { +update_modified(UpdateSeq modified) { CDWriter cdata(_cycler); - ++(cdata->_modified); + cdata->_modified = modified; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/userVertexSlider.I b/panda/src/gobj/userVertexSlider.I new file mode 100644 index 0000000000..2dbfed6d9f --- /dev/null +++ b/panda/src/gobj/userVertexSlider.I @@ -0,0 +1,52 @@ +// Filename: userVertexSlider.I +// Created by: drose (28Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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: UserVertexSlider::set_slider +// Access: Published +// Description: Stores the indicated slider value. +//////////////////////////////////////////////////////////////////// +INLINE void UserVertexSlider:: +set_slider(float slider) { + CDWriter cdata(_cycler); + cdata->_slider = slider; + mark_modified(); +} + +//////////////////////////////////////////////////////////////////// +// Function: UserVertexSlider::CData::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE UserVertexSlider::CData:: +CData() : + _slider(0.0f) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: UserVertexSlider::CData::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE UserVertexSlider::CData:: +CData(const UserVertexSlider::CData ©) : + _slider(copy._slider) +{ +} diff --git a/panda/src/gobj/userVertexSlider.cxx b/panda/src/gobj/userVertexSlider.cxx new file mode 100644 index 0000000000..4c0c81b1e4 --- /dev/null +++ b/panda/src/gobj/userVertexSlider.cxx @@ -0,0 +1,145 @@ +// Filename: userVertexSlider.cxx +// Created by: drose (28Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "userVertexSlider.h" +#include "bamReader.h" +#include "bamWriter.h" + +TypeHandle UserVertexSlider::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: UserVertexSlider::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +UserVertexSlider:: +UserVertexSlider(const string &name) : + VertexSlider(InternalName::make(name)) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: UserVertexSlider::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +UserVertexSlider:: +UserVertexSlider(const InternalName *name) : + VertexSlider(name) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: UserVertexSlider::get_slider +// Access: Published, Virtual +// Description: Returns the current slider value. +//////////////////////////////////////////////////////////////////// +float UserVertexSlider:: +get_slider() const { + CDReader cdata(_cycler); + return cdata->_slider; +} + +//////////////////////////////////////////////////////////////////// +// Function: UserVertexSlider::CData::make_copy +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +CycleData *UserVertexSlider::CData:: +make_copy() const { + return new CData(*this); +} + +//////////////////////////////////////////////////////////////////// +// Function: UserVertexSlider::register_with_read_factory +// Access: Public, Static +// Description: Tells the BamReader how to create objects of type +// UserVertexSlider. +//////////////////////////////////////////////////////////////////// +void UserVertexSlider:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: UserVertexSlider::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void UserVertexSlider:: +write_datagram(BamWriter *manager, Datagram &dg) { + VertexSlider::write_datagram(manager, dg); + + manager->write_cdata(dg, _cycler); +} + +//////////////////////////////////////////////////////////////////// +// Function: UserVertexSlider::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type UserVertexSlider is encountered +// in the Bam file. It should create the UserVertexSlider +// and extract its information from the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *UserVertexSlider:: +make_from_bam(const FactoryParams ¶ms) { + UserVertexSlider *object = new UserVertexSlider(""); + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + object->fillin(scan, manager); + + return object; +} + +//////////////////////////////////////////////////////////////////// +// Function: UserVertexSlider::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 UserVertexSlider. +//////////////////////////////////////////////////////////////////// +void UserVertexSlider:: +fillin(DatagramIterator &scan, BamReader *manager) { + VertexSlider::fillin(scan, manager); + + manager->read_cdata(scan, _cycler); +} + +//////////////////////////////////////////////////////////////////// +// Function: UserVertexSlider::CData::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void UserVertexSlider::CData:: +write_datagram(BamWriter *manager, Datagram &dg) const { +} + +//////////////////////////////////////////////////////////////////// +// Function: UserVertexSlider::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 UserVertexSlider. +//////////////////////////////////////////////////////////////////// +void UserVertexSlider::CData:: +fillin(DatagramIterator &scan, BamReader *manager) { +} diff --git a/panda/src/gobj/userVertexSlider.h b/panda/src/gobj/userVertexSlider.h new file mode 100644 index 0000000000..61cd175ce5 --- /dev/null +++ b/panda/src/gobj/userVertexSlider.h @@ -0,0 +1,91 @@ +// Filename: userVertexSlider.h +// Created by: drose (28Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 USERVERTEXSLIDER_H +#define USERVERTEXSLIDER_H + +#include "pandabase.h" +#include "vertexSlider.h" +#include "cycleData.h" +#include "cycleDataReader.h" +#include "cycleDataWriter.h" +#include "pipelineCycler.h" + +//////////////////////////////////////////////////////////////////// +// Class : UserVertexSlider +// Description : This is a specialization on VertexSlider that +// allows the user to specify any arbitrary slider +// valie he likes. This is rarely used except for +// testing. +// +// This is part of the experimental Geom rewrite. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA UserVertexSlider : public VertexSlider { +PUBLISHED: + UserVertexSlider(const string &name); + UserVertexSlider(const InternalName *name); + + INLINE void set_slider(float slider); + virtual float get_slider() const; + +private: + // This is the data that must be cycled between pipeline stages. + class EXPCL_PANDA CData : public CycleData { + public: + INLINE CData(); + INLINE CData(const CData ©); + virtual CycleData *make_copy() const; + virtual void write_datagram(BamWriter *manager, Datagram &dg) const; + virtual void fillin(DatagramIterator &scan, BamReader *manager); + + float _slider; + }; + + 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() { + VertexSlider::init_type(); + register_type(_type_handle, "UserVertexSlider", + VertexSlider::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 "userVertexSlider.I" + +#endif diff --git a/panda/src/gobj/userVertexTransform.cxx b/panda/src/gobj/userVertexTransform.cxx index f2cc6832c1..aea489251b 100644 --- a/panda/src/gobj/userVertexTransform.cxx +++ b/panda/src/gobj/userVertexTransform.cxx @@ -51,7 +51,7 @@ get_matrix(LMatrix4f &matrix) const { //////////////////////////////////////////////////////////////////// void UserVertexTransform:: output(ostream &out) const { - out << get_name(); + out << get_type() << " " << get_name(); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/vertexSlider.I b/panda/src/gobj/vertexSlider.I new file mode 100644 index 0000000000..0599acf32e --- /dev/null +++ b/panda/src/gobj/vertexSlider.I @@ -0,0 +1,70 @@ +// Filename: vertexSlider.I +// Created by: drose (28Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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: VertexSlider::get_name +// Access: Published +// Description: Returns the name of this particular slider. Every +// unique blend shape within a particular Geom must be +// identified with a different name, which is shared by +// the slider that controls it. +//////////////////////////////////////////////////////////////////// +INLINE const InternalName *VertexSlider:: +get_name() const { + return _name; +} + +//////////////////////////////////////////////////////////////////// +// Function: VertexSlider::get_modified +// Access: Published +// Description: Returns a sequence number that's guaranteed to change +// at least every time the value reported by +// get_slider() changes. +//////////////////////////////////////////////////////////////////// +INLINE UpdateSeq VertexSlider:: +get_modified() const { + CDReader cdata(_cycler); + return cdata->_modified; +} + +//////////////////////////////////////////////////////////////////// +// Function: VertexSlider::CData::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE VertexSlider::CData:: +CData() { +} + +//////////////////////////////////////////////////////////////////// +// Function: VertexSlider::CData::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE VertexSlider::CData:: +CData(const VertexSlider::CData ©) : + _modified(copy._modified) +{ +} + +INLINE ostream & +operator << (ostream &out, const VertexSlider &obj) { + obj.output(out); + return out; +} diff --git a/panda/src/gobj/vertexSlider.cxx b/panda/src/gobj/vertexSlider.cxx new file mode 100644 index 0000000000..be67fb7647 --- /dev/null +++ b/panda/src/gobj/vertexSlider.cxx @@ -0,0 +1,154 @@ +// Filename: vertexSlider.cxx +// Created by: drose (28Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "vertexSlider.h" +#include "vertexTransform.h" +#include "bamReader.h" +#include "bamWriter.h" +#include "indent.h" + +TypeHandle VertexSlider::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: VertexSlider::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +VertexSlider:: +VertexSlider(const InternalName *name) : _name(name) { +} + +//////////////////////////////////////////////////////////////////// +// Function: VertexSlider::Destructor +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +VertexSlider:: +~VertexSlider() { + // We shouldn't destruct while any SliderTables are holding our + // pointer. + nassertv(_tables.empty()); +} + +//////////////////////////////////////////////////////////////////// +// Function: VertexSlider::output +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void VertexSlider:: +output(ostream &out) const { + out << get_type() << " " << get_name(); +} + +//////////////////////////////////////////////////////////////////// +// Function: VertexSlider::write +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void VertexSlider:: +write(ostream &out, int indent_level) const { + indent(out, indent_level) + << *this << " = " << get_slider() << "\n"; +} + +//////////////////////////////////////////////////////////////////// +// Function: VertexSlider::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_slider() may not +// be propagated through the system. +//////////////////////////////////////////////////////////////////// +void VertexSlider:: +mark_modified() { + CDWriter cdata(_cycler); + cdata->_modified = VertexTransform::get_next_modified(); + + Tables::iterator ti; + for (ti = _tables.begin(); ti != _tables.end(); ++ti) { + (*ti)->update_modified(cdata->_modified); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: VertexSlider::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void VertexSlider:: +write_datagram(BamWriter *manager, Datagram &dg) { + TypedWritable::write_datagram(manager, dg); +} + +//////////////////////////////////////////////////////////////////// +// Function: VertexSlider::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 VertexSlider. +//////////////////////////////////////////////////////////////////// +void VertexSlider:: +fillin(DatagramIterator &scan, BamReader *manager) { + TypedWritable::fillin(scan, manager); +} + +//////////////////////////////////////////////////////////////////// +// Function: VertexSlider::CData::make_copy +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +CycleData *VertexSlider::CData:: +make_copy() const { + return new CData(*this); +} + +//////////////////////////////////////////////////////////////////// +// Function: VertexSlider::CData::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void VertexSlider::CData:: +write_datagram(BamWriter *manager, Datagram &dg) const { +} + +//////////////////////////////////////////////////////////////////// +// Function: VertexSlider::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 VertexSlider::CData:: +complete_pointers(TypedWritable **p_list, BamReader *manager) { + int pi = CycleData::complete_pointers(p_list, manager); + + return pi; +} + +//////////////////////////////////////////////////////////////////// +// Function: VertexSlider::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 VertexSlider. +//////////////////////////////////////////////////////////////////// +void VertexSlider::CData:: +fillin(DatagramIterator &scan, BamReader *manager) { +} diff --git a/panda/src/gobj/vertexSlider.h b/panda/src/gobj/vertexSlider.h new file mode 100644 index 0000000000..df43e7d9b5 --- /dev/null +++ b/panda/src/gobj/vertexSlider.h @@ -0,0 +1,119 @@ +// Filename: vertexSlider.h +// Created by: drose (28Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 VERTEXSLIDER_H +#define VERTEXSLIDER_H + +#include "pandabase.h" +#include "typedWritableReferenceCount.h" +#include "internalName.h" +#include "updateSeq.h" +#include "pset.h" +#include "cycleData.h" +#include "cycleDataReader.h" +#include "cycleDataWriter.h" +#include "pipelineCycler.h" + +class SliderTable; + +//////////////////////////////////////////////////////////////////// +// Class : VertexSlider +// Description : This is an abstract base class that retains some +// slider value, which is a linear value that typically +// ranges from 0.0 to 1.0, and is used to control the +// animation of morphs (blend shapes). +// +// It is similar to VertexTransform, which keeps a full +// 4x4 transform matrix, but the VertexSlider only keeps +// a single float value. +// +// This is part of the experimental Geom rewrite. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA VertexSlider : public TypedWritableReferenceCount { +PUBLISHED: + VertexSlider(const InternalName *name); + virtual ~VertexSlider(); + + INLINE const InternalName *get_name() const; + + virtual float get_slider() const=0; + INLINE UpdateSeq get_modified() const; + + virtual void output(ostream &out) const; + virtual void write(ostream &out, int indent_level) const; + +protected: + void mark_modified(); + +private: + CPT(InternalName) _name; + + typedef pset Tables; + Tables _tables; + + // 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, "VertexSlider", + 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 SliderTable; +}; + +INLINE ostream &operator << (ostream &out, const VertexSlider &obj); + +#include "vertexSlider.I" + +#endif