14

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

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

4

3 回答 3

10

让我们以这段代码为例,我用它来为我工作的游戏中的角色设置动画。我也使用 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正如教程Skeletal Animation with Assimp中提到的那样,或者正确地根节点scene->mRootNode->mTransformation的变换是从局部空间到全局空间的变换。举个例子,当在 3D 建模器中(例如选择 Blender)创建网格或加载角色时,它通常(默认情况下)位于笛卡尔平面的原点,并且其旋转设置为身份四元数。

但是,您可以将网格/角色从原点平移/旋转(0,0,0)到其他地方,并在单个场景中甚至具有不同位置的多个网格。当您加载它们时,特别是如果您执行骨骼动画,必须将它们转换回本地空间(即回到原点0,0,0),这就是您必须将所有内容乘以的原因InverseGlobal(这会将您的网格带回本地空间)。

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

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

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

希望能帮助到你。

于 2015-04-18T20:02:10.003 回答
1

正如我已经假设的那样,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循环。

本教程使用附加m_GlobalInverseTransformboneMatrix. 但是,我不知道他们为什么这样做。基本上,这会撤消整个场景的整体转换。可能它用于使模型在视图中居中。

于 2015-04-17T20:05:18.710 回答
1

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

Vertex Position<0, 1, 2>

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

如果我们在这种情况下将一个顶点乘以偏移矩阵,我们将得到一个 <-10, -1, 2> 的顶点位置。

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

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

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

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

anim_vertex = (offset_matrix * anim_matrix) * mesh_vertex

这有帮助吗?

于 2015-04-13T12:19:44.003 回答