COLLADA:反向绑定姿势错误的空间?

(来自StackOverflow的Crosspost)

我正在写我自己的COLLADAimport商。 我已经相当的远,加载网格和材料等。 但是我在animation方面遇到了困难,特别是:联合轮换。

我用来剥皮网格的公式非常简单:

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; 

就文学而言,这是正确的公式。 现在,COLLADA为关节指定了两种types的旋转:局部和全局。 您必须将旋转连接在一起以获得关节的局部变换。

COLLADA文件没有区分的是联合的地方轮换和联合的全球轮换。 但在我见过的大多数模型中,旋转可以有rotate (全局)或jointOrient (本地)的id。

当我忽视全球轮换,只使用本地的轮回,我得到了模型的绑定姿势。 但是,当我把这个全球轮换join联合的地方转型时,奇怪的事情就开始发生了。

这是没有使用全球轮换:

绑定姿势

这是与全球轮换:

奇怪的

在这两个截图中,我使用线条绘制骨骼,但首先它是不可见的,因为关节在网格内。 在第二个屏幕截图中,顶点遍布整个地方!

为了比较,这是第二个截图应该是这样的:

Collada查看器

很难看,但你可以看到,在第二个截图的关节是在正确的位置。

但现在奇怪的事情。 如果我不考虑COLLADA指定的反向绑定姿态,而是将关节的本地变换的倒数乘以关节的局部变换,我得到以下结果:

在这里输入图像描述

在这个截图中,我画了一条从每个顶点到有影响的关节的线。 我得到绑定姿势的事实并不奇怪,因为公式现在变成了:

 world_matrix * inverse_world_matrix * position * weight 

但是这让我怀疑COLLADA的反绑定姿态是错误的。

所以我的问题是:在什么空间COLLADA指定其反向绑定的姿势? 而且我怎样才能把反向绑定姿态转换成我需要的空间呢?

我开始通过比较我从Assimp(一个开源的模型加载器)读取的值。 通过代码,我看着他们在哪里建立绑定matrix和反向绑定matrix。

最终我结束了在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; } 

globalInverseMeshTransform始终是标识,因为网格不会转换任何东西。 currentGlobalTransform是绑定matrix,是关节的父本地matrix与关节的局部matrix连接在一起的。 而mOffsetMatrix是反向绑定matrix,它直接来自皮肤。

我检查了这些matrix的价值是否属于我自己的(哦,是的,我把它们在一个观察窗口中进行了比较),它们是完全一样的,可能是0.0001%,但这是微不足道的。 那么为什么Assimp的版本和我的版本不一样呢?

这是我得到的:

倒!

当Assimp最后将matrix上传到外观着色器时,它们执行以下操作:

 helper->piEffect->SetMatrixTransposeArray( "gBoneMatrix", (D3DXMATRIX*)matrices, 60); 

等一下 他们上传他们转置 ? 这不可能那么容易。 没门。

在这里输入图像描述

对。

还有一些我做错了: 应用蒙皮matrix之前,我正在将坐标转换为正确的系统(厘米为米)。 这导致完全扭曲的模型,因为matrix是为原始坐标系devise的。

未来的GOOGLERS

  • 按照接收到的顺序读取所有节点转换(旋转,平移,缩放等)。
  • 将它们连接到联合的本地matrix
  • 取关节的父母,并将其与本地matrix相乘。
  • 将其存储为绑定matrix
  • 阅读皮肤信息。
  • 存储关节的反绑定姿态matrix
  • 存储每个顶点的联合权重
  • 绑定matrix逆绑定姿态matrix相乘转置它 ,称之为剥皮matrix
  • 皮肤matrix乘以位置乘以关节重量并将其添加到加权位置
  • 使用加权位置进行渲染。

完成!