fix morphs in character flattening; better support for flattening animated + unanimated

This commit is contained in:
David Rose 2007-02-16 19:19:19 +00:00
parent cffe4156eb
commit e43f4f5c64
16 changed files with 373 additions and 123 deletions

View File

@ -90,6 +90,8 @@
#include "configVariableString.h" #include "configVariableString.h"
#include "transformBlendTable.h" #include "transformBlendTable.h"
#include "transformBlend.h" #include "transformBlend.h"
#include "sparseArray.h"
#include "bitArray.h"
#include <ctype.h> #include <ctype.h>
#include <algorithm> #include <algorithm>
@ -2094,6 +2096,7 @@ make_vertex_data(const EggRenderState *render_state,
temp_format->set_animation(animation); temp_format->set_animation(animation);
blend_table = new TransformBlendTable; blend_table = new TransformBlendTable;
blend_table->set_rows(SparseArray::lower_on(vertex_pool->size()));
PT(GeomVertexArrayFormat) anim_array_format = new GeomVertexArrayFormat; PT(GeomVertexArrayFormat) anim_array_format = new GeomVertexArrayFormat;
anim_array_format->add_column anim_array_format->add_column
@ -2101,21 +2104,21 @@ make_vertex_data(const EggRenderState *render_state,
Geom::NT_uint16, Geom::C_index); Geom::NT_uint16, Geom::C_index);
temp_format->add_array(anim_array_format); temp_format->add_array(anim_array_format);
pset<string> slider_names; pmap<string, BitArray> slider_names;
EggVertexPool::const_iterator vi; EggVertexPool::const_iterator vi;
for (vi = vertex_pool->begin(); vi != vertex_pool->end(); ++vi) { for (vi = vertex_pool->begin(); vi != vertex_pool->end(); ++vi) {
EggVertex *vertex = (*vi); EggVertex *vertex = (*vi);
EggMorphVertexList::const_iterator mvi; EggMorphVertexList::const_iterator mvi;
for (mvi = vertex->_dxyzs.begin(); mvi != vertex->_dxyzs.end(); ++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(), record_morph(anim_array_format, character_maker, (*mvi).get_name(),
InternalName::get_vertex(), 3); InternalName::get_vertex(), 3);
} }
if (vertex->has_normal()) { if (vertex->has_normal()) {
EggMorphNormalList::const_iterator mni; EggMorphNormalList::const_iterator mni;
for (mni = vertex->_dnormals.begin(); mni != vertex->_dnormals.end(); ++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(), record_morph(anim_array_format, character_maker, (*mni).get_name(),
InternalName::get_normal(), 3); InternalName::get_normal(), 3);
} }
@ -2123,7 +2126,7 @@ make_vertex_data(const EggRenderState *render_state,
if (has_colors && vertex->has_color()) { if (has_colors && vertex->has_color()) {
EggMorphColorList::const_iterator mci; EggMorphColorList::const_iterator mci;
for (mci = vertex->_drgbas.begin(); mci != vertex->_drgbas.end(); ++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(), record_morph(anim_array_format, character_maker, (*mci).get_name(),
InternalName::get_color(), 4); InternalName::get_color(), 4);
} }
@ -2137,7 +2140,7 @@ make_vertex_data(const EggRenderState *render_state,
EggMorphTexCoordList::const_iterator mti; EggMorphTexCoordList::const_iterator mti;
for (mti = egg_uv->_duvs.begin(); mti != egg_uv->_duvs.end(); ++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(), record_morph(anim_array_format, character_maker, (*mti).get_name(),
iname, has_w ? 3 : 2); iname, has_w ? 3 : 2);
} }
@ -2149,10 +2152,10 @@ make_vertex_data(const EggRenderState *render_state,
slider_table = new SliderTable; slider_table = new SliderTable;
pset<string>::iterator si; pmap<string, BitArray>::iterator si;
for (si = slider_names.begin(); si != slider_names.end(); ++si) { for (si = slider_names.begin(); si != slider_names.end(); ++si) {
VertexSlider *slider = character_maker->egg_to_slider(*si); PT(VertexSlider) slider = character_maker->egg_to_slider((*si).first);
slider_table->add_slider(slider); slider_table->add_slider(slider, (*si).second);
} }
} }

