summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoromniscient <17525998+omnisci3nce@users.noreply.github.com>2024-04-05 00:28:24 +1100
committeromniscient <17525998+omnisci3nce@users.noreply.github.com>2024-04-05 00:28:24 +1100
commite5495790aeba905505152ad3b6690f459a44df03 (patch)
tree719095667250b5163c05325452179e6779612b7d /src
parent9baff5661f2ba8b57e1b0794e490e239b7ef80ca (diff)
close.
Diffstat (limited to 'src')
-rw-r--r--src/animation.c38
-rw-r--r--src/animation.h11
-rw-r--r--src/defines.h4
-rw-r--r--src/maths/maths.h49
-rw-r--r--src/resources/gltf.c61
-rw-r--r--src/resources/obj.c1
-rw-r--r--src/std/mem.c2
7 files changed, 149 insertions, 17 deletions
diff --git a/src/animation.c b/src/animation.c
index e69de29..f6741e8 100644
--- a/src/animation.c
+++ b/src/animation.c
@@ -0,0 +1,38 @@
+#include "animation.h"
+#include "maths.h"
+#include "log.h"
+
+keyframe animation_sample(animation_sampler *sampler, f32 t) {
+ size_t previous_index = 0;
+ f32 previous_time = 0.0;
+ // look forwards
+ DEBUG("%d\n", sampler->animation.values.kind);
+ TRACE("Here %d", sampler->animation.n_timestamps);
+ for (u32 i = 1; i < sampler->animation.n_timestamps; i++) {
+ f32 current_time = sampler->animation.timestamps[i];
+ if (current_time > t) {
+ break;
+ }
+ previous_time = current_time;
+ 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 - sampler->animation.timestamps[next_index]) / time_diff;
+
+ quat interpolated_rot = quat_slerp(sampler->animation.values.values[previous_index].rotation,
+ sampler->animation.values.values[next_index].rotation, percent);
+
+ return (keyframe){ .rotation = interpolated_rot };
+} \ No newline at end of file
diff --git a/src/animation.h b/src/animation.h
index b7c8ca4..81e150a 100644
--- a/src/animation.h
+++ b/src/animation.h
@@ -29,18 +29,21 @@ typedef struct keyframes {
} keyframes;
typedef struct animation_spline {
- f32_darray timestamps;
+ f32* timestamps;
+ size_t n_timestamps;
keyframes values;
interpolation interpolation;
} animation_spline;
typedef struct animation_sampler {
int current_index;
+ f32 min;
+ f32 max;
animation_spline animation;
} animation_sampler;
/** @brief Sample an animation at a given time `t` */
-keyframe animation_sample(animation_sampler sampler, f32 t);
+keyframe animation_sample(animation_sampler* sampler, f32 t);
typedef struct animation_clip {
// A clip contains one or more animation curves
@@ -50,4 +53,6 @@ typedef struct animation_clip {
animation_sampler* translation;
animation_sampler* scale;
animation_sampler* weights;
-} animation_clip; \ No newline at end of file
+} animation_clip;
+
+void animation_play(animation_clip* clip); \ No newline at end of file
diff --git a/src/defines.h b/src/defines.h
index 52aa7b0..5110f5a 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -71,6 +71,6 @@ Renderer backend defines:
#endif
#if defined(CEL_PLATFORM_MAC)
-#define CEL_REND_BACKEND_METAL 1
-// #define CEL_REND_BACKEND_OPENGL 1
+// #define CEL_REND_BACKEND_METAL 1
+#define CEL_REND_BACKEND_OPENGL 1
#endif \ No newline at end of file
diff --git a/src/maths/maths.h b/src/maths/maths.h
index a16a6b4..76531f2 100644
--- a/src/maths/maths.h
+++ b/src/maths/maths.h
@@ -83,6 +83,55 @@ static quat quat_from_axis_angle(vec3 axis, f32 angle, bool normalize) {
return q;
}
+// TODO: grok this.
+static inline quat quat_slerp(quat a, quat b, f32 percentage) {
+ quat out_quaternion;
+
+ quat q0 = quat_normalise(a);
+ quat q1 = quat_normalise(b);
+
+ // Compute the cosine of the angle between the two vectors.
+ f32 dot = quat_dot(q0, q1);
+
+ // If the dot product is negative, slerp won't take
+ // the shorter path. Note that v1 and -v1 are equivalent when
+ // the negation is applied to all four components. Fix by
+ // reversing one quaternion.
+ if (dot < 0.0f) {
+ q1.x = -q1.x;
+ q1.y = -q1.y;
+ q1.z = -q1.z;
+ q1.w = -q1.w;
+ dot = -dot;
+ }
+
+ const f32 DOT_THRESHOLD = 0.9995f;
+ if (dot > DOT_THRESHOLD) {
+ // If the inputs are too close for comfort, linearly interpolate
+ // and normalize the result.
+ out_quaternion = (quat){q0.x + ((q1.x - q0.x) * percentage),
+ q0.y + ((q1.y - q0.y) * percentage),
+ q0.z + ((q1.z - q0.z) * percentage),
+ q0.w + ((q1.w - q0.w) * percentage)};
+
+ return quat_normalise(out_quaternion);
+ }
+
+ // Since dot is in range [0, DOT_THRESHOLD], acos is safe
+ f32 theta_0 = cos(dot); // theta_0 = angle between input vectors
+ f32 theta = theta_0 * percentage; // theta = angle between v0 and result
+ f32 sin_theta = sin(theta); // compute this value only once
+ f32 sin_theta_0 = sin(theta_0); // compute this value only once
+
+ f32 s0 =
+ cos(theta) -
+ dot * sin_theta / sin_theta_0; // == sin(theta_0 - theta) / sin(theta_0)
+ f32 s1 = sin_theta / sin_theta_0;
+
+ return (quat){(q0.x * s0) + (q1.x * s1), (q0.y * s0) + (q1.y * s1),
+ (q0.z * s0) + (q1.z * s1), (q0.w * s0) + (q1.w * s1)};
+}
+
// --- Matrix Implementations
static inline mat4 mat4_ident() {
diff --git a/src/resources/gltf.c b/src/resources/gltf.c
index b6e100f..6081e45 100644
--- a/src/resources/gltf.c
+++ b/src/resources/gltf.c
@@ -10,6 +10,7 @@
#include "mem.h"
#include "path.h"
#include "render.h"
+#include "render_backend.h"
#include "render_types.h"
#include "str.h"
@@ -236,10 +237,12 @@ bool model_load_gltf_str(const char *file_string, const char *filepath, str8 rel
size_t num_animations = data->animations_count;
if (num_animations > 0) {
// Create an arena for all animation related data
-#define ANIMATION_STORAGE_ARENA_SIZE (1024 * 1024)
+#define ANIMATION_STORAGE_ARENA_SIZE (1024 * 1024 * 1024)
char *animation_backing_storage = malloc(ANIMATION_STORAGE_ARENA_SIZE);
// We'll store data on this arena so we can easily free it all at once later
- arena anim_arena = arena_create(animation_backing_storage, ANIMATION_STORAGE_ARENA_SIZE);
+ out_model->animation_data_arena =
+ arena_create(animation_backing_storage, ANIMATION_STORAGE_ARENA_SIZE);
+ arena *arena = &out_model->animation_data_arena;
if (!out_model->animations) {
out_model->animations = animation_clip_darray_new(num_animations);
@@ -252,38 +255,74 @@ bool model_load_gltf_str(const char *file_string, const char *filepath, str8 rel
for (size_t c = 0; c < animation.channels_count; c++) {
cgltf_animation_channel channel = animation.channels[c];
- animation_sampler *sampler = arena_alloc(&anim_arena, sizeof(animation_sampler));
+ animation_sampler *sampler = arena_alloc(arena, sizeof(animation_sampler));
- animation_sampler **target_property;
+ // animation_sampler **target_property;
keyframe_kind data_type;
switch (channel.target_path) {
case cgltf_animation_path_type_rotation:
- target_property = &clip.rotation;
+ // target_property = &clip.rotation;
data_type = KEYFRAME_ROTATION;
break;
default:
WARN("unsupported animation type");
return false;
}
- *target_property = sampler;
+ // *target_property = sampler;
sampler->current_index = 0;
+ printf("1 %d index\n", sampler->current_index);
sampler->animation.interpolation = INTERPOLATION_LINEAR;
// keyframe times
size_t n_frames = channel.sampler->input->count;
+ printf("n_frames: %d\n", n_frames);
assert(channel.sampler->input->component_type == cgltf_component_type_r_32f);
- // FIXME: CASSERT_MSG function "Expected animation sampler input component to be type f32 (keyframe times)");
-
- sampler,
-
+ // FIXME: CASSERT_MSG function "Expected animation sampler input component to be type f32
+ // (keyframe times)");
+ printf("2 %d index\n", sampler->current_index);
+ f32 *times = arena_alloc(arena, n_frames * sizeof(f32));
+ printf("3 %d index\n", sampler->current_index);
+ sampler->animation.n_timestamps = n_frames;
+ printf("n_timestamps: %d\n", sampler->animation.n_timestamps);
+ sampler->animation.timestamps = times;
+ cgltf_accessor_unpack_floats(channel.sampler->input, times, n_frames);
+
+ printf("4 %d index\n", sampler->current_index);
+
+ if (channel.target_path == cgltf_animation_path_type_rotation) {
+ assert(channel.sampler->output->component_type == cgltf_component_type_r_32f);
+ assert(channel.sampler->output->type == cgltf_type_vec4);
+ }
+
// keyframe values
size_t n_values = channel.sampler->output->count;
assert(n_frames == n_values);
+ ERROR("N frames %d", n_frames);
- sampler->animation.timestamps
+ keyframes keyframes = { 0 };
+ keyframes.kind = KEYFRAME_ROTATION;
+ keyframes.count = n_values;
+ keyframes.values = arena_alloc(arena, n_values * sizeof(keyframe));
+ for (cgltf_size v = 0; v < channel.sampler->output->count; ++v) {
+ quat rot;
+ cgltf_accessor_read_float(channel.sampler->output, v, &rot.x, 4);
+ printf("Quat %f %f %f %f\n", rot.x, rot.y, rot.z, rot.w);
+ keyframes.values[v].rotation = rot;
+ }
+ sampler->animation.values = keyframes;
+
+ sampler->min = channel.sampler->input->min[0];
+ sampler->max = channel.sampler->input->max[0];
+
+ clip.rotation = sampler;
+ printf("%d timestamps\n", sampler->animation.n_timestamps);
+ printf("%d index\n", sampler->current_index);
}
+
+ WARN("stuff %ld", clip.rotation->animation.n_timestamps);
+ animation_clip_darray_push(out_model->animations, clip);
}
}
diff --git a/src/resources/obj.c b/src/resources/obj.c
index c6e9fa6..ea73ffa 100644
--- a/src/resources/obj.c
+++ b/src/resources/obj.c
@@ -18,6 +18,7 @@
#include "mem.h"
#include "path.h"
#include "render.h"
+#include "render_backend.h"
#include "render_types.h"
#include "str.h"
diff --git a/src/std/mem.c b/src/std/mem.c
index d7c0f4c..25c9563 100644
--- a/src/std/mem.c
+++ b/src/std/mem.c
@@ -15,7 +15,7 @@ void* arena_alloc_align(arena* a, size_t size, size_t align) {
if (available < 0 || (ptrdiff_t)size > available) {
ERROR_EXIT("Arena ran out of memory\n");
}
- void* p = a->begin + padding;
+ void* p = a->curr + padding;
a->curr += padding + size;
return memset(p, 0, size);
}