我工作的一个项目搭建的网格骨头已下列目标: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;' –