View File

@ -1244,8 +1244,19 @@ update_animated_vertices(GeomVertexData::CData *cdata, Thread *current_thread) {
int num_morphs = orig_format->get_num_morphs(); int num_morphs = orig_format->get_num_morphs();
for (int mi = 0; mi < num_morphs; mi++) { for (int mi = 0; mi < num_morphs; mi++) {
CPT(InternalName) slider_name = orig_format->get_morph_slider(mi); CPT(InternalName) slider_name = orig_format->get_morph_slider(mi);
const VertexSlider *slider = slider_table->find_slider(slider_name);
if (slider != (VertexSlider *)NULL) { 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(); float slider_value = slider->get_slider();
if (slider_value != 0.0f) { if (slider_value != 0.0f) {
CPT(InternalName) base_name = orig_format->get_morph_base(mi); CPT(InternalName) base_name = orig_format->get_morph_base(mi);
@ -1253,11 +1264,17 @@ update_animated_vertices(GeomVertexData::CData *cdata, Thread *current_thread) {
GeomVertexRewriter data(new_data, base_name); GeomVertexRewriter data(new_data, base_name);
GeomVertexReader delta(this, delta_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()->get_num_values() == 4) {
if (data.get_column()->has_homogeneous_coord()) { if (data.get_column()->has_homogeneous_coord()) {
for (int i = 0; i < num_rows; i++) {
// Scale the delta by the homogeneous coordinate. // 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(); LPoint4f vertex = data.get_data4f();
LPoint3f d = delta.get_data3f(); LPoint3f d = delta.get_data3f();
d *= slider_value * vertex[3]; d *= slider_value * vertex[3];
@ -1266,18 +1283,30 @@ update_animated_vertices(GeomVertexData::CData *cdata, Thread *current_thread) {
vertex[2] + d[2], vertex[2] + d[2],
vertex[3]); vertex[3]);
} }
}
} else { } else {
// Just apply the four-component delta. // Just apply the four-component delta.
for (int i = 0; i < num_rows; i++) { 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(); const LPoint4f &vertex = data.get_data4f();
LPoint4f d = delta.get_data4f(); LPoint4f d = delta.get_data4f();
data.set_data4f(vertex + d * slider_value); data.set_data4f(vertex + d * slider_value);
} }
} }
}
} else { } else {
// 3-component or smaller values; don't worry about a // 3-component or smaller values; don't worry about a
// homogeneous coordinate. // homogeneous coordinate.
for (int i = 0; i < num_rows; i++) { 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(); const LPoint3f &vertex = data.get_data3f();
LPoint3f d = delta.get_data3f(); LPoint3f d = delta.get_data3f();
data.set_data3f(vertex + d * slider_value); data.set_data3f(vertex + d * slider_value);
@ -1287,6 +1316,9 @@ update_animated_vertices(GeomVertexData::CData *cdata, Thread *current_thread) {
} }
} }
} }
}
}
}
// Then apply the transforms. // Then apply the transforms.
CPT(TransformBlendTable) tb_table = cdata->_transform_blend_table; CPT(TransformBlendTable) tb_table = cdata->_transform_blend_table;
@ -1310,20 +1342,33 @@ update_animated_vertices(GeomVertexData::CData *cdata, Thread *current_thread) {
return; return;
} }
const SparseArray &rows = tb_table->get_rows();
int num_subranges = rows.get_num_subranges();
int ci; int ci;
for (ci = 0; ci < orig_format->get_num_points(); ci++) { for (ci = 0; ci < orig_format->get_num_points(); ci++) {
GeomVertexRewriter data(new_data, orig_format->get_point(ci)); GeomVertexRewriter data(new_data, orig_format->get_point(ci));
blendi.set_row(0);
if (data.get_column()->get_num_values() == 4) { if (data.get_column()->get_num_values() == 4) {
for (int i = 0; i < num_rows; i++) { 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(); LPoint4f vertex = data.get_data4f();
int bi = blendi.get_data1i(); int bi = blendi.get_data1i();
tb_table->get_blend(bi).transform_point(vertex, current_thread); tb_table->get_blend(bi).transform_point(vertex, current_thread);
data.set_data4f(vertex); data.set_data4f(vertex);
} }
}
} else { } else {
for (int i = 0; i < num_rows; i++) { 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(); LPoint3f vertex = data.get_data3f();
int bi = blendi.get_data1i(); int bi = blendi.get_data1i();
tb_table->get_blend(bi).transform_point(vertex, current_thread); tb_table->get_blend(bi).transform_point(vertex, current_thread);
@ -1331,11 +1376,15 @@ update_animated_vertices(GeomVertexData::CData *cdata, Thread *current_thread) {
} }
} }
} }
}
for (ci = 0; ci < orig_format->get_num_vectors(); ci++) { for (ci = 0; ci < orig_format->get_num_vectors(); ci++) {
GeomVertexRewriter data(new_data, orig_format->get_vector(ci)); GeomVertexRewriter data(new_data, orig_format->get_vector(ci));
blendi.set_row(0); for (int i = 0; i < num_subranges; ++i) {
int begin = rows.get_subrange_begin(i);
for (int i = 0; i < num_rows; 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(); LVector3f vertex = data.get_data3f();
int bi = blendi.get_data1i(); int bi = blendi.get_data1i();
tb_table->get_blend(bi).transform_vector(vertex, current_thread); tb_table->get_blend(bi).transform_vector(vertex, current_thread);
@ -1343,6 +1392,7 @@ update_animated_vertices(GeomVertexData::CData *cdata, Thread *current_thread) {
} }
} }
} }
}
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -1564,6 +1614,25 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) {
_modified = Geom::get_next_modified(); _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; return pi;
} }

