Browse Source

finally got the skinning matrix right

David Rose 21 years ago
parent
commit
2ed895f54f
2 changed files with 96 additions and 5 deletions
  1. 58 0
      pandatool/src/xfileegg/xFileMaker.cxx
  2. 38 5
      pandatool/src/xfileegg/xFileMesh.cxx

+ 58 - 0
pandatool/src/xfileegg/xFileMaker.cxx

@@ -109,6 +109,64 @@ open(const Filename &filename) {
     &TID_D3DRMMeshMaterialList,
     &TID_D3DRMMeshMaterialList,
     &TID_D3DRMFrameTransformMatrix,
     &TID_D3DRMFrameTransformMatrix,
     &TID_D3DRMFrame,
     &TID_D3DRMFrame,
+
+    /*
+      This is the complete list I extracted out of the Windows header
+      files.
+
+    &TID_D3DRMInfo,
+    &TID_D3DRMMesh,
+    &TID_D3DRMVector,
+    &TID_D3DRMMeshFace,
+    &TID_D3DRMMaterial,
+    &TID_D3DRMMaterialArray,
+    &TID_D3DRMFrame,
+    &TID_D3DRMFrameTransformMatrix,
+    &TID_D3DRMMeshMaterialList,
+    &TID_D3DRMMeshTextureCoords,
+    &TID_D3DRMMeshNormals,
+    &TID_D3DRMCoords2d,
+    &TID_D3DRMMatrix4x4,
+    &TID_D3DRMAnimation,
+    &TID_D3DRMAnimationSet,
+    &TID_D3DRMAnimationKey,
+    &TID_D3DRMFloatKeys,
+    &TID_D3DRMMaterialAmbientColor,
+    &TID_D3DRMMaterialDiffuseColor,
+    &TID_D3DRMMaterialSpecularColor,
+    &TID_D3DRMMaterialEmissiveColor,
+    &TID_D3DRMMaterialPower,
+    &TID_D3DRMColorRGBA,
+    &TID_D3DRMColorRGB,
+    &TID_D3DRMGuid,
+    &TID_D3DRMTextureFilename,
+    &TID_D3DRMTextureReference,
+    &TID_D3DRMIndexedColor,
+    &TID_D3DRMMeshVertexColors,
+    &TID_D3DRMMaterialWrap,
+    &TID_D3DRMBoolean,
+    &TID_D3DRMMeshFaceWraps,
+    &TID_D3DRMBoolean2d,
+    &TID_D3DRMTimedFloatKeys,
+    &TID_D3DRMAnimationOptions,
+    &TID_D3DRMFramePosition,
+    &TID_D3DRMFrameVelocity,
+    &TID_D3DRMFrameRotation,
+    &TID_D3DRMLight,
+    &TID_D3DRMCamera,
+    &TID_D3DRMAppData,
+    &TID_D3DRMLightUmbra,
+    &TID_D3DRMLightRange,
+    &TID_D3DRMLightPenumbra,
+    &TID_D3DRMLightAttenuation,
+    &TID_D3DRMInlineData,
+    &TID_D3DRMUrl,
+    &TID_D3DRMProgressiveMesh,
+    &TID_D3DRMExternalVisual,
+    &TID_D3DRMStringProperty, 
+    &TID_D3DRMPropertyBag, 
+    &TID_D3DRMRightHanded, 
+    */
   };
   };
   static const int num_temps = sizeof(temps) / sizeof(temps[0]);
   static const int num_temps = sizeof(temps) / sizeof(temps[0]);
   hr = _dx_file_save->SaveTemplates(num_temps, temps);
   hr = _dx_file_save->SaveTemplates(num_temps, temps);

+ 38 - 5
pandatool/src/xfileegg/xFileMesh.cxx

@@ -324,9 +324,43 @@ create_polygons(XFileToEggConverter *converter) {
         temp_vtx.set_normal(LCAST(double, normal->_normal));
         temp_vtx.set_normal(LCAST(double, normal->_normal));
       }
       }
 
 
-      // Transform the vertex into the appropriate (global) coordinate
-      // space.
-      temp_vtx.transform(_egg_parent->get_node_to_vertex());
+      // We are given the vertex in local space; we need to transform
+      // it into global space.  If the vertex has been skinned, that
+      // means the global space of all of its joints (modified by the
+      // matrix_offset provided in the skinning data).
+      double net_weight = 0.0;
+      LMatrix4d weighted_transform(0.0, 0.0, 0.0, 0.0,
+                                   0.0, 0.0, 0.0, 0.0,
+                                   0.0, 0.0, 0.0, 0.0,
+                                   0.0, 0.0, 0.0, 0.0);
+      SkinWeights::const_iterator swi;
+      for (swi = _skin_weights.begin(); swi != _skin_weights.end(); ++swi) {
+        const SkinWeightsData &data = (*swi);
+        WeightMap::const_iterator wmi = data._weight_map.find(vertex_index);
+        if (wmi != data._weight_map.end()) {
+          EggGroup *joint = converter->find_joint(data._joint_name);
+          if (joint != (EggGroup *)NULL) {
+            double weight = (*wmi).second;
+            LMatrix4d mat = LCAST(double, data._matrix_offset);
+            mat *= joint->get_node_to_vertex();
+            weighted_transform += mat * weight;
+            net_weight += weight;
+          }
+        }
+      }
+
+      if (net_weight == 0.0) {
+        // The vertex had no joint membership.  Transform it into the
+        // appropriate (global) space based on its parent.
+        temp_vtx.transform(_egg_parent->get_node_to_vertex());
+
+      } else {
+        // The vertex was skinned into one or more joints.  Therefore,
+        // transform it according to the blended matrix_offset from
+        // the skinning data.
+        weighted_transform /= net_weight;
+        temp_vtx.transform(weighted_transform);
+      }
 
 
       // Now get a real EggVertex matching our template.
       // Now get a real EggVertex matching our template.
       EggVertex *egg_vtx = vpool->create_unique_vertex(temp_vtx);
       EggVertex *egg_vtx = vpool->create_unique_vertex(temp_vtx);
@@ -352,8 +386,7 @@ create_polygons(XFileToEggConverter *converter) {
       const SkinWeightsData &data = (*swi);
       const SkinWeightsData &data = (*swi);
       WeightMap::const_iterator wmi = data._weight_map.find(vertex_index);
       WeightMap::const_iterator wmi = data._weight_map.find(vertex_index);
       if (wmi != data._weight_map.end()) {
       if (wmi != data._weight_map.end()) {
-        EggGroup *joint = converter->find_joint(data._joint_name,
-                                                data._matrix_offset);
+        EggGroup *joint = converter->find_joint(data._joint_name);
         if (joint != (EggGroup *)NULL) {
         if (joint != (EggGroup *)NULL) {
           double weight = (*wmi).second;
           double weight = (*wmi).second;
           joint->ref_vertex(egg_vtx, weight);
           joint->ref_vertex(egg_vtx, weight);