渲染在OpenGL中加载Assimp的动画模型时折叠的网格

时间:2018-04-03 08:36:57

标签: java animation opengl glsl assimp

所以我正在加载和渲染动画模型,我可以在静态位置渲染网格没问题,也可以用调试线绘制动画骨骼。

Here is a short video illustrating the issue.

正如您在视频中看到的那样,我已经正确显示了动画“棒图”。然而,网格顶部似乎只是部分正确显示。

正如标题中所提到的,我正在使用Assimp和OpenGL。

在我在场景中加载的事物的模型加载方面,遍历保持父子旋转的节点,识别骨骼节点并将骨骼信息添加到节点。

└───Scene
     ├───Camera
     ├───Armature
     │    └───Torso : [ ROOT_BONE ]
     │        ├───Chest : [ BONE ]
     │        │    ├───Neck : [ BONE ]
     │        │    │    └───Head : [ BONE ]
     │        │    ├───Upper_Arm_L : [ BONE ]
     │        │    │    └───Lower_Arm_L : [ BONE ]
     │        │    │        └───Hand_L : [ BONE ]
     │        │    └───Upper_Arm_R : [ BONE ]
     │        │        └───Lower_Arm_R : [ BONE ]
     │        │            └───Hand_R : [ BONE ]
     │        ├───Upper_Leg_L : [ BONE ]
     │        │    └───Lower_Leg_L : [ BONE ]
     │        │        └───Foot_L : [ BONE ]
     │        └───Upper_Leg_R : [ BONE ]
     │            └───Lower_Leg_R : [ BONE ]
     │                └───Foot_R : [ BONE ]
     └───Character: [ 1 MESH(ES) ]

这是我当前模型节点结构的一个示例。 每个节点都有一个变换矩阵,它们旁边的[ROOT_BONE] / [BONE]也包含一个偏移矩阵。

要渲染动画骨骼,我会在动画关键帧中读取,根据插值位置旋转和缩放值为每个“通道”(骨骼)构建矩阵。当我将动画矩阵相乘(基于父层次结构)时,我得到了世界空间中的骨骼/连接位置。(我似乎不需要知道任何节点变换矩阵或骨骼偏移矩阵来得到这个正确渲染。(只需将动画矩阵与其父动画矩阵相乘)

为了渲染网格,我尝试了一些东西,只使用动画中的矩阵得到的结果与上面显示的视频类似,但是躯干正躺在地面前面然而,调试骨架,手臂/腿仍然显示与视频相同。视频中显示的结果是通过将动画矩阵乘以各自的骨骼来实现的,然后将结果传递给顶点着色器。

uniform mat4 uModelViewProjection;
uniform mat4 uBones[100];

in vec4 aPosition;

in  vec4 aWeights;
in ivec4 aBoneIds;

void main(void) {
    mat4 skinMat =
    uBones[aBoneIds[0]] * aWeights[0] +
    uBones[aBoneIds[1]] * aWeights[1] +
    uBones[aBoneIds[2]] * aWeights[2] +
    uBones[aBoneIds[3]] * aWeights[3];

    gl_Position = uModelViewProjection * skinMat * aPosition;
}

以下是顶点着色器的相关代码。我在这里尝试了几种不同的方法,结果相同(或者在某些情况下更糟)。

我在看到奇怪的“倒塌”顶点后立即想到的一些事情可能是骨质矩阵没有正确传递,我确实记录了它们以确认它们确实被发送了,我还检查了着色器的统一位置处理以确保它们被正确找到。

我假设我错过了某个地方的某个步骤,或者只是在错误的顺序中找错了。我一直在为这个主题制作一个充满不同“教程”的手,但它们都很难遵循。 (代码遍布整个地方而没有最好的文档,我无法运行任何代码,因为所有示例都需要不同的语言/现有的框架,或者它只是简单的破解。)

其他信息:

  • 我目前正在尝试加载的模型是Collada(.dae)文件。
  • 我正在使用LWJGL绑定Assimp和OpenGL。

1 个答案:

答案 0 :(得分:1)

我终于弄明白了这个问题。在OpenGL着色器中使用ivec4(或任何其他i前缀数据类型)作为属性时,必须使用glVertexAttribIPointer而不是glVertexAttribPointer(请注意I)。如果不指定,缓冲区数据将作为浮动发送到GPU。