mcmonkey4eva
mcmonkey4eva

Reputation: 1377

Skeletal Animation in OpenGL (GLSL) with Assimp

I am trying to implement GLSL-powered skeletal animation in a program... and rather than beautiful 3D animation, I've created a monster: https://i.sstatic.net/iPkN6.gif

After trying a few different techniques, I created a less terrifying but still monstrous thing:

Monster

The model is a basic human in a suit, the animation is supposed to be the leg swinging while all else stays still (a very simple test animation). All bones have static keyframes at t=0 in their original locations in an attempt to minimize them jumping out of place every few seconds.

The problem... should be fairly visible. Also, I'm fairly sure the model is taller than it's supposed to be.

Anyway, this was my original Vertex Shader:

#version 430 core
layout (location = 0) in vec4 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec2 texcoords;
layout (location = 3) in vec4 color;
layout (location = 4) in vec4 Weights;
layout (location = 5) in vec4 BoneID;
layout (location = 0) out vec4 f_position;
layout (location = 1) out vec3 f_normal;
layout (location = 2) out vec2 f_texcoord;
const int MAX_BONES = 50;
layout (location = 1) uniform mat4 proj_matrix;
layout (location = 2) uniform mat4 mv_matrix;
layout (location = 6) uniform mat4 boneTrans[MAX_BONES];
void main(void)
{
mat4 boneTransform = (boneTrans[int(BoneID[0])] * Weights[0]) +
(boneTrans[int(BoneID[1])] * Weights[1]) +
(boneTrans[int(BoneID[2])] * Weights[2]) +
(boneTrans[int(BoneID[3])] * Weights[3]);
float rem = 1 - (Weights[0] + Weights[1] + Weights[2] + Weights[3]);
boneTransform += mat4(1.0) * rem;
f_texcoord = texcoords;
f_position = mv_matrix * (boneTransform * position);
mat4 mv_mat_simple = mv_matrix;
mv_mat_simple[3][0] = 0.0;
mv_mat_simple[3][1] = 0.0;
mv_mat_simple[3][2] = 0.0;
vec4 norm1 = boneTransform * vec4(normal, 1.0);
vec4 nnormal = mv_mat_simple * vec4(norm1.xyz, 1.0);
f_normal = nnormal.xyz / nnormal.w; // TODO: Normalize?
vec4 pos1 = boneTransform * position;
gl_Position = proj_matrix * mv_matrix * vec4(pos1.xyz, 1.0);
}

and this is my new one:

#version 430 core

layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec2 texcoords;
layout (location = 3) in vec4 color;
layout (location = 4) in vec4 Weights;
layout (location = 5) in vec4 BoneID;

layout (location = 0) out vec4 f_position;
layout (location = 1) out vec3 f_normal;
layout (location = 2) out vec2 f_texcoord;

const int MAX_BONES = 50;

layout (location = 1) uniform mat4 proj_matrix;
layout (location = 2) uniform mat4 mv_matrix;
layout (location = 6) uniform mat4 boneTrans[MAX_BONES];

void main(void)
{
    vec4 pos1 = vec4(position, 1.0);
    pos1 += (boneTrans[int(BoneID[0])] * vec4(position, 0.0)) * Weights[0];
    pos1 += (boneTrans[int(BoneID[1])] * vec4(position, 0.0)) * Weights[1];
    pos1 += (boneTrans[int(BoneID[2])] * vec4(position, 0.0)) * Weights[2];
    pos1 += (boneTrans[int(BoneID[3])] * vec4(position, 0.0)) * Weights[3];
    vec4 norm1 = vec4(normal, 1.0);
    norm1 += (boneTrans[int(BoneID[0])] * vec4(normal, 0.0)) * Weights[0];
    norm1 += (boneTrans[int(BoneID[1])] * vec4(normal, 0.0)) * Weights[1];
    norm1 += (boneTrans[int(BoneID[2])] * vec4(normal, 0.0)) * Weights[2];
    norm1 += (boneTrans[int(BoneID[3])] * vec4(normal, 0.0)) * Weights[3];
    f_texcoord = texcoords;
    f_position = mv_matrix * vec4(pos1.xyz, 1.0);
    mat4 mv_mat_simple = mv_matrix;
    mv_mat_simple[3][0] = 0.0;
    mv_mat_simple[3][1] = 0.0;
    mv_mat_simple[3][2] = 0.0;
    //vec4 norm1 = boneTransform * vec4(normal, 1.0);
    vec4 nnormal = mv_mat_simple * vec4(norm1.xyz, 1.0);
    f_normal = nnormal.xyz / nnormal.w; // TODO: Normalize?
    gl_Position = proj_matrix * mv_matrix * vec4(pos1.xyz, 1.0);
}

The bone handling code is neither pretty nor short: http://pastebin.com/A8x1GdUw

That code and the original shader were derived from http://ogldev.atspace.co.uk/www/tutorial38/tutorial38.html

The new shader was derived from googling at random.

EDIT: I now get this:

Leg twisty twisty

With this code: http://pastebin.com/PvCWUdJn

Now... what am I doing wrong?! What's the "proper" method to handle this? Are there any higher-quality tutorials I should use in place of this one?

UPDATE: FULL SOURCE CODE FOR A TEST APP: https://github.com/mcmonkey4eva/skeletalanimationtest

Upvotes: 3

Views: 833

Answers (1)

mcmonkey4eva
mcmonkey4eva

Reputation: 1377

So the answer is simple - don't multiply matrix x vector, multiple vector x matrix in the shader.

Upvotes: 1

Related Questions