kni*_*666 13 c++ math skinning matrix collada
我正在编写自己的COLLADA导入器.我已经相当远,加载网格和材料等.但我在动画方面遇到了障碍,特别是联合轮换.
我用来为我的网格蒙皮的公式是直截了当的:
weighted;
for (i = 0; i < joint_influences; i++)
{
weighted +=
joint[joint_index[i]]->parent->local_matrix *
joint[joint_index[i]]->local_matrix *
skin->inverse_bind_pose[joint_index[i]] *
position *
skin->weight[j];
}
position = weighted;
Run Code Online (Sandbox Code Playgroud)
就文献而言,这是正确的公式.现在,COLLADA为关节指定了两种类型的旋转:局部和全局.您必须将旋转连接在一起以获得关节的局部变换.
COLLADA文档没有区分的是联合的局部轮换和联合的全局轮换.但在我见过的大多数模型中,旋转可以具有rotate(全局)或jointOrient(本地)的id .
当我忽略全局旋转并仅使用本地旋转时,我得到了模型的绑定姿势.但是当我将全局旋转添加到关节的局部转换时,奇怪的事情开始发生.
这不使用全局轮换:

这是全球轮换:

在这两个截图中,我使用线条绘制骨架,但在第一个中它是不可见的,因为关节位于网格内部.在第二个屏幕截图中,顶点到处都是!
为了比较,这是第二个截图应该是这样的:

很难看到,但你可以看到第二个屏幕截图中的关节处于正确的位置.
但现在奇怪的是.如果我忽略了COLLADA指定的反向绑定姿势,而是采用关节的父本地变换的倒数乘以关节的局部变换,我得到以下结果:

在这个截图中,我从每个顶点到有影响的关节画一条线.我得到绑定姿势的事实并不那么奇怪,因为现在公式变为:
world_matrix * inverse_world_matrix * position * weight
Run Code Online (Sandbox Code Playgroud)
但它让我怀疑COLLADA的反向绑定姿势是在错误的空间.
所以我的问题是:COLLADA在什么空间指定其反向绑定姿势?如何将逆绑定姿势转换为我需要的空间?
kni*_*666 12
我首先将我的值与我从Assimp(开源模型加载器)中读取的值进行比较.单步执行代码,我查看了它们构建绑定矩阵和反向绑定矩阵的位置.
最终我最终进入了SceneAnimator::GetBoneMatrices,其中包含以下内容:
// Bone matrices transform from mesh coordinates in bind pose to mesh coordinates in skinned pose
// Therefore the formula is offsetMatrix * currentGlobalTransform * inverseCurrentMeshTransform
for( size_t a = 0; a < mesh->mNumBones; ++a)
{
const aiBone* bone = mesh->mBones[a];
const aiMatrix4x4& currentGlobalTransform
= GetGlobalTransform( mBoneNodesByName[ bone->mName.data ]);
mTransforms[a] = globalInverseMeshTransform * currentGlobalTransform * bone->mOffsetMatrix;
}
Run Code Online (Sandbox Code Playgroud)
globalInverseMeshTransform永远是身份,因为网格不会转换任何东西.currentGlobalTransform是绑定矩阵,关节的父节点的局部矩阵与关节的局部矩阵连接在一起.并且mOffsetMatrix是反向绑定矩阵,它直接来自皮肤.
我检查了这些矩阵的值到我自己(哦,是的,我在观察窗口比较它们)和它们完全相同,可能是0.0001%,但这是微不足道的.那么,为什么Assimp的版本能够正常运行,而我的版本虽然公式是相同的但仍然没有?
这是我得到的:

当Assimp最终将矩阵上传到蒙皮着色器时,它们会执行以下操作:
helper->piEffect->SetMatrixTransposeArray( "gBoneMatrix", (D3DXMATRIX*)matrices, 60);
Run Code Online (Sandbox Code Playgroud)
Waaaaait一秒钟.他们上传到换位?这可不容易.没门.

对.
还有别的我做错了:在应用蒙皮矩阵之前,我正在将坐标转换成正确的系统(厘米到米).这导致完全失真的模型,因为矩阵是为原始坐标系设计的.
未来的高层建筑
完成!