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 \todo
9 - shz_quat_rotate_towards()
10 - shz_quat_to_angles_xyz()
11 - shz_quat_angle_between()
12
13 \author 2025, 2026 Falco Girgis
14 \author 2025 Oleg Endo
15
16 \copyright MIT License
17*/
18
19#ifndef SHZ_QUAT_H
20#define SHZ_QUAT_H
21
22#include "shz_vector.h"
23#include "shz_mem.h"
24
25/*! \defgroup quat Quaternions
26 \brief Routines for quaternion math.
27*/
28
29//! Minimum epsilon below which shz_quat_slerp() performs no interpolation.
30#define SHZ_QUAT_SLERP_PHI_EPSILON SHZ_FLT_EPSILON
31
32SHZ_DECLS_BEGIN
33
34/*! Represents a 3D quaternion.
35
36 Quaternions are a mathematical structure representing a rotation
37 about a single arbitrary axis.
38*/
39typedef struct shz_quat {
40 union { //!< Convenience anonymous union between named and array-indexed components.
41 struct { //!< Anonymous structure with named components.
42 float w; //!< Scalar component/real part of quaternion.
43 union { //!< Convenience anonymous union for vector components.
44 struct {
45 float x; //!< X component of axis of rotation (imaginary)
46 float y; //!< Y component of axis of rotation (imaginary)
47 float z; //!< Z component of axis of rotation (imaginary)
48 };
49 shz_vec3_t axis; //!< 3D vector representing axis of rotation
50 };
51 };
52 float e[4]; //!< Array-indexed components.
53 };
54} shz_quat_t;
55
56//! Alternate shz_quat_t C typedef for those who hate POSIX style.
57typedef shz_quat_t shz_quat;
58
59/*! \name Initialization
60 \brief Routines for creating and initializing quaternions.
61 @{
62*/
63
64//! Initializes and returns a new quaternion with the given components, in WXYZ order.
65SHZ_FORCE_INLINE shz_quat_t shz_quat_init(float w, float x, float y, float z) SHZ_NOEXCEPT;
66
67//! Initializes and returns an identity quaternion.
68SHZ_FORCE_INLINE shz_quat_t shz_quat_identity(void) SHZ_NOEXCEPT;
69
70//! Returns true if the two given quaternions are considered equal based on either absolute or relative tolerance.
71SHZ_FORCE_INLINE bool shz_quat_equal(shz_quat_t a, shz_quat_t b) SHZ_NOEXCEPT;
72
73/*! Initializes and returns a quaternion with the given X-Y-Z rotations in radians.
74
75 The rotation is applied first around the X-axis, then the Y-, then the Z-axis.
76
77 \note
78 These angles are Tait-Bryan angles representing an intrinsic rotation.
79
80*/
81SHZ_INLINE shz_quat_t shz_quat_from_angles_xyz(float xangle, float yangle, float zangle) SHZ_NOEXCEPT;
82
83//! Initializes and returns a quaternion representing a rotation of \p angle radians about the given \p axis.
84SHZ_INLINE shz_quat_t shz_quat_from_axis_angle(shz_vec3_t axis, float angle) SHZ_NOEXCEPT;
85
86//! Creates a quaternion looking in the given direction with the given reference direction.
87shz_quat_t shz_quat_from_look_axis(shz_vec3_t forward, shz_vec3_t up) SHZ_NOEXCEPT;
88
89//! Returns the quaternion representing the rotation from axis \p v1 to \p v2.
90SHZ_INLINE shz_quat_t shz_quat_from_rotated_axis(shz_vec3_t v1, shz_vec3_t v2) SHZ_NOEXCEPT;
91
92//! Returns the quaternion that is linearly interpolating \p a to \p b, by a t factor of `0.0f-1.0f`.
93SHZ_INLINE shz_quat_t shz_quat_lerp(shz_quat_t a, shz_quat_t b, float t) SHZ_NOEXCEPT;
94
95//! Equivalent to shz_quat_lerp(), except that the resulting quaternion is normalized.
96SHZ_FORCE_INLINE shz_quat_t shz_quat_nlerp(shz_quat_t a, shz_quat_t b, float t) SHZ_NOEXCEPT;
97
98/*! Returns the quaternion that is spherically linearly interpolating \p a to \p b, by a \p t factor of `0.0f-1.0f`.
99
100 \warning The returned quaternion is not guaranteed to be normalized due to a floating-point error.
101 Callers should normalize the result before reuse, especially when performing repeated interpolations.
102*/
103SHZ_INLINE shz_quat_t shz_quat_slerp(shz_quat_t q, shz_quat_t p, float t) SHZ_NOEXCEPT;
104
105//! @}
106
107/*! \name Properties
108 \brief Routines returning derived values from a quaternion.
109 @{
110*/
111
112//! Returns the angle of rotation from the given quaternion.
113SHZ_INLINE float shz_quat_angle(shz_quat_t q) SHZ_NOEXCEPT;
114
115//! Returns the axis of rotation from the given quaternion.
116SHZ_INLINE shz_vec3_t shz_quat_axis(shz_quat_t q) SHZ_NOEXCEPT;
117
118// Returns the angle of rotation the quaternion represents about the X axis in radians.
119SHZ_INLINE float shz_quat_angle_x(shz_quat_t q) SHZ_NOEXCEPT;
120
121// Returns the angle of rotation the quaternion represents about the Y axis in radians.
122SHZ_INLINE float shz_quat_angle_y(shz_quat_t q) SHZ_NOEXCEPT;
123
124// Returns the angle of rotation the quaternion represents about the Z axis in radians.
125SHZ_INLINE float shz_quat_angle_z(shz_quat_t q) SHZ_NOEXCEPT;
126
127//! Returns both the axis and angle of rotation simultaneously (faster if both are needed) from the given quaternion.
128SHZ_INLINE void shz_quat_to_axis_angle(shz_quat_t q, shz_vec3_t* vec, float* angle) SHZ_NOEXCEPT;
129
130//! Returns the roll, pitch, and yaw angles of rotation represented by the given quaternion.
131SHZ_INLINE shz_vec3_t shz_quat_to_angles_xyz(shz_quat_t q) SHZ_NOEXCEPT;
132
133//! Returns the squared magnitude of the given quaternion.
134SHZ_FORCE_INLINE float shz_quat_magnitude_sqr(shz_quat_t quat) SHZ_NOEXCEPT;
135
136//! Returns the magnitude of the given quaternion.
137SHZ_FORCE_INLINE float shz_quat_magnitude(shz_quat_t quat) SHZ_NOEXCEPT;
138
139//! Returns the inverse magnitude of the given quaternion.
140SHZ_FORCE_INLINE float shz_quat_magnitude_inv(shz_quat_t quat) SHZ_NOEXCEPT;
141
142//! @}
143
144/*! \name Modifiers
145 \brief Routines for returning new quaternions derived from existing ones.
146 @{
147*/
148
149//! Returns the normalized form of the given quaternion.
150SHZ_FORCE_INLINE shz_quat_t shz_quat_normalize(shz_quat_t quat) SHZ_NOEXCEPT;
151
152/*! SAFELY returns the normalized form of the given quaternion.
153
154 Returns the identity quaternion when magnitude is 0.0f.
155*/
156SHZ_FORCE_INLINE shz_quat_t shz_quat_normalize_safe(shz_quat_t quat) SHZ_NOEXCEPT;
157
158//! Returns the conjugate of the given quaternion.
159SHZ_FORCE_INLINE shz_quat_t shz_quat_conjugate(shz_quat_t quat) SHZ_NOEXCEPT;
160
161//! Returns the inverse of the given quaternion
162SHZ_FORCE_INLINE shz_quat_t shz_quat_inv(shz_quat_t quat) SHZ_NOEXCEPT;
163
164//! @}
165
166/*! \name Arithmetic
167 \brief Routines performing calculations with quaternions.
168 @{
169*/
170
171//! Returns the quaternion produced from adding each component of the given quaternions.
172SHZ_FORCE_INLINE shz_quat_t shz_quat_add(shz_quat_t q, shz_quat_t p) SHZ_NOEXCEPT;
173
174//! Scales the components of the given quaternion by the given factor.
175SHZ_FORCE_INLINE shz_quat_t shz_quat_scale(shz_quat_t q, float f) SHZ_NOEXCEPT;
176
177//! Multiplies the two quaternions, returning the result as a new quaternion.
178SHZ_INLINE shz_quat_t shz_quat_mult(shz_quat_t q1, shz_quat_t q2) SHZ_NOEXCEPT;
179
180//! Returns the dot product of the two quaternions.
181SHZ_FORCE_INLINE float shz_quat_dot(shz_quat_t q1, shz_quat_t q2) SHZ_NOEXCEPT;
182
183//! Returns the two dot products taken between the \p l quaternion and the \p r1 and \p r2 quaternions.
184SHZ_FORCE_INLINE shz_vec2_t shz_quat_dot2(shz_quat_t l, shz_quat_t r1, shz_quat_t r2) SHZ_NOEXCEPT;
185
186//! Returns the two dot products taken between the \p l quaternion and the \p r1, \p r2, and \p r3 quaternions.
187SHZ_FORCE_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;
188
189//! @}
190
191/*! Rotates a vector by the given quaternion.
192
193 \note
194 This routine is meant for one-off rotations of a single vector by a single
195 quaternion. If you plan to rotate multiple vectors by the same quaternion,
196 you should use the XMTRX API to apply the quaternion as a rotation matrix.
197
198 \sa shz_xmtrx_apply_rotation_quat()
199*/
200SHZ_INLINE shz_vec3_t shz_quat_transform_vec3(shz_quat_t q, shz_vec3_t v) SHZ_NOEXCEPT;
201
202#include "inline/shz_quat.inl.h"
203
204SHZ_DECLS_END
205
206#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:57
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_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...
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_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_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.
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.
#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:39
float e[4]
Array-indexed components.
Definition shz_quat.h:52
float z
Z component of axis of rotation (imaginary)
Definition shz_quat.h:47
float w
< Anonymous structure with named components.
Definition shz_quat.h:42
float y
Y component of axis of rotation (imaginary)
Definition shz_quat.h:46
shz_vec3_t axis
3D vector representing axis of rotation
Definition shz_quat.h:49
float x
X component of axis of rotation (imaginary)
Definition shz_quat.h:45