hi everyone,
i’d like to know how to setup a skeletal animation, how to structure the necessary data practically. first, assimp gives me the data like this:
struct Bone {
mat4 offset;
vector<pair<int, float>> vertexweights;
};
struct Mesh {
vector<vec3> vertices;
vector<vec3> normals;
...
vector<Bone> Bones;
};
struct Scene {
vector<Mesh> meshes;
vector<Animation> animations;
...
};
i know how to extract the geometry so that i can draw the model without bones, for each mesh i create a “drawarrays” call. but there are several things to keep in mind:
- a “joint” (or “bone”) has a offset matrix, it transforms from mesh space to “bind pose”
- the order in which the joint matrices are multiplied is crucial
how i plan to do it: (vertex shader)
#version 450 core
/* uniform */
/****************************************************/
layout (std140, binding = 1) uniform StreamBuffer {
mat4 View;
mat4 Projection;
};
layout (std140, binding = 2) uniform BoneBuffer {
mat4 Bones[256];
};
layout (location = 0) uniform mat4 Model = mat4(1);
/****************************************************/
/* input */
/****************************************************/
layout (location = 0) in vec3 in_position;
layout (location = 1) in vec2 in_texcoord;
layout (location = 2) in vec3 in_normal;
layout (location = 3) in vec3 in_tangent;
layout (location = 4) in vec3 in_bitangent;
layout (location = 5) in uvec4 in_boneindices;
layout (location = 6) in vec4 in_boneweights;
/****************************************************/
/* output */
/****************************************************/
out VS_FS {
smooth vec3 position;
smooth vec2 texcoord;
smooth vec3 normal;
} vs_out;
/****************************************************/
mat4 Animation()
{
mat4 animation = mat4(0);
vec4 weights = normalize(in_boneweights);
for (uint i = 0; i < 4; i++)
animation += Bones[in_boneindices[i]] * weights[i];
return animation;
}
void main()
{
mat4 Transformation = Model;// * Animation();
mat4 MVP = Projection * View * Transformation;
gl_Position = MVP * vec4(in_position, 1);
vs_out.position = (Transformation * vec4(in_position, 1)).xyz;
vs_out.texcoord = in_texcoord;
vs_out.normal = (Transformation * vec4(in_normal, 0)).xyz;
}
so i need to send up to 4 references to joint matrices up to the vertexshader.
if a vertex need less than 4 joint matrices, then i’ll fill the rest with a reference to the very first joint matrix which is by default mat4(1) –> to eliminate undesired effects (as a fallback). i a vertex needs more then 4 joint matrix references, then … what ?
how to build these attribute data ?
vector<vector<unsigned int> indices_lists(vertexcount);
vector<vector<float>> weights_lists(vertexcount);
for (each bone of this mesh)
–> fill both arrays:
each array element belongs to e certain vertex, and is an array of needed joint references (index to uniform joint matrix + weight)
is this the “usual way” to do this or am i thinking a little too simple/complicated/weird ? :doh:
assuming thats rihgt, the next thing is to KEEP THE JOINT MATRIX ORDER, that means i have to rebuild these 2 arrays (of arrays of references to joints): how ?
i guess that i just have to sort the indices (to uniform joint matrices) ascending, and BEFORE that i recursively go through the scene node tree and add needed “bones” BEFORE i add their needed children (if any) … correct, or wrong ?
when done, and assuming thats correct (?), what data to i need on the cpu-side?
– joint offset matrix array
– array of the same size of type mat4, containing computed joint matrices (i have to send as uniform block)
– animations
when computing animations, how to compute the mat4s ?
for each animation
– for each “channel” (affecting exact 1 joint)
---- uniformJoints[…certain.index…] = jointOffsetMatrix[…certain.index…] * interpolatedKeys
… where “interpolatedKeys” are pairs of vec3 location / quat rotation / vec3 scale
is this how its done ?
(i’ve searched for simple examples, could find anything [including model file] that is understandable … this one is simply not transpaerent enough for me :()
i appreciate every advice !!