Banjo API 1.0.0-rc.2
Low-level C99 game development API
Loading...
Searching...
No Matches
quat.h
Go to the documentation of this file.
1
39#ifndef BJ_QUAT_H
40#define BJ_QUAT_H
41
42#include <banjo/api.h>
43#include <banjo/math.h>
44#include <banjo/vec.h>
45#include <banjo/mat.h>
46
58 void
59) {
60 return (struct bj_vec4){ BJ_FZERO, BJ_FZERO, BJ_FZERO, BJ_F(1.0) };
61}
62
74 struct bj_vec4 a,
75 struct bj_vec4 b
76) {
77 return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
78}
79
89 struct bj_vec4 q
90) {
91 return bj_quat_dot(q, q);
92}
93
101 struct bj_vec4 q
102) {
103 return bj_sqrt(bj_quat_norm2(q));
104}
105
116 struct bj_vec4 q
117) {
118 const bj_real n2 = bj_quat_norm2(q);
119 if (n2 <= BJ_EPSILON) {
120 return bj_quat_identity();
121 }
122 const bj_real inv = BJ_F(1.0) / bj_sqrt(n2);
123 return (struct bj_vec4){ q.x * inv, q.y * inv, q.z * inv, q.w * inv };
124}
125
139 struct bj_vec4 q
140) {
141 return (struct bj_vec4){ -q.x, -q.y, -q.z, q.w };
142}
143
157 struct bj_vec4 q
158) {
159 const bj_real n2 = bj_quat_norm2(q);
160 if (n2 <= BJ_EPSILON) {
161 return bj_quat_identity();
162 }
163 const bj_real inv = BJ_F(1.0) / n2;
164 return (struct bj_vec4){ -q.x * inv, -q.y * inv, -q.z * inv, q.w * inv };
165}
166
179 struct bj_vec4 p,
180 struct bj_vec4 q
181) {
182 return (struct bj_vec4){
183 p.w*q.x + p.x*q.w + p.y*q.z - p.z*q.y,
184 p.w*q.y - p.x*q.z + p.y*q.w + p.z*q.x,
185 p.w*q.z + p.x*q.y - p.y*q.x + p.z*q.w,
186 p.w*q.w - p.x*q.x - p.y*q.y - p.z*q.z
187 };
188}
189
205 struct bj_vec4 a,
206 struct bj_vec4 b,
207 bj_real t
208) {
209 bj_real cos_omega = bj_quat_dot(a, b);
210 struct bj_vec4 bb = b;
211 if (cos_omega < BJ_FZERO) {
212 cos_omega = -cos_omega;
213 bb.x = -b.x;
214 bb.y = -b.y;
215 bb.z = -b.z;
216 bb.w = -b.w;
217 }
218
219 /* Clamp for numerical safety */
220 if (cos_omega > BJ_F(1.0)) cos_omega = BJ_F(1.0);
221 if (cos_omega < -BJ_F(1.0)) cos_omega = -BJ_F(1.0);
222
223 if (cos_omega > BJ_F(1.0) - BJ_EPSILON) {
224 return bj_quat_normalize((struct bj_vec4){
225 a.x + t*(bb.x - a.x),
226 a.y + t*(bb.y - a.y),
227 a.z + t*(bb.z - a.z),
228 a.w + t*(bb.w - a.w)
229 });
230 }
231
232 const bj_real omega = bj_acos(cos_omega);
233 const bj_real sin_omega = bj_sin(omega);
234 if (sin_omega <= BJ_EPSILON) {
235 /* Fallback to nlerp */
236 return bj_quat_normalize((struct bj_vec4){
237 a.x + t*(bb.x - a.x),
238 a.y + t*(bb.y - a.y),
239 a.z + t*(bb.z - a.z),
240 a.w + t*(bb.w - a.w)
241 });
242 }
243
244 const bj_real wa = bj_sin((BJ_F(1.0) - t) * omega) / sin_omega;
245 const bj_real wb = bj_sin(t * omega) / sin_omega;
246 return (struct bj_vec4){
247 wa * a.x + wb * bb.x,
248 wa * a.y + wb * bb.y,
249 wa * a.z + wb * bb.z,
250 wa * a.w + wb * bb.w
251 };
252}
253
264 struct bj_vec3 axis,
265 bj_real angle_rad
266) {
267 const bj_real alen2 = axis.x*axis.x + axis.y*axis.y + axis.z*axis.z;
268 if (alen2 <= BJ_EPSILON) {
269 return bj_quat_identity();
270 }
271 const bj_real invlen = BJ_F(1.0) / bj_sqrt(alen2);
272 const struct bj_vec3 n = (struct bj_vec3){
273 axis.x * invlen, axis.y * invlen, axis.z * invlen
274 };
275 const bj_real h = angle_rad * BJ_F(0.5);
276 const bj_real s = bj_sin(h);
277 const bj_real c = bj_cos(h);
278 return (struct bj_vec4){ n.x * s, n.y * s, n.z * s, c };
279}
280
292 struct bj_vec4 q,
293 struct bj_vec3 v
294) {
295 struct bj_vec3 u = (struct bj_vec3){ q.x, q.y, q.z };
296 struct bj_vec3 t = bj_vec3_cross(u, v);
297 t.x += t.x; t.y += t.y; t.z += t.z; /* 2*(u×v) */
298 struct bj_vec3 r = (struct bj_vec3){
299 v.x + q.w * t.x + (u.y * t.z - u.z * t.y),
300 v.y + q.w * t.y + (u.z * t.x - u.x * t.z),
301 v.z + q.w * t.z + (u.x * t.y - u.y * t.x)
302 };
303 return r;
304}
305
314 struct bj_vec4 q,
315 struct bj_vec4 v
316) {
317 struct bj_vec3 r3 = bj_quat_rotate_vec3(q, (struct bj_vec3){ v.x, v.y, v.z });
318 return (struct bj_vec4){ .x = r3.x, .y = r3.y, .z = r3.z, .w = v.w };
319}
320
331 struct bj_mat4x4* BJ_RESTRICT M,
332 struct bj_vec4 q
333) {
334 q = bj_quat_normalize(q);
335 bj_real xx = q.x * q.x, yy = q.y * q.y, zz = q.z * q.z;
336 bj_real xy = q.x * q.y, xz = q.x * q.z, yz = q.y * q.z;
337 bj_real wx = q.w * q.x, wy = q.w * q.y, wz = q.w * q.z;
338
340
341 bj_real* m = M->m;
342 /* Column 0 */
343 m[BJ_M4(0,0)] = BJ_F(1.0) - BJ_F(2.0) * (yy + zz);
344 m[BJ_M4(0,1)] = BJ_F(2.0) * (xy + wz);
345 m[BJ_M4(0,2)] = BJ_F(2.0) * (xz - wy);
346 m[BJ_M4(0,3)] = BJ_FZERO;
347 /* Column 1 */
348 m[BJ_M4(1,0)] = BJ_F(2.0) * (xy - wz);
349 m[BJ_M4(1,1)] = BJ_F(1.0) - BJ_F(2.0) * (xx + zz);
350 m[BJ_M4(1,2)] = BJ_F(2.0) * (yz + wx);
351 m[BJ_M4(1,3)] = BJ_FZERO;
352 /* Column 2 */
353 m[BJ_M4(2,0)] = BJ_F(2.0) * (xz + wy);
354 m[BJ_M4(2,1)] = BJ_F(2.0) * (yz - wx);
355 m[BJ_M4(2,2)] = BJ_F(1.0) - BJ_F(2.0) * (xx + yy);
356 m[BJ_M4(2,3)] = BJ_FZERO;
357 /* Column 3 */
358 m[BJ_M4(3,0)] = BJ_FZERO;
359 m[BJ_M4(3,1)] = BJ_FZERO;
360 m[BJ_M4(3,2)] = BJ_FZERO;
361 m[BJ_M4(3,3)] = BJ_F(1.0);
362}
363
375 const struct bj_mat4x4* BJ_RESTRICT M
376) {
377 const bj_real* m = M->m;
378 bj_real m00 = m[BJ_M4(0,0)], m01 = m[BJ_M4(1,0)], m02 = m[BJ_M4(2,0)];
379 bj_real m10 = m[BJ_M4(0,1)], m11 = m[BJ_M4(1,1)], m12 = m[BJ_M4(2,1)];
380 bj_real m20 = m[BJ_M4(0,2)], m21 = m[BJ_M4(1,2)], m22 = m[BJ_M4(2,2)];
381
382 const bj_real trace = m00 + m11 + m22;
383 if (trace > BJ_FZERO) {
384 const bj_real s = bj_sqrt(trace + BJ_F(1.0)) * BJ_F(2.0);
385 const bj_real w = BJ_F(0.25) * s;
386 const bj_real x = (m21 - m12) / s;
387 const bj_real y = (m02 - m20) / s;
388 const bj_real z = (m10 - m01) / s;
389 return bj_quat_normalize((struct bj_vec4){ x, y, z, w });
390 }
391
392 if (m00 > m11 && m00 > m22) {
393 const bj_real s = bj_sqrt(BJ_F(1.0) + m00 - m11 - m22) * BJ_F(2.0);
394 const bj_real w = (m21 - m12) / s;
395 const bj_real x = BJ_F(0.25) * s;
396 const bj_real y = (m01 + m10) / s;
397 const bj_real z = (m02 + m20) / s;
398 return bj_quat_normalize((struct bj_vec4){ x, y, z, w });
399 } else if (m11 > m22) {
400 const bj_real s = bj_sqrt(BJ_F(1.0) - m00 + m11 - m22) * BJ_F(2.0);
401 const bj_real w = (m02 - m20) / s;
402 const bj_real x = (m01 + m10) / s;
403 const bj_real y = BJ_F(0.25) * s;
404 const bj_real z = (m12 + m21) / s;
405 return bj_quat_normalize((struct bj_vec4){ x, y, z, w });
406 } else {
407 const bj_real s = bj_sqrt(BJ_F(1.0) - m00 - m11 + m22) * BJ_F(2.0);
408 const bj_real w = (m10 - m01) / s;
409 const bj_real x = (m02 + m20) / s;
410 const bj_real y = (m12 + m21) / s;
411 const bj_real z = BJ_F(0.25) * s;
412 return bj_quat_normalize((struct bj_vec4){ x, y, z, w });
413 }
414}
415
416#endif /* BJ_QUAT_H */
417
General-purpose definitions for Banjo API.
#define BJ_INLINE
BJ_INLINE expands to an inline specifier appropriate for the toolchain.
Definition api.h:241
#define BJ_RESTRICT
BJ_RESTRICT expands to the appropriate restrict qualifier per toolchain.
Definition api.h:207
bj_real z
Z component.
Definition vec.h:82
bj_real x
X component.
Definition vec.h:65
bj_real w
W component (scalar part for quaternions).
Definition vec.h:83
bj_real z
Z component.
Definition vec.h:67
bj_real x
X component.
Definition vec.h:80
bj_real y
Y component.
Definition vec.h:66
bj_real y
Y component.
Definition vec.h:81
static struct bj_vec4 bj_quat_mul(struct bj_vec4 p, struct bj_vec4 q)
Hamilton product p * q.
Definition quat.h:178
static bj_real bj_quat_dot(struct bj_vec4 a, struct bj_vec4 b)
4D dot product between two quaternions.
Definition quat.h:73
static void bj_quat_to_mat4(struct bj_mat4x4 *restrict M, struct bj_vec4 q)
Fill a 4×4 rotation matrix from a quaternion.
Definition quat.h:330
static void bj_mat4_set_identity(struct bj_mat4x4 *restrict M)
Set a 4×4 matrix to identity.
Definition mat.h:729
static struct bj_vec4 bj_quat_normalize(struct bj_vec4 q)
Normalise a quaternion.
Definition quat.h:115
static struct bj_vec4 bj_quat_slerp(struct bj_vec4 a, struct bj_vec4 b, bj_real t)
Spherical linear interpolation between two orientations.
Definition quat.h:204
#define bj_acos
Arc cosine.
Definition math.h:234
#define bj_sin
Sine.
Definition math.h:246
static struct bj_vec4 bj_quat_rotate_vec4(struct bj_vec4 q, struct bj_vec4 v)
Rotate a 4D vector by a quaternion, preserving w.
Definition quat.h:313
#define BJ_FZERO
Zero constant in bj_real.
Definition math.h:89
static struct bj_vec4 bj_quat_from_axis_angle(struct bj_vec3 axis, bj_real angle_rad)
Build a quaternion from a rotation axis and angle.
Definition quat.h:263
static struct bj_vec4 bj_quat_conjugate(struct bj_vec4 q)
Conjugate of a quaternion.
Definition quat.h:138
static struct bj_vec3 bj_vec3_cross(struct bj_vec3 l, struct bj_vec3 r)
3D cross product: l × r (right-hand rule).
Definition vec.h:567
#define bj_cos
Cosine.
Definition math.h:237
static bj_real bj_quat_norm2(struct bj_vec4 q)
Squared Euclidean norm.
Definition quat.h:88
#define BJ_EPSILON
Machine epsilon for bj_real when float is selected.
Definition math.h:80
static struct bj_vec4 bj_quat_identity(void)
Return the identity quaternion.
Definition quat.h:57
static struct bj_vec3 bj_quat_rotate_vec3(struct bj_vec4 q, struct bj_vec3 v)
Rotate a 3D vector by a quaternion.
Definition quat.h:291
#define BJ_F(x)
Literal suffix helper for bj_real when float is selected.
Definition math.h:78
#define bj_sqrt
Square root.
Definition math.h:247
static struct bj_vec4 bj_quat_inverse(struct bj_vec4 q)
Multiplicative inverse of a quaternion.
Definition quat.h:156
float bj_real
Selected real type for float configuration.
Definition math.h:76
#define BJ_M4(c, r)
Index a 4×4 matrix element at column c, row r. 0 <= c,r < 4.
Definition mat.h:81
static bj_real bj_quat_norm(struct bj_vec4 q)
Euclidean norm (length).
Definition quat.h:100
static struct bj_vec4 bj_quat_from_mat4(const struct bj_mat4x4 *restrict M)
Build a quaternion from a 4×4 rotation matrix.
Definition quat.h:374
4×4 column-major matrix.
Definition mat.h:79
3D vector of bj_real components.
Definition vec.h:64
4D vector of bj_real components.
Definition vec.h:79
Matrix types and operations for 2D and 3D transforms.
C99 math shim with bj_real precision type and scalar utilities.
Fixed-size vector types (2D, 3D, 4D) and inline operations.