diff --git a/pandatool/src/eggcharbase/Sources.pp b/pandatool/src/eggcharbase/Sources.pp index 1f416f4f95..24b89a20f6 100644 --- a/pandatool/src/eggcharbase/Sources.pp +++ b/pandatool/src/eggcharbase/Sources.pp @@ -13,8 +13,11 @@ #define SOURCES \ config_eggcharbase.h eggBackPointer.h \ eggCharacterCollection.h eggCharacterCollection.I \ - eggCharacterData.h eggCharacterData.I eggCharacterFilter.h \ - eggComponentData.h eggComponentData.I eggJointData.h \ + eggCharacterData.h eggCharacterData.I \ + eggCharacterDb.I eggCharacterDb.h \ + eggCharacterFilter.h \ + eggComponentData.h eggComponentData.I \ + eggJointData.h \ eggJointData.I eggJointPointer.h eggJointPointer.I \ eggJointNodePointer.h \ eggMatrixTablePointer.h eggScalarTablePointer.h \ @@ -24,6 +27,7 @@ #define INCLUDED_SOURCES \ config_eggcharbase.cxx eggBackPointer.cxx \ eggCharacterCollection.cxx eggCharacterData.cxx \ + eggCharacterDb.cxx \ eggCharacterFilter.cxx eggComponentData.cxx eggJointData.cxx \ eggJointPointer.cxx eggJointNodePointer.cxx \ eggMatrixTablePointer.cxx eggScalarTablePointer.cxx \ @@ -34,7 +38,9 @@ #define INSTALL_HEADERS \ eggBackPointer.h \ eggCharacterCollection.I eggCharacterCollection.h \ - eggCharacterData.I eggCharacterData.h eggCharacterFilter.h \ + eggCharacterData.I eggCharacterData.h \ + eggCharacterDb.I eggCharacterDb.h \ + eggCharacterFilter.h \ eggComponentData.I eggComponentData.h \ eggJointData.h eggJointData.I \ eggJointPointer.h eggJointPointer.I \ diff --git a/pandatool/src/eggcharbase/eggCharacterData.cxx b/pandatool/src/eggcharbase/eggCharacterData.cxx index c4ad6599ad..e21f1926b4 100644 --- a/pandatool/src/eggcharbase/eggCharacterData.cxx +++ b/pandatool/src/eggcharbase/eggCharacterData.cxx @@ -18,6 +18,7 @@ #include "eggCharacterData.h" #include "eggCharacterCollection.h" +#include "eggCharacterDb.h" #include "eggJointData.h" #include "eggSliderData.h" #include "indent.h" @@ -227,8 +228,13 @@ do_reparent() { // frame. Models::const_iterator mi; for (mi = _models.begin(); mi != _models.end(); ++mi) { + EggCharacterDb db; int model_index = (*mi)._model_index; int num_frames = get_num_frames(model_index); + nout << " computing " << (mi - _models.begin()) + 1 + << " of " << _models.size() + << ": " << (*mi)._egg_data->get_egg_filename() + << " (" << num_frames << " frames)\n"; for (int f = 0; f < num_frames; f++) { // First, walk through all the joints and flush the computed net // transforms from before. @@ -242,20 +248,26 @@ do_reparent() { // caching net transforms as necessary. for (ji = _joints.begin(); ji != _joints.end(); ++ji) { EggJointData *joint_data = (*ji); - if (!joint_data->do_compute_reparent(model_index, f)) { + if (!joint_data->do_compute_reparent(model_index, f, db)) { // Oops, we got an invalid transform. invalid_set.insert(joint_data); } } } + + // Finally, apply the computations to the joints. + for (ji = _joints.begin(); ji != _joints.end(); ++ji) { + EggJointData *joint_data = (*ji); + if (!joint_data->do_joint_rebuild(model_index, db)) { + invalid_set.insert(joint_data); + } + } } // Now remove all of the old children and add in the new children. for (ji = _joints.begin(); ji != _joints.end(); ++ji) { EggJointData *joint_data = (*ji); - if (!joint_data->do_finish_reparent()) { - invalid_set.insert(joint_data); - } + joint_data->do_finish_reparent(); } // Report the set of joints that failed. It really shouldn't be @@ -299,19 +311,21 @@ do_reparent() { //////////////////////////////////////////////////////////////////// void EggCharacterData:: choose_optimal_hierarchy() { + EggCharacterDb db; + Joints::const_iterator ji, jj; for (ji = _joints.begin(); ji != _joints.end(); ++ji) { EggJointData *joint_data = (*ji); EggJointData *best_parent = joint_data->get_parent(); - int best_score = joint_data->score_reparent_to(best_parent); + int best_score = joint_data->score_reparent_to(best_parent, db); for (jj = _joints.begin(); jj != _joints.end(); ++jj) { EggJointData *possible_parent = (*jj); if (possible_parent != joint_data && possible_parent != best_parent && !joint_data->is_new_ancestor(possible_parent)) { - int score = joint_data->score_reparent_to(possible_parent); + int score = joint_data->score_reparent_to(possible_parent, db); if (score >= 0 && (best_score < 0 || score < best_score)) { best_parent = possible_parent; best_score = score; @@ -322,7 +336,7 @@ choose_optimal_hierarchy() { // Also consider reparenting the node to the root. EggJointData *possible_parent = get_root_joint(); if (possible_parent != best_parent) { - int score = joint_data->score_reparent_to(possible_parent); + int score = joint_data->score_reparent_to(possible_parent, db); if (score >= 0 && (best_score < 0 || score < best_score)) { best_parent = possible_parent; best_score = score; @@ -377,6 +391,36 @@ make_slider(const string &name) { return slider; } +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterData::estimate_db_size +// Access: Public +// Description: Returns the estimated amount of memory, in megabytes, +// that will be required to perform the do_reparent() +// operation. This is used mainly be EggCharacterDb to +// decide up front whether to store this data in-RAM or +// on-disk. +//////////////////////////////////////////////////////////////////// +size_t EggCharacterData:: +estimate_db_size() const { + // Count how much memory we will need to store the interim + // transforms. This is models * joints * frames * 3 * + // sizeof(LMatrix4d). + size_t mj_frames = 0; + Models::const_iterator mi; + for (mi = _models.begin(); mi != _models.end(); ++mi) { + int model_index = (*mi)._model_index; + size_t num_frames = (size_t)get_num_frames(model_index); + mj_frames += num_frames * _joints.size(); + } + + // We do this operation a bit carefully, to guard against integer + // overflow. + size_t mb_needed = ((mj_frames * 3 / 1024) * sizeof(LMatrix4d)) / 1024; + + return mb_needed; +} + + //////////////////////////////////////////////////////////////////// // Function: EggCharacterData::write // Access: Public, Virtual diff --git a/pandatool/src/eggcharbase/eggCharacterData.h b/pandatool/src/eggcharbase/eggCharacterData.h index f3f89d9cac..586664da10 100644 --- a/pandatool/src/eggcharbase/eggCharacterData.h +++ b/pandatool/src/eggcharbase/eggCharacterData.h @@ -22,7 +22,6 @@ #include "pandatoolbase.h" #include "eggJointData.h" - #include "eggNode.h" #include "eggData.h" #include "pointerTo.h" @@ -33,6 +32,7 @@ class EggCharacterCollection; class EggSliderData; +class EggCharacterDb; //////////////////////////////////////////////////////////////////// // Class : EggCharacterData @@ -81,6 +81,7 @@ public: INLINE EggJointData *make_new_joint(const string &name, EggJointData *parent); INLINE int get_num_joints() const; INLINE EggJointData *get_joint(int n) const; + bool do_reparent(); void choose_optimal_hierarchy(); @@ -92,6 +93,8 @@ public: INLINE int get_num_components() const; INLINE EggComponentData *get_component(int n) const; + size_t estimate_db_size() const; + virtual void write(ostream &out, int indent_level = 0) const; private: diff --git a/pandatool/src/eggcharbase/eggCharacterDb.I b/pandatool/src/eggcharbase/eggCharacterDb.I new file mode 100644 index 0000000000..618ca9303a --- /dev/null +++ b/pandatool/src/eggcharbase/eggCharacterDb.I @@ -0,0 +1,47 @@ +// Filename: eggCharacterDb.I +// Created by: drose (05Oct06) +// +//////////////////////////////////////////////////////////////////// +// +// 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: EggCharacterDb::Key::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE EggCharacterDb::Key:: +Key(const EggJointPointer *joint, TableType table_type, int frame) : + _joint(joint), + _table_type(table_type), + _frame(frame) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterDb::Key::operator < +// Access: Public +// Description: Provides an arbitrary unique ordering for all keys. +//////////////////////////////////////////////////////////////////// +INLINE bool EggCharacterDb::Key:: +operator < (const EggCharacterDb::Key &other) const { + if (_joint != other._joint) { + return _joint < other._joint; + } + if (_table_type != other._table_type) { + return _table_type < other._table_type; + } + return _frame < other._frame; +} diff --git a/pandatool/src/eggcharbase/eggCharacterDb.cxx b/pandatool/src/eggcharbase/eggCharacterDb.cxx new file mode 100644 index 0000000000..f640e09ea9 --- /dev/null +++ b/pandatool/src/eggcharbase/eggCharacterDb.cxx @@ -0,0 +1,143 @@ +// Filename: eggCharacterDb.cxx +// Created by: drose (05Oct06) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "eggCharacterDb.h" +#include "eggCharacterData.h" + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterDb::Constructor +// Access: Public +// Description: Constructs a database for storing the interim work +// for the indicated EggCharacterData. The parameter +// max_ram_mb indicates the maximum amount of RAM (in +// MB) that the database should consume; if it the +// database would roughly fit within this limit, it will +// be stored in RAM; otherwise, it will be written to +// disk (if Berkeley DB is available). +//////////////////////////////////////////////////////////////////// +EggCharacterDb:: +EggCharacterDb() { + /* +#ifdef HAVE_BDB + _db = NULL; + + _db = new Db(NULL, 0); + _db_filename = Filename::temporary("", "eggc_", ".db"); + + string os_db_filename = _db_filename.to_os_specific(); + _db->open(NULL, os_db_filename.c_str(), NULL, + DB_BTREE, DB_CREATE | DB_EXCL, 0); + + nout << "Using " << os_db_filename << " for rebuild database.\n"; +#endif // HAVE_BDB + */ +} + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterDb::Destructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +EggCharacterDb:: +~EggCharacterDb() { + /* +#ifdef HAVE_BDB + if (_db != (Db *)NULL){ + _db->close(0); + delete _db; + _db = NULL; + + string os_db_filename = _db_filename.to_os_specific(); + Db rmdb(NULL, 0); + rmdb.remove(os_db_filename.c_str(), NULL, 0); + } +#endif // HAVE_BDB + */ +} + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterDb::get_matrix +// Access: Public +// Description: Looks up the data for the indicated joint, type, and +// frame, and fills it in result (and returns true) if +// it is found. Returns false if this data has not been +// stored in the database. +//////////////////////////////////////////////////////////////////// +bool EggCharacterDb:: +get_matrix(const EggJointPointer *joint, TableType type, + int frame, LMatrix4d &mat) const { + Key key(joint, type, frame); + + /* +#ifdef HAVE_BDB + if (_db != (Db *)NULL){ + Dbt db_key(&key, sizeof(Key)); + Dbt db_data(&mat, sizeof(LMatrix4d)); + db_data.set_ulen(sizeof(LMatrix4d)); + db_data.set_flags(DB_DBT_USERMEM); + + int result = _db->get(NULL, &db_key, &db_data, 0); + if (result == DB_NOTFOUND) { + return false; + } + nassertr(result == 0, false); + return true; + } +#endif // HAVE_BDB + */ + + Table::const_iterator ti; + ti = _table.find(key); + if (ti == _table.end()) { + return false; + } + + mat = (*ti).second; + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterDb::set_matrix +// Access: Public +// Description: Stores the matrix for the indicated joint, type, and +// frame in the database. It is an error to call this +// more than once for any given key combination (not for +// any technical reason, but because we don't expect +// this to happen). +//////////////////////////////////////////////////////////////////// +void EggCharacterDb:: +set_matrix(const EggJointPointer *joint, TableType type, + int frame, const LMatrix4d &mat) { + Key key(joint, type, frame); + + /* +#ifdef HAVE_BDB + if (_db != (Db *)NULL){ + Dbt db_key(&key, sizeof(Key)); + Dbt db_data((void *)&mat, sizeof(LMatrix4d)); + int result = _db->put(NULL, &db_key, &db_data, DB_NOOVERWRITE); + nassertv(result != DB_KEYEXIST); + nassertv(result == 0); + return; + } +#endif // HAVE_BDB + */ + + bool inserted = _table.insert(Table::value_type(key, mat)).second; + nassertv(inserted); +} diff --git a/pandatool/src/eggcharbase/eggCharacterDb.h b/pandatool/src/eggcharbase/eggCharacterDb.h new file mode 100644 index 0000000000..f6287825b1 --- /dev/null +++ b/pandatool/src/eggcharbase/eggCharacterDb.h @@ -0,0 +1,93 @@ +// Filename: eggCharacterDb.h +// Created by: drose (05Oct06) +// +//////////////////////////////////////////////////////////////////// +// +// 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 EGGCHARACTERDB_H +#define EGGCHARACTERDB_H + +#include "pandatoolbase.h" +#include "pmap.h" + +/* +#ifdef HAVE_BDB + +// Apparently, we have to define this to make db_cxx files include the +// modern header files. +#define HAVE_CXX_STDHEADERS 1 +#include + +#endif // HAVE_BDB +*/ + +class EggJointPointer; + +//////////////////////////////////////////////////////////////////// +// Class : EggCharacterDb +// Description : This class is used during joint optimization or +// restructuring to store the table of interim joint +// computations. +// +// That is to say, this class provides an temporary data +// store for three tables of matrices per each +// EggJointPointer per frame. +//////////////////////////////////////////////////////////////////// +class EggCharacterDb { +public: + EggCharacterDb(); + ~EggCharacterDb(); + + enum TableType { + TT_rebuild_frame, + TT_net_frame, + TT_net_frame_inv, + }; + + bool get_matrix(const EggJointPointer *joint, TableType type, + int frame, LMatrix4d &mat) const; + void set_matrix(const EggJointPointer *joint, TableType type, + int frame, const LMatrix4d &mat); + +private: + class Key { + public: + INLINE Key(const EggJointPointer *joint, + TableType table_type, + int frame); + INLINE bool operator < (const Key &other) const; + + private: + const EggJointPointer *_joint; + TableType _table_type; + int _frame; + }; + + /* +#ifdef HAVE_BDB + Db *_db; + Filename _db_filename; +#endif // HAVE_BDB + */ + + typedef pmap Table; + Table _table; +}; + +#include "eggCharacterDb.I" + +#endif + + diff --git a/pandatool/src/eggcharbase/eggJointData.cxx b/pandatool/src/eggcharbase/eggJointData.cxx index 850304e837..0f48674991 100644 --- a/pandatool/src/eggcharbase/eggJointData.cxx +++ b/pandatool/src/eggcharbase/eggJointData.cxx @@ -74,7 +74,7 @@ get_frame(int model_index, int n) const { // in the indicated model. //////////////////////////////////////////////////////////////////// LMatrix4d EggJointData:: -get_net_frame(int model_index, int n) const { +get_net_frame(int model_index, int n, EggCharacterDb &db) const { EggBackPointer *back = get_model(model_index); if (back == (EggBackPointer *)NULL) { return LMatrix4d::ident_mat(); @@ -82,23 +82,18 @@ get_net_frame(int model_index, int n) const { EggJointPointer *joint; DCAST_INTO_R(joint, back, LMatrix4d::ident_mat()); - - if (joint->get_num_net_frames() < n) { - // Recursively get the previous frame's net, so we have a place to - // stuff this frame's value. - get_net_frame(model_index, n - 1); - } - - if (joint->get_num_net_frames() == n) { + + LMatrix4d mat; + if (!db.get_matrix(joint, EggCharacterDb::TT_net_frame, n, mat)) { // Compute this frame's net, and stuff it in. - LMatrix4d mat = get_frame(model_index, n); + mat = get_frame(model_index, n); if (_parent != (EggJointData *)NULL) { - mat = mat * _parent->get_net_frame(model_index, n); + mat = mat * _parent->get_net_frame(model_index, n, db); } - joint->add_net_frame(mat); + db.set_matrix(joint, EggCharacterDb::TT_net_frame, n, mat); } - return joint->get_net_frame(n); + return mat; } //////////////////////////////////////////////////////////////////// @@ -107,7 +102,7 @@ get_net_frame(int model_index, int n) const { // Description: Returns the inverse of get_net_frame(). //////////////////////////////////////////////////////////////////// LMatrix4d EggJointData:: -get_net_frame_inv(int model_index, int n) const { +get_net_frame_inv(int model_index, int n, EggCharacterDb &db) const { EggBackPointer *back = get_model(model_index); if (back == (EggBackPointer *)NULL) { return LMatrix4d::ident_mat(); @@ -116,20 +111,15 @@ get_net_frame_inv(int model_index, int n) const { EggJointPointer *joint; DCAST_INTO_R(joint, back, LMatrix4d::ident_mat()); - if (joint->get_num_net_frame_invs() < n) { - // Recursively get the previous frame's net, so we have a place to - // stuff this frame's value. - get_net_frame_inv(model_index, n - 1); - } - - if (joint->get_num_net_frame_invs() == n) { + LMatrix4d mat; + if (!db.get_matrix(joint, EggCharacterDb::TT_net_frame_inv, n, mat)) { // Compute this frame's net inverse, and stuff it in. - LMatrix4d mat = get_net_frame(model_index, n); + LMatrix4d mat = get_net_frame(model_index, n, db); mat.invert_in_place(); - joint->add_net_frame_inv(mat); + db.set_matrix(joint, EggCharacterDb::TT_net_frame_inv, n, mat); } - return joint->get_net_frame_inv(n); + return mat; } //////////////////////////////////////////////////////////////////// @@ -202,7 +192,7 @@ move_vertices_to(EggJointData *new_owner) { // error. //////////////////////////////////////////////////////////////////// int EggJointData:: -score_reparent_to(EggJointData *new_parent) { +score_reparent_to(EggJointData *new_parent, EggCharacterDb &db) { if (!FFTCompressor::is_compression_available()) { // If we don't have compression compiled in, we can't meaningfully // score the joints. @@ -232,17 +222,17 @@ score_reparent_to(EggJointData *new_parent) { } else if (_parent == (EggJointData *)NULL) { // We are moving from outside the joint hierarchy to within it. - transform = new_parent->get_net_frame_inv(model_index, n); + transform = new_parent->get_net_frame_inv(model_index, n, db); } else if (new_parent == (EggJointData *)NULL) { // We are moving from within the hierarchy to outside it. - transform = _parent->get_net_frame(model_index, n); + transform = _parent->get_net_frame(model_index, n, db); } else { // We are changing parents within the hierarchy. transform = - _parent->get_net_frame(model_index, n) * - new_parent->get_net_frame_inv(model_index, n); + _parent->get_net_frame(model_index, n, db) * + new_parent->get_net_frame_inv(model_index, n, db); } transform = joint->get_frame(n) * transform; @@ -304,14 +294,14 @@ score_reparent_to(EggJointData *new_parent) { } //////////////////////////////////////////////////////////////////// -// Function: EggJointData::do_rebuild +// Function: EggJointData::do_rebuild_all // Access: Public // Description: Calls do_rebuild() on all models, and recursively on // all joints at this node and below. Returns true if // all models returned true, false otherwise. //////////////////////////////////////////////////////////////////// bool EggJointData:: -do_rebuild() { +do_rebuild_all(EggCharacterDb &db) { bool all_ok = true; BackPointers::iterator bpi; @@ -320,7 +310,7 @@ do_rebuild() { if (back != (EggBackPointer *)NULL) { EggJointPointer *joint; DCAST_INTO_R(joint, back, false); - if (!joint->do_rebuild()) { + if (!joint->do_rebuild(db)) { all_ok = false; } } @@ -329,7 +319,7 @@ do_rebuild() { Children::iterator ci; for (ci = _children.begin(); ci != _children.end(); ++ci) { EggJointData *child = (*ci); - if (!child->do_rebuild()) { + if (!child->do_rebuild_all(db)) { all_ok = false; } } @@ -497,15 +487,6 @@ void EggJointData:: do_begin_reparent() { _got_new_parent_depth = false; _children.clear(); - - int num_models = get_num_models(); - for (int model_index = 0; model_index < num_models; model_index++) { - if (has_model(model_index)) { - EggJointPointer *joint; - DCAST_INTO_V(joint, get_model(model_index)); - joint->begin_rebuild(); - } - } } //////////////////////////////////////////////////////////////////// @@ -568,7 +549,7 @@ do_begin_compute_reparent() { // false on failure. //////////////////////////////////////////////////////////////////// bool EggJointData:: -do_compute_reparent(int model_index, int n) { +do_compute_reparent(int model_index, int n, EggCharacterDb &db) { if (_computed_reparent) { // We've already done this joint. This is possible because we // have to recursively compute joints upwards, so we might visit @@ -597,52 +578,73 @@ do_compute_reparent(int model_index, int n) { LMatrix4d transform; if (_parent == (EggJointData *)NULL) { // We are moving from outside the joint hierarchy to within it. - transform = _new_parent->get_new_net_frame_inv(model_index, n); + transform = _new_parent->get_new_net_frame_inv(model_index, n, db); } else if (_new_parent == (EggJointData *)NULL) { // We are moving from within the hierarchy to outside it. - transform = _parent->get_net_frame(model_index, n); + transform = _parent->get_net_frame(model_index, n, db); } else { // We are changing parents within the hierarchy. transform = - _parent->get_net_frame(model_index, n) * - _new_parent->get_new_net_frame_inv(model_index, n); + _parent->get_net_frame(model_index, n, db) * + _new_parent->get_new_net_frame_inv(model_index, n, db); } - nassertr(n == joint->get_num_rebuild_frames(), false); + db.set_matrix(joint, EggCharacterDb::TT_rebuild_frame, n, + joint->get_frame(n) * transform); + _computed_ok = true; - _computed_ok = joint->add_rebuild_frame(joint->get_frame(n) * transform); return _computed_ok; } +//////////////////////////////////////////////////////////////////// +// Function: EggJointData::do_joint_rebuild +// Access: Protected +// Description: Calls do_rebuild() on the joint for the indicated +// model index. Returns true on success, false on +// failure (false shouldn't be possible). +//////////////////////////////////////////////////////////////////// +bool EggJointData:: +do_joint_rebuild(int model_index, EggCharacterDb &db) { + bool all_ok = true; + + EggJointPointer *parent_joint = NULL; + if (_new_parent != NULL && _new_parent->has_model(model_index)) { + DCAST_INTO_R(parent_joint, _new_parent->get_model(model_index), false); + } + + if (has_model(model_index)) { + EggJointPointer *joint; + DCAST_INTO_R(joint, get_model(model_index), false); + if (!joint->do_rebuild(db)) { + all_ok = false; + } + } + + return all_ok; +} + //////////////////////////////////////////////////////////////////// // Function: EggJointData::do_finish_reparent // Access: Protected // Description: Performs the actual reparenting operation // by removing all of the old children and replacing -// them with the set of new children. Returns true on -// success, false on failure. +// them with the set of new children. //////////////////////////////////////////////////////////////////// -bool EggJointData:: +void EggJointData:: do_finish_reparent() { - bool all_ok = true; - int num_models = get_num_models(); for (int model_index = 0; model_index < num_models; model_index++) { EggJointPointer *parent_joint = NULL; if (_new_parent != NULL && _new_parent->has_model(model_index)) { - DCAST_INTO_R(parent_joint, _new_parent->get_model(model_index), false); + DCAST_INTO_V(parent_joint, _new_parent->get_model(model_index)); } if (has_model(model_index)) { EggJointPointer *joint; - DCAST_INTO_R(joint, get_model(model_index), false); + DCAST_INTO_V(joint, get_model(model_index)); joint->do_finish_reparent(parent_joint); - joint->clear_net_frames(); - if (!joint->do_rebuild()) { - all_ok = false; - } } } @@ -650,8 +652,6 @@ do_finish_reparent() { if (_parent != (EggJointData *)NULL) { _parent->_children.push_back(this); } - - return all_ok; } //////////////////////////////////////////////////////////////////// @@ -760,11 +760,11 @@ is_new_ancestor(EggJointData *child) const { // useful only when called within do_compute_reparent(). //////////////////////////////////////////////////////////////////// const LMatrix4d &EggJointData:: -get_new_net_frame(int model_index, int n) { +get_new_net_frame(int model_index, int n, EggCharacterDb &db) { if (!_got_new_net_frame) { - _new_net_frame = get_new_frame(model_index, n); + _new_net_frame = get_new_frame(model_index, n, db); if (_new_parent != (EggJointData *)NULL) { - _new_net_frame = _new_net_frame * _new_parent->get_new_net_frame(model_index, n); + _new_net_frame = _new_net_frame * _new_parent->get_new_net_frame(model_index, n, db); } _got_new_net_frame = true; } @@ -777,11 +777,11 @@ get_new_net_frame(int model_index, int n) { // Description: Returns the inverse of get_new_net_frame(). //////////////////////////////////////////////////////////////////// const LMatrix4d &EggJointData:: -get_new_net_frame_inv(int model_index, int n) { +get_new_net_frame_inv(int model_index, int n, EggCharacterDb &db) { if (!_got_new_net_frame_inv) { - _new_net_frame_inv.invert_from(get_new_frame(model_index, n)); + _new_net_frame_inv.invert_from(get_new_frame(model_index, n, db)); if (_new_parent != (EggJointData *)NULL) { - _new_net_frame_inv = _new_parent->get_new_net_frame_inv(model_index, n) * _new_net_frame_inv; + _new_net_frame_inv = _new_parent->get_new_net_frame_inv(model_index, n, db) * _new_net_frame_inv; } _got_new_net_frame_inv = true; } @@ -797,8 +797,8 @@ get_new_net_frame_inv(int model_index, int n) { // called. //////////////////////////////////////////////////////////////////// LMatrix4d EggJointData:: -get_new_frame(int model_index, int n) { - do_compute_reparent(model_index, n); +get_new_frame(int model_index, int n, EggCharacterDb &db) { + do_compute_reparent(model_index, n, db); EggBackPointer *back = get_model(model_index); if (back == (EggBackPointer *)NULL) { @@ -808,9 +808,12 @@ get_new_frame(int model_index, int n) { EggJointPointer *joint; DCAST_INTO_R(joint, back, LMatrix4d::ident_mat()); - if (joint->get_num_rebuild_frames() > 0) { - return joint->get_rebuild_frame(n); - } else { + LMatrix4d mat; + if (!db.get_matrix(joint, EggCharacterDb::TT_rebuild_frame, n, mat)) { + // No rebuild frame; return the regular frame. return joint->get_frame(n); } + + // Return the rebuild frame, as computed. + return mat; } diff --git a/pandatool/src/eggcharbase/eggJointData.h b/pandatool/src/eggcharbase/eggJointData.h index 14febaa0e5..7e0b9a3811 100644 --- a/pandatool/src/eggcharbase/eggJointData.h +++ b/pandatool/src/eggcharbase/eggJointData.h @@ -20,12 +20,13 @@ #define EGGJOINTDATA_H #include "pandatoolbase.h" - #include "eggComponentData.h" #include "eggGroup.h" #include "luse.h" #include "pset.h" +class EggCharacterDb; + //////////////////////////////////////////////////////////////////// // Class : EggJointData // Description : This is one node of a hierarchy of EggJointData @@ -45,8 +46,8 @@ public: INLINE EggJointData *find_joint(const string &name); LMatrix4d get_frame(int model_index, int n) const; - LMatrix4d get_net_frame(int model_index, int n) const; - LMatrix4d get_net_frame_inv(int model_index, int n) const; + LMatrix4d get_net_frame(int model_index, int n, EggCharacterDb &db) const; + LMatrix4d get_net_frame_inv(int model_index, int n, EggCharacterDb &db) const; INLINE bool has_rest_frame() const; INLINE bool rest_frames_differ() const; @@ -55,9 +56,9 @@ public: INLINE void reparent_to(EggJointData *new_parent); void move_vertices_to(EggJointData *new_owner); - int score_reparent_to(EggJointData *new_parent); + int score_reparent_to(EggJointData *new_parent, EggCharacterDb &db); - bool do_rebuild(); + bool do_rebuild_all(EggCharacterDb &db); void optimize(); void expose(EggGroup::DCSType dcs_type = EggGroup::DC_default); void zero_channels(const string &components); @@ -70,8 +71,9 @@ protected: void do_begin_reparent(); bool calc_new_parent_depth(pset &chain); void do_begin_compute_reparent(); - bool do_compute_reparent(int model_index, int n); - bool do_finish_reparent(); + bool do_compute_reparent(int model_index, int n, EggCharacterDb &db); + bool do_joint_rebuild(int model_index, EggCharacterDb &db); + void do_finish_reparent(); private: EggJointData *make_new_joint(const string &name); @@ -79,9 +81,9 @@ private: EggJointData *find_joint_matches(const string &name); bool is_new_ancestor(EggJointData *child) const; - const LMatrix4d &get_new_net_frame(int model_index, int n); - const LMatrix4d &get_new_net_frame_inv(int model_index, int n); - LMatrix4d get_new_frame(int model_index, int n); + const LMatrix4d &get_new_net_frame(int model_index, int n, EggCharacterDb &db); + const LMatrix4d &get_new_net_frame_inv(int model_index, int n, EggCharacterDb &db); + LMatrix4d get_new_frame(int model_index, int n, EggCharacterDb &db); bool _has_rest_frame; bool _rest_frames_differ; diff --git a/pandatool/src/eggcharbase/eggJointNodePointer.cxx b/pandatool/src/eggcharbase/eggJointNodePointer.cxx index 0028a13292..b330218e75 100644 --- a/pandatool/src/eggcharbase/eggJointNodePointer.cxx +++ b/pandatool/src/eggcharbase/eggJointNodePointer.cxx @@ -140,23 +140,6 @@ move_vertices_to(EggJointPointer *new_joint) { } } -//////////////////////////////////////////////////////////////////// -// Function: EggJointNodePointer::add_rebuild_frame -// Access: Public, Virtual -// Description: Adds a new frame to the set of rebuild frames. See -// begin_rebuild() and do_rebuild(). Returns true if -// this is valid, false otherwise (e.g. adding multiple -// frames to a static joint). -//////////////////////////////////////////////////////////////////// -bool EggJointNodePointer:: -add_rebuild_frame(const LMatrix4d &mat) { - if (!_rebuild_frames.empty()) { - // Only one frame may be added to a . - return false; - } - return EggJointPointer::add_rebuild_frame(mat); -} - //////////////////////////////////////////////////////////////////// // Function: EggJointNodePointer::do_rebuild // Access: Public, Virtual @@ -171,17 +154,18 @@ add_rebuild_frame(const LMatrix4d &mat) { // acceptable, or false if there is some problem. //////////////////////////////////////////////////////////////////// bool EggJointNodePointer:: -do_rebuild() { - if (_rebuild_frames.empty()) { +do_rebuild(EggCharacterDb &db) { + LMatrix4d mat; + if (!db.get_matrix(this, EggCharacterDb::TT_rebuild_frame, 0, mat)) { + // No rebuild frame; this is OK. return true; } - if (_rebuild_frames.size() != 1) { - return false; - } + _joint->set_transform3d(mat); - _joint->set_transform3d(_rebuild_frames[0]); - _rebuild_frames.clear(); + // We shouldn't have a frame 1. + nassertr(!db.get_matrix(this, EggCharacterDb::TT_rebuild_frame, 1, mat), false); + return true; } diff --git a/pandatool/src/eggcharbase/eggJointNodePointer.h b/pandatool/src/eggcharbase/eggJointNodePointer.h index 6932f212d5..f58b709aec 100644 --- a/pandatool/src/eggcharbase/eggJointNodePointer.h +++ b/pandatool/src/eggcharbase/eggJointNodePointer.h @@ -41,8 +41,7 @@ public: virtual void do_finish_reparent(EggJointPointer *new_parent); virtual void move_vertices_to(EggJointPointer *new_joint); - virtual bool add_rebuild_frame(const LMatrix4d &mat); - virtual bool do_rebuild(); + virtual bool do_rebuild(EggCharacterDb &db); virtual void expose(EggGroup::DCSType dcs_type); virtual bool has_vertices() const; diff --git a/pandatool/src/eggcharbase/eggJointPointer.I b/pandatool/src/eggcharbase/eggJointPointer.I index 1df0f50f15..4db7bea29b 100644 --- a/pandatool/src/eggcharbase/eggJointPointer.I +++ b/pandatool/src/eggcharbase/eggJointPointer.I @@ -16,116 +16,3 @@ // //////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////// -// Function: EggJointPointer::get_num_rebuild_frames -// Access: Public -// Description: Returns the number of rebuild frames that have been -// added so far. -//////////////////////////////////////////////////////////////////// -INLINE int EggJointPointer:: -get_num_rebuild_frames() const { - return _rebuild_frames.size(); -} - -//////////////////////////////////////////////////////////////////// -// Function: EggJointPointer::get_rebuild_frame -// Access: Public -// Description: Returns the nth matrix that has been added to the set -// of rebuild frames. -//////////////////////////////////////////////////////////////////// -INLINE const LMatrix4d &EggJointPointer:: -get_rebuild_frame(int n) const { - nassertr(n >= 0 && n < (int)_rebuild_frames.size(), LMatrix4d::ident_mat()); - return _rebuild_frames[n]; -} - -//////////////////////////////////////////////////////////////////// -// Function: EggJointPointer::clear_net_frames -// Access: Public -// Description: Resets the cache of net frames for this joint. -//////////////////////////////////////////////////////////////////// -INLINE void EggJointPointer:: -clear_net_frames() { - _net_frames.clear(); -} - -//////////////////////////////////////////////////////////////////// -// Function: EggJointPointer::add_net_frame -// Access: Public, Virtual -// Description: Adds a new frame to the set of net frames. This is -// used to cache the net transform from the root for -// this particular joint. -//////////////////////////////////////////////////////////////////// -INLINE void EggJointPointer:: -add_net_frame(const LMatrix4d &mat) { - _net_frames.push_back(mat); -} - -//////////////////////////////////////////////////////////////////// -// Function: EggJointPointer::get_num_net_frames -// Access: Public -// Description: Returns the number of net frames that have been -// added so far. -//////////////////////////////////////////////////////////////////// -INLINE int EggJointPointer:: -get_num_net_frames() const { - return _net_frames.size(); -} - -//////////////////////////////////////////////////////////////////// -// Function: EggJointPointer::get_net_frame -// Access: Public -// Description: Returns the nth matrix that has been added to the set -// of net frames. -//////////////////////////////////////////////////////////////////// -INLINE const LMatrix4d &EggJointPointer:: -get_net_frame(int n) const { - nassertr(n >= 0 && n < (int)_net_frames.size(), LMatrix4d::ident_mat()); - return _net_frames[n]; -} - -//////////////////////////////////////////////////////////////////// -// Function: EggJointPointer::clear_net_frame_invs -// Access: Public -// Description: Resets the cache of net_inv frames for this joint. -//////////////////////////////////////////////////////////////////// -INLINE void EggJointPointer:: -clear_net_frame_invs() { - _net_frame_invs.clear(); -} - -//////////////////////////////////////////////////////////////////// -// Function: EggJointPointer::add_net_frame_inv -// Access: Public, Virtual -// Description: Adds a new frame to the set of net_inv frames. This is -// used to cache the inverse net transform from the root -// for this particular joint. -//////////////////////////////////////////////////////////////////// -INLINE void EggJointPointer:: -add_net_frame_inv(const LMatrix4d &mat) { - _net_frame_invs.push_back(mat); -} - -//////////////////////////////////////////////////////////////////// -// Function: EggJointPointer::get_num_net_frame_invs -// Access: Public -// Description: Returns the number of net_inv frames that have been -// added so far. -//////////////////////////////////////////////////////////////////// -INLINE int EggJointPointer:: -get_num_net_frame_invs() const { - return _net_frame_invs.size(); -} - -//////////////////////////////////////////////////////////////////// -// Function: EggJointPointer::get_net_frame_inv -// Access: Public -// Description: Returns the nth matrix that has been added to the set -// of net_inv frames. -//////////////////////////////////////////////////////////////////// -INLINE const LMatrix4d &EggJointPointer:: -get_net_frame_inv(int n) const { - nassertr(n >= 0 && n < (int)_net_frame_invs.size(), LMatrix4d::ident_mat()); - return _net_frame_invs[n]; -} diff --git a/pandatool/src/eggcharbase/eggJointPointer.cxx b/pandatool/src/eggcharbase/eggJointPointer.cxx index 721c95e173..75fcd493a1 100644 --- a/pandatool/src/eggcharbase/eggJointPointer.cxx +++ b/pandatool/src/eggcharbase/eggJointPointer.cxx @@ -44,35 +44,6 @@ void EggJointPointer:: move_vertices_to(EggJointPointer *) { } -//////////////////////////////////////////////////////////////////// -// Function: EggJointPointer::begin_rebuild -// Access: Public -// Description: Resets the set of rebuild frames in preparation for -// rebuilding the complete table of frames. Repeated -// calls to add_rebuild_frame() will build up the frames -// without changing the values returned by get_frame(); -// the table will eventually be updated when do_rebuild -// is called. -//////////////////////////////////////////////////////////////////// -void EggJointPointer:: -begin_rebuild() { - _rebuild_frames.clear(); -} - -//////////////////////////////////////////////////////////////////// -// Function: EggJointPointer::add_rebuild_frame -// Access: Public, Virtual -// Description: Adds a new frame to the set of rebuild frames. See -// begin_rebuild() and do_rebuild(). Returns true if -// this is valid, false otherwise (e.g. adding multiple -// frames to a static joint). -//////////////////////////////////////////////////////////////////// -bool EggJointPointer:: -add_rebuild_frame(const LMatrix4d &mat) { - _rebuild_frames.push_back(mat); - return true; -} - //////////////////////////////////////////////////////////////////// // Function: EggJointPointer::do_rebuild // Access: Public, Virtual @@ -87,12 +58,8 @@ add_rebuild_frame(const LMatrix4d &mat) { // acceptable, or false if there is some problem. //////////////////////////////////////////////////////////////////// bool EggJointPointer:: -do_rebuild() { - if (_rebuild_frames.empty()) { - return true; - } - _rebuild_frames.clear(); - return false; +do_rebuild(EggCharacterDb &db) { + return true; } //////////////////////////////////////////////////////////////////// diff --git a/pandatool/src/eggcharbase/eggJointPointer.h b/pandatool/src/eggcharbase/eggJointPointer.h index c6d6e79bb6..b5d585395a 100644 --- a/pandatool/src/eggcharbase/eggJointPointer.h +++ b/pandatool/src/eggcharbase/eggJointPointer.h @@ -20,11 +20,12 @@ #define EGGJOINTPOINTER_H #include "pandatoolbase.h" - #include "eggBackPointer.h" #include "eggGroup.h" #include "luse.h" +class EggCharacterDb; + //////////////////////////////////////////////////////////////////// // Class : EggJointPointer // Description : This is a base class for EggJointNodePointer and @@ -44,21 +45,7 @@ public: virtual void do_finish_reparent(EggJointPointer *new_parent)=0; virtual void move_vertices_to(EggJointPointer *new_joint); - void begin_rebuild(); - virtual bool add_rebuild_frame(const LMatrix4d &mat); - INLINE int get_num_rebuild_frames() const; - INLINE const LMatrix4d &get_rebuild_frame(int n) const; - virtual bool do_rebuild(); - - INLINE void clear_net_frames(); - INLINE void add_net_frame(const LMatrix4d &mat); - INLINE int get_num_net_frames() const; - INLINE const LMatrix4d &get_net_frame(int n) const; - - INLINE void clear_net_frame_invs(); - INLINE void add_net_frame_inv(const LMatrix4d &mat); - INLINE int get_num_net_frame_invs() const; - INLINE const LMatrix4d &get_net_frame_inv(int n) const; + virtual bool do_rebuild(EggCharacterDb &db); virtual void optimize(); virtual void expose(EggGroup::DCSType dcs_type); @@ -67,12 +54,6 @@ public: virtual EggJointPointer *make_new_joint(const string &name)=0; -protected: - typedef pvector RebuildFrames; - RebuildFrames _rebuild_frames; - RebuildFrames _net_frames; - RebuildFrames _net_frame_invs; - public: static TypeHandle get_class_type() { return _type_handle; diff --git a/pandatool/src/eggcharbase/eggMatrixTablePointer.cxx b/pandatool/src/eggcharbase/eggMatrixTablePointer.cxx index dff73db7bc..735a2bce19 100644 --- a/pandatool/src/eggcharbase/eggMatrixTablePointer.cxx +++ b/pandatool/src/eggcharbase/eggMatrixTablePointer.cxx @@ -189,8 +189,10 @@ do_finish_reparent(EggJointPointer *new_parent) { // acceptable, or false if there is some problem. //////////////////////////////////////////////////////////////////// bool EggMatrixTablePointer:: -do_rebuild() { - if (_rebuild_frames.empty()) { +do_rebuild(EggCharacterDb &db) { + LMatrix4d mat; + if (!db.get_matrix(this, EggCharacterDb::TT_rebuild_frame, 0, mat)) { + // No rebuild frame; this is OK. return true; } @@ -201,14 +203,19 @@ do_rebuild() { bool all_ok = true; _xform->clear_data(); - RebuildFrames::const_iterator fi; - for (fi = _rebuild_frames.begin(); fi != _rebuild_frames.end(); ++fi) { - if (!_xform->add_data(*fi)) { - all_ok = false; - } + if (!_xform->add_data(mat)) { + all_ok = false; + } + + // Assume all frames will be contiguous. + int n = 1; + while (db.get_matrix(this, EggCharacterDb::TT_rebuild_frame, n, mat)) { + if (!_xform->add_data(mat)) { + all_ok = false; + } + ++n; } - _rebuild_frames.clear(); return all_ok; } diff --git a/pandatool/src/eggcharbase/eggMatrixTablePointer.h b/pandatool/src/eggcharbase/eggMatrixTablePointer.h index 10bd826b5b..5b110a4a84 100644 --- a/pandatool/src/eggcharbase/eggMatrixTablePointer.h +++ b/pandatool/src/eggcharbase/eggMatrixTablePointer.h @@ -46,7 +46,7 @@ public: virtual void do_finish_reparent(EggJointPointer *new_parent); - virtual bool do_rebuild(); + virtual bool do_rebuild(EggCharacterDb &db); virtual void optimize(); virtual void zero_channels(const string &components); diff --git a/pandatool/src/eggcharbase/eggcharbase_composite1.cxx b/pandatool/src/eggcharbase/eggcharbase_composite1.cxx index d39d2228ad..5aa73594b8 100644 --- a/pandatool/src/eggcharbase/eggcharbase_composite1.cxx +++ b/pandatool/src/eggcharbase/eggcharbase_composite1.cxx @@ -3,6 +3,7 @@ #include "eggBackPointer.cxx" #include "eggCharacterCollection.cxx" #include "eggCharacterData.cxx" +#include "eggCharacterDb.cxx" #include "eggCharacterFilter.cxx" #include "eggComponentData.cxx" #include "eggJointData.cxx" diff --git a/pandatool/src/eggprogs/eggRetargetAnim.cxx b/pandatool/src/eggprogs/eggRetargetAnim.cxx index 314a3a4372..e324a93a36 100644 --- a/pandatool/src/eggprogs/eggRetargetAnim.cxx +++ b/pandatool/src/eggprogs/eggRetargetAnim.cxx @@ -22,6 +22,7 @@ #include "eggJointData.h" #include "eggCharacterCollection.h" #include "eggCharacterData.h" +#include "eggCharacterDb.h" #include "eggJointPointer.h" #include "eggTable.h" #include "compose_matrix.h" @@ -127,9 +128,10 @@ run() { keep_names.insert(*si); } + EggCharacterDb db; EggJointData *root_joint = char_data->get_root_joint(); - retarget_anim(char_data, root_joint, reference_model, keep_names); - root_joint->do_rebuild(); + retarget_anim(char_data, root_joint, reference_model, keep_names, db); + root_joint->do_rebuild_all(db); write_eggs(); } @@ -143,7 +145,8 @@ run() { //////////////////////////////////////////////////////////////////// void EggRetargetAnim:: retarget_anim(EggCharacterData *char_data, EggJointData *joint_data, - int reference_model, const pset &keep_names) { + int reference_model, const pset &keep_names, + EggCharacterDb &db) { if (keep_names.find(joint_data->get_name()) != keep_names.end()) { // Don't retarget this joint; keep the translation and scale and whatever. @@ -176,11 +179,9 @@ retarget_anim(EggCharacterData *char_data, EggJointData *joint_data, nout << "Could not decompose matrix for " << joint_data->get_name() << "\n"; } - - if (!joint->add_rebuild_frame(mat)) { - nout << "Unable to combine animations.\n"; - exit(1); - } + + db.set_matrix(joint, EggCharacterDb::TT_rebuild_frame, + f, mat); } } } @@ -190,7 +191,7 @@ retarget_anim(EggCharacterData *char_data, EggJointData *joint_data, int num_children = joint_data->get_num_children(); for (int i = 0; i < num_children; i++) { EggJointData *next_joint_data = joint_data->get_child(i); - retarget_anim(char_data, next_joint_data, reference_model, keep_names); + retarget_anim(char_data, next_joint_data, reference_model, keep_names, db); } } diff --git a/pandatool/src/eggprogs/eggRetargetAnim.h b/pandatool/src/eggprogs/eggRetargetAnim.h index 7a44a01142..a98b0f2b52 100644 --- a/pandatool/src/eggprogs/eggRetargetAnim.h +++ b/pandatool/src/eggprogs/eggRetargetAnim.h @@ -28,6 +28,7 @@ class EggCharacterData; class EggJointData; +class EggCharacterDb; //////////////////////////////////////////////////////////////////// // Class : EggRetargetAnim @@ -43,7 +44,8 @@ public: void run(); void retarget_anim(EggCharacterData *char_data, EggJointData *joint_data, - int reference_model, const pset &keep_names); + int reference_model, const pset &keep_names, + EggCharacterDb &db); Filename _reference_filename; vector_string _keep_joints; diff --git a/pandatool/src/eggprogs/eggTopstrip.cxx b/pandatool/src/eggprogs/eggTopstrip.cxx index f6275200d8..47ebd3438f 100644 --- a/pandatool/src/eggprogs/eggTopstrip.cxx +++ b/pandatool/src/eggprogs/eggTopstrip.cxx @@ -22,6 +22,7 @@ #include "eggJointData.h" #include "eggCharacterCollection.h" #include "eggCharacterData.h" +#include "eggCharacterDb.h" #include "eggJointPointer.h" #include "eggTable.h" #include "compose_matrix.h" @@ -125,6 +126,8 @@ run() { } // Now process each character. + EggCharacterDb db; + int ci; for (ci = 0; ci < num_characters; ci++) { EggCharacterData *char_data = _collection->get_character(ci); @@ -163,7 +166,7 @@ run() { int num_children = root_joint->get_num_children(); for (int i = 0; i < num_children; i++) { EggJointData *joint_data = root_joint->get_child(i); - strip_anim(char_data, joint_data, from_model, from_char, top_joint); + strip_anim(char_data, joint_data, from_model, from_char, top_joint, db); } // We also need to transform the vertices for any models involved @@ -173,7 +176,7 @@ run() { EggNode *node = char_data->get_model_root(m); if (!node->is_of_type(EggTable::get_class_type())) { strip_anim_vertices(node, char_data->get_model_index(m), - from_model, top_joint); + from_model, top_joint, db); } } } @@ -181,7 +184,7 @@ run() { // Now, trigger the actual rebuilding of all the joint data. for (ci = 0; ci < num_characters; ci++) { EggCharacterData *char_data = _collection->get_character(ci); - char_data->get_root_joint()->do_rebuild(); + char_data->get_root_joint()->do_rebuild_all(db); } write_eggs(); @@ -235,11 +238,10 @@ check_transform_channels() { void EggTopstrip:: strip_anim(EggCharacterData *char_data, EggJointData *joint_data, int from_model, EggCharacterData *from_char, - EggJointData *top_joint) { + EggJointData *top_joint, EggCharacterDb &db) { int num_models = joint_data->get_num_models(); for (int i = 0; i < num_models; i++) { int model = (from_model < 0) ? i : from_model; - if (joint_data->has_model(i)) { if (!top_joint->has_model(model)) { nout << "Warning: Joint " << top_joint->get_name() @@ -258,23 +260,16 @@ strip_anim(EggCharacterData *char_data, EggJointData *joint_data, DCAST_INTO_V(joint, back); // Compute and apply the new transforms. - joint->begin_rebuild(); int f; for (f = 0; f < num_frames; f++) { LMatrix4d into = joint_data->get_frame(i, f % num_into_frames); - LMatrix4d from = top_joint->get_net_frame(model, f % num_from_frames); + LMatrix4d from = top_joint->get_net_frame(model, f % num_from_frames, db); adjust_transform(from); - if (!joint->add_rebuild_frame(into * from)) { - nout << - "Cannot apply multiple frames of animation to a model file.\n" - "In general, -r cannot be used when a model file is being " - "adjusted, unless the named source is a one-frame animation " - "file, or another model file.\n"; - exit(1); - } + db.set_matrix(joint, EggCharacterDb::TT_rebuild_frame, + f, into * from); } } } @@ -288,7 +283,7 @@ strip_anim(EggCharacterData *char_data, EggJointData *joint_data, //////////////////////////////////////////////////////////////////// void EggTopstrip:: strip_anim_vertices(EggNode *egg_node, int into_model, int from_model, - EggJointData *top_joint) { + EggJointData *top_joint, EggCharacterDb &db) { int model = (from_model < 0) ? into_model : from_model; if (!top_joint->has_model(model)) { nout << "Warning: Joint " << top_joint->get_name() @@ -296,7 +291,7 @@ strip_anim_vertices(EggNode *egg_node, int into_model, int from_model, return; } - LMatrix4d from = top_joint->get_net_frame(model, 0); + LMatrix4d from = top_joint->get_net_frame(model, 0, db); adjust_transform(from); egg_node->transform_vertices_only(from); diff --git a/pandatool/src/eggprogs/eggTopstrip.h b/pandatool/src/eggprogs/eggTopstrip.h index 3199230f11..58b6bbc712 100644 --- a/pandatool/src/eggprogs/eggTopstrip.h +++ b/pandatool/src/eggprogs/eggTopstrip.h @@ -27,6 +27,7 @@ #include "pvector.h" class EggCharacterData; +class EggCharacterDb; class EggJointData; class EggJointPointer; @@ -47,9 +48,10 @@ public: void strip_anim(EggCharacterData *char_data, EggJointData *joint_data, int from_model, EggCharacterData *from_char, - EggJointData *top_joint); + EggJointData *top_joint, EggCharacterDb &db); void strip_anim_vertices(EggNode *egg_node, int into_model, - int from_model, EggJointData *top_joint); + int from_model, EggJointData *top_joint, + EggCharacterDb &db); void adjust_transform(LMatrix4d &mat) const;