1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
#include "animation.h"
#include "immdraw.h"
#include "log.h"
#include "maths.h"
#include "maths_types.h"
#include "ral_types.h"
Keyframe Animation_Sample(AnimationSampler* sampler, f32 t) {
size_t previous_index = 0;
f32 previous_time = 0.0;
// look forwards
DEBUG("%d\n", keyframe_kind_strings[sampler->animation.values.kind]);
TRACE("Total timestamps %d", sampler->animation.n_timestamps);
for (u32 i = 0; i < sampler->animation.n_timestamps; i++) {
f32 current_time = sampler->animation.timestamps[i];
if (current_time > t) {
break;
}
previous_time = sampler->animation.timestamps[i];
previous_index = i;
}
size_t next_index = (previous_index + 1) % sampler->animation.n_timestamps;
f32 next_time = sampler->animation.timestamps[next_index];
printf("%d %f %d %f\n", previous_index, previous_time, next_index, next_time);
Keyframe prev_value = sampler->animation.values.values[previous_index];
Keyframe next_value = sampler->animation.values.values[next_index];
printf("%d %d\n", previous_index, next_index);
f32 time_diff =
sampler->animation.timestamps[next_index] - sampler->animation.timestamps[previous_index];
f32 percent = (t - previous_time) / time_diff;
switch (sampler->animation.values.kind) {
case KEYFRAME_ROTATION:
return (Keyframe){ .rotation = quat_slerp(
sampler->animation.values.values[previous_index].rotation,
sampler->animation.values.values[next_index].rotation, percent) };
case KEYFRAME_TRANSLATION:
case KEYFRAME_SCALE:
case KEYFRAME_WEIGHTS:
WARN("TODO: other keyframe kind interpolation");
return prev_value;
}
}
void Animation_Tick(AnimationClip* clip, Armature* armature, f32 time) {
TRACE("Ticking animation %s", clip->clip_name);
for (u32 c_i = 0; c_i < clip->channels->len; c_i++) {
AnimationSampler* sampler = clip->channels->data;
// Interpolated keyframe based on time
Keyframe k = Animation_Sample(sampler, time);
// Get the joint in the armature
Joint* joint = &armature->joints->data[sampler->target_joint_idx];
if (sampler->animation.values.kind == KEYFRAME_ROTATION) {
// Update the joints rotation
joint->transform_components.rotation = k.rotation;
} else {
WARN("not yet implemented animation kind");
}
}
}
void Animation_VisualiseJoints(Armature* armature) {
for (int j = 0; j < armature->joints->len; j++) {
Joint joint = armature->joints->data[j];
Transform tf = joint.transform_components;
tf.scale = vec3(0.05, 0.05, 0.05);
Immdraw_Sphere(tf, vec4(0, 1, 1, 1), true);
}
}
ShaderDataLayout AnimData_GetLayout(void* data) {
AnimDataUniform* d = data;
bool has_data = data != NULL;
ShaderBinding b1 = { .label = "AnimData",
.kind = BINDING_BYTES,
.data.bytes.size = sizeof(AnimDataUniform) };
if (has_data) {
b1.data.bytes.data = d;
}
return (ShaderDataLayout){ .bindings = { b1 }, .binding_count = 1 };
}
|