gpu蒙皮的矩阵计算



我正尝试在OpenGL中使用Assimp作为我的模型导入库来制作骨骼动画。

对于骨骼的offsetMatrix变量,我到底需要什么?我需要把它乘以什么?

让我们以这段代码为例,我在工作的一个游戏中用它来制作角色的动画。我也使用了Assimp来加载骨骼信息,并阅读了Nico已经指出的OGL教程。

glm::mat4 getParentTransform()
{
if (this->parent)
return parent->nodeTransform;
else 
return glm::mat4(1.0f);
}
void updateSkeleton(Bone* bone = NULL)
{ 
bone->nodeTransform =  bone->getParentTransform() // This retrieve the transformation one level above in the tree
* bone->transform //bone->transform is the assimp matrix assimp_node->mTransformation
* bone->localTransform;  //this is your T * R matrix
bone->finalTransform = inverseGlobal // which is scene->mRootNode->mTransformation from assimp
* bone->nodeTransform  //defined above
* bone->boneOffset;  //which is ai_mesh->mBones[i]->mOffsetMatrix

for (int i = 0; i < bone->children.size(); i++) {
updateSkeleton (&bone->children[i]);
}
}

从本质上讲,GlobalTransform(如教程"使用Assimp的骨骼动画"中所述),或者正确地说,根节点scene->mRootNode->mTransformation的变换是从局部空间到全局空间的变换。举个例子,当在三维建模器(例如,让我们选择Blender)中创建网格或加载角色时,它通常位于(默认情况下)笛卡尔平面的原点,并且其旋转设置为单位四元数。

但是,您可以将网格/角色从原点(0,0,0)平移/旋转到其他位置,并在单个场景中甚至具有多个不同位置的网格。加载它们时,尤其是在执行骨骼动画时,必须将它们平移回局部空间(即,平移回原点0,0,0),这就是为什么必须将所有内容乘以InverseGlobal(这将使网格返回到局部空间)的原因。

之后,您需要将其乘以节点变换,该变换是parentTransform(树中一级以上的变换,这是整体变换)、transform(以前的assimp_node->mTransformation,它只是骨骼相对于节点父对象的变换)和您要应用的局部变换(任何T*R)的乘积:正向运动学,反向运动学插值或关键帧插值。

最后是boneOffset(ai_mesh->mBones[i]->mOffsetMatrix),它在绑定姿势下从网格空间转换到骨骼空间,如文档中所述。

如果你想查看我的Skeleton类的整个代码,这里有一个指向GitHub的链接。

希望能有所帮助。

偏移矩阵定义了在网格空间中变换顶点的变换(平移、缩放、旋转),并将其转换为"骨骼"空间。例如,考虑以下顶点和具有以下特性的骨骼;

Vertex Position<0, 1, 2>
Bone Position<10, 2, 4>
Bone Rotation<0,0,0,1>  // Note - no rotation
Bone Scale<1, 1, 1>

在这种情况下,如果我们将顶点乘以偏移矩阵,我们将得到&lt-10,-1,2>。

我们如何使用它?关于如何使用这个矩阵,您有两个选项,这取决于我们如何将顶点数据存储在顶点缓冲区中。选项包括:;

1) 将网格顶点存储在网格空间中2) 将网格顶点存储在骨骼空间中

在#1的情况下,我们将获取offsetMatrix,并在构建顶点缓冲区时将其应用于受骨骼影响的顶点。然后,当我们为网格设置动画时,我们稍后会为该骨骼应用动画矩阵。

在#2的情况下,当转换存储在顶点缓冲区中的顶点时,我们将使用offsetMatrix与该骨骼的动画矩阵相结合。所以它可能是这样的(注意:您可能需要在这里切换矩阵连接);

anim_vertex = (offset_matrix * anim_matrix) * mesh_vertex

这有帮助吗?

正如我已经假设的,mOffsetMatrix是反绑定姿态矩阵。本教程介绍了线性混合蒙皮所需的正确变换:

首先需要评估动画状态。这将为每个骨骼提供从动画骨骼空间到世界空间的系统变换(教程中的GlobalTransformation)。mOffsetMatrix是从世界空间到绑定姿势骨骼空间的系统变换。因此,蒙皮操作如下(假设特定顶点受单个骨骼的影响):使用mOffsetMatrix变换顶点到骨骼空间。现在假设一个动画骨骼,并将中间结果从动画骨骼空间变换回世界空间。因此:

boneMatrix[i] = animationMatrix[i] * mOffsetMatrix[i]

如果顶点受到多个骨骼的影响,LBS只需对结果取平均值。这就是重量发挥作用的地方。蒙皮通常在顶点着色器中实现:

vec4 result = vec4(0);
for each influencing bone i
result += weight[i] * boneMatrix[i] * vertexPos;

通常,影响骨骼的最大数量是固定的,您可以展开for循环。

本教程为boneMatrix使用了一个附加的m_GlobalInverseTransform。然而,我不知道他们为什么这么做。基本上,这会取消整个场景的整体变换。它可能用于使模型在视图中居中。

相关内容

  • 没有找到相关文章

最新更新