2016-01-13 66 views
0

我工作的一个项目搭建的网格骨头已下列目标:Assimp:操纵手动

  • 负载操纵三维网格(如人的骨骼)与Assimp.NET
  • 操纵网格的骨头这么它适合你自己的身体(与微软Kinect V2)
  • 执行顶点剥皮

加载着装网和提取没有任何问题(根据本教程骨信息工程(希望): http://www.richardssoftware.net/2013/10/skinned-models-in-directx-11-with.html)。每个骨(类 “ModelBone”)包括如下信息:

Assimp.Matrix4x4 LocalTransform 
Assimp.Matrix4x4 GlobalTransform 
Assimp.Matrix4x4 Offset 

LocalTransform直接从assimp节点(node.Transform)萃取。

GlobalTransform包括自己的LocalTransform和所有父母的LocalTransform(查看代码剪辑calculateGlobalTransformation())。

Offset直接从assimp骨提取(bone.OffsetMatrix)。

目前我没有实现GPU顶点蒙皮,但我遍历每个顶点并操纵它的位置和法向量。

 foreach (Vertex vertex in this.Vertices) 
     { 
      Vector3D newPosition = new Vector3D(); 
      Vector3D newNormal = new Vector3D(); 

      for (int i=0; i < vertex.boneIndices.Length; i++) 
      { 
       int boneIndex = vertex.boneIndices[i]; 
       float boneWeight = vertex.boneWeights[i]; 

       ModelBone bone = this.BoneHierarchy.Bones[boneIndex]; 

       Matrix4x4 finalTransform = bone.GlobalTransform * bone.Offset; 

       // Calculate new vertex position and normal 
       newPosition += boneWeight * (finalTransform * vertex.originalPosition); 
       newNormal += boneWeight * (finalTransform * vertex.originalNormal); 
      } 

      // Apply new vertex position and normal 
      vertex.position = newPosition; 
      vertex.normal = newNormal; 
     } 

就像我已经说过的,我想操纵与Kinect的传感器V2的骨头,所以我不会用动画(如关键帧插值,...)!但是一开始我希望能够手动操作骨骼(例如,将网格的躯干旋转90度)。因此我通过调用Assimp.Matrix4x4.FromRotationX(1.5708f);创建一个4x4旋转矩阵(围绕x轴90度)。然后,我取代骨中的LocalTransform这个旋转矩阵:

Assimp.Matrix4x4 rotation = Assimp.Matrix4x4.FromRotationX(1.5708f); 
bone.LocalTransform = rotation; 

UpdateTransformations(bone); 

我用下面的代码来计算骨的新GlobalTransform骨操作后,它的孩子骨骼:

public void UpdateTransformations(ModelBone bone) 
    { 
     this.calculateGlobalTransformation(bone); 

     foreach (var child in bone.Children) 
     { 
      UpdateTransformations(child); 
     } 
    } 

    private void calculateGlobalTransformation(ModelBone bone) 
    { 
     // Global transformation includes own local transformation ... 
     bone.GlobalTransform = bone.LocalTransform; 

     ModelBone parent = bone.Parent; 

     while (parent != null) 
     { 
      // ... and all local transformations of the parent bones (recursively) 
      bone.GlobalTransform = parent.LocalTransform * bone.GlobalTransform; 
      parent = parent.Parent; 
     } 
    } 

这种做法的结果这image。该转换似乎正确地应用于所有儿童骨骼,但被操纵的骨骼围绕世界空间原点旋转,而不是围绕其自身的局部空间:(我已经尝试将GlobalTransform翻译(GlobalTransform的最后一行)包括到旋转矩阵中它设置为LocalTransform,但没有成功......

我希望有人可以帮我解决这个问题

在此先感谢

回答

0

最后我找到了解决办法:)所有的计算是正确的除外:

Matrix4x4 finalTransform = bone.GlobalTransform * bone.Offset; 

对我来说,正确的计算方法是:

Matrix4x4 finalTransform = bone.GlobalTransform * bone.Offset; 
finalTransform.transpose(); 

所以它似乎是一个行 - 主要/列 - 主要问题。我的最终CPU顶点蒙皮代码是:

public void PerformSmoothVertexSkinning() 
    { 
     // Precompute final transformation matrix for each bone 
     List<Matrix4x4> FinalTransforms = new List<Matrix4x4>(); 

     foreach (ModelBone bone in this.BoneHierarchy.Bones) 
     { 
      // Multiplying a vector (e.g. vertex position/normal) by finalTransform will (from right to left): 
      //  1. transform the vector from mesh space to bone space (by bone.Offset) 
      //  2. transform the vector from bone space to world space (by bone.GlobalTransform) 
      Matrix4x4 finalTransform = bone.GlobalTransform * bone.Offset; 
      finalTransform.Transpose(); 

      FinalTransforms.Add(finalTransform); 
     } 

     foreach (Submesh submesh in this.Submeshes) 
     { 
      foreach (Vertex vertex in submesh.Vertices) 
      { 
       Vector3D newPosition = new Vector3D(); 
       Vector3D newNormal = new Vector3D(); 

       for (int i = 0; i < vertex.BoneIndices.Length; i++) 
       { 
        int boneIndex = vertex.BoneIndices[i]; 
        float boneWeight = vertex.BoneWeights[i]; 

        // Get final transformation matrix to transform each vertex position 
        Matrix4x4 finalVertexTransform = FinalTransforms[boneIndex]; 

        // Get final transformation matrix to transform each vertex normal (has to be inverted and transposed!) 
        Matrix4x4 finalNormalTransform = FinalTransforms[boneIndex]; 
        finalNormalTransform.Inverse(); 
        finalNormalTransform.Transpose(); 

        // Calculate new vertex position and normal (average of influencing bones) 
        // Formula: newPosition += boneWeight * (finalVertexTransform * vertex.OriginalPosition); 
        //      += boneWeight * (bone.GlobalTransform * bone.Offset * vertex.OriginalPosition); 
        // From right to left: 
        //  1. Transform vertex position from mesh space to bone space (by bone.Offset) 
        //  2. Transform vertex position from bone space to world space (by bone.GlobalTransform) 
        //  3. Apply bone weight 
        newPosition += boneWeight * (finalVertexTransform * vertex.OriginalPosition); 
        newNormal += boneWeight * (finalNormalTransform * vertex.OriginalNormal); 
       } 

       // Apply new vertex position and normal 
       vertex.Position = newPosition; 
       vertex.Normal = newNormal; 
      } 
     } 
    } 

希望这个线程对其他人有帮助。感谢您的帮助谢尔盖!

0

要改变你应该使用它的偏移矩阵骨:! http://assimp.sourceforge.net/lib_html/structai_bone.html#a9ae5293b5c937436e4b338e20221cc2e 偏移矩阵从全局变换步入骨骼空间。如果你想旋转骨围绕它的起源,你应该:

  1. 转化为骨空间
  2. 应用旋转
  3. 转化为

所以骨骼的全球变换可以这样来计算的全球空间:

bonesGlobalTransform = parentGlobalTransform * 
     bone.offset.inverse() * 
     boneLocalTransform * 
     bone.offset; 

所以:

  1. 转化为骨空间偏移矩阵
  2. 应用本地变换
  3. 转变为全球空间offset.inverse()矩阵
+0

嗨。我认为既计算GlobalTransformation和顶点蒙皮也是不正确的 你应该在calculateGlobalTransformation中使用偏移矩阵并且不应该在顶点蒙皮中使用 –

+0

Hey Sergey,我很高兴你回答。几乎放弃了这个话题。自从我上一篇文章以来,我改变了两件小事(矩阵乘法顺序)。所以我已经更新了我的初始文章(请参阅'calculateGlobalTransformation'和顶点蒙皮代码),它现在反映了我当前的代码。我确定'GlobalTransform'的计算是正确的,因为当在我的视口中显示每个骨骼的GlobalTransform的转换部分作为点时,它会生成以下图像:http://goo.gl/ncBSF4。所以我认为这个问题是皮肤问题(例如'FinalTransform'错误)。 – wombat

+0

在我的回答中,您可以看到骨骼的GlobalTransform的计算。 你不需要FinalTransform。您应该使用GlobalTransform来转换顶点。 喜欢这个问题: 'resultVertexTransformation + = m_bonesGlobalTransforms [boneIdx] * boneWeight;' –