Skip to main content

raylib_sys/
matrix_quat_math.rs

1use crate::{Matrix, Quaternion, Vector3};
2
3// ─── Matrix ──────────────────────────────────────────────────────────────────
4
5impl Matrix {
6    /// Identity matrix. (raymath `MatrixIdentity`)
7    #[inline]
8    #[must_use]
9    pub fn identity() -> Self {
10        // SAFETY: MatrixIdentity is a pure value-out raymath fn; no preconditions.
11        unsafe { crate::MatrixIdentity() }
12    }
13
14    /// Matrix determinant. (raymath `MatrixDeterminant`)
15    #[inline]
16    #[must_use]
17    pub fn determinant(self) -> f32 {
18        // SAFETY: pure value-in/out, no preconditions.
19        unsafe { crate::MatrixDeterminant(self) }
20    }
21
22    /// Trace of the matrix (sum of diagonal values). (raymath `MatrixTrace`)
23    #[inline]
24    #[must_use]
25    pub fn trace(self) -> f32 {
26        // SAFETY: pure value-in/out, no preconditions.
27        unsafe { crate::MatrixTrace(self) }
28    }
29
30    /// Transpose matrix. (raymath `MatrixTranspose`)
31    #[inline]
32    #[must_use]
33    pub fn transpose(self) -> Self {
34        // SAFETY: pure value-in/out, no preconditions.
35        unsafe { crate::MatrixTranspose(self) }
36    }
37
38    /// Invert matrix. (raymath `MatrixInvert`)
39    #[inline]
40    #[must_use]
41    pub fn invert(self) -> Self {
42        // SAFETY: pure value-in/out, no preconditions.
43        unsafe { crate::MatrixInvert(self) }
44    }
45
46    /// Multiply matrix by scalar. (raymath `MatrixMultiplyValue`)
47    #[inline]
48    #[must_use]
49    pub fn mul_value(self, value: f32) -> Self {
50        // SAFETY: pure value-in/out, no preconditions.
51        unsafe { crate::MatrixMultiplyValue(self, value) }
52    }
53
54    /// Translate matrix. (raymath `MatrixTranslate`)
55    #[inline]
56    #[must_use]
57    pub fn translate(x: f32, y: f32, z: f32) -> Self {
58        // SAFETY: pure value-in/out, no preconditions.
59        unsafe { crate::MatrixTranslate(x, y, z) }
60    }
61
62    /// Rotate matrix by axis and angle (radians). (raymath `MatrixRotate`)
63    #[inline]
64    #[must_use]
65    pub fn rotate(axis: Vector3, angle: f32) -> Self {
66        // SAFETY: pure value-in/out, no preconditions.
67        unsafe { crate::MatrixRotate(axis, angle) }
68    }
69
70    /// Rotate around X axis (radians). (raymath `MatrixRotateX`)
71    #[inline]
72    #[must_use]
73    pub fn rotate_x(angle: f32) -> Self {
74        // SAFETY: pure value-in/out, no preconditions.
75        unsafe { crate::MatrixRotateX(angle) }
76    }
77
78    /// Rotate around Y axis (radians). (raymath `MatrixRotateY`)
79    #[inline]
80    #[must_use]
81    pub fn rotate_y(angle: f32) -> Self {
82        // SAFETY: pure value-in/out, no preconditions.
83        unsafe { crate::MatrixRotateY(angle) }
84    }
85
86    /// Rotate around Z axis (radians). (raymath `MatrixRotateZ`)
87    #[inline]
88    #[must_use]
89    pub fn rotate_z(angle: f32) -> Self {
90        // SAFETY: pure value-in/out, no preconditions.
91        unsafe { crate::MatrixRotateZ(angle) }
92    }
93
94    /// Rotate around XYZ axes (radians, intrinsic order). (raymath `MatrixRotateXYZ`)
95    #[inline]
96    #[must_use]
97    pub fn rotate_xyz(angle: Vector3) -> Self {
98        // SAFETY: pure value-in/out, no preconditions.
99        unsafe { crate::MatrixRotateXYZ(angle) }
100    }
101
102    /// Rotate around ZYX axes (radians, intrinsic order). (raymath `MatrixRotateZYX`)
103    #[inline]
104    #[must_use]
105    pub fn rotate_zyx(angle: Vector3) -> Self {
106        // SAFETY: pure value-in/out, no preconditions.
107        unsafe { crate::MatrixRotateZYX(angle) }
108    }
109
110    /// Scale matrix. (raymath `MatrixScale`)
111    #[inline]
112    #[must_use]
113    pub fn scale(x: f32, y: f32, z: f32) -> Self {
114        // SAFETY: pure value-in/out, no preconditions.
115        unsafe { crate::MatrixScale(x, y, z) }
116    }
117
118    /// Frustum projection matrix. (raymath `MatrixFrustum`)
119    #[inline]
120    #[must_use]
121    pub fn frustum(left: f64, right: f64, bottom: f64, top: f64, near: f64, far: f64) -> Self {
122        // SAFETY: pure value-in/out, no preconditions.
123        unsafe { crate::MatrixFrustum(left, right, bottom, top, near, far) }
124    }
125
126    /// Perspective projection matrix. (raymath `MatrixPerspective`)
127    #[inline]
128    #[must_use]
129    pub fn perspective(fov_y: f64, aspect: f64, near: f64, far: f64) -> Self {
130        // SAFETY: pure value-in/out, no preconditions.
131        unsafe { crate::MatrixPerspective(fov_y, aspect, near, far) }
132    }
133
134    /// Orthographic projection matrix. (raymath `MatrixOrtho`)
135    #[inline]
136    #[must_use]
137    pub fn ortho(left: f64, right: f64, bottom: f64, top: f64, near: f64, far: f64) -> Self {
138        // SAFETY: pure value-in/out, no preconditions.
139        unsafe { crate::MatrixOrtho(left, right, bottom, top, near, far) }
140    }
141
142    /// Look-at view matrix. (raymath `MatrixLookAt`)
143    #[inline]
144    #[must_use]
145    pub fn look_at(eye: Vector3, target: Vector3, up: Vector3) -> Self {
146        // SAFETY: pure value-in/out, no preconditions.
147        unsafe { crate::MatrixLookAt(eye, target, up) }
148    }
149
150    /// Convert matrix to float array. (raymath `MatrixToFloatV`)
151    #[inline]
152    #[must_use]
153    pub fn to_float_array(self) -> crate::float16 {
154        // SAFETY: pure value-in/out, no preconditions.
155        unsafe { crate::MatrixToFloatV(self) }
156    }
157
158    /// Compose a matrix from translation, rotation quaternion, and scale. (raymath `MatrixCompose`)
159    #[inline]
160    #[must_use]
161    pub fn compose(translation: Vector3, rotation: Quaternion, scale: Vector3) -> Self {
162        // SAFETY: pure value-in/out, no preconditions.
163        unsafe { crate::MatrixCompose(translation, rotation, scale) }
164    }
165}
166
167impl core::ops::Mul for Matrix {
168    type Output = Matrix;
169    #[inline]
170    fn mul(self, rhs: Matrix) -> Matrix {
171        // SAFETY: MatrixMultiply is a pure value-in/out raymath fn; no preconditions.
172        unsafe { crate::MatrixMultiply(self, rhs) }
173    }
174}
175impl core::ops::MulAssign for Matrix {
176    #[inline]
177    fn mul_assign(&mut self, rhs: Matrix) {
178        *self = *self * rhs;
179    }
180}
181
182impl core::ops::Add for Matrix {
183    type Output = Matrix;
184    #[inline]
185    fn add(self, rhs: Matrix) -> Matrix {
186        // SAFETY: MatrixAdd is a pure value-in/out raymath fn; no preconditions.
187        unsafe { crate::MatrixAdd(self, rhs) }
188    }
189}
190impl core::ops::AddAssign for Matrix {
191    #[inline]
192    fn add_assign(&mut self, rhs: Matrix) {
193        *self = *self + rhs;
194    }
195}
196
197impl core::ops::Sub for Matrix {
198    type Output = Matrix;
199    #[inline]
200    fn sub(self, rhs: Matrix) -> Matrix {
201        // SAFETY: MatrixSubtract is a pure value-in/out raymath fn; no preconditions.
202        unsafe { crate::MatrixSubtract(self, rhs) }
203    }
204}
205impl core::ops::SubAssign for Matrix {
206    #[inline]
207    fn sub_assign(&mut self, rhs: Matrix) {
208        *self = *self - rhs;
209    }
210}
211
212/// Decompose a matrix into translation, rotation quaternion, and scale.
213/// (raymath `MatrixDecompose`)
214pub fn matrix_decompose(mat: Matrix) -> (Vector3, Quaternion, Vector3) {
215    let mut translation = Vector3 {
216        x: 0.0,
217        y: 0.0,
218        z: 0.0,
219    };
220    let mut rotation = Quaternion {
221        x: 0.0,
222        y: 0.0,
223        z: 0.0,
224        w: 0.0,
225    };
226    let mut scale = Vector3 {
227        x: 0.0,
228        y: 0.0,
229        z: 0.0,
230    };
231    // SAFETY: MatrixDecompose writes through non-null, properly aligned out-ptrs;
232    // all three are distinct stack allocations with no aliasing.
233    unsafe { crate::MatrixDecompose(mat, &mut translation, &mut rotation, &mut scale) };
234    (translation, rotation, scale)
235}
236
237// ─── Quaternion ──────────────────────────────────────────────────────────────
238
239impl Quaternion {
240    /// Identity quaternion (0, 0, 0, 1). (raymath `QuaternionIdentity`)
241    #[inline]
242    #[must_use]
243    pub fn identity() -> Self {
244        // SAFETY: QuaternionIdentity is a pure value-out raymath fn; no preconditions.
245        unsafe { crate::QuaternionIdentity() }
246    }
247
248    /// Add scalar to each component. (raymath `QuaternionAddValue`)
249    #[inline]
250    #[must_use]
251    pub fn add_value(self, add: f32) -> Self {
252        // SAFETY: pure value-in/out, no preconditions.
253        unsafe { crate::QuaternionAddValue(self, add) }
254    }
255
256    /// Subtract scalar from each component. (raymath `QuaternionSubtractValue`)
257    #[inline]
258    #[must_use]
259    pub fn sub_value(self, sub: f32) -> Self {
260        // SAFETY: pure value-in/out, no preconditions.
261        unsafe { crate::QuaternionSubtractValue(self, sub) }
262    }
263
264    /// Quaternion length. (raymath `QuaternionLength`)
265    #[inline]
266    #[must_use]
267    pub fn length(self) -> f32 {
268        // SAFETY: pure value-in/out, no preconditions.
269        unsafe { crate::QuaternionLength(self) }
270    }
271
272    /// Normalize quaternion. (raymath `QuaternionNormalize`)
273    #[inline]
274    #[must_use]
275    pub fn normalize(self) -> Self {
276        // SAFETY: pure value-in/out, no preconditions.
277        unsafe { crate::QuaternionNormalize(self) }
278    }
279
280    /// Invert quaternion. (raymath `QuaternionInvert`)
281    #[inline]
282    #[must_use]
283    pub fn invert(self) -> Self {
284        // SAFETY: pure value-in/out, no preconditions.
285        unsafe { crate::QuaternionInvert(self) }
286    }
287
288    /// Linear interpolation. (raymath `QuaternionLerp`)
289    #[inline]
290    #[must_use]
291    pub fn lerp(self, other: Quaternion, amount: f32) -> Self {
292        // SAFETY: pure value-in/out, no preconditions.
293        unsafe { crate::QuaternionLerp(self, other, amount) }
294    }
295
296    /// Normalized linear interpolation. (raymath `QuaternionNlerp`)
297    #[inline]
298    #[must_use]
299    pub fn nlerp(self, other: Quaternion, amount: f32) -> Self {
300        // SAFETY: pure value-in/out, no preconditions.
301        unsafe { crate::QuaternionNlerp(self, other, amount) }
302    }
303
304    /// Spherical linear interpolation. (raymath `QuaternionSlerp`)
305    #[inline]
306    #[must_use]
307    pub fn slerp(self, other: Quaternion, amount: f32) -> Self {
308        // SAFETY: pure value-in/out, no preconditions.
309        unsafe { crate::QuaternionSlerp(self, other, amount) }
310    }
311
312    /// Cubic Hermite spline interpolation. (raymath `QuaternionCubicHermiteSpline`)
313    #[inline]
314    #[must_use]
315    pub fn cubic_hermite_spline(
316        self,
317        out_tangent1: Quaternion,
318        q2: Quaternion,
319        in_tangent2: Quaternion,
320        t: f32,
321    ) -> Self {
322        // SAFETY: pure value-in/out, no preconditions.
323        unsafe { crate::QuaternionCubicHermiteSpline(self, out_tangent1, q2, in_tangent2, t) }
324    }
325
326    /// Quaternion for rotation from one vector to another. (raymath `QuaternionFromVector3ToVector3`)
327    #[inline]
328    #[must_use]
329    pub fn from_vector3_to_vector3(from: Vector3, to: Vector3) -> Self {
330        // SAFETY: pure value-in/out, no preconditions.
331        unsafe { crate::QuaternionFromVector3ToVector3(from, to) }
332    }
333
334    /// Quaternion from rotation matrix. (raymath `QuaternionFromMatrix`)
335    #[inline]
336    #[must_use]
337    pub fn from_matrix(mat: Matrix) -> Self {
338        // SAFETY: pure value-in/out, no preconditions.
339        unsafe { crate::QuaternionFromMatrix(mat) }
340    }
341
342    /// Rotation matrix from quaternion. (raymath `QuaternionToMatrix`)
343    #[inline]
344    #[must_use]
345    pub fn to_matrix(self) -> Matrix {
346        // SAFETY: pure value-in/out, no preconditions.
347        unsafe { crate::QuaternionToMatrix(self) }
348    }
349
350    /// Quaternion from axis and angle (radians). (raymath `QuaternionFromAxisAngle`)
351    #[inline]
352    #[must_use]
353    pub fn from_axis_angle(axis: Vector3, angle: f32) -> Self {
354        // SAFETY: pure value-in/out, no preconditions.
355        unsafe { crate::QuaternionFromAxisAngle(axis, angle) }
356    }
357
358    /// Quaternion from Euler angles (pitch, yaw, roll in radians). (raymath `QuaternionFromEuler`)
359    #[inline]
360    #[must_use]
361    pub fn from_euler(pitch: f32, yaw: f32, roll: f32) -> Self {
362        // SAFETY: pure value-in/out, no preconditions.
363        unsafe { crate::QuaternionFromEuler(pitch, yaw, roll) }
364    }
365
366    /// Convert quaternion to Euler angles (roll, pitch, yaw in radians). (raymath `QuaternionToEuler`)
367    #[inline]
368    #[must_use]
369    pub fn to_euler(self) -> Vector3 {
370        // SAFETY: pure value-in/out, no preconditions.
371        unsafe { crate::QuaternionToEuler(self) }
372    }
373
374    /// Transform quaternion by matrix. (raymath `QuaternionTransform`)
375    #[inline]
376    #[must_use]
377    pub fn transform(self, mat: Matrix) -> Self {
378        // SAFETY: pure value-in/out, no preconditions.
379        unsafe { crate::QuaternionTransform(self, mat) }
380    }
381
382    /// Approximate equality (uses raymath epsilon). (raymath `QuaternionEquals`)
383    #[inline]
384    #[must_use]
385    pub fn equals(self, other: Quaternion) -> bool {
386        // SAFETY: pure value-in/out, no preconditions.
387        unsafe { crate::QuaternionEquals(self, other) != 0 }
388    }
389}
390
391impl core::ops::Add for Quaternion {
392    type Output = Quaternion;
393    #[inline]
394    fn add(self, rhs: Quaternion) -> Quaternion {
395        // SAFETY: QuaternionAdd is a pure value-in/out raymath fn; no preconditions.
396        unsafe { crate::QuaternionAdd(self, rhs) }
397    }
398}
399impl core::ops::AddAssign for Quaternion {
400    #[inline]
401    fn add_assign(&mut self, rhs: Quaternion) {
402        *self = *self + rhs;
403    }
404}
405
406impl core::ops::Sub for Quaternion {
407    type Output = Quaternion;
408    #[inline]
409    fn sub(self, rhs: Quaternion) -> Quaternion {
410        // SAFETY: QuaternionSubtract is a pure value-in/out raymath fn; no preconditions.
411        unsafe { crate::QuaternionSubtract(self, rhs) }
412    }
413}
414impl core::ops::SubAssign for Quaternion {
415    #[inline]
416    fn sub_assign(&mut self, rhs: Quaternion) {
417        *self = *self - rhs;
418    }
419}
420
421impl core::ops::Mul for Quaternion {
422    type Output = Quaternion;
423    #[inline]
424    fn mul(self, rhs: Quaternion) -> Quaternion {
425        // SAFETY: QuaternionMultiply is a pure value-in/out raymath fn; no preconditions.
426        unsafe { crate::QuaternionMultiply(self, rhs) }
427    }
428}
429impl core::ops::MulAssign for Quaternion {
430    #[inline]
431    fn mul_assign(&mut self, rhs: Quaternion) {
432        *self = *self * rhs;
433    }
434}
435
436impl core::ops::Mul<f32> for Quaternion {
437    type Output = Quaternion;
438    #[inline]
439    fn mul(self, rhs: f32) -> Quaternion {
440        // SAFETY: QuaternionScale is a pure value-in/out raymath fn; no preconditions.
441        unsafe { crate::QuaternionScale(self, rhs) }
442    }
443}
444impl core::ops::MulAssign<f32> for Quaternion {
445    #[inline]
446    fn mul_assign(&mut self, rhs: f32) {
447        *self = *self * rhs;
448    }
449}
450
451impl core::ops::Div for Quaternion {
452    type Output = Quaternion;
453    #[inline]
454    fn div(self, rhs: Quaternion) -> Quaternion {
455        // SAFETY: QuaternionDivide is a pure value-in/out raymath fn; no preconditions.
456        unsafe { crate::QuaternionDivide(self, rhs) }
457    }
458}
459impl core::ops::DivAssign for Quaternion {
460    #[inline]
461    fn div_assign(&mut self, rhs: Quaternion) {
462        *self = *self / rhs;
463    }
464}
465
466/// Convert quaternion to axis-angle representation.
467/// Returns `(axis, angle_radians)`. (raymath `QuaternionToAxisAngle`)
468pub fn quaternion_to_axis_angle(q: Quaternion) -> (Vector3, f32) {
469    let mut out_axis = Vector3 {
470        x: 0.0,
471        y: 0.0,
472        z: 0.0,
473    };
474    let mut out_angle: f32 = 0.0;
475    // SAFETY: QuaternionToAxisAngle writes through non-null, properly aligned out-ptrs;
476    // both are distinct stack allocations with no aliasing.
477    unsafe { crate::QuaternionToAxisAngle(q, &mut out_axis, &mut out_angle) };
478    (out_axis, out_angle)
479}