john_connor

06-03-2017, 12:20 PM

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:

1. a "joint" (or "bone") has a offset matrix, it transforms from mesh space to "bind pose"

2. 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 (http://ogldev.atspace.co.uk/www/tutorial38/tutorial38.html) is simply not transpaerent enough for me :()

i appreciate every advice !!

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:

1. a "joint" (or "bone") has a offset matrix, it transforms from mesh space to "bind pose"

2. 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 (http://ogldev.atspace.co.uk/www/tutorial38/tutorial38.html) is simply not transpaerent enough for me :()

i appreciate every advice !!