The way I'm doing things right now is:
For static meshes, I calculate a "toRootTransformation" 4x4 matrix for every node, based on the hierarchy of the nodes. Then for every node that contains a mesh, I render the mesh with a shader looking like this:
#version 430
uniform mat4 ProjectionMatrix;
uniform mat4 CameraMatrix;
uniform mat4 ModelMatrix;
layout(location = 0) in vec3 vertex;
layout(location = 1) in vec2 uvs;
layout(location = 2) in vec3 normal;
out vec2 fsUvs;
out vec3 fsNormal;
void main()
{
gl_Position = ProjectionMatrix * CameraMatrix * ModelMatrix * vec4(vertex, 1.0);
fsUvs = uvs;
fsNormal = normal;
}
Before that I set the ModelMatrix uniform to that toRootTransformation.
For skinning, I upload the bone matrix array uniform to the shader, calculate each vertex position based on it, and multiply by the same "toRootTransformation" as before.
Here's the main part of the vertex shader:
void main()
{
vec4 final = vec4(0);
for(int i = 0; i < NUM_INFLUENCE_BONES; i++)
{
vec4 v = Bones[boneIndices[i]] * vec4(vertex, 1.0) * vertexWeights[i];
final += v;
}
gl_Position = ProjectionMatrix * CameraMatrix * ModelMatrix * final;
}
Every bone matrix is a multiplication of the bone's inverseBindPos matrix and the matrix that is the product of all the rotations/translations of the bone at the current time, based on the node hierarchy. In code:
void Bone::calculateFinalMatrix() { //matrix for the shader
_finalMatrix = _animationMatrix * _inverseBindPosMatrix; //_animationMatrix is already calculated by AnimationController
}
To be honest this is the product of like a week of struggling to get skinning done, and I'm not sure if I'm doing it right. (please correct me if not)
The question that I ask myself is why do I need to multiply each bone by the inverseBindPos first. It transforms each vertex from world to local space, before multiplying by the animation matrix. But the thing is that the vertex isn't in world space to begin with, but in local space. So basically we're going from local space to local space (then animating) which doesn't make sense.