From 8f338d05a81efa27bb7d4c8136a0223f2cfd224b Mon Sep 17 00:00:00 2001 From: David Rose Date: Tue, 27 Feb 2001 20:07:01 +0000 Subject: [PATCH] *** empty log message *** --- panda/src/chan/auto_bind.cxx | 2 +- panda/src/egg/eggSAnimData.I | 13 +++ panda/src/egg/eggSAnimData.h | 1 + panda/src/egg/eggXfmSAnim.I | 11 +++ panda/src/egg/eggXfmSAnim.cxx | 176 +++++++++++++++++++++++++++++++++- panda/src/egg/eggXfmSAnim.h | 4 + 6 files changed, 205 insertions(+), 2 deletions(-) diff --git a/panda/src/chan/auto_bind.cxx b/panda/src/chan/auto_bind.cxx index 0dacc5a245..c7086cf8cb 100644 --- a/panda/src/chan/auto_bind.cxx +++ b/panda/src/chan/auto_bind.cxx @@ -79,7 +79,7 @@ bind_anims(const PartNodes &parts, const AnimNodes &anims, PT(AnimControl) control = part->bind_anim(anim, hierarchy_match_flags); if (control != (AnimControl *)NULL) { - controls.store_anim(control, (*ani)->get_name()); + controls.store_anim(control, anim->get_name()); } if (chan_cat.is_info()) { diff --git a/panda/src/egg/eggSAnimData.I b/panda/src/egg/eggSAnimData.I index cc596759f5..e8f3e7b428 100644 --- a/panda/src/egg/eggSAnimData.I +++ b/panda/src/egg/eggSAnimData.I @@ -62,3 +62,16 @@ get_value(int row) const { } +//////////////////////////////////////////////////////////////////// +// Function: EggSAnimData::set_value +// Access: Public +// Description: Changes the value at the indicated row. Row must be +// in the range 0 <= row < get_num_rows(). +//////////////////////////////////////////////////////////////////// +INLINE void EggSAnimData:: +set_value(int row, double value) { + nassertv(row >= 0 && row < get_num_rows()); + _data[row] = value; +} + + diff --git a/panda/src/egg/eggSAnimData.h b/panda/src/egg/eggSAnimData.h index bdf501d9a7..567a7a50fe 100644 --- a/panda/src/egg/eggSAnimData.h +++ b/panda/src/egg/eggSAnimData.h @@ -24,6 +24,7 @@ public: INLINE int get_num_rows() const; INLINE double get_value(int row) const; + INLINE void set_value(int row, double value); void optimize(); diff --git a/panda/src/egg/eggXfmSAnim.I b/panda/src/egg/eggXfmSAnim.I index e4951f7d1f..02656fe6cd 100644 --- a/panda/src/egg/eggXfmSAnim.I +++ b/panda/src/egg/eggXfmSAnim.I @@ -145,3 +145,14 @@ INLINE CoordinateSystem EggXfmSAnim:: get_coordinate_system() const { return _coordsys; } + +//////////////////////////////////////////////////////////////////// +// Function: EggXfmSAnim::clear_data +// Access: Public +// Description: Removes all data from the table. It does this by +// removing all of its children. +//////////////////////////////////////////////////////////////////// +INLINE void EggXfmSAnim:: +clear_data() { + EggGroupNode::clear(); +} diff --git a/panda/src/egg/eggXfmSAnim.cxx b/panda/src/egg/eggXfmSAnim.cxx index 92a44f51d4..4957fbde93 100644 --- a/panda/src/egg/eggXfmSAnim.cxx +++ b/panda/src/egg/eggXfmSAnim.cxx @@ -86,6 +86,85 @@ optimize() { } } +//////////////////////////////////////////////////////////////////// +// Function: EggXfmSAnim::normalize +// Access: Public +// Description: The inverse operation of optimize(), this ensures +// that all the sub-tables have the same length by +// duplicating rows as necessary. This is needed before +// doing operations like add_data() or set_value() on an +// existing table. +//////////////////////////////////////////////////////////////////// +void EggXfmSAnim:: +normalize() { + iterator ci; + + // First, determine which tables we already have, and how long they + // are. + int num_tables = 0; + int table_length = 1; + string remaining_tables = "ijkhprxyz"; + + for (ci = begin(); ci != end(); ++ci) { + if ((*ci)->is_of_type(EggSAnimData::get_class_type())) { + EggSAnimData *sanim = DCAST(EggSAnimData, *ci); + + nassertv(sanim->get_name().length() == 1); + char name = sanim->get_name()[0]; + size_t p = remaining_tables.find(name); + nassertv(p != string::npos); + remaining_tables[p] = ' '; + + num_tables++; + if (sanim->get_num_rows() > 1) { + if (table_length == 1) { + table_length = sanim->get_num_rows(); + } else { + nassertv(sanim->get_num_rows() == table_length); + } + } + } + } + + if (num_tables < 9) { + // Create new, default, children for each table we lack. + for (size_t p = 0; p < remaining_tables.length(); p++) { + if (remaining_tables[p] != ' ') { + double default_value; + switch (remaining_tables[p]) { + case 'i': + case 'j': + case 'k': + default_value = 1.0; + break; + + default: + default_value = 0.0; + } + + string name(1, remaining_tables[p]); + EggSAnimData *sanim = new EggSAnimData(name); + add_child(sanim); + sanim->add_data(default_value); + } + } + } + + // Now expand any one-row tables as needed. + for (ci = begin(); ci != end(); ++ci) { + if ((*ci)->is_of_type(EggSAnimData::get_class_type())) { + EggSAnimData *sanim = DCAST(EggSAnimData, *ci); + if (sanim->get_num_rows() == 1) { + double value = sanim->get_value(0); + for (int i = 1; i < table_length; i++) { + sanim->add_data(value); + } + } + nassertv(sanim->get_num_rows() == table_length); + } + } +} + //////////////////////////////////////////////////////////////////// // Function: EggXfmSAnim::write // Access: Public, Virtual @@ -230,7 +309,101 @@ get_value(int row, LMatrix4d &mat) const { // So now we've got the nine components; build a matrix. compose_matrix(mat, scale, hpr, translate, _coordsys); } + +//////////////////////////////////////////////////////////////////// +// Function: EggXfmSAnim::set_value +// Access: Public +// Description: Replaces the indicated row of the table with the +// given matrix. +// +// This function can only be called if all the +// constraints of add_data(), below, are met. Call +// normalize() first if you are not sure. +// +// The return value is true if the matrix can be +// decomposed and stored as scale, rotate, and +// translate, or false otherwise. +//////////////////////////////////////////////////////////////////// +bool EggXfmSAnim:: +set_value(int row, const LMatrix4d &mat) { + LVector3d scale, hpr, translate; + bool result = decompose_matrix(mat, scale, hpr, translate, _coordsys); + if (!result) { + return false; + } + // Sanity check our sub-tables. +#ifndef NDEBUG + int table_length = -1; + int num_tables = 0; +#endif + + const_iterator ci; + for (ci = begin(); ci != end(); ++ci) { + if ((*ci)->is_of_type(EggSAnimData::get_class_type())) { + EggSAnimData *sanim = DCAST(EggSAnimData, *ci); + +#ifndef NDEBUG + num_tables++; + + // Each table must have the same length. + if (table_length < 0) { + table_length = sanim->get_num_rows(); + } else { + nassertr(sanim->get_num_rows() == table_length, false); + } +#endif + + // Each child SAnimData table should have a one-letter name. + nassertr(sanim->get_name().length() == 1, false); + + switch (sanim->get_name()[0]) { + case 'i': + sanim->set_value(row, scale[0]); + break; + + case 'j': + sanim->set_value(row, scale[1]); + break; + + case 'k': + sanim->set_value(row, scale[2]); + break; + + case 'h': + sanim->set_value(row, hpr[0]); + break; + + case 'p': + sanim->set_value(row, hpr[1]); + break; + + case 'r': + sanim->set_value(row, hpr[2]); + break; + + case 'x': + sanim->set_value(row, translate[0]); + break; + + case 'y': + sanim->set_value(row, translate[1]); + break; + + case 'z': + sanim->set_value(row, translate[2]); + break; + + default: + // One of the child tables had an invalid name. + nassertr(false, false); + } + } + } + + nassertr(num_tables == 9, false); + return true; +} //////////////////////////////////////////////////////////////////// // Function: EggXfmSAnim::add_data @@ -251,7 +424,8 @@ get_value(int row, LMatrix4d &mat) const { // EggXfmSAnim object and start adding matrices to the // end; you must clear out the original data first. (As // a special exception, if no tables exist, they will be -// created.) +// created.) The method normalize() will do this for +// you on an existing EggXfmSAnim. // // This function may fail silently if the matrix cannot // be decomposed into scale, rotate, and translate. In diff --git a/panda/src/egg/eggXfmSAnim.h b/panda/src/egg/eggXfmSAnim.h index 0cb83182b0..d4fd6133ac 100644 --- a/panda/src/egg/eggXfmSAnim.h +++ b/panda/src/egg/eggXfmSAnim.h @@ -43,9 +43,13 @@ public: INLINE CoordinateSystem get_coordinate_system() const; void optimize(); + void normalize(); int get_num_rows() const; void get_value(int row, LMatrix4d &mat) const; + bool set_value(int row, const LMatrix4d &mat); + + INLINE void clear_data(); bool add_data(const LMatrix4d &mat); virtual void write(ostream &out, int indent_level) const;