View File

@ -79,34 +79,47 @@ get_num_sliders() const {
INLINE const VertexSlider *SliderTable:: INLINE const VertexSlider *SliderTable::
get_slider(int n) const { get_slider(int n) const {
nassertr(n >= 0 && n < (int)_sliders.size(), NULL); 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 // Access: Published
// Description: Returns the slider with the indicated name, or NULL // Description: Returns the set of rows (vertices) governed by the
// if no slider in the table has that name. // nth slider in the table.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE const VertexSlider *SliderTable:: INLINE const SparseArray &SliderTable::
find_slider(const InternalName *name) const { 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; SlidersByName::const_iterator sni;
sni = _sliders_by_name.find(name); sni = _sliders_by_name.find(name);
if (sni != _sliders_by_name.end()) { if (sni != _sliders_by_name.end()) {
return (*sni).second; return (*sni).second;
} }
return NULL; return _empty_array;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: SliderTable::has_slider // Function: SliderTable::has_slider
// Access: Published // Access: Published
// Description: Returns true if the table has a slider by the // Description: Returns true if the table has at least one slider by
// indicated name, false otherwise. // the indicated name, false otherwise.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE bool SliderTable:: INLINE bool SliderTable::
has_slider(const InternalName *name) const { has_slider(const InternalName *name) const {
return (find_slider(name) != (VertexSlider *)NULL); return (!find_sliders(name).is_zero());
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////

View File

@ -21,6 +21,7 @@
#include "bamWriter.h" #include "bamWriter.h"
#include "vertexTransform.h" #include "vertexTransform.h"
SparseArray SliderTable::_empty_array;
TypeHandle SliderTable::_type_handle; TypeHandle SliderTable::_type_handle;
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -82,13 +83,29 @@ set_slider(int n, const VertexSlider *slider) {
nassertv(!_is_registered); nassertv(!_is_registered);
nassertv(n >= 0 && n < (int)_sliders.size()); nassertv(n >= 0 && n < (int)_sliders.size());
if (_sliders[n]->get_name() != slider->get_name()) { if (_sliders[n]._slider->get_name() != slider->get_name()) {
// Not allowed to move a slider this way. _sliders_by_name[_sliders[n]._slider->get_name()].clear_bit(n);
nassertv(!has_slider(slider->get_name())); _sliders_by_name[slider->get_name()].set_bit(n);
} }
_sliders[n] = slider; _sliders[n]._slider = slider;
_sliders_by_name[slider->get_name()] = 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(!_is_registered);
nassertv(n >= 0 && n < (int)_sliders.size()); nassertv(n >= 0 && n < (int)_sliders.size());
SlidersByName::iterator si = _sliders_by_name.find(_sliders[n]->get_name()); _sliders_by_name[_sliders[n]._slider->get_name()].clear_bit(n);
nassertv(si != _sliders_by_name.end());
_sliders_by_name.erase(si);
_sliders.erase(_sliders.begin() + n); _sliders.erase(_sliders.begin() + n);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: SliderTable::add_slider // Function: SliderTable::add_slider
// Access: Published // Access: Published
// Description: Adds a new slider to the table, or replaces an // Description: Adds a new slider to the table, and returns the
// existing slider with the same name, and returns the
// index number of the new slider. Only valid for // index number of the new slider. Only valid for
// unregistered tables. // unregistered tables.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
int SliderTable:: int SliderTable::
add_slider(const VertexSlider *slider) { add_slider(const VertexSlider *slider, const SparseArray &rows) {
nassertr(!_is_registered, -1); 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(); 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; return new_index;
} }
@ -149,7 +153,8 @@ add_slider(const VertexSlider *slider) {
void SliderTable:: void SliderTable::
write(ostream &out) const { write(ostream &out) const {
for (size_t i = 0; i < _sliders.size(); ++i) { 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; Sliders::iterator si;
for (si = _sliders.begin(); si != _sliders.end(); ++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; bool inserted = ((VertexSlider *)slider)->_tables.insert(this).second;
nassertv(inserted); nassertv(inserted);
} }
@ -183,7 +188,7 @@ do_unregister() {
Sliders::iterator si; Sliders::iterator si;
for (si = _sliders.begin(); si != _sliders.end(); ++si) { for (si = _sliders.begin(); si != _sliders.end(); ++si) {
const VertexSlider *slider = (*si); const VertexSlider *slider = (*si)._slider;
((VertexSlider *)slider)->_tables.erase(this); ((VertexSlider *)slider)->_tables.erase(this);
} }
_is_registered = false; _is_registered = false;
@ -213,8 +218,9 @@ write_datagram(BamWriter *manager, Datagram &dg) {
dg.add_uint16(_sliders.size()); dg.add_uint16(_sliders.size());
Sliders::const_iterator si; Sliders::const_iterator si;
for (si = _sliders.begin(); si != _sliders.end(); ++si) { for (si = _sliders.begin(); si != _sliders.end(); ++si) {
manager->write_pointer(dg, (*si)->get_name()); manager->write_pointer(dg, (*si)._slider->get_name());
manager->write_pointer(dg, (*si)); manager->write_pointer(dg, (*si)._slider);
(*si)._rows.write_datagram(manager, dg);
} }
manager->write_cdata(dg, _cycler); manager->write_cdata(dg, _cycler);
@ -231,15 +237,12 @@ int SliderTable::
complete_pointers(TypedWritable **p_list, BamReader *manager) { complete_pointers(TypedWritable **p_list, BamReader *manager) {
int pi = TypedWritableReferenceCount::complete_pointers(p_list, manager); int pi = TypedWritableReferenceCount::complete_pointers(p_list, manager);
Sliders::iterator si; for (size_t n = 0; n < _sliders.size(); ++n) {
for (si = _sliders.begin(); si != _sliders.end(); ++si) {
CPT(InternalName) name = DCAST(InternalName, p_list[pi++]); CPT(InternalName) name = DCAST(InternalName, p_list[pi++]);
PT(VertexSlider) slider = DCAST(VertexSlider, p_list[pi++]); PT(VertexSlider) slider = DCAST(VertexSlider, p_list[pi++]);
(*si) = slider; _sliders[n]._slider = slider;
_sliders_by_name[name].set_bit(n);
bool inserted = _sliders_by_name.insert(SlidersByName::value_type(name, slider.p())).second;
nassertr(inserted, pi);
} }
return pi; return pi;
@ -281,7 +284,14 @@ fillin(DatagramIterator &scan, BamReader *manager) {
for (size_t i = 0; i < num_sliders; ++i) { for (size_t i = 0; i < num_sliders; ++i) {
manager->read_pointer(scan); manager->read_pointer(scan);
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); manager->read_cdata(scan, _cycler);

View File

@ -28,7 +28,7 @@
#include "cycleDataReader.h" #include "cycleDataReader.h"
#include "cycleDataWriter.h" #include "cycleDataWriter.h"
#include "pipelineCycler.h" #include "pipelineCycler.h"
#include "sparseArray.h"
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Class : SliderTable // Class : SliderTable
@ -55,15 +55,17 @@ PUBLISHED:
INLINE int get_num_sliders() const; INLINE int get_num_sliders() const;
INLINE const VertexSlider *get_slider(int n) 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 has_slider(const InternalName *name) const;
INLINE bool is_empty() const; INLINE bool is_empty() const;
INLINE UpdateSeq get_modified(Thread *current_thread) const; INLINE UpdateSeq get_modified(Thread *current_thread) const;
void set_slider(int n, const VertexSlider *slider); void set_slider(int n, const VertexSlider *slider);
void set_slider_rows(int n, const SparseArray &rows);
void remove_slider(int n); 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; void write(ostream &out) const;
@ -75,12 +77,20 @@ private:
private: private:
bool _is_registered; bool _is_registered;
typedef pvector< CPT(VertexSlider) > Sliders; class SliderDef {
public:
CPT(VertexSlider) _slider;
SparseArray _rows;
};
typedef pvector<SliderDef> Sliders;
Sliders _sliders; Sliders _sliders;
typedef pmap< CPT(InternalName), const VertexSlider *> SlidersByName; typedef pmap< CPT(InternalName), SparseArray > SlidersByName;
SlidersByName _sliders_by_name; SlidersByName _sliders_by_name;
static SparseArray _empty_array;
// This is the data that must be cycled between pipeline stages. // This is the data that must be cycled between pipeline stages.
class EXPCL_PANDA CData : public CycleData { class EXPCL_PANDA CData : public CycleData {
public: public:

View File

@ -88,6 +88,43 @@ get_max_simultaneous_transforms() const {
return _max_simultaneous_transforms; 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 // Function: TransformBlendTable::consider_rebuild_index
// Access: Private // Access: Private

View File

@ -39,7 +39,8 @@ TransformBlendTable() {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
TransformBlendTable:: TransformBlendTable::
TransformBlendTable(const TransformBlendTable &copy) : TransformBlendTable(const TransformBlendTable &copy) :
_blends(copy._blends) _blends(copy._blends),
_rows(copy._rows)
{ {
} }
@ -51,6 +52,7 @@ TransformBlendTable(const TransformBlendTable &copy) :
void TransformBlendTable:: void TransformBlendTable::
operator = (const TransformBlendTable &copy) { operator = (const TransformBlendTable &copy) {
_blends = copy._blends; _blends = copy._blends;
_rows = copy._rows;
clear_index(); clear_index();
} }
@ -229,6 +231,8 @@ write_datagram(BamWriter *manager, Datagram &dg) {
(*bi).write_datagram(manager, dg); (*bi).write_datagram(manager, dg);
} }
_rows.write_datagram(manager, dg);
manager->write_cdata(dg, _cycler); manager->write_cdata(dg, _cycler);
} }
@ -291,6 +295,14 @@ fillin(DatagramIterator &scan, BamReader *manager) {
_blends.push_back(blend); _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); manager->read_cdata(scan, _cycler);
} }

View File

@ -32,6 +32,7 @@
#include "cycleDataReader.h" #include "cycleDataReader.h"
#include "cycleDataWriter.h" #include "cycleDataWriter.h"
#include "pipelineCycler.h" #include "pipelineCycler.h"
#include "sparseArray.h"
class FactoryParams; class FactoryParams;
@ -68,6 +69,10 @@ PUBLISHED:
INLINE int get_num_transforms() const; INLINE int get_num_transforms() const;
INLINE int get_max_simultaneous_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; void write(ostream &out, int indent_level) const;
private: private:
@ -88,6 +93,8 @@ private:
typedef pvector<TransformBlend> Blends; typedef pvector<TransformBlend> Blends;
Blends _blends; Blends _blends;
SparseArray _rows;
// This map indexes directly into the above vector. That means any // This map indexes directly into the above vector. That means any
// time we add or remove anything from the vector, we must // time we add or remove anything from the vector, we must
// completely rebuild the index (since the vector might reallocate, // completely rebuild the index (since the vector might reallocate,

View File

@ -601,9 +601,15 @@ collect_vertex_data(Geom *geom, int collect_bits) {
new_btable = new_data->modify_transform_blend_table(); new_btable = new_data->modify_transform_blend_table();
} else { } else {
new_btable = new TransformBlendTable; new_btable = new TransformBlendTable;
new_btable->add_blend(TransformBlend());
new_data->set_transform_blend_table(new_btable); 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. // We still need to build up the IndexMap.
IndexMap blend_map; IndexMap blend_map;
@ -644,7 +650,9 @@ collect_vertex_data(Geom *geom, int collect_bits) {
} }
int num_sliders = old_sliders->get_num_sliders(); int num_sliders = old_sliders->get_num_sliders();
for (int si = 0; si < num_sliders; ++si) { 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)); new_data->set_slider_table(SliderTable::register_table(new_sliders));
} }

View File

@ -5779,7 +5779,7 @@ flatten_strong() {
gr.apply_attribs(node()); gr.apply_attribs(node());
int num_removed = gr.flatten(node(), ~0); 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()); gr.unify(node());
return num_removed; return num_removed;

View File

@ -100,10 +100,7 @@ PUBLISHED:
CVD_usage_hint = 0x040, CVD_usage_hint = 0x040,
// If set, GeomVertexDatas with unanimated vertices will not be // If set, GeomVertexDatas with unanimated vertices will not be
// combined with GeomVertexDatas with animated vertices. Although // combined with GeomVertexDatas with animated vertices.
// 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.
CVD_animation_type = 0x080, CVD_animation_type = 0x080,
}; };

View File

@ -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 5 on 5/6/05 for new Geom implementation.
// Bumped to major version 6 on 2/11/06 to factor out PandaNode::CData. // 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 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 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 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 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 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 6 on 2/5/07 to change GeomPrimitive::_num_vertices.
// Bumped to minor version 7 on 2/15/07 to change SliderTable.
#endif #endif

View File

@ -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();
}

View File

@ -30,6 +30,10 @@
#include "checksumHashGenerator.h" #include "checksumHashGenerator.h"
class SparseArray; class SparseArray;
class BamWriter;
class BamReader;
class Datagram;
class DatagramIterator;
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Class : BitArray // Class : BitArray
@ -136,6 +140,10 @@ private:
Array _array; Array _array;
int _highest_bits; // Either 0 or 1. int _highest_bits; // Either 0 or 1.
public:
void write_datagram(BamWriter *manager, Datagram &dg) const;
void read_datagram(DatagramIterator &scan, BamReader *manager);
public: public:
static TypeHandle get_class_type() { static TypeHandle get_class_type() {
return _type_handle; return _type_handle;

View File

@ -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();
}

View File

@ -23,6 +23,10 @@
#include "ordered_vector.h" #include "ordered_vector.h"
class BitArray; class BitArray;
class BamWriter;
class BamReader;
class Datagram;
class DatagramIterator;
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Class : SparseArray // Class : SparseArray
@ -144,6 +148,10 @@ private:
Subranges _subranges; Subranges _subranges;
bool _inverse; bool _inverse;
public:
void write_datagram(BamWriter *manager, Datagram &dg) const;
void read_datagram(DatagramIterator &scan, BamReader *manager);
public: public:
static TypeHandle get_class_type() { static TypeHandle get_class_type() {
return _type_handle; return _type_handle;