summaryrefslogtreecommitdiff
path: root/src/maths
diff options
context:
space:
mode:
authoromnisci3nce <omniscient.oce@gmail.com>2024-04-27 13:08:03 +1000
committeromnisci3nce <omniscient.oce@gmail.com>2024-04-27 13:08:03 +1000
commit4cbc38b92edaa331fd0f6a077bbe7d7aebdb9ecf (patch)
tree753d23b07b09e3494e4cce594bd4b0f4710566f8 /src/maths
parentd6837defc03e431517f6616ec8e49a8eb3643011 (diff)
parentc7c33cd18e057bc826a0d31e1860b0ac396a00b6 (diff)
Merge remote-tracking branch 'origin/cel-67-load-animation-data-from-gltf' into ral
Diffstat (limited to 'src/maths')
-rw-r--r--src/maths/maths.h54
-rw-r--r--src/maths/maths_types.h6
2 files changed, 55 insertions, 5 deletions
diff --git a/src/maths/maths.h b/src/maths/maths.h
index 638d9f6..e0d39d7 100644
--- a/src/maths/maths.h
+++ b/src/maths/maths.h
@@ -83,6 +83,52 @@ 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() {
@@ -253,7 +299,7 @@ static inline mat4 mat4_look_at(vec3 position, vec3 target, vec3 up) {
#define TRANSFORM_DEFAULT \
((transform){ .position = VEC3_ZERO, \
- .rotation = (quat){ .x = 0., .y = 0., .z = 0., .w = 0. }, \
+ .rotation = (quat){ .x = 0., .y = 0., .z = 0., .w = 1. }, \
.scale = 1.0, \
.is_dirty = false })
@@ -262,10 +308,10 @@ static transform transform_create(vec3 pos, quat rot, f32 scale) {
}
static inline mat4 transform_to_mat(transform *tf) {
- mat4 trans = mat4_translation(tf->position);
- mat4 rot = mat4_rotation(tf->rotation);
mat4 scale = mat4_scale(tf->scale);
- return mat4_mult(trans, mat4_mult(rot, scale));
+ mat4 rotation = mat4_rotation(tf->rotation);
+ mat4 translation = mat4_translation(tf->position);
+ return mat4_mult(translation, mat4_mult(rotation, scale));
}
// --- Sizing asserts
diff --git a/src/maths/maths_types.h b/src/maths/maths_types.h
index 6d38fc7..53cac55 100644
--- a/src/maths/maths_types.h
+++ b/src/maths/maths_types.h
@@ -64,4 +64,8 @@ typedef struct transform {
typedef struct vec4i {
i32 x, y, z, w;
-} vec4i; \ No newline at end of file
+} vec4i;
+
+typedef struct vec4u {
+ u32 x, y, z, w;
+} vec4u; \ No newline at end of file