From e43f4f5c64a3a2eeac38d6954e43ea67af9217fc Mon Sep 17 00:00:00 2001 From: David Rose Date: Fri, 16 Feb 2007 19:19:19 +0000 Subject: [PATCH] fix morphs in character flattening; better support for flattening animated + unanimated --- panda/src/egg2pg/eggLoader.cxx | 19 +-- panda/src/gobj/geomVertexData.cxx | 175 +++++++++++++++++-------- panda/src/gobj/sliderTable.I | 33 +++-- panda/src/gobj/sliderTable.cxx | 88 +++++++------ panda/src/gobj/sliderTable.h | 20 ++- panda/src/gobj/transformBlendTable.I | 37 ++++++ panda/src/gobj/transformBlendTable.cxx | 14 +- panda/src/gobj/transformBlendTable.h | 7 + panda/src/pgraph/geomTransformer.cxx | 10 +- panda/src/pgraph/nodePath.cxx | 2 +- panda/src/pgraph/sceneGraphReducer.h | 5 +- panda/src/putil/bam.h | 3 +- panda/src/putil/bitArray.cxx | 32 +++++ panda/src/putil/bitArray.h | 8 ++ panda/src/putil/sparseArray.cxx | 35 +++++ panda/src/putil/sparseArray.h | 8 ++ 16 files changed, 373 insertions(+), 123 deletions(-) diff --git a/panda/src/egg2pg/eggLoader.cxx b/panda/src/egg2pg/eggLoader.cxx index 969ee8b2ba..4f8d440e39 100644 --- a/panda/src/egg2pg/eggLoader.cxx +++ b/panda/src/egg2pg/eggLoader.cxx @@ -90,6 +90,8 @@ #include "configVariableString.h" #include "transformBlendTable.h" #include "transformBlend.h" +#include "sparseArray.h" +#include "bitArray.h" #include #include @@ -2094,6 +2096,7 @@ make_vertex_data(const EggRenderState *render_state, temp_format->set_animation(animation); blend_table = new TransformBlendTable; + blend_table->set_rows(SparseArray::lower_on(vertex_pool->size())); PT(GeomVertexArrayFormat) anim_array_format = new GeomVertexArrayFormat; anim_array_format->add_column @@ -2101,21 +2104,21 @@ make_vertex_data(const EggRenderState *render_state, Geom::NT_uint16, Geom::C_index); temp_format->add_array(anim_array_format); - pset slider_names; + pmap slider_names; EggVertexPool::const_iterator vi; for (vi = vertex_pool->begin(); vi != vertex_pool->end(); ++vi) { EggVertex *vertex = (*vi); EggMorphVertexList::const_iterator mvi; for (mvi = vertex->_dxyzs.begin(); mvi != vertex->_dxyzs.end(); ++mvi) { - slider_names.insert((*mvi).get_name()); + slider_names[(*mvi).get_name()].set_bit(vertex->get_index()); record_morph(anim_array_format, character_maker, (*mvi).get_name(), InternalName::get_vertex(), 3); } if (vertex->has_normal()) { EggMorphNormalList::const_iterator mni; for (mni = vertex->_dnormals.begin(); mni != vertex->_dnormals.end(); ++mni) { - slider_names.insert((*mni).get_name()); + slider_names[(*mni).get_name()].set_bit(vertex->get_index()); record_morph(anim_array_format, character_maker, (*mni).get_name(), InternalName::get_normal(), 3); } @@ -2123,7 +2126,7 @@ make_vertex_data(const EggRenderState *render_state, if (has_colors && vertex->has_color()) { EggMorphColorList::const_iterator mci; for (mci = vertex->_drgbas.begin(); mci != vertex->_drgbas.end(); ++mci) { - slider_names.insert((*mci).get_name()); + slider_names[(*mci).get_name()].set_bit(vertex->get_index()); record_morph(anim_array_format, character_maker, (*mci).get_name(), InternalName::get_color(), 4); } @@ -2137,7 +2140,7 @@ make_vertex_data(const EggRenderState *render_state, EggMorphTexCoordList::const_iterator mti; for (mti = egg_uv->_duvs.begin(); mti != egg_uv->_duvs.end(); ++mti) { - slider_names.insert((*mti).get_name()); + slider_names[(*mti).get_name()].set_bit(vertex->get_index()); record_morph(anim_array_format, character_maker, (*mti).get_name(), iname, has_w ? 3 : 2); } @@ -2149,10 +2152,10 @@ make_vertex_data(const EggRenderState *render_state, slider_table = new SliderTable; - pset::iterator si; + pmap::iterator si; for (si = slider_names.begin(); si != slider_names.end(); ++si) { - VertexSlider *slider = character_maker->egg_to_slider(*si); - slider_table->add_slider(slider); + PT(VertexSlider) slider = character_maker->egg_to_slider((*si).first); + slider_table->add_slider(slider, (*si).second); } } diff --git a/panda/src/gobj/geomVertexData.cxx b/panda/src/gobj/geomVertexData.cxx index 7672b3ce40..1815df679c 100644 --- a/panda/src/gobj/geomVertexData.cxx +++ b/panda/src/gobj/geomVertexData.cxx @@ -1244,43 +1244,75 @@ update_animated_vertices(GeomVertexData::CData *cdata, Thread *current_thread) { int num_morphs = orig_format->get_num_morphs(); for (int mi = 0; mi < num_morphs; mi++) { CPT(InternalName) slider_name = orig_format->get_morph_slider(mi); - const VertexSlider *slider = slider_table->find_slider(slider_name); - if (slider != (VertexSlider *)NULL) { - float slider_value = slider->get_slider(); - if (slider_value != 0.0f) { - CPT(InternalName) base_name = orig_format->get_morph_base(mi); - CPT(InternalName) delta_name = orig_format->get_morph_delta(mi); - - GeomVertexRewriter data(new_data, base_name); - GeomVertexReader delta(this, delta_name); - if (data.get_column()->get_num_values() == 4) { - if (data.get_column()->has_homogeneous_coord()) { - for (int i = 0; i < num_rows; 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]); + const SparseArray &sliders = slider_table->find_sliders(slider_name); + if (!sliders.is_zero()) { + nassertv(!sliders.is_inverse()); + int num_slider_subranges = sliders.get_num_subranges(); + for (int sni = 0; sni < num_slider_subranges; ++sni) { + int slider_begin = sliders.get_subrange_begin(sni); + int slider_end = sliders.get_subrange_end(sni); + for (int sn = slider_begin; sn < slider_end; ++sn) { + const VertexSlider *slider = slider_table->get_slider(sn); + const SparseArray &rows = slider_table->get_slider_rows(sn); + nassertv(!rows.is_inverse()); + + float slider_value = slider->get_slider(); + if (slider_value != 0.0f) { + CPT(InternalName) base_name = orig_format->get_morph_base(mi); + CPT(InternalName) delta_name = orig_format->get_morph_delta(mi); + + GeomVertexRewriter data(new_data, base_name); + GeomVertexReader delta(this, delta_name); + int num_subranges = rows.get_num_subranges(); + + if (data.get_column()->get_num_values() == 4) { + if (data.get_column()->has_homogeneous_coord()) { + // Scale the delta by the homogeneous coordinate. + for (int i = 0; i < num_subranges; ++i) { + int begin = rows.get_subrange_begin(i); + int end = rows.get_subrange_end(i); + data.set_row(begin); + delta.set_row(begin); + for (int j = begin; j < end; ++j) { + 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_subranges; ++i) { + int begin = rows.get_subrange_begin(i); + int end = rows.get_subrange_end(i); + data.set_row(begin); + delta.set_row(begin); + for (int j = begin; j < end; ++j) { + 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_subranges; ++i) { + int begin = rows.get_subrange_begin(i); + int end = rows.get_subrange_end(i); + data.set_row(begin); + delta.set_row(begin); + for (int j = begin; j < end; ++j) { + const LPoint3f &vertex = data.get_data3f(); + LPoint3f d = delta.get_data3f(); + data.set_data3f(vertex + d * slider_value); + } + } } - } else { - // Just apply the four-component delta. - for (int i = 0; i < num_rows; 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_rows; i++) { - const LPoint3f &vertex = data.get_data3f(); - LPoint3f d = delta.get_data3f(); - data.set_data3f(vertex + d * slider_value); } } } @@ -1310,36 +1342,54 @@ update_animated_vertices(GeomVertexData::CData *cdata, Thread *current_thread) { return; } + const SparseArray &rows = tb_table->get_rows(); + int num_subranges = rows.get_num_subranges(); + int ci; for (ci = 0; ci < orig_format->get_num_points(); ci++) { GeomVertexRewriter data(new_data, orig_format->get_point(ci)); - blendi.set_row(0); if (data.get_column()->get_num_values() == 4) { - for (int i = 0; i < num_rows; i++) { - LPoint4f vertex = data.get_data4f(); - int bi = blendi.get_data1i(); - tb_table->get_blend(bi).transform_point(vertex, current_thread); - data.set_data4f(vertex); + for (int i = 0; i < num_subranges; ++i) { + int begin = rows.get_subrange_begin(i); + int end = rows.get_subrange_end(i); + data.set_row(begin); + blendi.set_row(begin); + for (int j = begin; j < end; ++j) { + LPoint4f vertex = data.get_data4f(); + int bi = blendi.get_data1i(); + tb_table->get_blend(bi).transform_point(vertex, current_thread); + data.set_data4f(vertex); + } } } else { - for (int i = 0; i < num_rows; i++) { - LPoint3f vertex = data.get_data3f(); - int bi = blendi.get_data1i(); - tb_table->get_blend(bi).transform_point(vertex, current_thread); - data.set_data3f(vertex); + for (int i = 0; i < num_subranges; ++i) { + int begin = rows.get_subrange_begin(i); + int end = rows.get_subrange_end(i); + data.set_row(begin); + blendi.set_row(begin); + for (int j = begin; j < end; ++j) { + LPoint3f vertex = data.get_data3f(); + int bi = blendi.get_data1i(); + tb_table->get_blend(bi).transform_point(vertex, current_thread); + data.set_data3f(vertex); + } } } } for (ci = 0; ci < orig_format->get_num_vectors(); ci++) { GeomVertexRewriter data(new_data, orig_format->get_vector(ci)); - blendi.set_row(0); - - for (int i = 0; i < num_rows; i++) { - LVector3f vertex = data.get_data3f(); - int bi = blendi.get_data1i(); - tb_table->get_blend(bi).transform_vector(vertex, current_thread); - data.set_data3f(vertex); + for (int i = 0; i < num_subranges; ++i) { + int begin = rows.get_subrange_begin(i); + int end = rows.get_subrange_end(i); + data.set_row(begin); + blendi.set_row(begin); + for (int j = begin; j < end; ++j) { + LVector3f vertex = data.get_data3f(); + int bi = blendi.get_data1i(); + tb_table->get_blend(bi).transform_vector(vertex, current_thread); + data.set_data3f(vertex); + } } } } @@ -1564,6 +1614,25 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) { _modified = Geom::get_next_modified(); + if (!_arrays.empty() && manager->get_file_minor_ver() < 7) { + // Bam files prior to 6.7 did not store a SparseArray in the + // SliderTable or TransformBlendTable entries. We need to make up + // a SparseArray for each of them that reflects the complete + // number of rows in the data. + SparseArray all_rows; + all_rows.set_range(0, _arrays[0]->get_num_rows()); + + if (_slider_table != (SliderTable *)NULL) { + int num_sliders = _slider_table->get_num_sliders(); + for (int i = 0; i < num_sliders; ++i) { + ((SliderTable *)_slider_table.p())->set_slider_rows(i, all_rows); + } + } + if (_transform_blend_table != (TransformBlendTable *)NULL) { + _transform_blend_table->set_rows(all_rows); + } + } + return pi; } diff --git a/panda/src/gobj/sliderTable.I b/panda/src/gobj/sliderTable.I index c1d2b471d9..f4761c4fdc 100644 --- a/panda/src/gobj/sliderTable.I +++ b/panda/src/gobj/sliderTable.I @@ -79,34 +79,47 @@ get_num_sliders() const { INLINE const VertexSlider *SliderTable:: get_slider(int n) const { nassertr(n >= 0 && n < (int)_sliders.size(), NULL); - return _sliders[n]; + return _sliders[n]._slider; } //////////////////////////////////////////////////////////////////// -// Function: SliderTable::find_slider +// Function: SliderTable::get_slider_rows // Access: Published -// Description: Returns the slider with the indicated name, or NULL -// if no slider in the table has that name. +// Description: Returns the set of rows (vertices) governed by the +// nth slider in the table. //////////////////////////////////////////////////////////////////// -INLINE const VertexSlider *SliderTable:: -find_slider(const InternalName *name) const { +INLINE const SparseArray &SliderTable:: +get_slider_rows(int n) const { + nassertr(n >= 0 && n < (int)_sliders.size(), _empty_array); + return _sliders[n]._rows; +} + +//////////////////////////////////////////////////////////////////// +// Function: SliderTable::find_sliders +// Access: Published +// Description: Returns a list of slider indices that represent the +// list of sliders with the indicated name, or an empty +// SparseArray if no slider in the table has that name. +//////////////////////////////////////////////////////////////////// +INLINE const SparseArray &SliderTable:: +find_sliders(const InternalName *name) const { SlidersByName::const_iterator sni; sni = _sliders_by_name.find(name); if (sni != _sliders_by_name.end()) { return (*sni).second; } - return NULL; + return _empty_array; } //////////////////////////////////////////////////////////////////// // Function: SliderTable::has_slider // Access: Published -// Description: Returns true if the table has a slider by the -// indicated name, false otherwise. +// Description: Returns true if the table has at least one slider by +// the indicated name, false otherwise. //////////////////////////////////////////////////////////////////// INLINE bool SliderTable:: has_slider(const InternalName *name) const { - return (find_slider(name) != (VertexSlider *)NULL); + return (!find_sliders(name).is_zero()); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/sliderTable.cxx b/panda/src/gobj/sliderTable.cxx index 9db65b7c71..3311e450fc 100644 --- a/panda/src/gobj/sliderTable.cxx +++ b/panda/src/gobj/sliderTable.cxx @@ -21,6 +21,7 @@ #include "bamWriter.h" #include "vertexTransform.h" +SparseArray SliderTable::_empty_array; TypeHandle SliderTable::_type_handle; //////////////////////////////////////////////////////////////////// @@ -82,13 +83,29 @@ set_slider(int n, const VertexSlider *slider) { nassertv(!_is_registered); nassertv(n >= 0 && n < (int)_sliders.size()); - if (_sliders[n]->get_name() != slider->get_name()) { - // Not allowed to move a slider this way. - nassertv(!has_slider(slider->get_name())); + if (_sliders[n]._slider->get_name() != slider->get_name()) { + _sliders_by_name[_sliders[n]._slider->get_name()].clear_bit(n); + _sliders_by_name[slider->get_name()].set_bit(n); } - _sliders[n] = slider; - _sliders_by_name[slider->get_name()] = slider; + _sliders[n]._slider = slider; +} + +//////////////////////////////////////////////////////////////////// +// Function: SliderTable::set_slider_rows +// Access: Published +// Description: Replaces the rows affected by the nth slider. Only +// valid for unregistered tables. +//////////////////////////////////////////////////////////////////// +void SliderTable:: +set_slider_rows(int n, const SparseArray &rows) { + // We don't actually enforce the registration requirement, since + // gee, it doesn't actually matter here; and the GeomVertexData + // needs to be able to change the SparseArrays in the bam reader. + // nassertv(!_is_registered); + nassertv(n >= 0 && n < (int)_sliders.size()); + + _sliders[n]._rows = rows; } //////////////////////////////////////////////////////////////////// @@ -102,41 +119,28 @@ remove_slider(int n) { nassertv(!_is_registered); nassertv(n >= 0 && n < (int)_sliders.size()); - SlidersByName::iterator si = _sliders_by_name.find(_sliders[n]->get_name()); - nassertv(si != _sliders_by_name.end()); - _sliders_by_name.erase(si); - + _sliders_by_name[_sliders[n]._slider->get_name()].clear_bit(n); _sliders.erase(_sliders.begin() + n); } //////////////////////////////////////////////////////////////////// // Function: SliderTable::add_slider // Access: Published -// Description: Adds a new slider to the table, or replaces an -// existing slider with the same name, and returns the +// Description: Adds a new slider to the table, and returns the // index number of the new slider. Only valid for // unregistered tables. //////////////////////////////////////////////////////////////////// int SliderTable:: -add_slider(const VertexSlider *slider) { +add_slider(const VertexSlider *slider, const SparseArray &rows) { nassertr(!_is_registered, -1); - SlidersByName::iterator sni = _sliders_by_name.find(slider->get_name()); - if (sni != _sliders_by_name.end()) { - // We've already got a slider with this name; replace it. - CPT(VertexSlider) orig_slider = (*sni).second; - Sliders::iterator si = find(_sliders.begin(), _sliders.end(), orig_slider); - nassertr(si != _sliders.end(), -1); - (*si) = slider; - (*sni).second = slider; - - return si - _sliders.begin(); - } - - // This is the first slider with this name. int new_index = (int)_sliders.size(); - _sliders.push_back(slider); - _sliders_by_name[slider->get_name()] = slider; + + SliderDef slider_def; + slider_def._slider = slider; + slider_def._rows = rows; + _sliders.push_back(slider_def); + _sliders_by_name[slider->get_name()].set_bit(new_index); return new_index; } @@ -149,7 +153,8 @@ add_slider(const VertexSlider *slider) { void SliderTable:: write(ostream &out) const { for (size_t i = 0; i < _sliders.size(); ++i) { - out << i << ". " << *_sliders[i] << "\n"; + out << i << ". " << *_sliders[i]._slider << " " + << _sliders[i]._rows << "\n"; } } @@ -164,7 +169,7 @@ do_register() { Sliders::iterator si; for (si = _sliders.begin(); si != _sliders.end(); ++si) { - const VertexSlider *slider = (*si); + const VertexSlider *slider = (*si)._slider; bool inserted = ((VertexSlider *)slider)->_tables.insert(this).second; nassertv(inserted); } @@ -183,7 +188,7 @@ do_unregister() { Sliders::iterator si; for (si = _sliders.begin(); si != _sliders.end(); ++si) { - const VertexSlider *slider = (*si); + const VertexSlider *slider = (*si)._slider; ((VertexSlider *)slider)->_tables.erase(this); } _is_registered = false; @@ -213,8 +218,9 @@ write_datagram(BamWriter *manager, Datagram &dg) { dg.add_uint16(_sliders.size()); Sliders::const_iterator si; for (si = _sliders.begin(); si != _sliders.end(); ++si) { - manager->write_pointer(dg, (*si)->get_name()); - manager->write_pointer(dg, (*si)); + manager->write_pointer(dg, (*si)._slider->get_name()); + manager->write_pointer(dg, (*si)._slider); + (*si)._rows.write_datagram(manager, dg); } manager->write_cdata(dg, _cycler); @@ -231,15 +237,12 @@ int SliderTable:: complete_pointers(TypedWritable **p_list, BamReader *manager) { int pi = TypedWritableReferenceCount::complete_pointers(p_list, manager); - Sliders::iterator si; - for (si = _sliders.begin(); si != _sliders.end(); ++si) { + for (size_t n = 0; n < _sliders.size(); ++n) { CPT(InternalName) name = DCAST(InternalName, p_list[pi++]); PT(VertexSlider) slider = DCAST(VertexSlider, p_list[pi++]); - (*si) = slider; - - bool inserted = _sliders_by_name.insert(SlidersByName::value_type(name, slider.p())).second; - nassertr(inserted, pi); + _sliders[n]._slider = slider; + _sliders_by_name[name].set_bit(n); } return pi; @@ -281,7 +284,14 @@ fillin(DatagramIterator &scan, BamReader *manager) { for (size_t i = 0; i < num_sliders; ++i) { manager->read_pointer(scan); manager->read_pointer(scan); - _sliders.push_back(NULL); + _sliders.push_back(SliderDef()); + if (manager->get_file_minor_ver() >= 7) { + _sliders[i]._rows.read_datagram(scan, manager); + } else { + // In this case, for bam files prior to 6.7, we must define the + // SparseArray with the full number of vertices. This is done + // in GeomVertexData::complete_pointers(). + } } manager->read_cdata(scan, _cycler); diff --git a/panda/src/gobj/sliderTable.h b/panda/src/gobj/sliderTable.h index bd706db635..1f371e1b89 100644 --- a/panda/src/gobj/sliderTable.h +++ b/panda/src/gobj/sliderTable.h @@ -28,7 +28,7 @@ #include "cycleDataReader.h" #include "cycleDataWriter.h" #include "pipelineCycler.h" - +#include "sparseArray.h" //////////////////////////////////////////////////////////////////// // Class : SliderTable @@ -55,15 +55,17 @@ PUBLISHED: INLINE int get_num_sliders() const; INLINE const VertexSlider *get_slider(int n) const; + INLINE const SparseArray &get_slider_rows(int n) const; - INLINE const VertexSlider *find_slider(const InternalName *name) const; + INLINE const SparseArray &find_sliders(const InternalName *name) const; INLINE bool has_slider(const InternalName *name) const; INLINE bool is_empty() const; INLINE UpdateSeq get_modified(Thread *current_thread) const; void set_slider(int n, const VertexSlider *slider); + void set_slider_rows(int n, const SparseArray &rows); void remove_slider(int n); - int add_slider(const VertexSlider *slider); + int add_slider(const VertexSlider *slider, const SparseArray &rows); void write(ostream &out) const; @@ -75,12 +77,20 @@ private: private: bool _is_registered; - typedef pvector< CPT(VertexSlider) > Sliders; + class SliderDef { + public: + CPT(VertexSlider) _slider; + SparseArray _rows; + }; + + typedef pvector Sliders; Sliders _sliders; - typedef pmap< CPT(InternalName), const VertexSlider *> SlidersByName; + typedef pmap< CPT(InternalName), SparseArray > SlidersByName; SlidersByName _sliders_by_name; + static SparseArray _empty_array; + // This is the data that must be cycled between pipeline stages. class EXPCL_PANDA CData : public CycleData { public: diff --git a/panda/src/gobj/transformBlendTable.I b/panda/src/gobj/transformBlendTable.I index 208112b132..698d57a9f1 100644 --- a/panda/src/gobj/transformBlendTable.I +++ b/panda/src/gobj/transformBlendTable.I @@ -88,6 +88,43 @@ get_max_simultaneous_transforms() const { return _max_simultaneous_transforms; } +//////////////////////////////////////////////////////////////////// +// Function: TransformBlendTable::set_rows +// Access: Published +// Description: Specifies the subset of rows (vertices) in the +// associated GeomVertexData that this +// TransformBlendTable actually affects. +//////////////////////////////////////////////////////////////////// +INLINE void TransformBlendTable:: +set_rows(const SparseArray &rows) { + _rows = rows; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlendTable::get_rows +// Access: Published +// Description: Returns the subset of rows (vertices) in the +// associated GeomVertexData that this +// TransformBlendTable actually affects. +//////////////////////////////////////////////////////////////////// +INLINE const SparseArray &TransformBlendTable:: +get_rows() const { + return _rows; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformBlendTable::modify_rows +// Access: Published +// Description: Returns a modifiable reference to the SparseArray +// that specifies the subset of rows (vertices) in the +// associated GeomVertexData that this +// TransformBlendTable actually affects. +//////////////////////////////////////////////////////////////////// +INLINE SparseArray &TransformBlendTable:: +modify_rows() { + return _rows; +} + //////////////////////////////////////////////////////////////////// // Function: TransformBlendTable::consider_rebuild_index // Access: Private diff --git a/panda/src/gobj/transformBlendTable.cxx b/panda/src/gobj/transformBlendTable.cxx index 90e3055438..bd055ade41 100644 --- a/panda/src/gobj/transformBlendTable.cxx +++ b/panda/src/gobj/transformBlendTable.cxx @@ -39,7 +39,8 @@ TransformBlendTable() { //////////////////////////////////////////////////////////////////// TransformBlendTable:: TransformBlendTable(const TransformBlendTable ©) : - _blends(copy._blends) + _blends(copy._blends), + _rows(copy._rows) { } @@ -51,6 +52,7 @@ TransformBlendTable(const TransformBlendTable ©) : void TransformBlendTable:: operator = (const TransformBlendTable ©) { _blends = copy._blends; + _rows = copy._rows; clear_index(); } @@ -229,6 +231,8 @@ write_datagram(BamWriter *manager, Datagram &dg) { (*bi).write_datagram(manager, dg); } + _rows.write_datagram(manager, dg); + manager->write_cdata(dg, _cycler); } @@ -291,6 +295,14 @@ fillin(DatagramIterator &scan, BamReader *manager) { _blends.push_back(blend); } + if (manager->get_file_minor_ver() >= 7) { + _rows.read_datagram(scan, manager); + } else { + // In this case, for bam files prior to 6.7, we must define the + // SparseArray with the full number of vertices. This is done + // in GeomVertexData::complete_pointers(). + } + manager->read_cdata(scan, _cycler); } diff --git a/panda/src/gobj/transformBlendTable.h b/panda/src/gobj/transformBlendTable.h index fefb7a014a..9ef82c2509 100644 --- a/panda/src/gobj/transformBlendTable.h +++ b/panda/src/gobj/transformBlendTable.h @@ -32,6 +32,7 @@ #include "cycleDataReader.h" #include "cycleDataWriter.h" #include "pipelineCycler.h" +#include "sparseArray.h" class FactoryParams; @@ -68,6 +69,10 @@ PUBLISHED: INLINE int get_num_transforms() const; INLINE int get_max_simultaneous_transforms() const; + INLINE void set_rows(const SparseArray &rows); + INLINE const SparseArray &get_rows() const; + INLINE SparseArray &modify_rows(); + void write(ostream &out, int indent_level) const; private: @@ -88,6 +93,8 @@ private: typedef pvector Blends; Blends _blends; + SparseArray _rows; + // 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, diff --git a/panda/src/pgraph/geomTransformer.cxx b/panda/src/pgraph/geomTransformer.cxx index f7873dd018..7c9d93941e 100644 --- a/panda/src/pgraph/geomTransformer.cxx +++ b/panda/src/pgraph/geomTransformer.cxx @@ -601,9 +601,15 @@ collect_vertex_data(Geom *geom, int collect_bits) { new_btable = new_data->modify_transform_blend_table(); } else { new_btable = new TransformBlendTable; + new_btable->add_blend(TransformBlend()); new_data->set_transform_blend_table(new_btable); } + SparseArray new_rows = old_btable->get_rows(); + new_rows <<= offset; + new_rows |= new_btable->get_rows(); + new_btable->set_rows(new_rows); + // We still need to build up the IndexMap. IndexMap blend_map; @@ -644,7 +650,9 @@ collect_vertex_data(Geom *geom, int collect_bits) { } int num_sliders = old_sliders->get_num_sliders(); for (int si = 0; si < num_sliders; ++si) { - new_sliders->add_slider(old_sliders->get_slider(si)); + SparseArray new_rows = old_sliders->get_slider_rows(si); + new_rows <<= offset; + new_sliders->add_slider(old_sliders->get_slider(si), new_rows); } new_data->set_slider_table(SliderTable::register_table(new_sliders)); } diff --git a/panda/src/pgraph/nodePath.cxx b/panda/src/pgraph/nodePath.cxx index 775aa17f5b..dd709434d1 100644 --- a/panda/src/pgraph/nodePath.cxx +++ b/panda/src/pgraph/nodePath.cxx @@ -5779,7 +5779,7 @@ flatten_strong() { gr.apply_attribs(node()); int num_removed = gr.flatten(node(), ~0); - gr.collect_vertex_data(node(), ~(SceneGraphReducer::CVD_format | SceneGraphReducer::CVD_name)); + gr.collect_vertex_data(node(), ~(SceneGraphReducer::CVD_format | SceneGraphReducer::CVD_name | SceneGraphReducer::CVD_animation_type)); gr.unify(node()); return num_removed; diff --git a/panda/src/pgraph/sceneGraphReducer.h b/panda/src/pgraph/sceneGraphReducer.h index 5c04433a50..8f6da03e22 100644 --- a/panda/src/pgraph/sceneGraphReducer.h +++ b/panda/src/pgraph/sceneGraphReducer.h @@ -100,10 +100,7 @@ PUBLISHED: CVD_usage_hint = 0x040, // If set, GeomVertexDatas with unanimated vertices will not be - // combined with GeomVertexDatas with animated vertices. Although - // it is legal to mix unanimated and animated vertex datas, doing - // so will convert the unanimated vertices to animated vertices, - // which can result in additional processing requirements. + // combined with GeomVertexDatas with animated vertices. CVD_animation_type = 0x080, }; diff --git a/panda/src/putil/bam.h b/panda/src/putil/bam.h index 7a8b8b585b..cb80f6732d 100644 --- a/panda/src/putil/bam.h +++ b/panda/src/putil/bam.h @@ -36,13 +36,14 @@ static const unsigned short _bam_major_ver = 6; // Bumped to major version 5 on 5/6/05 for new Geom implementation. // Bumped to major version 6 on 2/11/06 to factor out PandaNode::CData. -static const unsigned short _bam_minor_ver = 6; +static const unsigned short _bam_minor_ver = 7; // Bumped to minor version 1 on 3/12/06 to add Texture::_compression. // Bumped to minor version 2 on 3/17/06 to add PandaNode::_draw_control_mask. // Bumped to minor version 3 on 3/21/06 to add Texture::_ram_images. // Bumped to minor version 4 on 7/26/06 to add CharacterJoint::_character. // Bumped to minor version 5 on 11/15/06 to add PartBundleNode::_num_bundles. // Bumped to minor version 6 on 2/5/07 to change GeomPrimitive::_num_vertices. +// Bumped to minor version 7 on 2/15/07 to change SliderTable. #endif diff --git a/panda/src/putil/bitArray.cxx b/panda/src/putil/bitArray.cxx index cc23c980ee..89bafca5d4 100755 --- a/panda/src/putil/bitArray.cxx +++ b/panda/src/putil/bitArray.cxx @@ -808,3 +808,35 @@ normalize() { } } } + +//////////////////////////////////////////////////////////////////// +// Function: BitArray::write_datagram +// Access: Public +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void BitArray:: +write_datagram(BamWriter *manager, Datagram &dg) const { + dg.add_uint32(_array.size()); + Array::const_iterator ai; + for (ai = _array.begin(); ai != _array.end(); ++ai) { + dg.add_uint32((*ai).get_word()); + } + dg.add_uint8(_highest_bits); +} + +//////////////////////////////////////////////////////////////////// +// Function: BitArray::read_datagram +// Access: Public +// Description: Reads the object that was previously written to a Bam +// file. +//////////////////////////////////////////////////////////////////// +void BitArray:: +read_datagram(DatagramIterator &scan, BamReader *manager) { + size_t num_words = scan.get_uint32(); + _array = Array::empty_array(num_words); + for (size_t i = 0; i < num_words; ++i) { + _array[i] = WordType(scan.get_uint32()); + } + _highest_bits = scan.get_uint8(); +} diff --git a/panda/src/putil/bitArray.h b/panda/src/putil/bitArray.h index 4499fa7f99..e72dd2c177 100755 --- a/panda/src/putil/bitArray.h +++ b/panda/src/putil/bitArray.h @@ -30,6 +30,10 @@ #include "checksumHashGenerator.h" class SparseArray; +class BamWriter; +class BamReader; +class Datagram; +class DatagramIterator; //////////////////////////////////////////////////////////////////// // Class : BitArray @@ -136,6 +140,10 @@ private: Array _array; int _highest_bits; // Either 0 or 1. +public: + void write_datagram(BamWriter *manager, Datagram &dg) const; + void read_datagram(DatagramIterator &scan, BamReader *manager); + public: static TypeHandle get_class_type() { return _type_handle; diff --git a/panda/src/putil/sparseArray.cxx b/panda/src/putil/sparseArray.cxx index f9b37e87c2..e2d667af1a 100644 --- a/panda/src/putil/sparseArray.cxx +++ b/panda/src/putil/sparseArray.cxx @@ -515,3 +515,38 @@ do_shift(int offset) { } } } + +//////////////////////////////////////////////////////////////////// +// Function: SparseArray::write_datagram +// Access: Public +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void SparseArray:: +write_datagram(BamWriter *manager, Datagram &dg) const { + dg.add_uint32(_subranges.size()); + Subranges::const_iterator si; + for (si = _subranges.begin(); si != _subranges.end(); ++si) { + dg.add_int32((*si)._begin); + dg.add_int32((*si)._end); + } + dg.add_bool(_inverse); +} + +//////////////////////////////////////////////////////////////////// +// Function: SparseArray::read_datagram +// Access: Public +// Description: Reads the object that was previously written to a Bam +// file. +//////////////////////////////////////////////////////////////////// +void SparseArray:: +read_datagram(DatagramIterator &scan, BamReader *manager) { + size_t num_subranges = scan.get_uint32(); + _subranges.reserve(num_subranges); + for (size_t i = 0; i < num_subranges; ++i) { + int begin = scan.get_int32(); + int end = scan.get_int32(); + _subranges.push_back(Subrange(begin, end)); + } + _inverse = scan.get_bool(); +} diff --git a/panda/src/putil/sparseArray.h b/panda/src/putil/sparseArray.h index 330f4c3cd5..5f091be484 100644 --- a/panda/src/putil/sparseArray.h +++ b/panda/src/putil/sparseArray.h @@ -23,6 +23,10 @@ #include "ordered_vector.h" class BitArray; +class BamWriter; +class BamReader; +class Datagram; +class DatagramIterator; //////////////////////////////////////////////////////////////////// // Class : SparseArray @@ -144,6 +148,10 @@ private: Subranges _subranges; bool _inverse; +public: + void write_datagram(BamWriter *manager, Datagram &dg) const; + void read_datagram(DatagramIterator &scan, BamReader *manager); + public: static TypeHandle get_class_type() { return _type_handle;