Implement basic keyframe-per-frame animation
This commit is contained in:
1 parent
2a603dc364
commit
4c94812b48
3 files changed
+40
-53
No files matched your search
+23
-11
@@ -1,26 +1,26 @@
|
|||||||
#include "animation.h"
|
#include "animation.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
static mat4_t bone_transform(bone_t bone)
|
static mat4_t bone_transform(bone_t bone)
|
||||||
{
|
{
|
||||||
return mat4_mul(
|
return mat4_mul(
|
||||||
mat4_translate_vec3(bone.translation),
|
mat4_translate_vec3(bone.translation),
|
||||||
mat4_mul(
|
mat4_rotate_quaternion(bone.rotation));
|
||||||
mat4_rotate_quaternion(bone.rotation),
|
|
||||||
mat4_scale_vec3(bone.scale)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void compute_bone_matrices(
|
static void compute_bone_matrices(
|
||||||
size_t bone_count, const bone_t *bones,
|
const bone_t *bones, size_t bone_count, const uint32_t *bone_parents,
|
||||||
const mat4_t *inverse_bind_matrices, mat4_t *matrices)
|
const mat4_t *inverse_bind_matrices, mat4_t *matrices)
|
||||||
{
|
{
|
||||||
matrices[0] = bone_transform(bones[0]);
|
matrices[0] = bone_transform(bones[0]);
|
||||||
for (unsigned i = 1; i < bone_count; ++i) {
|
for (unsigned i = 1; i < bone_count; ++i) {
|
||||||
const mat4_t transform = bone_transform(bones[i]);
|
const mat4_t transform = bone_transform(bones[i]);
|
||||||
assert(bones[i].parent < bone_count);
|
const uint32_t parent = bone_parents[i];
|
||||||
matrices[i] = mat4_mul(matrices[bones[i].parent], transform);
|
assert(parent < bone_count);
|
||||||
|
matrices[i] = mat4_mul(matrices[parent], transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned i = 0; i < bone_count; ++i)
|
for (unsigned i = 0; i < bone_count; ++i)
|
||||||
@@ -29,7 +29,7 @@ static void compute_bone_matrices(
|
|||||||
|
|
||||||
animation_state_t animation_init(const model_t *model)
|
animation_state_t animation_init(const model_t *model)
|
||||||
{
|
{
|
||||||
mat4_t *bone_matrices = calloc(model->bone_count, sizeof(mat4_t));
|
mat4_t *bone_matrices = malloc(model->bone_count * sizeof(mat4_t));
|
||||||
assert(bone_matrices != nullptr);
|
assert(bone_matrices != nullptr);
|
||||||
return (animation_state_t) { .bone_matrices = bone_matrices };
|
return (animation_state_t) { .bone_matrices = bone_matrices };
|
||||||
}
|
}
|
||||||
@@ -42,9 +42,21 @@ void animation_cleanup(animation_state_t *state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void animation_update(animation_state_t state, const model_t *model)
|
void animation_start(animation_state_t *state, const model_t *model)
|
||||||
{
|
{
|
||||||
compute_bone_matrices(
|
state->current = model->bones;
|
||||||
model->bone_count, model->bones, model->inverse_bind_matrices,
|
}
|
||||||
state.bone_matrices);
|
|
||||||
|
void animation_update(animation_state_t *state, const model_t *model)
|
||||||
|
{
|
||||||
|
const size_t offset = state->keyframe * model->bone_count;
|
||||||
|
state->current = model->animation.keyframes + offset;
|
||||||
|
|
||||||
|
compute_bone_matrices(
|
||||||
|
state->current, model->bone_count, model->bone_parents,
|
||||||
|
model->inverse_bind_matrices, state->bone_matrices);
|
||||||
|
|
||||||
|
++state->keyframe;
|
||||||
|
if (state->keyframe >= model->animation.keyframe_count)
|
||||||
|
state->keyframe = 0;
|
||||||
}
|
}
|
||||||
+4
-1
@@ -5,11 +5,14 @@
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
mat4_t *bone_matrices;
|
mat4_t *bone_matrices;
|
||||||
|
bone_t *current;
|
||||||
|
unsigned keyframe;
|
||||||
} animation_state_t;
|
} animation_state_t;
|
||||||
|
|
||||||
animation_state_t animation_init(const model_t *model);
|
animation_state_t animation_init(const model_t *model);
|
||||||
void animation_cleanup(animation_state_t *state);
|
void animation_cleanup(animation_state_t *state);
|
||||||
|
|
||||||
void animation_update(animation_state_t state, const model_t *model);
|
void animation_start(animation_state_t *state, const model_t *model);
|
||||||
|
void animation_update(animation_state_t *state, const model_t *model);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -10,14 +10,6 @@
|
|||||||
#define W 800
|
#define W 800
|
||||||
#define H 600
|
#define H 600
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
AXIS_X,
|
|
||||||
AXIS_Y,
|
|
||||||
AXIS_Z,
|
|
||||||
} axis_t;
|
|
||||||
|
|
||||||
static axis_t rot_axis = AXIS_Y;
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
key_callback(GLFWwindow *window, int key, int scancode, int action, int mods)
|
key_callback(GLFWwindow *window, int key, int scancode, int action, int mods)
|
||||||
{
|
{
|
||||||
@@ -32,16 +24,6 @@ key_callback(GLFWwindow *window, int key, int scancode, int action, int mods)
|
|||||||
case GLFW_KEY_Q:
|
case GLFW_KEY_Q:
|
||||||
glfwSetWindowShouldClose(window, GL_TRUE);
|
glfwSetWindowShouldClose(window, GL_TRUE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GLFW_KEY_X:
|
|
||||||
rot_axis = AXIS_X;
|
|
||||||
break;
|
|
||||||
case GLFW_KEY_Y:
|
|
||||||
rot_axis = AXIS_Y;
|
|
||||||
break;
|
|
||||||
case GLFW_KEY_Z:
|
|
||||||
rot_axis = AXIS_Z;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,40 +56,30 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
// Initialise animation
|
// Initialise animation
|
||||||
animation_state_t anim = animation_init(&model);
|
animation_state_t anim = animation_init(&model);
|
||||||
animation_update(anim, &model);
|
|
||||||
|
|
||||||
const vec3_t cam = { 0, 4, -4 };
|
const vec3_t cam = { 0, 4, -4 };
|
||||||
const vec3_t tgt = { 0, 0.5, 0 };
|
const vec3_t tgt = { 0, 0.5, 0 };
|
||||||
mvp_t mvp = {
|
mvp_t mvp = {
|
||||||
.model = (mat4_t) {
|
.model = mat4_mul(
|
||||||
{ 0, 0, -1, 0 },
|
MAT4_TRANSLATE(1, 0, 0),
|
||||||
{ -1, 0, 0, 0 },
|
(mat4_t) {
|
||||||
{ 0, 1, 0, 0 },
|
{ 0, 0, -1, 0 },
|
||||||
{ 0, 0, 0, 1 },
|
{ -1, 0, 0, 0 },
|
||||||
},
|
{ 0, 1, 0, 0 },
|
||||||
|
{ 0, 0, 0, 1 },
|
||||||
|
}),
|
||||||
.view = mat4_lookat(cam, tgt, (vec3_t) { 0, 1, 0 }),
|
.view = mat4_lookat(cam, tgt, (vec3_t) { 0, 1, 0 }),
|
||||||
.proj = mat4_perspective((float)W / H, PI / 12, 0.1, 10.0),
|
.proj = mat4_perspective((float)W / H, PI / 8, 0.1, 10.0),
|
||||||
};
|
};
|
||||||
|
|
||||||
const mat4_t rotx = MAT4_ROTATE_X(PI / 128);
|
const mat4_t rot = MAT4_ROTATE_Y(PI / 128);
|
||||||
const mat4_t roty = MAT4_ROTATE_Y(PI / 128);
|
animation_start(&anim, &model);
|
||||||
const mat4_t rotz = MAT4_ROTATE_Z(PI / 128);
|
|
||||||
|
|
||||||
while (!glfwWindowShouldClose(window)) {
|
while (!glfwWindowShouldClose(window)) {
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
|
|
||||||
switch (rot_axis) {
|
mvp.model = mat4_mul(rot, mvp.model);
|
||||||
case AXIS_X:
|
animation_update(&anim, &model);
|
||||||
mvp.model = mat4_mul(rotx, mvp.model);
|
|
||||||
break;
|
|
||||||
case AXIS_Y:
|
|
||||||
mvp.model = mat4_mul(roty, mvp.model);
|
|
||||||
break;
|
|
||||||
case AXIS_Z:
|
|
||||||
mvp.model = mat4_mul(rotz, mvp.model);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
gpu_render(&gpu, &mvp, anim.bone_matrices);
|
gpu_render(&gpu, &mvp, anim.bone_matrices);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user