我工作的一個項目搭建的網格骨頭已下列目標: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
,但沒有成功......
我希望有人可以幫我解決這個問題
在此先感謝
嗨。我認爲既計算GlobalTransformation和頂點蒙皮也是不正確的 你應該在calculateGlobalTransformation中使用偏移矩陣並且不應該在頂點蒙皮中使用 –
Hey Sergey,我很高興你回答。幾乎放棄了這個話題。自從我上一篇文章以來,我改變了兩件小事(矩陣乘法順序)。所以我已經更新了我的初始文章(請參閱'calculateGlobalTransformation'和頂點蒙皮代碼),它現在反映了我當前的代碼。我確定'GlobalTransform'的計算是正確的,因爲當在我的視口中顯示每個骨骼的GlobalTransform的轉換部分作爲點時,它會生成以下圖像:http://goo.gl/ncBSF4。所以我認爲這個問題是皮膚問題(例如'FinalTransform'錯誤)。 – wombat
在我的回答中,您可以看到骨骼的GlobalTransform的計算。 你不需要FinalTransform。您應該使用GlobalTransform來轉換頂點。 喜歡這個問題: 'resultVertexTransformation + = m_bonesGlobalTransforms [boneIdx] * boneWeight;' –