瀏覽代碼

fix problem with misassignment of vertices when eliminating top joint

David Rose 22 年之前
父節點
當前提交
b37e90743e

+ 27 - 6
pandatool/src/egg-optchar/eggOptchar.cxx

@@ -185,7 +185,7 @@ run() {
   // Now we can analyze the joints for their properties.
   for (ci = 0; ci < num_characters; ci++) {
     EggCharacterData *char_data = _collection->get_character(ci);
-    analyze_joints(char_data->get_root_joint());
+    analyze_joints(char_data->get_root_joint(), 0);
     analyze_sliders(char_data);
   }
 
@@ -419,7 +419,7 @@ determine_removed_components() {
   for (int ci = 0; ci < num_characters; ci++) {
     EggCharacterData *char_data = _collection->get_character(ci);
     int num_components = char_data->get_num_components();
-    cerr << char_data->get_name() << " has " << num_components << " components.\n";
+    nout << char_data->get_name() << " has " << num_components << " components.\n";
     for (int i = 0; i < num_components; i++) {
       EggComponentData *comp_data = char_data->get_component(i);
       nassertv(comp_data != (EggComponentData *)NULL);
@@ -446,7 +446,19 @@ determine_removed_components() {
       } else {
         // Remove this component if it's unanimated or empty.
         if ((user_data->_flags & (EggOptcharUserData::F_static | EggOptcharUserData::F_empty)) != 0) {
-          user_data->_flags |= EggOptcharUserData::F_remove;
+          if ((user_data->_flags & (EggOptcharUserData::F_top | EggOptcharUserData::F_empty)) == EggOptcharUserData::F_top) {
+            // Actually, we can't remove it if it's a top joint,
+            // unless it's also empty.  That's because vertices that
+            // are partially assigned to this joint would then have no
+            // joint to represent the same partial assignment, and
+            // they would then appear to be wholly assigned to their
+            // other joint, which would be incorrect.
+
+          } else {
+            // But joints that aren't top joints (or that are empty)
+            // are o.k. to remove.
+            user_data->_flags |= EggOptcharUserData::F_remove;
+          }
         }
       }
     }
@@ -523,7 +535,6 @@ move_vertices() {
 ////////////////////////////////////////////////////////////////////
 bool EggOptchar::
 process_joints() {
-  cerr << "process_joints\n";
   bool removed_any = false;
   int num_characters = _collection->get_num_characters();
   for (int ci = 0; ci < num_characters; ci++) {
@@ -772,10 +783,17 @@ zero_channels() {
 //               joint.
 ////////////////////////////////////////////////////////////////////
 void EggOptchar::
-analyze_joints(EggJointData *joint_data) {
+analyze_joints(EggJointData *joint_data, int level) {
   PT(EggOptcharUserData) user_data = new EggOptcharUserData;
   joint_data->set_user_data(user_data);
 
+  if (level == 1) {
+    // The child joints of the root joint are deemed "top" joints.
+    // These may not be removed unless they are empty (because their
+    // vertices have no joint to be moved into).
+    user_data->_flags |= EggOptcharUserData::F_top;
+  }
+
   // Analyze the table of matrices for this joint, checking to see if
   // they're all the same across all frames, or if any of them are
   // different; also look for empty joints (that control no vertices).
@@ -831,7 +849,7 @@ analyze_joints(EggJointData *joint_data) {
 
   int num_children = joint_data->get_num_children();
   for (i = 0; i < num_children; i++) {
-    analyze_joints(joint_data->get_child(i));
+    analyze_joints(joint_data->get_child(i), level + 1);
   }
 }
 
@@ -999,6 +1017,9 @@ describe_component(EggComponentData *comp_data, int indent_level,
     if (user_data->is_empty()) {
       cout << " (empty)";
     }
+    if (user_data->is_top()) {
+      cout << " (top)";
+    }
   }
   cout << "\n";
 }

+ 1 - 1
pandatool/src/egg-optchar/eggOptchar.h

@@ -64,7 +64,7 @@ private:
 
   bool apply_user_reparents();
   bool zero_channels();
-  void analyze_joints(EggJointData *joint_data);
+  void analyze_joints(EggJointData *joint_data, int level);
   void analyze_sliders(EggCharacterData *char_data);
   void list_joints(EggJointData *joint_data, int indent_level, bool verbose);
   void list_joints_p(EggJointData *joint_data, int &col);

+ 10 - 0
pandatool/src/egg-optchar/eggOptcharUserData.I

@@ -87,3 +87,13 @@ INLINE bool EggOptcharUserData::
 is_empty() const {
   return (_flags & F_empty) != 0;
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggOptcharUserData::is_top
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE bool EggOptcharUserData::
+is_top() const {
+  return (_flags & F_top) != 0;
+}

+ 4 - 2
pandatool/src/egg-optchar/eggOptcharUserData.h

@@ -38,13 +38,15 @@ public:
   INLINE bool is_static() const;
   INLINE bool is_identity() const;
   INLINE bool is_empty() const;
+  INLINE bool is_top() const;
 
   enum Flags {
     F_static   = 0x0001,
     F_identity = 0x0002,
     F_empty    = 0x0004,
-    F_remove   = 0x0008,
-    F_expose   = 0x0010,
+    F_top      = 0x0008,
+    F_remove   = 0x0010,
+    F_expose   = 0x0020,
   };
   int _flags;
   LMatrix4d _static_mat;