Sync it
Sync it

Reputation: 1198

opengl bone/joint animation formula

I am currently working on animating an model using joint's and vertex weight's. My question isn't program specific but GLSL based. In my shader I have the following info loaded

uniform mat4 projection,camera,model;
in vec3 vertex;

struct Joint
{
 mat4 invBind;
 mat4 global;
};
uniform Joint transforms[16];
in ivec4 jointIndices;
in vec4  weights;

Here Joint in an structure that is used to transform an vertex. It has 2 types of info

invBind:- this matrix is the inverse of an joint's local bind transform in global/model space which is used to transform the model from model space to local joint space

global:- this matrix is used to transform an vertex from an joint's local space to it's final global/model[or world] space

global=parent_global_joint_transform*joint_local_bind_transform. I have loaded my model from blender .dae file and so "joint_local_bind_transform" is transposed and then used

in ivec4 jointIndices:- is the list of all possible joint's that affect this vertex

in vec4 weights:- is the weight associated with the corresponding joint affecting this vertex

I have an array of size 16 of these joint's because there are that many joint's in my model

So with all this information how do we calculate gl_Position?. Is there more information that need's to be loaded as uniforms or as vertex attributes?. Sorry for my noobish question but many tutorial's don't give an straight forward answer.

An simple vertex shader code answer would be nice. Thank You

Upvotes: 0

Views: 784

Answers (1)

Nico Schertler
Nico Schertler

Reputation: 32587

Without any guarantee of correctness, something like the following should work for simple linear blend skinning. If it is not working directly, you should be able to understand what is going on and adapt accordingly:

//make a 4D vector from the vertex' position
vec4 position = vec4(vertex, 1.0);

//accumulate the final position
vec4 p = vec4(0, 0, 0, 0);
for(int i = 0; i < 4; ++i)
{
    Joint joint = transforms[jointIndices[i]];
    p += weights[i] * joint.global * joint.invBind * position;
}
gl_Position = p;

In the loop, you iterate all influencing bones. For every bone, you calculate the vertex' position in the bone's coordinate system and transform it back to the global coordinate system according to the bone's orientation in the current frame. Finally, you just blend the result for all influencing bones.

To reduce the amount of data you are transferring to the GPU, you can also precalculate joint.global * joint.invBind.

Upvotes: 1

Related Questions