diff --git a/pandatool/src/egg-optchar/eggOptchar.cxx b/pandatool/src/egg-optchar/eggOptchar.cxx index 347c0bd05a..1cac8d3302 100644 --- a/pandatool/src/egg-optchar/eggOptchar.cxx +++ b/pandatool/src/egg-optchar/eggOptchar.cxx @@ -45,6 +45,7 @@ EggOptchar() { add_path_store_options(); add_normals_options(); add_transform_options(); + add_fixrest_option(); set_program_description ("egg-optchar performs basic optimizations of a character model " diff --git a/pandatool/src/eggcharbase/eggCharacterCollection.cxx b/pandatool/src/eggcharbase/eggCharacterCollection.cxx index cd546fc8ae..fb7966c300 100644 --- a/pandatool/src/eggcharbase/eggCharacterCollection.cxx +++ b/pandatool/src/eggcharbase/eggCharacterCollection.cxx @@ -673,21 +673,28 @@ write(ostream &out, int indent_level) const { // detected, such as inconsistent animation tables. // // In addition to reporting this errors, calling this -// function will also ensure that they are all repaired -// (although certain kinds of errors will be repaired -// regardless). +// function will also ensure that they are all repaired. +// Pass force_initial_rest_frame as true to also force +// rest frames from different models to be the same if +// they are initially different. //////////////////////////////////////////////////////////////////// void EggCharacterCollection:: -check_errors(ostream &out) { +check_errors(ostream &out, bool force_initial_rest_frame) { Characters::const_iterator ci; for (ci = _characters.begin(); ci != _characters.end(); ++ci) { EggCharacterData *char_data = (*ci); int num_joints = char_data->get_num_joints(); for (int j = 0; j < num_joints; j++) { EggJointData *joint_data = char_data->get_joint(j); - if (joint_data->_forced_rest_frames_equal) { - out << "Warning: rest frames for " << joint_data->get_name() - << " were different.\n"; + if (joint_data->rest_frames_differ()) { + if (force_initial_rest_frame) { + joint_data->force_initial_rest_frame(); + out << "Forced rest frames the same for " << joint_data->get_name() + << ".\n"; + } else { + out << "Warning: rest frames for " << joint_data->get_name() + << " differ.\n"; + } } } diff --git a/pandatool/src/eggcharbase/eggCharacterCollection.h b/pandatool/src/eggcharbase/eggCharacterCollection.h index 85600b305c..971c3fc35b 100644 --- a/pandatool/src/eggcharbase/eggCharacterCollection.h +++ b/pandatool/src/eggcharbase/eggCharacterCollection.h @@ -55,7 +55,7 @@ public: INLINE EggCharacterData *get_character_by_model_index(int model_index) const; virtual void write(ostream &out, int indent_level = 0) const; - void check_errors(ostream &out); + void check_errors(ostream &out, bool force_initial_rest_frame); virtual EggCharacterData *make_character_data(); virtual EggJointData *make_joint_data(EggCharacterData *char_data); diff --git a/pandatool/src/eggcharbase/eggCharacterFilter.cxx b/pandatool/src/eggcharbase/eggCharacterFilter.cxx index 77ffde1bc8..055bb8894c 100644 --- a/pandatool/src/eggcharbase/eggCharacterFilter.cxx +++ b/pandatool/src/eggcharbase/eggCharacterFilter.cxx @@ -29,6 +29,8 @@ EggCharacterFilter:: EggCharacterFilter() : EggMultiFilter(false) { _collection = (EggCharacterCollection *)NULL; + + _force_initial_rest_frame = false; } //////////////////////////////////////////////////////////////////// @@ -43,6 +45,23 @@ EggCharacterFilter:: } } +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterFilter::add_fixrest_option +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +void EggCharacterFilter:: +add_fixrest_option() { + add_option + ("fixrest", "", 50, + "Specify this to force all the initial rest frames of the various " + "model files to the same value as the first model specified. This " + "is a fairly drastic way to repair models whose initial rest frame " + "values are completely bogus, but should not be performed when the " + "input models are correct.", + &EggCharacterFilter::dispatch_none, &_force_initial_rest_frame); +} + //////////////////////////////////////////////////////////////////// // Function: EggCharacterFilter::post_command_line @@ -70,7 +89,7 @@ post_command_line() { } } - _collection->check_errors(nout); + _collection->check_errors(nout, _force_initial_rest_frame); return true; } diff --git a/pandatool/src/eggcharbase/eggCharacterFilter.h b/pandatool/src/eggcharbase/eggCharacterFilter.h index 607f3aac68..f404b54c48 100644 --- a/pandatool/src/eggcharbase/eggCharacterFilter.h +++ b/pandatool/src/eggcharbase/eggCharacterFilter.h @@ -42,6 +42,8 @@ public: EggCharacterFilter(); virtual ~EggCharacterFilter(); + void add_fixrest_option(); + protected: virtual bool post_command_line(); virtual void write_eggs(); @@ -49,6 +51,7 @@ protected: virtual EggCharacterCollection *make_collection(); EggCharacterCollection *_collection; + bool _force_initial_rest_frame; }; #endif diff --git a/pandatool/src/eggcharbase/eggJointData.I b/pandatool/src/eggcharbase/eggJointData.I index 2046de71ea..2e3aa8b793 100644 --- a/pandatool/src/eggcharbase/eggJointData.I +++ b/pandatool/src/eggcharbase/eggJointData.I @@ -61,6 +61,19 @@ has_rest_frame() const { return _has_rest_frame; } +//////////////////////////////////////////////////////////////////// +// Function: EggJointData::rest_frames_differ +// Access: Public +// Description: Returns true if the rest frames for different models +// differ in their initial value. This is not +// technically an error, but it is unusual enough to be +// suspicious. +//////////////////////////////////////////////////////////////////// +INLINE bool EggJointData:: +rest_frames_differ() const { + return _rest_frames_differ; +} + //////////////////////////////////////////////////////////////////// // Function: EggJointData::get_rest_frame // Access: Public diff --git a/pandatool/src/eggcharbase/eggJointData.cxx b/pandatool/src/eggcharbase/eggJointData.cxx index 7e43cff6b7..8eeef98d43 100644 --- a/pandatool/src/eggcharbase/eggJointData.cxx +++ b/pandatool/src/eggcharbase/eggJointData.cxx @@ -41,7 +41,7 @@ EggJointData(EggCharacterCollection *collection, _parent = (EggJointData *)NULL; _new_parent = (EggJointData *)NULL; _has_rest_frame = false; - _forced_rest_frames_equal = false; + _rest_frames_differ = false; } //////////////////////////////////////////////////////////////////// @@ -103,6 +103,33 @@ get_net_frame(int model_index, int n) const { return mat; } +//////////////////////////////////////////////////////////////////// +// Function: EggJointData::force_initial_rest_frame +// Access: Public +// Description: Forces all of the joints to have the same rest frame +// value as the first joint read in. This is a drastic +// way to repair models whose rest frame values are +// completely bogus, but should not be performed on +// models that are otherwise correct. +//////////////////////////////////////////////////////////////////// +void EggJointData:: +force_initial_rest_frame() { + if (!has_rest_frame()) { + return; + } + 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)); + if (joint->is_of_type(EggJointNodePointer::get_class_type())) { + joint->set_frame(0, get_rest_frame()); + } + } + } + _rest_frames_differ = false; +} + //////////////////////////////////////////////////////////////////// // Function: EggJointData::move_vertices_to // Access: Public @@ -185,8 +212,8 @@ optimize() { //////////////////////////////////////////////////////////////////// // Function: EggJointData::expose // Access: Public -// Description: Calls expose() on all models, and recursively on -// all joints at this node and below. +// Description: Calls expose() on all models for this joint, but does +// not recurse downwards. //////////////////////////////////////////////////////////////////// void EggJointData:: expose(EggGroup::DCSType dcs_type) { @@ -199,19 +226,13 @@ expose(EggGroup::DCSType dcs_type) { joint->expose(dcs_type); } } - - Children::iterator ci; - for (ci = _children.begin(); ci != _children.end(); ++ci) { - EggJointData *child = (*ci); - child->expose(dcs_type); - } } //////////////////////////////////////////////////////////////////// // Function: EggJointData::zero_channels // Access: Public -// Description: Calls zero_channels() on all models, and recursively on -// all joints at this node and below. +// Description: Calls zero_channels() on all models for this joint, +// but does not recurse downwards. //////////////////////////////////////////////////////////////////// void EggJointData:: zero_channels(const string &components) { @@ -224,12 +245,6 @@ zero_channels(const string &components) { joint->zero_channels(components); } } - - Children::iterator ci; - for (ci = _children.begin(); ci != _children.end(); ++ci) { - EggJointData *child = (*ci); - child->zero_channels(components); - } } //////////////////////////////////////////////////////////////////// @@ -253,21 +268,9 @@ add_back_pointer(int model_index, EggObject *egg_object) { // If this new node doesn't come within an acceptable tolerance // of our first reading of this joint's rest frame, set a // warning flag. - if (!_rest_frame.almost_equal(joint->get_frame(0), 0.001)) { - _forced_rest_frames_equal = true; + if (!_rest_frame.almost_equal(joint->get_frame(0), 0.0001)) { + _rest_frames_differ = true; } - - // In any case, ensure the rest frames are exactly equal. - - // Actually, this may not be a good idea; it is, in fact, valid - // (although unusual) for different models to have different - // rest frames, provided their vertices appriopriately reflect - // the different rest frames. But we do have at least one - // character, Mickey, for which some of the lower-level LOD's - // have different rest frames that are in fact completely wrong, - // so forcing them all to the same value is correct in that - // case. Maybe this should be a command-line option. - joint->set_frame(0, _rest_frame); } } else if (egg_object->is_of_type(EggTable::get_class_type())) { diff --git a/pandatool/src/eggcharbase/eggJointData.h b/pandatool/src/eggcharbase/eggJointData.h index e2506be24b..3c4d368888 100644 --- a/pandatool/src/eggcharbase/eggJointData.h +++ b/pandatool/src/eggcharbase/eggJointData.h @@ -47,7 +47,9 @@ public: LMatrix4d get_net_frame(int model_index, int n) const; INLINE bool has_rest_frame() const; + INLINE bool rest_frames_differ() const; INLINE const LMatrix4d &get_rest_frame() const; + void force_initial_rest_frame(); INLINE void reparent_to(EggJointData *new_parent); void move_vertices_to(EggJointData *new_owner); @@ -72,7 +74,7 @@ private: LMatrix4d get_new_frame(int model_index, int n); bool _has_rest_frame; - bool _forced_rest_frames_equal; + bool _rest_frames_differ; LMatrix4d _rest_frame; // These are used to cache the above results for optimizing