浏览代码

add fixrest

David Rose 22 年之前
父节点
当前提交
85636c31ca

+ 1 - 0
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 "

+ 14 - 7
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";
+        }
       }
     }
 

+ 1 - 1
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);

+ 20 - 1
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;
 }

+ 3 - 0
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

+ 13 - 0
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

+ 34 - 31
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())) {

+ 3 - 1
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