SH4ZAM! 0.1.0
Fast math library for the Sega Dreamcast's SH4 CPU
Loading...
Searching...
No Matches
shz_quat.h
Go to the documentation of this file.
1/*! \file
2 \brief Routines for operating upon quaternions.
3 \ingroup quat
4
5 This file contains the public type(s) and interface providing the
6 quaternion math API.
7
8 \author 2025, 2026 Falco Girgis
9 \author 2025 Oleg Endo
10
11 \copyright MIT License
12*/
13
14#ifndef SHZ_QUAT_H
15#define SHZ_QUAT_H
16
17#include "shz_vector.h"
18#include "shz_mem.h"
19
20/*! \defgroup quat Quaternions
21 \brief Routines for quaternion math.
22*/
23
24//! Minimum epsilon below which shz_quat_slerp() performs no interpolation.
25#define SHZ_QUAT_SLERP_PHI_EPSILON SHZ_FLT_EPSILON
26
27SHZ_DECLS_BEGIN
28
29/*! Represents a 3D quaternion.
30
31 Quaternions are a mathematical structure representing a rotation
32 about a single arbitrary axis.
33*/
34typedef struct shz_quat {
35 union { //!< Convenience anonymous union between named and array-indexed components.
36 struct { //!< Anonymous structure with named components.
37 float w; //!< W or scalar component/real part of quaternion.
38 union { //!< Convenience anonymous union for vector components.
39 struct {
40 float x; //!< X component of axis of rotation (imaginary)
41 float y; //!< Y component of axis of rotation (imaginary)
42 float z; //!< Z component of axis of rotation (imaginary)
43 };
44 shz_vec3_t axis; //!< 3D vector representing axis of rotation
45 };
46 };
47 float e[4]; //!< Array-indexed components.
48 };
49} shz_quat_t;
50
51//! Alternate shz_quat_t C typedef for those who hate POSIX style.
52typedef shz_quat_t shz_quat;
53
54/*! \name Initialization
55 \brief Routines for creating and initializing quaternions.
56 @{
57*/
58
59//! Initializes and returns a new quaternion with the given components, in WXYZ order.
60SHZ_INLINE shz_quat_t shz_quat_init(float w, float x, float y, float z) SHZ_NOEXCEPT;
61
62//! Initializes and returns an identity quaternion.
63SHZ_INLINE shz_quat_t shz_quat_identity(void) SHZ_NOEXCEPT;
64
65//! Returns true if the two given quaternions are considered equal based on either absolute or relative tolerance.
66SHZ_INLINE bool shz_quat_equal(shz_quat_t a, shz_quat_t b) SHZ_NOEXCEPT;
67
68/*! Initializes and returns a quaternion with the given X-Y-Z rotations in radians.
69
70 The rotation is applied first around the X-axis, then the Y-, then the Z-axis.
71
72 \note
73 These angles are Tait-Bryan angles representing an intrinsic rotation.
74
75*/
76SHZ_INLINE shz_quat_t shz_quat_from_angles_xyz(float xangle, float yangle, float zangle) SHZ_NOEXCEPT;
77
78//! Initializes and returns a quaternion representing a rotation of \p angle radians about the given \p axis.
79SHZ_INLINE shz_quat_t shz_quat_from_axis_angle(shz_vec3_t axis, float angle) SHZ_NOEXCEPT;
80
81//! Creates a quaternion looking in the given direction with the given reference direction.
82shz_quat_t shz_quat_from_look_axis(shz_vec3_t forward, shz_vec3_t up) SHZ_NOEXCEPT;
83
84//! Returns the quaternion representing the rotation from axis \p v1 to \p v2.
85SHZ_INLINE shz_quat_t shz_quat_from_rotated_axis(shz_vec3_t v1, shz_vec3_t v2) SHZ_NOEXCEPT;
86
87//! Returns the quaternion that is linearly interpolating \p a to \p b, by a t factor of `0.0f-1.0f`.
88SHZ_INLINE shz_quat_t shz_quat_lerp(shz_quat_t a, shz_quat_t b, float t) SHZ_NOEXCEPT;
89
90//! Equivalent to shz_quat_lerp(), except that the resulting quaternion is normalized.
91SHZ_INLINE shz_quat_t shz_quat_nlerp(shz_quat_t a, shz_quat_t b, float t) SHZ_NOEXCEPT;
92
93//! Returns the quaternion that is spherically linearly interpolating \p a to \p b, by a \p t factor of `0.0f-1.0f`.
94SHZ_INLINE shz_quat_t shz_quat_slerp(shz_quat_t q, shz_quat_t p, float t) SHZ_NOEXCEPT;
95
96/*! Evaluates a smooth cubic spherical interpolation (SQUAD) at parameter \p t.
97
98 \note
99 SQUAD(q1, q2, s1, s2, t) = slerp(slerp(q1, q2, t), slerp(s1, s2, t), 2t(1-t))
100
101 \param q1 Start quaternion.
102 \param q2 End quaternion.
103 \param s1 Inner control point for \p q1 (typically computed from surrounding keyframes).
104 \param s2 Inner control point for \p q2 (typically computed from surrounding keyframes).
105 \param t Interpolation factor in [0, 1].
106
107 \returns Resulting interpolated quaternion
108*/
109SHZ_INLINE shz_quat_t shz_quat_squad(shz_quat_t q1, shz_quat_t q2, shz_quat_t s1, shz_quat_t s2, float t) SHZ_NOEXCEPT;
110
111//! @}
112
113/*! \name Properties
114 \brief Routines returning derived values from a quaternion.
115 @{
116*/
117
118//! Returns the angle of rotation from the given quaternion.
119SHZ_INLINE float shz_quat_angle(shz_quat_t q) SHZ_NOEXCEPT;
120
121//! Returns the axis of rotation from the given quaternion.
122SHZ_INLINE shz_vec3_t shz_quat_axis(shz_quat_t q) SHZ_NOEXCEPT;
123
124//! Returns the angle of rotation the quaternion represents about the X axis in radians.
125SHZ_INLINE float shz_quat_angle_x(shz_quat_t q) SHZ_NOEXCEPT;
126
127//! Returns the angle of rotation the quaternion represents about the Y axis in radians.
128SHZ_INLINE float shz_quat_angle_y(shz_quat_t q) SHZ_NOEXCEPT;
129
130//! Returns the angle of rotation the quaternion represents about the Z axis in radians.
131SHZ_INLINE float shz_quat_angle_z(shz_quat_t q) SHZ_NOEXCEPT;
132
133//! Returns both the axis and angle of rotation simultaneously (faster if both are needed) from the given quaternion.
134SHZ_INLINE void shz_quat_to_axis_angle(shz_quat_t q, shz_vec3_t* vec, float* angle) SHZ_NOEXCEPT;
135
136//! Returns the roll, pitch, and yaw angles of rotation represented by the given quaternion.
137SHZ_INLINE shz_vec3_t shz_quat_to_angles_xyz(shz_quat_t q) SHZ_NOEXCEPT;
138
139//! Returns the squared magnitude of the given quaternion.
140SHZ_INLINE float shz_quat_magnitude_sqr(shz_quat_t quat) SHZ_NOEXCEPT;
141
142//! Returns the magnitude of the given quaternion.
143SHZ_INLINE float shz_quat_magnitude(shz_quat_t quat) SHZ_NOEXCEPT;
144
145//! Returns the inverse magnitude of the given quaternion.
146SHZ_INLINE float shz_quat_magnitude_inv(shz_quat_t quat) SHZ_NOEXCEPT;
147
148//! @}
149
150/*! \name Modifiers
151 \brief Routines for returning new quaternions derived from existing ones.
152 @{
153*/
154
155//! Returns the normalized form of the given quaternion.
156SHZ_INLINE shz_quat_t shz_quat_normalize(shz_quat_t quat) SHZ_NOEXCEPT;
157
158/*! SAFELY returns the normalized form of the given quaternion.
159
160 Returns the identity quaternion when magnitude is 0.0f.
161*/
162SHZ_INLINE shz_quat_t shz_quat_normalize_safe(shz_quat_t quat) SHZ_NOEXCEPT;
163
164//! Returns the conjugate of the given quaternion.
165SHZ_INLINE shz_quat_t shz_quat_conjugate(shz_quat_t quat) SHZ_NOEXCEPT;
166
167//! Returns the inverse of the given quaternion
168SHZ_INLINE shz_quat_t shz_quat_inv(shz_quat_t quat) SHZ_NOEXCEPT;
169
170//! Returns the negation of the given quaternion.
171SHZ_INLINE shz_quat_t shz_quat_neg(shz_quat_t quat) SHZ_NOEXCEPT;
172
173//! @}
174
175/*! \name Arithmetic
176 \brief Routines performing calculations with quaternions.
177 @{
178*/
179
180//! Returns the quaternion produced from adding each component of the given quaternions.
181SHZ_INLINE shz_quat_t shz_quat_add(shz_quat_t q, shz_quat_t p) SHZ_NOEXCEPT;
182
183//! Returns the quaternion produced from subtracting each component of quaternion \p p from quaterion \p q.
184SHZ_INLINE shz_quat_t shz_quat_sub(shz_quat_t q, shz_quat_t p) SHZ_NOEXCEPT;
185
186//! Scales the components of the given quaternion by the given factor.
187SHZ_INLINE shz_quat_t shz_quat_scale(shz_quat_t q, float f) SHZ_NOEXCEPT;
188
189//! Multiplies the two quaternions, returning the result as a new quaternion.
190SHZ_INLINE shz_quat_t shz_quat_mult(shz_quat_t q1, shz_quat_t q2) SHZ_NOEXCEPT;
191
192//! Divides quaternion \p p by quaternion \p q (multiplying by its inverse), returning the resulting quaternion.
193SHZ_INLINE shz_quat_t shz_quat_div(shz_quat_t q, shz_quat_t p) SHZ_NOEXCEPT;
194
195//! Returns the dot product of the two quaternions.
196SHZ_INLINE float shz_quat_dot(shz_quat_t q1, shz_quat_t q2) SHZ_NOEXCEPT;
197
198//! Returns the two dot products taken between the \p l quaternion and the \p r1 and \p r2 quaternions.
199SHZ_INLINE shz_vec2_t shz_quat_dot2(shz_quat_t l, shz_quat_t r1, shz_quat_t r2) SHZ_NOEXCEPT;
200
201//! Returns the two dot products taken between the \p l quaternion and the \p r1, \p r2, and \p r3 quaternions.
202SHZ_INLINE shz_vec3_t shz_quat_dot3(shz_quat_t l, shz_quat_t r1, shz_quat_t r2, shz_quat_t r3) SHZ_NOEXCEPT;
203
204//! @}
205
206/*! \name Miscellaneous
207 \brief Other types of quaternion operations.
208 @{
209*/
210
211//! Returns the angle in radians between the rotations represented by quaternions \p q and \p p.
212SHZ_INLINE float shz_quat_angle_between(shz_quat_t q, shz_quat_t p) SHZ_NOEXCEPT;
213
214/*! Rotates quaternion \p from towards quaternion \p to by at most \p max_angle radians.
215
216 \note Returns \p to if the angle between them is already less than \p max_angle.
217*/
218SHZ_INLINE shz_quat_t shz_quat_rotate_towards(shz_quat_t from, shz_quat_t to, float max_angle) SHZ_NOEXCEPT;
219
220//! @}
221
222/*! \name Transformations
223 \brief Routines for applying quaternion transforms.
224 @{
225*/
226
227/*! Rotates a vector by the given quaternion.
228
229 \note
230 This routine is meant for one-off rotations of a single vector by a single
231 quaternion. If you plan to rotate multiple vectors by the same quaternion,
232 you should use the XMTRX API to apply the quaternion as a rotation matrix.
233
234 \sa shz_xmtrx_apply_rotation_quat()
235*/
236SHZ_INLINE shz_vec3_t shz_quat_transform_vec3(shz_quat_t q, shz_vec3_t v) SHZ_NOEXCEPT;
237
238//! @}
239
240#include "inline/shz_quat.inl.h"
241
242SHZ_DECLS_END
243
244#endif // SHZ_QUAT_H
float shz_quat_magnitude_sqr(shz_quat_t quat) SHZ_NOEXCEPT
Returns the squared magnitude of the given quaternion.
float shz_quat_magnitude(shz_quat_t quat) SHZ_NOEXCEPT
Returns the magnitude of the given quaternion.
shz_vec3_t shz_quat_axis(shz_quat_t q) SHZ_NOEXCEPT
Returns the axis of rotation from the given quaternion.
shz_quat_t shz_quat_inv(shz_quat_t quat) SHZ_NOEXCEPT
Returns the inverse of the given quaternion.
shz_quat_t shz_quat
Alternate shz_quat_t C typedef for those who hate POSIX style.
Definition shz_quat.h:52
shz_quat_t shz_quat_nlerp(shz_quat_t a, shz_quat_t b, float t) SHZ_NOEXCEPT
Equivalent to shz_quat_lerp(), except that the resulting quaternion is normalized.
shz_quat_t shz_quat_from_axis_angle(shz_vec3_t axis, float angle) SHZ_NOEXCEPT
Initializes and returns a quaternion representing a rotation of angle radians about the given axis.
shz_quat_t shz_quat_neg(shz_quat_t quat) SHZ_NOEXCEPT
Returns the negation of the given quaternion.
shz_quat_t shz_quat_scale(shz_quat_t q, float f) SHZ_NOEXCEPT
Scales the components of the given quaternion by the given factor.
bool shz_quat_equal(shz_quat_t a, shz_quat_t b) SHZ_NOEXCEPT
Returns true if the two given quaternions are considered equal based on either absolute or relative t...
float shz_quat_angle_between(shz_quat_t q, shz_quat_t p) SHZ_NOEXCEPT
Returns the angle in radians between the rotations represented by quaternions q and p.
shz_quat_t shz_quat_from_look_axis(shz_vec3_t forward, shz_vec3_t up) SHZ_NOEXCEPT
Creates a quaternion looking in the given direction with the given reference direction.
shz_vec3_t shz_quat_transform_vec3(shz_quat_t q, shz_vec3_t v) SHZ_NOEXCEPT
Rotates a vector by the given quaternion.
shz_quat_t shz_quat_add(shz_quat_t q, shz_quat_t p) SHZ_NOEXCEPT
Returns the quaternion produced from adding each component of the given quaternions.
float shz_quat_magnitude_inv(shz_quat_t quat) SHZ_NOEXCEPT
Returns the inverse magnitude of the given quaternion.
shz_quat_t shz_quat_from_rotated_axis(shz_vec3_t v1, shz_vec3_t v2) SHZ_NOEXCEPT
Returns the quaternion representing the rotation from axis v1 to v2.
float shz_quat_angle(shz_quat_t q) SHZ_NOEXCEPT
Returns the angle of rotation from the given quaternion.
shz_quat_t shz_quat_slerp(shz_quat_t q, shz_quat_t p, float t) SHZ_NOEXCEPT
Returns the quaternion that is spherically linearly interpolating a to b, by a t factor of 0....
shz_quat_t shz_quat_normalize_safe(shz_quat_t quat) SHZ_NOEXCEPT
SAFELY returns the normalized form of the given quaternion.
shz_quat_t shz_quat_lerp(shz_quat_t a, shz_quat_t b, float t) SHZ_NOEXCEPT
Returns the quaternion that is linearly interpolating a to b, by a t factor of 0.0f-1....
shz_quat_t shz_quat_div(shz_quat_t q, shz_quat_t p) SHZ_NOEXCEPT
Divides quaternion p by quaternion q (multiplying by its inverse), returning the resulting quaternion...
float shz_quat_angle_x(shz_quat_t q) SHZ_NOEXCEPT
Returns the angle of rotation the quaternion represents about the X axis in radians.
shz_vec3_t shz_quat_to_angles_xyz(shz_quat_t q) SHZ_NOEXCEPT
Returns the roll, pitch, and yaw angles of rotation represented by the given quaternion.
shz_quat_t shz_quat_rotate_towards(shz_quat_t from, shz_quat_t to, float max_angle) SHZ_NOEXCEPT
Rotates quaternion from towards quaternion to by at most max_angle radians.
shz_vec2_t shz_quat_dot2(shz_quat_t l, shz_quat_t r1, shz_quat_t r2) SHZ_NOEXCEPT
Returns the two dot products taken between the l quaternion and the r1 and r2 quaternions.
shz_quat_t shz_quat_normalize(shz_quat_t quat) SHZ_NOEXCEPT
Returns the normalized form of the given quaternion.
shz_quat_t shz_quat_squad(shz_quat_t q1, shz_quat_t q2, shz_quat_t s1, shz_quat_t s2, float t) SHZ_NOEXCEPT
Evaluates a smooth cubic spherical interpolation (SQUAD) at parameter t.
float shz_quat_dot(shz_quat_t q1, shz_quat_t q2) SHZ_NOEXCEPT
Returns the dot product of the two quaternions.
shz_quat_t shz_quat_identity(void) SHZ_NOEXCEPT
Initializes and returns an identity quaternion.
void shz_quat_to_axis_angle(shz_quat_t q, shz_vec3_t *vec, float *angle) SHZ_NOEXCEPT
Returns both the axis and angle of rotation simultaneously (faster if both are needed) from the given...
shz_quat_t shz_quat_init(float w, float x, float y, float z) SHZ_NOEXCEPT
Initializes and returns a new quaternion with the given components, in WXYZ order.
shz_vec3_t shz_quat_dot3(shz_quat_t l, shz_quat_t r1, shz_quat_t r2, shz_quat_t r3) SHZ_NOEXCEPT
Returns the two dot products taken between the l quaternion and the r1, r2, and r3 quaternions.
shz_quat_t shz_quat_from_angles_xyz(float xangle, float yangle, float zangle) SHZ_NOEXCEPT
Initializes and returns a quaternion with the given X-Y-Z rotations in radians.
shz_quat_t shz_quat_conjugate(shz_quat_t quat) SHZ_NOEXCEPT
Returns the conjugate of the given quaternion.
shz_quat_t shz_quat_mult(shz_quat_t q1, shz_quat_t q2) SHZ_NOEXCEPT
Multiplies the two quaternions, returning the result as a new quaternion.
float shz_quat_angle_z(shz_quat_t q) SHZ_NOEXCEPT
Returns the angle of rotation the quaternion represents about the Z axis in radians.
shz_quat_t shz_quat_sub(shz_quat_t q, shz_quat_t p) SHZ_NOEXCEPT
Returns the quaternion produced from subtracting each component of quaternion p from quaterion q.
float shz_quat_angle_y(shz_quat_t q) SHZ_NOEXCEPT
Returns the angle of rotation the quaternion represents about the Y axis in radians.
#define SHZ_FLT_EPSILON
Floating-point epsilon used with inexact FP-based comparisons.
Definition shz_scalar.h:40
Represents a 3D quaternion.
Definition shz_quat.h:34
float e[4]
Array-indexed components.
Definition shz_quat.h:47
float z
Z component of axis of rotation (imaginary)
Definition shz_quat.h:42
float w
< Anonymous structure with named components.
Definition shz_quat.h:37
float y
Y component of axis of rotation (imaginary)
Definition shz_quat.h:41
shz_vec3_t axis
3D vector representing axis of rotation
Definition shz_quat.h:44
float x
X component of axis of rotation (imaginary)
Definition shz_quat.h:40