stereokit_rust/maths.rs
1use crate::{
2 material::Cull,
3 mesh::{Mesh, VindT, mesh_ray_intersect},
4 model::{Model, model_ray_intersect},
5};
6use std::{
7 fmt::Display,
8 ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
9};
10
11/// Native code use this as bool
12pub type Bool32T = i32;
13
14/// Blends (Linear Interpolation) between two scalars, based on a 'blend' value, where 0 is a, and 1 is b. Doesn't clamp
15/// percent for you.
16/// <https://stereokit.net/Pages/StereoKit/SKMath/Lerp.html>
17/// * `a` - First item in the blend, or '0.0' blend.
18/// * `b` - Second item in the blend, or '1.0' blend.
19/// * `t` - A blend value between 0 and 1. Can be outside this range, it'll just interpolate outside of the a, b range.
20///
21/// Returns an unclamped blend of a and b.
22/// see also [`crate::util::Color128::lerp`]
23pub fn lerp(a: f32, b: f32, t: f32) -> f32 {
24 a + (b - a) * t
25}
26
27/// Calculates the minimum angle 'distance' between two angles. This covers wraparound cases like: the minimum distance
28/// between 10 and 350 is 20.
29/// <https://stereokit.net/Pages/StereoKit/SKMath/AngleDist.html>
30/// * `a` - First angle, in degrees.
31/// * `b` - Second angle, in degrees.
32///
33/// returns : Degrees 0-180, the minimum angle between a and b.
34pub fn angle_dist(a: f32, b: f32) -> f32 {
35 let delta = (b - a + 180.0) % 360.0 - 180.0;
36 (if delta < -180.0 { delta + 360.0 } else { delta }).abs()
37}
38
39pub mod units {
40 /// Converts centimeters to meters. There are 100cm in 1m. In StereoKit 1 unit is also 1 meter,
41 /// so `25 * Units.cm2m == 0.25`, 25 centimeters is .25 meters/units.
42 pub const CM2M: f32 = 0.01;
43 /// Converts millimeters to meters. There are 1000mm in 1m. In StereoKit 1 unit is 1 meter,
44 /// so `250 * Units.mm2m == 0.25`, 250 millimeters is .25 meters/units.
45 pub const MM2M: f32 = 0.001;
46 ///Converts meters to centimeters. There are 100cm in 1m, so this just multiplies by 100.
47 pub const M2CM: f32 = 100.0;
48 ///Converts meters to millimeters. There are 1000mm in 1m, so this just multiplies by 1000.
49 pub const M2MM: f32 = 1000.0;
50
51 /// Converts centimeters to meters. There are 100cm in 1m. In StereoKit 1 unit is also 1 meter,
52 /// so `25 * U.cm == 0.25`, 25 centimeters is .25 meters/units.
53 pub const CM: f32 = 0.01;
54 /// Converts millimeters to meters. There are 1000mm in 1m. In StereoKit 1 unit is 1 meter,
55 /// so `250 * Units.mm2m == 0.25`, 250 millimeters is .25 meters/units.
56 pub const MM: f32 = 0.001;
57 /// StereoKit's default unit is meters, but sometimes it's nice to be explicit!
58 pub const M: f32 = 1.0;
59 /// Converts meters to kilometers. There are 1000m in 1km, so this just multiplies by 1000.
60 pub const KM: f32 = 1000.0;
61}
62
63/// A vector with 2 components: x and y. This can represent a point in 2D space, a directional vector, or any other sort
64/// of value with 2 dimensions to it!
65/// <https://stereokit.net/Pages/StereoKit/Vec2.html>
66///
67/// see also [`glam::Vec2`]
68/// ### Examples
69/// ```
70/// use stereokit_rust::maths::Vec2;
71///
72/// let vec2 = Vec2::new(1.0, 2.0);
73/// let vec2a = Vec2 { x: 1.0, y: 2.0 };
74/// let vec2b = Vec2::X + Vec2::Y * 2.0;
75/// let vec3c: Vec2 = [1.0, 2.0].into();
76///
77/// assert_eq!(vec2, vec2a);
78/// assert_eq!(vec2a + vec2b, Vec2 { x: 2.0, y: 4.0 });
79/// assert_eq!(vec3c, Vec2 { x: 1.0, y: 2.0 });
80/// assert_eq!(vec2a.length_sq(), 5.0);
81/// assert_eq!(Vec2::Y.angle(), 90.0);
82/// assert_eq!(vec2a.magnitude(), (5.0f32).sqrt());
83/// assert! (vec2a.get_normalized().length() - 1.0 < f32::EPSILON);
84/// assert_eq!(Vec2::angle_between(Vec2::X, Vec2::Y), 90.0);
85/// assert_eq!(Vec2::dot(Vec2::X, Vec2::Y), 0.0);
86/// ```
87#[derive(Debug, Default, Copy, Clone)]
88#[repr(C)]
89pub struct Vec2 {
90 pub x: f32,
91 pub y: f32,
92}
93
94impl From<glam::Vec2> for Vec2 {
95 fn from(val: glam::Vec2) -> Self {
96 Vec2 { x: val.x, y: val.y }
97 }
98}
99
100impl From<Vec2> for glam::Vec2 {
101 fn from(val: Vec2) -> Self {
102 Self::new(val.x, val.y)
103 }
104}
105
106impl From<[f32; 2]> for Vec2 {
107 fn from(val: [f32; 2]) -> Self {
108 Vec2 { x: val[0], y: val[1] }
109 }
110}
111
112/// Warning: Equality with a precision of 0.1 millimeter
113impl PartialEq for Vec2 {
114 /// Warning: Equality with a precision of 0.1 millimeter
115 /// ```
116 /// use stereokit_rust::maths::Vec2;
117 /// assert_eq!(
118 /// Vec2 { x: 0.045863353, y: 0.030000005 } ,
119 /// Vec2 { x: 0.045863353, y: 0.030000005 } );
120 /// ```
121 /// ```
122 /// use stereokit_rust::maths::Vec2;
123 /// assert_ne!(
124 /// Vec2 { x: 10.045863353, y: 0.030000005 } ,
125 /// Vec2 { x: 0.045863353, y: 0.030000005 } );
126 /// ```
127 fn eq(&self, other: &Self) -> bool {
128 ((self.x - other.x).abs() < 0.0001) && ((self.y - other.y).abs() < 0.0001)
129 }
130}
131
132impl Vec2 {
133 /// A Vec2 with all components at zero, this is the same as new Vec2(0,0).
134 /// <https://stereokit.net/Pages/StereoKit/Vec2/Zero.html>
135 pub const ZERO: Self = Self::new(0.0, 0.0);
136
137 /// A Vec2 with all components at one, this is the same as new Vec2(1,1).
138 /// <https://stereokit.net/Pages/StereoKit/Vec2/One.html>
139 pub const ONE: Self = Self::new(1.0, 1.0);
140
141 /// A normalized Vector that points down the X axis, this is the same as new Vec2(1,0).
142 /// <https://stereokit.net/Pages/StereoKit/Vec2/UnitX.html>
143 pub const X: Self = Self::new(1.0, 0.0);
144
145 /// A normalized Vector that points down the Y axis, this is the same as new Vec2(0,1).
146 /// <https://stereokit.net/Pages/StereoKit/Vec2/UnitY.html>
147 pub const Y: Self = Self::new(0.0, 1.0);
148
149 /// A normalized Vector that points up the X axis, this is the same as new Vec2(-1,0).
150 pub const NEG_X: Self = Self::new(-1.0, 0.0);
151
152 /// A normalized Vector that points up the Y axis, this is the same as new Vec2(0,-1).
153 pub const NEG_Y: Self = Self::new(0.0, -1.0);
154
155 /// A basic constructor, just copies the values in!
156 /// <https://stereokit.net/Pages/StereoKit/Vec2/Vec2.html>
157 #[inline]
158 pub const fn new(x: f32, y: f32) -> Self {
159 Self { x, y }
160 }
161
162 /// Returns the counter-clockwise degrees from `[1,0]`. Resulting value is between 0 and 360. Vector does not need
163 /// to be normalized.
164 /// <https://stereokit.net/Pages/StereoKit/Vec2/Angle.html>
165 ///
166 /// ### Examples
167 /// ```
168 /// use stereokit_rust::maths::Vec2;
169 ///
170 /// let vec2 = Vec2::new(1.0, 1.0);
171 /// assert_eq!(vec2.angle(), 45.0);
172 ///
173 /// let vec2 = Vec2::new(0.0, 1.0);
174 /// assert_eq!(vec2.angle(), 90.0);
175 ///
176 /// let vec2 = Vec2::new(-1.0, 1.0);
177 /// assert_eq!(vec2.angle(), 135.0);
178 ///
179 /// let vec2 = Vec2::new(-1.0, 0.0);
180 /// assert_eq!(vec2.angle(), 180.0);
181 ///
182 /// let vec2 = Vec2::new(-1.0, -1.0);
183 /// assert_eq!(vec2.angle(), 225.0);
184 /// ```
185 #[inline]
186 pub fn angle(&self) -> f32 {
187 let mut result = self.y.atan2(self.x).to_degrees();
188 if result < 0.0 {
189 result += 360.0
190 };
191 result
192 }
193
194 /// Checks if a point is within a certain radius of this one. This is an easily readable shorthand of the squared
195 /// distance check.
196 /// <https://stereokit.net/Pages/StereoKit/Vec2/InRadius.html>
197 /// * `point` - The point to check against.
198 /// * `radius` - The distance to check within.
199 ///
200 /// Returns true if the points are within radius of each other, false not.
201 /// ### Examples
202 /// ```
203 /// use stereokit_rust::maths::Vec2;
204 ///
205 /// let vec2 = Vec2::new(1.0, 1.0);
206 /// let vec2_in = Vec2::new(1.1, 1.1);
207 /// let vec2_out = Vec2::new(2.0, 2.0);
208 /// assert!(vec2.in_radius(vec2_in, 0.2));
209 /// assert!(!vec2.in_radius(vec2_out, 0.2));
210 /// ```
211 #[inline]
212 pub fn in_radius(&self, point: Self, radius: f32) -> bool {
213 Self::distance(*self, point) <= radius
214 }
215
216 /// Turns this vector into a normalized vector (vector with a length of 1) from the current vector. Will not work
217 /// properly if the vector has a length of zero. Vec2::get_normalized is faster.
218 /// <https://stereokit.net/Pages/StereoKit/Vec2/Normalize.html>
219 ///
220 /// ### Examples
221 /// ```
222 /// use stereokit_rust::maths::Vec2;
223 ///
224 /// let mut vec2 = Vec2::new(1.0, 1.0);
225 /// assert!((vec2.length() - 1.4142135).abs() < f32::EPSILON);
226 ///
227 /// vec2.normalize();
228 /// assert!((vec2.length() - 1.0).abs() < f32::EPSILON);
229 /// ```
230 #[inline]
231 pub fn normalize(&mut self) {
232 let n = *self * (self.length().recip());
233 self.x = n.x;
234 self.y = n.y;
235 }
236
237 /// This is the length of the vector! Or the distance from the origin to this point. Uses f32::sqrt, so it’s not
238 /// dirt cheap or anything.
239 /// <https://stereokit.net/Pages/StereoKit/Vec2/Length.html>
240 ///
241 /// ### Examples
242 /// ```
243 /// use stereokit_rust::maths::Vec2;
244 ///
245 /// let vec2 = Vec2::new(1.0, 1.0);
246 /// assert_eq!(vec2.length(), (2.0f32).sqrt());
247 /// ```
248 #[inline]
249 pub fn length(&self) -> f32 {
250 Self::dot(*self, *self).sqrt()
251 }
252
253 /// This is the squared length/magnitude of the vector! It skips the Sqrt call, and just gives you the squared
254 /// version for speedy calculations that can work with it squared.
255 /// <https://stereokit.net/Pages/StereoKit/Vec2/LengthSq.html>
256 ///
257 /// ### Examples
258 /// ```
259 /// use stereokit_rust::maths::Vec2;
260 ///
261 /// let vec2 = Vec2::new(1.0, 1.0);
262 /// assert_eq!(vec2.length_sq(), 2.0);
263 /// ```
264 #[inline]
265 pub fn length_sq(&self) -> f32 {
266 Self::dot(*self, *self)
267 }
268
269 /// Magnitude is the length of the vector! Or the distance from the origin to this point. Uses f32::sqrt, so it’s
270 /// not dirt cheap or anything.
271 /// <https://stereokit.net/Pages/StereoKit/Vec2/Magnitude.html>
272 ///
273 /// ### Examples
274 /// ```
275 /// use stereokit_rust::maths::Vec2;
276 ///
277 /// let vec2 = Vec2::new(1.0, 1.0);
278 /// assert_eq!(vec2.length(), vec2.magnitude());
279 /// ```
280 #[inline]
281 pub fn magnitude(&self) -> f32 {
282 self.length()
283 }
284
285 /// This is the squared magnitude of the vector! It skips the Sqrt call, and just gives you the squared version for
286 /// speedy calculations that can work with it squared. Vec2::length_squared is faster
287 /// <https://stereokit.net/Pages/StereoKit/Vec2/MagnitudeSq.html>
288 ///
289 /// ### Examples
290 /// ```
291 /// use stereokit_rust::maths::Vec2;
292 ///
293 /// let vec2 = Vec2::new(1.0, 1.0);
294 /// assert_eq!(vec2.length_sq(), vec2.magnitude_sq());
295 /// ```
296 #[inline]
297 pub fn magnitude_sq(&self) -> f32 {
298 self.length_sq()
299 }
300
301 /// Creates a normalized vector (vector with a length of 1) from the current vector. Will not work properly if the
302 /// vector has a length of zero.
303 /// <https://stereokit.net/Pages/StereoKit/Vec2/Normalized.html>
304 ///
305 /// ### Examples
306 /// ```
307 /// use stereokit_rust::maths::Vec2;
308 ///
309 /// let vec2 = Vec2::new(1.0, 1.0);
310 /// assert!((vec2.get_normalized().length() - 1.0).abs() < f32::EPSILON);
311 /// ```
312 #[inline]
313 pub fn get_normalized(&self) -> Self {
314 *self * (self.length().recip())
315 }
316
317 /// Promotes this Vec2 to a Vec3, using 0 for the Y axis.
318 /// <https://stereokit.net/Pages/StereoKit/Vec2/X0Y.html>
319 ///
320 /// ### Examples
321 /// ```
322 /// use stereokit_rust::maths::{Vec2, Vec3};
323 ///
324 /// let vec2 = Vec2::new(1.0, 1.0);
325 /// assert_eq!(vec2.x0y(), Vec3::new(1.0, 0.0, 1.0));
326 /// ```
327 #[inline]
328 pub fn x0y(&self) -> Vec3 {
329 Vec3 { x: self.x, y: 0.0, z: self.y }
330 }
331
332 /// Promotes this Vec2 to a Vec3, using 0 for the Z axis.
333 /// <https://stereokit.net/Pages/StereoKit/Vec2/XY0.html>
334 ///
335 /// ### Examples
336 /// ```
337 /// use stereokit_rust::maths::{Vec2, Vec3};
338 ///
339 /// let vec2 = Vec2::new(1.0, 1.0);
340 /// assert_eq!(vec2.xy0(), Vec3::new(1.0, 1.0, 0.0));
341 /// ```
342 #[inline]
343 pub fn xy0(&self) -> Vec3 {
344 Vec3 { x: self.x, y: self.y, z: 0.0 }
345 }
346
347 /// A transpose swizzle property, returns (y,x)
348 /// <https://stereokit.net/Pages/StereoKit/Vec2/YX.html>
349 ///
350 /// ### Examples
351 /// ```
352 /// use stereokit_rust::maths::{Vec2, Vec3};
353 ///
354 /// let vec2 = Vec2::new(1.1, 1.2);
355 /// assert_eq!(vec2.yx(), Vec2::new(1.2, 1.1));
356 /// ```
357 #[inline]
358 pub fn yx(&self) -> Self {
359 Self { x: self.y, y: self.x }
360 }
361
362 /// Calculates a signed angle between two vectors in degrees! Sign will be positive if B is counter-clockwise (left)
363 /// of A, and negative if B is clockwise (right) of A. Vectors do not need to be normalized. NOTE: Since this will
364 /// return a positive or negative angle, order of parameters matters!
365 /// <https://stereokit.net/Pages/StereoKit/Vec2/AngleBetween.html>
366 /// * `a` - The first, initial vector, A. Does not need to be normalized.
367 /// * `b` - The second, final vector, B. Does not need to be normalized.
368 ///
369 /// Returns a signed angle between two vectors in degrees! Sign will be positive if B is counter-clockwise (left)
370 /// of A, and negative if B is clockwise (right) of A.
371 /// ### Examples
372 /// ```
373 /// use stereokit_rust::maths::Vec2;
374 ///
375 /// let vec2_a = Vec2::new(1.0, 0.0);
376 /// let vec2_b = Vec2::new(0.0, 1.0);
377 /// assert_eq!(Vec2::angle_between(vec2_a, vec2_b), 90.0);
378 ///
379 /// let vec2_a = Vec2::new(1.0, 0.0);
380 /// let vec2_b = Vec2::new(0.0, -1.0);
381 /// assert_eq!(Vec2::angle_between(vec2_a, vec2_b), 90.0);
382 ///
383 /// let vec2_a = Vec2::new(1.0, 0.0);
384 /// let vec2_b = Vec2::new(-1.0, 0.0);
385 /// assert_eq!(Vec2::angle_between(vec2_a, vec2_b), 180.0);
386 ///
387 /// let vec2_a = Vec2::new(1.0, 0.0);
388 /// let vec2_b = Vec2::new(1.0, 0.0);
389 /// assert_eq!(Vec2::angle_between(vec2_a, vec2_b), 0.0);
390 /// ```
391 #[inline]
392 pub fn angle_between(a: Self, b: Self) -> f32 {
393 (Self::dot(a, b) / (a.length_sq() * b.length_sq()).sqrt()).acos().to_degrees()
394 }
395
396 /// Creates a normalized delta vector that points out from an origin point to a target point!
397 /// <https://stereokit.net/Pages/StereoKit/Vec2/Direction.html>
398 /// * `to` - The target point.
399 /// * `from` - And the origin point!
400 ///
401 /// Returns direction from one point to another.
402 /// ### Examples
403 /// ```
404 /// use stereokit_rust::maths::Vec2;
405 ///
406 /// let vec2_a = Vec2::new(1.0, 0.0);
407 /// let vec2_b = Vec2::new(0.0, 1.0);
408 /// assert_eq!(Vec2::direction(vec2_b, vec2_a), Vec2::new(-0.70710677, 0.70710677));
409 /// ```
410 #[inline]
411 pub fn direction(to: Self, from: Self) -> Self {
412 (to - from).get_normalized()
413 }
414
415 /// Calculates the distance between two points in space! Make sure they’re in the same coordinate space! Uses a Sqrt,
416 /// so it’s not blazing fast, prefer DistanceSq when possible.
417 /// <https://stereokit.net/Pages/StereoKit/Vec2/Distance.html>
418 /// * `a` - The first point.
419 /// * `b` - And the second point.
420 ///
421 /// Returns distance between the two points.
422 /// ### Examples
423 /// ```
424 /// use stereokit_rust::maths::Vec2;
425 ///
426 /// let vec2_a = Vec2::new(1.0, 0.0);
427 /// let vec2_b = Vec2::new(0.0, 1.0);
428 /// assert_eq!(Vec2::distance(vec2_a, vec2_b), (2.0f32).sqrt());
429 /// ```
430 #[inline]
431 pub fn distance(a: Self, b: Self) -> f32 {
432 (a - b).length()
433 }
434
435 /// Calculates the distance between two points in space, but leaves them squared! Make sure they’re in the same
436 /// coordinate space! This is a fast function :)
437 /// <https://stereokit.net/Pages/StereoKit/Vec2/DistanceSq.html>
438 /// - `a` - The first point.
439 /// - `b` - The second point.
440 ///
441 /// Returns distance between the two points, but squared.
442 /// ### Examples
443 /// ```
444 /// use stereokit_rust::maths::Vec2;
445 ///
446 /// let vec2_a = Vec2::new(1.0, 0.0);
447 /// let vec2_b = Vec2::new(0.0, 1.0);
448 /// assert_eq!(Vec2::distance_sq(vec2_a, vec2_b), 2.0);
449 /// ```
450 #[inline]
451 pub fn distance_sq(a: Self, b: Self) -> f32 {
452 (a - b).length_sq()
453 }
454
455 /// The dot product is an extremely useful operation! One major use is to determine how similar two vectors are.
456 /// If the vectors are Unit vectors (magnitude/length of 1), then the result will be 1 if the vectors are the same,
457 /// -1 if they’re opposite, and a gradient in-between with 0 being perpendicular.
458 /// <https://stereokit.net/Pages/StereoKit/Vec2/Dot.html>
459 /// * `a` - The first vector.
460 /// * `b` - The second vector.
461 ///
462 /// Returns the dot product!
463 /// ### Examples
464 /// ```
465 /// use stereokit_rust::maths::Vec2;
466 ///
467 /// let vec2_a = Vec2::new(1.0, 0.0);
468 /// let vec2_b = Vec2::new(0.0, 1.0);
469 /// assert_eq!(Vec2::dot(vec2_a, vec2_b), 0.0);
470 ///
471 /// let vec2_a = Vec2::new(1.0, 0.0);
472 /// let vec2_b = Vec2::new(1.0, 0.0);
473 /// assert_eq!(Vec2::dot(vec2_a, vec2_b), 1.0);
474 ///
475 /// let vec2_a = Vec2::new(1.0, 0.0);
476 /// let vec2_b = Vec2::new(-1.0, 0.0);
477 /// assert_eq!(Vec2::dot(vec2_a, vec2_b), -1.0);
478 /// ```
479 #[inline]
480 pub fn dot(a: Self, b: Self) -> f32 {
481 (a.x * b.x) + (a.y * b.y)
482 }
483
484 /// Creates a vector pointing in the direction of the angle, with a length of 1. Angles are counter-clockwise, and
485 /// start from (1,0), so an angle of 90 will be (0,1).
486 /// <https://stereokit.net/Pages/StereoKit/Vec2/FromAngle.html>
487 /// * `degrees` - Counter-clockwise angle from(1,0) in degrees.
488 ///
489 /// Returns a unit vector (length of 1), pointing towards degrees.
490 /// ### Examples
491 /// ```
492 /// use stereokit_rust::maths::Vec2;
493 ///
494 /// let vec2 = Vec2::from_angles(0.0);
495 /// assert_eq!(vec2, Vec2::new(1.0, 0.0));
496 ///
497 /// let vec2 = Vec2::from_angles(90.0);
498 /// assert_eq!(vec2, Vec2::new(0.0, 1.0));
499 ///
500 /// let vec2 = Vec2::from_angles(180.0);
501 /// assert_eq!(vec2, Vec2::new(-1.0, 0.0));
502 ///
503 /// let vec2 = Vec2::from_angles(270.0);
504 /// assert_eq!(vec2, Vec2::new(0.0, -1.0));
505 /// ```
506 #[inline]
507 pub fn from_angles(degree: f32) -> Self {
508 Self { x: degree.to_radians().cos(), y: degree.to_radians().sin() }
509 }
510
511 /// Blends (Linear Interpolation) between two vectors, based on a ‘blend’ value, where 0 is a, and 1 is b.
512 /// Doesn’t clamp percent for you.
513 /// <https://stereokit.net/Pages/StereoKit/Vec2/Lerp.html>
514 /// * `a` - The first vector to blend, or '0.0' blend.
515 /// * `b` - The second vector to blend, or '1.0' blend.
516 /// * `blend` - A value between 0 and 1. Can be outside this range, it’ll just interpolate outside of the a, b range.
517 ///
518 /// Returns an unclamped blend of a and b.
519 /// ### Examples
520 /// ```
521 /// use stereokit_rust::maths::Vec2;
522 ///
523 /// let vec2_a = Vec2::new(1.0, 0.0);
524 /// let vec2_b = Vec2::new(0.0, 1.0);
525 /// assert_eq!(Vec2::lerp(vec2_a, vec2_b, 0.5), Vec2::new(0.5, 0.5));
526 /// ```
527 #[inline]
528 pub fn lerp(a: Self, b: Self, blend: f32) -> Self {
529 a + ((b - a) * blend)
530 }
531
532 /// Returns a vector where each element is the maximum value for each corresponding pair.
533 /// <https://stereokit.net/Pages/StereoKit/Vec2/Max.html>
534 /// * `a` - Order isn't important here.
535 /// * `b` - Order isn't important here.
536 ///
537 /// Returns the maximum value for each corresponding vector pair.
538 /// ### Examples
539 /// ```
540 /// use stereokit_rust::maths::Vec2;
541 ///
542 /// let vec2_a = Vec2::new(1.0, 0.5);
543 /// let vec2_b = Vec2::new(0.9, 1.2);
544 /// assert_eq!(Vec2::max(vec2_a, vec2_b), Vec2::new(1.0, 1.2));
545 /// ```
546 #[inline]
547 pub fn max(a: Self, b: Self) -> Self {
548 Self { x: f32::max(a.x, b.x), y: f32::max(a.y, b.y) }
549 }
550
551 /// Returns a vector where each element is the minimum value for each corresponding pair.
552 /// <https://stereokit.net/Pages/StereoKit/Vec2/Min.html>
553 /// * `a` - Order isn't important here.
554 /// * `b` - Order isn't important here.
555 ///
556 /// Returns the minimum value for each corresponding vector pair.
557 /// ### Examples
558 /// ```
559 /// use stereokit_rust::maths::Vec2;
560 ///
561 /// let vec2_a = Vec2::new(1.0, 0.2);
562 /// let vec2_b = Vec2::new(0.1, 1.0);
563 /// assert_eq!(Vec2::min(vec2_a, vec2_b), Vec2::new(0.1, 0.2));
564 /// ```
565 #[inline]
566 pub fn min(a: Self, b: Self) -> Self {
567 Self { x: f32::min(a.x, b.x), y: f32::min(a.y, b.y) }
568 }
569
570 /// Absolute value of each component, this may be usefull in some case
571 ///
572 /// ### Examples
573 /// ```
574 /// use stereokit_rust::maths::Vec2;
575 ///
576 /// let vec2 = Vec2::new(-1.4, 1.2);
577 /// assert_eq!(vec2.abs(), Vec2::new(1.4, 1.2));
578 /// ```
579 #[inline]
580 pub fn abs(&self) -> Self {
581 Self { x: self.x.abs(), y: self.y.abs() }
582 }
583}
584
585impl Display for Vec2 {
586 /// Mostly for debug purposes, this is a decent way to log or inspect the vector in debug mode. Looks like “[x, y]”
587 /// <https://stereokit.net/Pages/StereoKit/Vec2/ToString.html>
588 ///
589 /// ### Examples
590 /// ```
591 /// use stereokit_rust::maths::Vec2;
592 ///
593 /// let vec2 = Vec2::new(1.0, 1.0);
594 /// assert_eq!(vec2.to_string(), "[x:1, y:1]");
595 /// ```
596 #[inline]
597 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
598 write!(f, "[x:{}, y:{}]", self.x, self.y)
599 }
600}
601/// A component-wise vector division.
602/// <https://stereokit.net/Pages/StereoKit/Vec2/op_Division.html>
603impl Div<Vec2> for Vec2 {
604 type Output = Self;
605
606 /// ### Examples
607 /// ```
608 /// use stereokit_rust::maths::Vec2;
609 ///
610 /// let vec2_a = Vec2::new(1.0, 2.0);
611 /// let vec2_b = Vec2::new(2.0, 4.0);
612 /// assert_eq!(vec2_a / vec2_b, Vec2::new(0.5, 0.5));
613 /// ```
614 #[inline]
615 fn div(self, rhs: Self) -> Self::Output {
616 Self { x: self.x.div(rhs.x), y: self.y.div(rhs.y) }
617 }
618}
619
620/// A component-wise vector division.
621/// <https://stereokit.net/Pages/StereoKit/Vec2/op_Division.html>
622impl DivAssign<Vec2> for Vec2 {
623 /// ### Examples
624 /// ```
625 /// use stereokit_rust::maths::Vec2;
626 ///
627 /// let mut vec2_a = Vec2::new(1.0, 2.0);
628 /// let vec2_b = Vec2::new(2.0, 4.0);
629 /// vec2_a /= vec2_b;
630 /// assert_eq!(vec2_a, Vec2::new(0.5, 0.5));
631 /// ```
632 #[inline]
633 fn div_assign(&mut self, rhs: Self) {
634 self.x.div_assign(rhs.x);
635 self.y.div_assign(rhs.y);
636 }
637}
638
639/// A component-wise vector division.
640/// <https://stereokit.net/Pages/StereoKit/Vec2/op_Division.html>
641impl Div<f32> for Vec2 {
642 type Output = Self;
643
644 /// ### Examples
645 /// ```
646 /// use stereokit_rust::maths::Vec2;
647 ///
648 /// let vec2_a = Vec2::new(1.0, 2.0);
649 /// assert_eq!(vec2_a / 2.0, Vec2::new(0.5, 1.0));
650 /// ```
651 #[inline]
652 fn div(self, rhs: f32) -> Self::Output {
653 Self { x: self.x.div(rhs), y: self.y.div(rhs) }
654 }
655}
656
657/// A component-wise vector division.
658/// <https://stereokit.net/Pages/StereoKit/Vec2/op_Division.html>
659impl DivAssign<f32> for Vec2 {
660 /// ### Examples
661 /// ```
662 /// use stereokit_rust::maths::Vec2;
663 ///
664 /// let mut vec2_a = Vec2::new(1.0, 2.0);
665 /// vec2_a /= 2.0;
666 /// assert_eq!(vec2_a, Vec2::new(0.5, 1.0));
667 /// ```
668 #[inline]
669 fn div_assign(&mut self, rhs: f32) {
670 self.x.div_assign(rhs);
671 self.y.div_assign(rhs);
672 }
673}
674
675/// A component-wise vector division.
676/// <https://stereokit.net/Pages/StereoKit/Vec2/op_Division.html>
677impl Div<Vec2> for f32 {
678 type Output = Vec2;
679
680 /// ### Examples
681 /// ```
682 /// use stereokit_rust::maths::Vec2;
683 ///
684 /// let vec2_a = Vec2::new(1.0, 2.0);
685 /// assert_eq!(2.0 / vec2_a, Vec2::new(2.0, 1.0));
686 /// ```
687 #[inline]
688 fn div(self, rhs: Vec2) -> Self::Output {
689 Vec2 { x: self.div(rhs.x), y: self.div(rhs.y) }
690 }
691}
692
693/// A component-wise vector multiplication, same thing as a non-uniform scale. NOT a dot product! Commutative.
694/// <https://stereokit.net/Pages/StereoKit/Vec2/op_Multiply.html>
695impl Mul<Vec2> for Vec2 {
696 type Output = Self;
697
698 /// ### Examples
699 /// ```
700 /// use stereokit_rust::maths::Vec2;
701 ///
702 /// let vec2_a = Vec2::new(1.0, 2.0);
703 /// let vec2_b = Vec2::new(2.0, 4.0);
704 /// assert_eq!(vec2_a * vec2_b, Vec2::new(2.0, 8.0));
705 /// ```
706 #[inline]
707 fn mul(self, rhs: Self) -> Self::Output {
708 Self { x: self.x.mul(rhs.x), y: self.y.mul(rhs.y) }
709 }
710}
711
712/// A component-wise vector multiplication, same thing as a non-uniform scale. NOT a dot product! Commutative.
713/// <https://stereokit.net/Pages/StereoKit/Vec2/op_Multiply.html>
714impl MulAssign<Vec2> for Vec2 {
715 /// ### Examples
716 /// ```
717 /// use stereokit_rust::maths::Vec2;
718 ///
719 /// let vec2_a = Vec2::new(1.0, 2.0);
720 /// let mut vec2_b = Vec2::new(2.0, 4.0);
721 /// vec2_b *= vec2_a;
722 /// assert_eq!(vec2_b, Vec2::new(2.0, 8.0));
723 /// ```
724 #[inline]
725 fn mul_assign(&mut self, rhs: Self) {
726 self.x.mul_assign(rhs.x);
727 self.y.mul_assign(rhs.y);
728 }
729}
730
731/// A component-wise vector multiplication, same thing as a non-uniform scale. NOT a dot product! Commutative.
732/// <https://stereokit.net/Pages/StereoKit/Vec2/op_Multiply.html>
733impl Mul<f32> for Vec2 {
734 type Output = Self;
735
736 /// ### Examples
737 /// ```
738 /// use stereokit_rust::maths::Vec2;
739 ///
740 /// let vec2_a = Vec2::new(1.0, 2.0);
741 /// assert_eq!(vec2_a * 2.0, Vec2::new(2.0, 4.0));
742 /// ```
743 #[inline]
744 fn mul(self, rhs: f32) -> Self::Output {
745 Self { x: self.x.mul(rhs), y: self.y.mul(rhs) }
746 }
747}
748
749/// A component-wise vector multiplication, same thing as a non-uniform scale. NOT a dot product! Commutative.
750/// <https://stereokit.net/Pages/StereoKit/Vec2/op_Multiply.html>
751impl MulAssign<f32> for Vec2 {
752 /// ### Examples
753 /// ```
754 /// use stereokit_rust::maths::Vec2;
755 ///
756 /// let mut vec2_a = Vec2::new(1.0, 2.0);
757 /// vec2_a *= 2.0;
758 /// assert_eq!(vec2_a, Vec2::new(2.0, 4.0));
759 ///```
760 #[inline]
761 fn mul_assign(&mut self, rhs: f32) {
762 self.x.mul_assign(rhs);
763 self.y.mul_assign(rhs);
764 }
765}
766
767/// A component-wise vector multiplication, same thing as a non-uniform scale. NOT a dot product! Commutative.
768/// <https://stereokit.net/Pages/StereoKit/Vec2/op_Multiply.html>
769impl Mul<Vec2> for f32 {
770 type Output = Vec2;
771
772 /// ### Examples
773 /// ```
774 /// use stereokit_rust::maths::Vec2;
775 ///
776 /// let vec2_a = Vec2::new(1.0, 2.0);
777 /// assert_eq!(2.0 * vec2_a, Vec2::new(2.0, 4.0));
778 /// ```
779 #[inline]
780 fn mul(self, rhs: Vec2) -> Self::Output {
781 Vec2 { x: self.mul(rhs.x), y: self.mul(rhs.y) }
782 }
783}
784
785/// Adds matching components together. Commutative.
786/// <https://stereokit.net/Pages/StereoKit/Vec2/op_Addition.html>
787impl Add<Vec2> for Vec2 {
788 type Output = Self;
789
790 /// ### Examples
791 /// ```
792 /// use stereokit_rust::maths::Vec2;
793 ///
794 /// let vec2_a = Vec2::new(1.0, 2.0);
795 /// let vec2_b = Vec2::new(2.0, 4.0);
796 /// assert_eq!(vec2_a + vec2_b, Vec2::new(3.0, 6.0));
797 /// ```
798 #[inline]
799 fn add(self, rhs: Self) -> Self::Output {
800 Self { x: self.x.add(rhs.x), y: self.y.add(rhs.y) }
801 }
802}
803
804/// Adds matching components together. Commutative.
805/// <https://stereokit.net/Pages/StereoKit/Vec2/op_Addition.html>
806impl AddAssign<Vec2> for Vec2 {
807 /// ### Examples
808 /// ```
809 /// use stereokit_rust::maths::Vec2;
810 ///
811 /// let mut vec2_a = Vec2::new(1.0, 2.0);
812 /// let vec2_b = Vec2::new(2.0, 4.0);
813 /// vec2_a += vec2_b;
814 /// assert_eq!(vec2_a, Vec2::new(3.0, 6.0));
815 /// ```
816 #[inline]
817 fn add_assign(&mut self, rhs: Self) {
818 self.x.add_assign(rhs.x);
819 self.y.add_assign(rhs.y);
820 }
821}
822
823/// Subtracts matching components from eachother. Not commutative.
824/// <https://stereokit.net/Pages/StereoKit/Vec2/op_Subtraction.html>
825impl Sub<Vec2> for Vec2 {
826 type Output = Self;
827
828 /// ### Examples
829 /// ```
830 /// use stereokit_rust::maths::Vec2;
831 ///
832 /// let vec2_a = Vec2::new(1.0, 2.0);
833 /// let vec2_b = Vec2::new(2.0, 4.0);
834 /// assert_eq!(vec2_a - vec2_b, Vec2::new(-1.0, -2.0));
835 /// ```
836 #[inline]
837 fn sub(self, rhs: Self) -> Self::Output {
838 Self { x: self.x.sub(rhs.x), y: self.y.sub(rhs.y) }
839 }
840}
841
842/// Subtracts matching components from eachother. Not commutative.
843/// <https://stereokit.net/Pages/StereoKit/Vec2/op_Subtraction.html>
844impl SubAssign<Vec2> for Vec2 {
845 /// ### Examples
846 /// ```
847 /// use stereokit_rust::maths::Vec2;
848 ///
849 /// let mut vec2_a = Vec2::new(1.0, 2.0);
850 /// let vec2_b = Vec2::new(2.0, 4.0);
851 /// vec2_a -= vec2_b;
852 /// assert_eq!(vec2_a, Vec2::new(-1.0, -2.0));
853 /// ```
854 #[inline]
855 fn sub_assign(&mut self, rhs: Vec2) {
856 self.x.sub_assign(rhs.x);
857 self.y.sub_assign(rhs.y);
858 }
859}
860
861/// Vector negation, returns a vector where each component has been negated.
862/// <https://stereokit.net/Pages/StereoKit/Vec2/op_UnaryNegation.html>
863impl Neg for Vec2 {
864 type Output = Self;
865 /// ### Examples
866 /// ```
867 /// use stereokit_rust::maths::Vec2;
868 ///
869 /// let vec2_a = Vec2::new(1.0, 2.0);
870 /// assert_eq!(-vec2_a, Vec2::new(-1.0, -2.0));
871 /// ```
872 #[inline]
873 fn neg(self) -> Self::Output {
874 self * -1.0
875 }
876}
877
878/// A vector with 3 components: x, y, z. This can represent a point in space, a directional vector, or any other sort of
879/// value with 3 dimensions to it!
880///
881/// StereoKit uses a right-handed coordinate system, where +x is to the right, +y is upwards, and -z is forward.
882/// <https://stereokit.net/Pages/StereoKit/Vec3.html>
883///
884/// see also [`glam::Vec3`]
885/// ### Examples
886/// ```
887/// use stereokit_rust::maths::Vec3;
888///
889/// let vec3 = Vec3::new(1.0, 2.0, 3.0);
890/// let vec3a = Vec3 { x: 1.0, y: 2.0, z:3.0 };
891/// let vec3b = Vec3::X + Vec3::Y * 2.0;
892/// let vec3c: Vec3 = [1.0, 2.0, 3.0].into();
893///
894/// assert_eq!(vec3, vec3a);
895/// assert_eq!(vec3a + vec3b, Vec3 { x: 2.0, y: 4.0, z: 3.0 });
896/// assert_eq!(vec3c, Vec3 { x: 1.0, y: 2.0, z: 3.0 });
897/// assert_eq!(vec3a.length_sq(), 14.0);
898/// assert_eq!(vec3a.magnitude(), (14.0f32).sqrt());
899/// assert! (vec3a.get_normalized().length() - 1.0 < f32::EPSILON);
900/// assert_eq!(Vec3::angle_between(Vec3::X, Vec3::Y), 90.0);
901/// assert_eq!(Vec3::dot(Vec3::X, Vec3::Y), 0.0);
902/// ```
903#[derive(Debug, Default, Copy, Clone)]
904#[repr(C)]
905pub struct Vec3 {
906 pub x: f32,
907 pub y: f32,
908 pub z: f32,
909}
910
911impl From<glam::Vec3> for Vec3 {
912 fn from(val: glam::Vec3) -> Self {
913 Vec3 { x: val.x, y: val.y, z: val.z }
914 }
915}
916
917impl From<Vec3> for glam::Vec3 {
918 fn from(val: Vec3) -> Self {
919 Self::new(val.x, val.y, val.z)
920 }
921}
922
923impl From<[f32; 3]> for Vec3 {
924 fn from(val: [f32; 3]) -> Self {
925 Vec3 { x: val[0], y: val[1], z: val[2] }
926 }
927}
928
929impl From<Vec3> for [f32; 3] {
930 fn from(val: Vec3) -> Self {
931 [val.x, val.y, val.z]
932 }
933}
934
935/// Warning: Equality with a precision of 0.1 millimeter
936impl PartialEq for Vec3 {
937 /// Warning: Equality with a precision of 0.1 millimeter
938 /// ### Example
939 /// ```
940 /// use stereokit_rust::maths::Vec3;
941 /// assert_eq!(
942 /// Vec3 { x: 0.045863353, y: 0.030000005, z: 0.0 } ,
943 /// Vec3 { x: 0.045863353, y: 0.030000005, z: 0.0 } );
944 /// ```
945 /// ```
946 /// use stereokit_rust::maths::Vec3;
947 /// assert_ne!(
948 /// Vec3 { x: 10.045863353, y: 0.030000005, z: 0.0 } ,
949 /// Vec3 { x: 0.045863353, y: 0.030000005, z: 0.0 } );
950 /// ```
951 fn eq(&self, other: &Self) -> bool {
952 ((self.x - other.x).abs() < 0.0001)
953 && ((self.y - other.y).abs() < 0.0001)
954 && ((self.z - other.z).abs() < 0.0001)
955 }
956}
957
958unsafe extern "C" {
959 pub fn vec3_cross(a: *const Vec3, b: *const Vec3) -> Vec3;
960}
961
962impl Vec3 {
963 /// StereoKit uses a right-handed coordinate system, which means that forward is looking down the -Z axis! This
964 /// value is the same as new Vec3(0,0,-1). This is NOT the same as UnitZ!
965 /// <https://stereokit.net/Pages/StereoKit/Vec3/Forward.html>
966 pub const FORWARD: Self = Self::NEG_Z;
967
968 /// Shorthand for a vector where all values are 1! Same as new Vec3(1,1,1).
969 /// <https://stereokit.net/Pages/StereoKit/Vec3/One.html>
970 pub const ONE: Self = Self::new(1.0, 1.0, 1.0);
971
972 /// Shorthand for a vector where all values are -1! Same as new Vec3(-1,-1,-1).
973 pub const NEG_ONE: Self = Self::new(-1.0, -1.0, -1.0);
974
975 /// When looking forward, this is the direction to the right! In StereoKit, this is the same as new Vec3(1,0,0)
976 /// <https://stereokit.net/Pages/StereoKit/Vec3/Right.html>
977 pub const RIGHT: Self = Self::X;
978
979 /// A normalized Vector that points down the X axis, this is the same as new Vec3(1,0,0).
980 /// <https://stereokit.net/Pages/StereoKit/Vec3/UnitX.html>
981 pub const X: Self = Self::new(1.0, 0.0, 0.0);
982
983 /// A normalized Vector that points down the Y axis, this is the same as new Vec3(0,1,0).
984 /// <https://stereokit.net/Pages/StereoKit/Vec3/UnitY.html>
985 pub const Y: Self = Self::new(0.0, 1.0, 0.0);
986
987 /// A normalized Vector that points down the Z axis, this is the same as new Vec3(0,0,1).
988 /// This is NOT the same as Forward!
989 /// <https://stereokit.net/Pages/StereoKit/Vec3/UnitZ.html>
990 pub const Z: Self = Self::new(0.0, 0.0, 1.0);
991
992 /// A normalized Vector that points up the Z axis, this is the same as new Vec3(0,0,-1).
993 pub const NEG_X: Self = Self::new(-1.0, 0.0, 0.0);
994
995 /// A normalized Vector that points up the Y axis, this is the same as new Vec3(0,-1,0).
996 pub const NEG_Y: Self = Self::new(0.0, -1.0, 0.0);
997
998 /// A normalized Vector that points up the Z axis, this is the same as new Vec3(0,0,-1).
999 /// This is the same as Forward!
1000 pub const NEG_Z: Self = Self::new(0.0, 0.0, -1.0);
1001
1002 /// A vector representing the up axis. In StereoKit, this is the same as new Vec3(0,1,0).
1003 /// <https://stereokit.net/Pages/StereoKit/Vec3/Up.html>
1004 pub const UP: Self = Self::Y;
1005
1006 /// Shorthand for a vector where all values are 0! Same as new Vec3(0,0,0).
1007 /// <https://stereokit.net/Pages/StereoKit/Vec3/Zero.html>
1008 pub const ZERO: Vec3 = Self::new(0.0, 0.0, 0.0);
1009
1010 /// Creates a vector from x, y, and z values! StereoKit uses a right-handed metric coordinate system, where +x is to
1011 /// the right, +y is upwards, and -z is forward.
1012 /// <https://stereokit.net/Pages/StereoKit/Vec3/Vec3.html>
1013 #[inline]
1014 pub const fn new(x: f32, y: f32, z: f32) -> Self {
1015 Self { x, y, z }
1016 }
1017
1018 /// Checks if a point is within a certain radius of this one. This is an easily readable shorthand of the squared
1019 /// distance check.
1020 /// <https://stereokit.net/Pages/StereoKit/Vec3/InRadius.html>
1021 /// * `point`- The point to check against.
1022 /// * `radius` - The radius to check within.
1023 ///
1024 /// Returns true if the points are within radius of each other, false not.
1025 /// ### Examples
1026 /// ```
1027 /// use stereokit_rust::maths::Vec3;
1028 ///
1029 /// let vec3_a = Vec3::new(1.0, 2.0, 3.0);
1030 /// let vec3_b = Vec3::new(2.0, 4.0, 6.0);
1031 /// assert_eq!(vec3_a.in_radius(vec3_b, 5.0), true);
1032 /// assert_eq!(vec3_a.in_radius(vec3_b, 2.0), false);
1033 /// ```
1034 #[inline]
1035 pub fn in_radius(&self, point: Self, radius: f32) -> bool {
1036 Self::distance(*self, point) <= radius
1037 }
1038
1039 /// Turns this vector into a normalized vector (vector with a length of 1) from the current vector. Will not work
1040 /// properly if the vector has a length of zero. Vec3::get_normalized is faster.
1041 /// <https://stereokit.net/Pages/StereoKit/Vec3/Normalize.html>
1042 ///
1043 /// ### Examples
1044 /// ```
1045 /// use stereokit_rust::maths::Vec3;
1046 ///
1047 /// let mut vec3_a = Vec3::new(1.0, 2.0, 3.0);
1048 /// vec3_a.normalize();
1049 /// assert_eq!(vec3_a, Vec3::new(0.26726124, 0.5345225, 0.8017837));
1050 /// ```
1051 #[inline]
1052 pub fn normalize(&mut self) {
1053 let n = *self * (self.length().recip());
1054 self.x = n.x;
1055 self.y = n.y;
1056 self.z = n.z;
1057 }
1058
1059 /// This is the length, or magnitude of the vector! The distance from the origin to this point.
1060 /// Uses f32::sqrt, so it’s not dirt cheap or anything.
1061 /// <https://stereokit.net/Pages/StereoKit/Vec3/Length.html>
1062 ///
1063 /// ### Examples
1064 /// ```
1065 /// use stereokit_rust::maths::Vec3;
1066 ///
1067 /// let vec3_a = Vec3::new(1.0, 2.0, 3.0);
1068 /// assert_eq!(vec3_a.length(), 3.7416575);
1069 /// ```
1070 #[inline]
1071 pub fn length(&self) -> f32 {
1072 Self::dot(*self, *self).sqrt()
1073 }
1074
1075 /// This is the squared length of the vector! It skips the Sqrt call, and just gives you the squared version for
1076 /// speedy calculations that can work with it squared.
1077 /// <https://stereokit.net/Pages/StereoKit/Vec3/LengthSq.html>
1078 ///
1079 /// ### Examples
1080 /// ```
1081 /// use stereokit_rust::maths::Vec3;
1082 ///
1083 /// let vec3_a = Vec3::new(1.0, 2.0, 3.0);
1084 /// assert_eq!(vec3_a.length_sq(), 14.0);
1085 /// ```
1086 #[inline]
1087 pub fn length_sq(&self) -> f32 {
1088 Self::dot(*self, *self)
1089 }
1090
1091 /// Magnitude is the length of the vector! The distance from the origin to this point. Uses f32::sqrt, so it’s not
1092 /// dirt cheap or anything.
1093 /// <https://stereokit.net/Pages/StereoKit/Vec3/Magnitude.html>
1094 ///
1095 /// ### Examples
1096 /// ```
1097 /// use stereokit_rust::maths::Vec3;
1098 ///
1099 /// let vec3_a = Vec3::new(1.0, 2.0, 3.0);
1100 /// assert_eq!(vec3_a.length(), 3.7416575);
1101 /// ```
1102 #[inline]
1103 pub fn magnitude(&self) -> f32 {
1104 self.length()
1105 }
1106
1107 /// This is the squared magnitude of the vector! It skips the Sqrt call, and just gives you the squared version for
1108 /// speedy calculations that can work with it squared.
1109 /// <https://stereokit.net/Pages/StereoKit/Vec3/MagnitudeSq.html>
1110 ///
1111 /// ### Examples
1112 /// ```
1113 /// use stereokit_rust::maths::Vec3;
1114 ///
1115 /// let vec3_a = Vec3::new(1.0, 2.0, 3.0);
1116 /// assert_eq!(vec3_a.magnitude_squared(), 14.0);
1117 /// ```
1118 #[inline]
1119 pub fn magnitude_squared(&self) -> f32 {
1120 self.length_sq()
1121 }
1122
1123 /// Creates a normalized vector (vector with a length of 1) from the current vector. Will not work properly if the
1124 /// vector has a length of zero.
1125 /// <https://stereokit.net/Pages/StereoKit/Vec3/Normalized.html>
1126 ///
1127 /// ### Examples
1128 /// ```
1129 /// use stereokit_rust::maths::Vec3;
1130 ///
1131 /// let vec3_a = Vec3::new(1.0, 2.0, 3.0);
1132 /// assert_eq!(vec3_a.get_normalized(), Vec3::new(0.26726124, 0.5345225, 0.8017837));
1133 /// ```
1134 #[inline]
1135 pub fn get_normalized(&self) -> Self {
1136 *self * (self.length().recip())
1137 }
1138
1139 /// This returns a Vec3 that has been flattened to 0 on the Y axis. No other changes are made.
1140 /// <https://stereokit.net/Pages/StereoKit/Vec3/X0Z.html>
1141 ///
1142 /// ### Examples
1143 /// ```
1144 /// use stereokit_rust::maths::Vec3;
1145 ///
1146 /// let vec3_a = Vec3::new(1.0, 2.0, 3.0);
1147 /// assert_eq!(vec3_a.x0z(), Vec3::new(1.0, 0.0, 3.0));
1148 /// ```
1149 #[inline]
1150 pub fn x0z(&self) -> Self {
1151 Self { x: self.x, y: 0.0, z: self.z }
1152 }
1153
1154 /// This returns a Vec3 that has been flattened to 0 on the Z axis. No other changes are made.
1155 /// <https://stereokit.net/Pages/StereoKit/Vec3/XY0.html>
1156 ///
1157 /// ### Examples
1158 /// ```
1159 /// use stereokit_rust::maths::Vec3;
1160 ///
1161 /// let vec3_a = Vec3::new(1.0, 2.0, 3.0);
1162 /// assert_eq!(vec3_a.xy0(), Vec3::new(1.0, 2.0, 0.0));
1163 /// ```
1164 #[inline]
1165 pub fn xy0(&self) -> Self {
1166 Self { x: self.x, y: self.y, z: 0.0 }
1167 }
1168
1169 /// This returns a Vec3 that has been set to 1 on the Z axis. No other changes are made
1170 /// <https://stereokit.net/Pages/StereoKit/Vec3/XY1.html>
1171 ///
1172 /// ### Examples
1173 /// ```
1174 /// use stereokit_rust::maths::Vec3;
1175 ///
1176 /// let vec3_a = Vec3::new(1.0, 2.0, 3.0);
1177 /// assert_eq!(vec3_a.xy1(), Vec3::new(1.0, 2.0, 1.0));
1178 /// ```
1179 #[inline]
1180 pub fn xy1(&self) -> Self {
1181 Self { x: self.x, y: self.y, z: 1.0 }
1182 }
1183
1184 /// This extracts the Vec2 from the X and Y axes.
1185 /// <https://stereokit.net/Pages/StereoKit/Vec3.html>
1186 ///
1187 /// ### Examples
1188 /// ```
1189 /// use stereokit_rust::maths::{Vec2, Vec3};
1190 ///
1191 /// let vec3_a = Vec3::new(1.0, 2.0, 3.0);
1192 /// assert_eq!(vec3_a.xy(), Vec2::new(1.0, 2.0));
1193 /// ```
1194 #[inline]
1195 pub fn xy(&self) -> Vec2 {
1196 Vec2::new(self.x, self.y)
1197 }
1198
1199 /// This extracts the Vec2 from the Y and Z axes.
1200 /// <https://stereokit.net/Pages/StereoKit/Vec3/YZ.html>
1201 ///
1202 /// ### Examples
1203 /// ```
1204 /// use stereokit_rust::maths::{Vec2, Vec3};
1205 ///
1206 /// let vec3_a = Vec3::new(1.0, 2.0, 3.0);
1207 /// assert_eq!(vec3_a.yz(), Vec2::new(2.0, 3.0));
1208 /// ```
1209 #[inline]
1210 pub fn yz(&self) -> Vec2 {
1211 Vec2::new(self.y, self.z)
1212 }
1213
1214 /// This extracts the Vec2 from the X and Z axes.
1215 /// <https://stereokit.net/Pages/StereoKit/Vec3.html>
1216 ///
1217 /// ### Examples
1218 /// ```
1219 /// use stereokit_rust::maths::{Vec2, Vec3};
1220 ///
1221 /// let vec3_a = Vec3::new(1.0, 2.0, 3.0);
1222 /// assert_eq!(vec3_a.xz(), Vec2::new(1.0, 3.0));
1223 /// ```
1224 #[inline]
1225 pub fn xz(&self) -> Vec2 {
1226 Vec2::new(self.x, self.z)
1227 }
1228
1229 /// Calculates the angle between two vectors in degrees! Vectors do not need to be normalized, and the result will
1230 /// always be positive.
1231 /// <https://stereokit.net/Pages/StereoKit/Vec3/AngleBetween.html>
1232 /// * `a` - The first, initial vector, A. Does not need to be normalized.
1233 /// * `b` - The second vector, B, that we're finding the angle to. Does not need to be normalized.
1234 ///
1235 /// Returns a positive angle between two vectors in degrees!
1236 /// ### Examples
1237 /// ```
1238 /// use stereokit_rust::maths::Vec3;
1239 ///
1240 /// let vec3_b = Vec3::new(0.0, 1.0, 0.0);
1241 /// assert_eq!(Vec3::angle_between(Vec3::X, vec3_b), 90.0);
1242 ///
1243 /// let vec3_c = Vec3::new(-1.0, 0.0, 0.0);
1244 /// assert_eq!(Vec3::angle_between(Vec3::X, vec3_c), 180.0);
1245 ///
1246 /// let vec3_d = Vec3::new(1.0, 0.0, 1.0);
1247 /// assert_eq!(Vec3::angle_between(Vec3::X, vec3_d), 45.0);
1248 /// ```
1249 #[inline]
1250 pub fn angle_between(a: Self, b: Self) -> f32 {
1251 (Self::dot(a, b) / (a.length_sq() * b.length_sq()).sqrt()).acos().to_degrees()
1252 }
1253
1254 /// Creates a vector that points out at the given 2D angle! This creates the vector on the XY plane, and allows you
1255 /// to specify a constant z value.
1256 /// <https://stereokit.net/Pages/StereoKit/Vec3/AngleXY.html>
1257 /// * `angle_deg` - The angle in degrees, starting from the (1,0) at 0, and continuing to (0,1) at 90, etc.
1258 /// * `z` - The constant Z value for this vector.
1259 ///
1260 /// Returns a vector pointing at the given angle! If z is zero, this will be a normalized vector (vector with
1261 /// a length of 1).
1262 /// ### Examples
1263 /// ```
1264 /// use stereokit_rust::maths::Vec3;
1265 ///
1266 /// let angle = 45.0;
1267 /// let z = 0.0;
1268 /// let vector = Vec3::angle_xy(angle, z);
1269 /// assert_eq!(vector, Vec3::new(0.70710677, 0.70710677, 0.0));
1270 /// ```
1271 #[inline]
1272 pub fn angle_xy(angle_deg: f32, z: f32) -> Vec3 {
1273 Self { x: angle_deg.to_radians().cos(), y: angle_deg.to_radians().sin(), z }
1274 }
1275
1276 /// Creates a vector that points out at the given 2D angle! This creates the vector on the XZ plane, and allows you
1277 /// to specify a constant y value.
1278 /// <https://stereokit.net/Pages/StereoKit/Vec3/AngleXZ.html>
1279 /// * `angle_deg` - The angle in degrees, starting from the (1,0) at 0, and continuing to (0,1) at 90, etc.
1280 /// * `y` - The constant Y value for this vector.
1281 ///
1282 /// Returns A Vector pointing at the given angle! If y is zero, this will be a normalized vector (vector with a
1283 /// length of 1).
1284 /// ### Examples
1285 /// ```
1286 /// use stereokit_rust::maths::Vec3;
1287 /// let vec = Vec3::angle_xz(90.0, 0.0);
1288 /// assert_eq!(vec, Vec3::new(0.0, 0.0, 1.0));
1289 /// ```
1290 #[inline]
1291 pub fn angle_xz(angle_deg: f32, y: f32) -> Self {
1292 Self { x: angle_deg.to_radians().cos(), y, z: angle_deg.to_radians().sin() }
1293 }
1294
1295 /// The cross product of two vectors!
1296 /// <https://stereokit.net/Pages/StereoKit/Vec3/Cross.html>
1297 /// * `a` - The first vector.
1298 /// * `b` - The second vector.
1299 ///
1300 /// Returns is **not** a unit vector, even if both ‘a’ and ‘b’ are unit vectors.
1301 /// see also [`vec3_cross`]
1302 /// ### Examples
1303 ///```
1304 /// use stereokit_rust::maths::Vec3;
1305 ///
1306 /// // Test case 1: Basic cross product
1307 /// let a = Vec3::new(1.0, 0.0, 0.0);
1308 /// let b = Vec3::new(0.0, 1.0, 0.0);
1309 /// let result = Vec3::cross(a, b);
1310 /// assert_eq!(result, Vec3::new(0.0, 0.0, 1.0));
1311 ///
1312 /// // Test case 2: Cross product in different direction
1313 /// let a = Vec3::new(0.0, 1.0, 0.0);
1314 /// let b = Vec3::new(1.0, 0.0, 0.0);
1315 /// let result = Vec3::cross(a, b);
1316 /// assert_eq!(result, Vec3::new(0.0, 0.0, -1.0));
1317 ///
1318 /// // Test case 3: Cross product with non-unit vectors
1319 /// let a = Vec3::new(2.0, 0.0, 0.0);
1320 /// let b = Vec3::new(0.0, 3.0, 0.0);
1321 /// let result = Vec3::cross(a, b);
1322 /// assert_eq!(result, Vec3::new(0.0, 0.0, 6.0));
1323 ///
1324 /// // Test case 4: Cross product of parallel vectors
1325 /// let a = Vec3::new(1.0, 0.0, 0.0);
1326 /// let b = Vec3::new(2.0, 0.0, 0.0);
1327 /// let result = Vec3::cross(a, b);
1328 /// assert_eq!(result, Vec3::ZERO);
1329 ///
1330 /// // Test case 5: cross product of orthogonal vector
1331 /// let a = Vec3::new(1.0, 2.0, 3.0);
1332 /// let b = Vec3::new(4.0, 5.0, 6.0);
1333 /// let result = Vec3::cross(a,b);
1334 /// assert_eq!(result, Vec3::new(-3.0, 6.0, -3.0));
1335 ///
1336 /// // Test case 6: cross product of orthogonal vector
1337 /// let a = Vec3::new(4.0, 5.0, 6.0);
1338 /// let b = Vec3::new(1.0, 2.0, 3.0);
1339 /// let result = Vec3::cross(a,b);
1340 /// assert_eq!(result, Vec3::new(3.0, -6.0, 3.0));
1341 /// ```
1342 #[inline]
1343 pub fn cross(a: Self, b: Self) -> Self {
1344 unsafe { vec3_cross(&a, &b) }
1345 }
1346
1347 /// Creates a normalized delta vector that points out from an origin point to a target point!
1348 /// <https://stereokit.net/Pages/StereoKit/Vec3/Direction.html>
1349 /// * `to` - The target point.
1350 /// * `from` - The origin point.
1351 ///
1352 /// Returns direction from one point to another.
1353 /// ### Examples
1354 /// ```
1355 /// use stereokit_rust::maths::Vec3;
1356 ///
1357 /// let a = Vec3::new(1.0, 2.0, 3.0);
1358 /// let b = Vec3::new(4.0, 5.0, 6.0);
1359 /// let direction = Vec3::direction(a, b);
1360 /// assert_eq!(direction, Vec3 { x: -0.57735026, y: -0.57735026, z: -0.57735026 });
1361 /// ```
1362 #[inline]
1363 pub fn direction(to: Self, from: Self) -> Self {
1364 (to - from).get_normalized()
1365 }
1366
1367 /// Calculates the distance between two points in space! Make sure they’re in the same coordinate space! Uses a
1368 /// Sqrt, so it’s not blazing fast, prefer DistanceSq when possible.
1369 /// <https://stereokit.net/Pages/StereoKit/Vec3/Distance.html>
1370 /// * `a` - The first point.
1371 /// * `b` - The second point.
1372 ///
1373 /// Returns the distance between the two points.
1374 /// ### Examples
1375 /// ```
1376 /// use stereokit_rust::maths::Vec3;
1377 ///
1378 /// let a = Vec3 { x: 1.0, y: 2.0, z: 3.0 };
1379 /// let b = Vec3 { x: 4.0, y: 5.0, z: 6.0 };
1380 /// let distance = Vec3::distance(a, b);
1381 /// assert_eq!(distance, 5.196152);
1382 /// ```
1383 #[inline]
1384 pub fn distance(a: Self, b: Self) -> f32 {
1385 (a - b).length()
1386 }
1387
1388 /// Calculates the distance between two points in space, but leaves them squared! Make sure they’re in the same
1389 /// coordinate space! This is a fast function :)
1390 /// <https://stereokit.net/Pages/StereoKit/Vec3/DistanceSq.html>
1391 /// * `a` - The first point.
1392 /// * `b` - The second point.
1393 ///
1394 /// Returns the distance between the two points, but squared.
1395 /// ### Examples
1396 /// ```
1397 /// use stereokit_rust::maths::Vec3;
1398 ///
1399 /// let a = Vec3::new(1.0, 2.0, 3.0);
1400 /// let b = Vec3::new(4.0, 5.0, 6.0);
1401 /// let distance = Vec3::distance_sq(a, b);
1402 /// assert_eq!(distance, 27.0);
1403 /// ```
1404 #[inline]
1405 pub fn distance_sq(a: Self, b: Self) -> f32 {
1406 (a - b).length_sq()
1407 }
1408
1409 /// The dot product is an extremely useful operation! One major use is to determine how similar two vectors are. If
1410 /// the vectors are Unit vectors (magnitude/length of 1), then the result will be 1 if the vectors are the same, -1
1411 /// if they’re opposite, and a gradient in-between with 0 being perpendicular. See [Freya Holmer’s excellent
1412 /// visualization of this concept](<https://twitter.com/FreyaHolmer/status/1200807790580768768>)
1413 /// <https://stereokit.net/Pages/StereoKit/Vec3/Dot.html>
1414 /// * `a` - The first vector.
1415 /// * `b` - The second vector.
1416 ///
1417 /// Returns the dot product of the two vectors.
1418 /// ### Examples
1419 /// ```
1420 /// use stereokit_rust::maths::Vec3;
1421 ///
1422 /// let a = Vec3::new(1.0, 0.0, 1.0);
1423 /// let b = Vec3::new(1.0, 1.0, 0.0);
1424 /// let dot_product = Vec3::dot(a, b);
1425 /// assert_eq!(dot_product, 1.0);
1426 /// ```
1427 #[inline]
1428 pub fn dot(a: Self, b: Self) -> f32 {
1429 (a.x * b.x) + (a.y * b.y) + (a.z * b.z)
1430 }
1431
1432 /// Blends (Linear Interpolation) between two vectors, based on a ‘blend’ value, where 0 is a, and 1 is b. Doesn’t
1433 /// clamp percent for you.
1434 /// <https://stereokit.net/Pages/StereoKit/Vec3/Lerp.html>
1435 /// * `a` - First item in the blend, or '0.0' blend.
1436 /// * `b` - Second item in the blend, or '1.0' blend.
1437 /// * `blend` - The blend value between 0 and 1. Can be outside this range, it’ll just interpolate outside of the a,
1438 /// b range.
1439 ///
1440 /// Returns a blend value between 0 and 1. Can be outside this range, it’ll just interpolate outside of the a, b
1441 /// range.
1442 /// ### Examples
1443 /// ```
1444 /// use stereokit_rust::maths::Vec3;
1445 ///
1446 /// let a = Vec3::new(1.0, 2.0, 3.0);
1447 /// let b = Vec3::new(4.0, 5.0, 6.0);
1448 /// let blend = 0.25;
1449 /// let result = Vec3::lerp(a, b, blend);
1450 /// assert_eq!(result, Vec3::new(1.75, 2.75, 3.75));
1451 /// ```
1452 #[inline]
1453 pub fn lerp(a: Self, b: Self, blend: f32) -> Self {
1454 a + ((b - a) * blend)
1455 }
1456
1457 /// Returns a vector where each element is the maximum value for each corresponding pair.
1458 /// <https://stereokit.net/Pages/StereoKit/Vec3/Max.html>
1459 /// * `a` - Order isn't important here.
1460 /// * `b` - Order isn't important here.
1461 ///
1462 /// Returns the maximum value for each corresponding vector pair.
1463 /// ### Examples
1464 /// ```
1465 /// use stereokit_rust::maths::Vec3;
1466 ///
1467 /// let a = Vec3::new(1.0, 6.0, 3.0);
1468 /// let b = Vec3::new(4.0, 5.0, 6.0);
1469 /// let result = Vec3::max(a, b);
1470 /// assert_eq!(result, Vec3::new(4.0, 6.0, 6.0));
1471 /// ```
1472 #[inline]
1473 pub fn max(a: Self, b: Self) -> Self {
1474 Self { x: f32::max(a.x, b.x), y: f32::max(a.y, b.y), z: f32::max(a.z, b.z) }
1475 }
1476
1477 /// Returns a vector where each element is the minimum value for each corresponding pair.
1478 /// <https://stereokit.net/Pages/StereoKit/Vec3/Min.html>
1479 /// * `a` - Order isn't important here.
1480 /// * `b` - Order isn't important here.
1481 ///
1482 /// Returns the minimum value for each corresponding vector pair.
1483 /// ### Examples
1484 /// ```
1485 /// use stereokit_rust::maths::Vec3;
1486 ///
1487 /// let a = Vec3::new(1.0, 2.0, 3.0);
1488 /// let b = Vec3::new(4.0, 1.0, 6.0);
1489 /// let result = Vec3::min(a, b);
1490 /// assert_eq!(result, Vec3::new(1.0, 1.0, 3.0));
1491 /// ```
1492 #[inline]
1493 pub fn min(a: Self, b: Self) -> Self {
1494 Self { x: f32::min(a.x, b.x), y: f32::min(a.y, b.y), z: f32::min(a.z, b.z) }
1495 }
1496
1497 /// Exactly the same as Vec3.Cross, but has some naming mnemonics for getting the order right when trying to find a
1498 /// perpendicular vector using the cross product. This’ll also make it more obvious to read if that’s what you’re
1499 /// actually going for when crossing vectors!
1500 /// If you consider a forward vector and an up vector, then the direction to the right is pretty trivial to imagine
1501 /// in relation to those vectors!
1502 /// <https://stereokit.net/Pages/StereoKit/Vec3/PerpendicularRight.html>
1503 /// * `forward` - What way are you facing?
1504 /// * `up` - Which direction is up?
1505 ///
1506 /// Returns your direction to the right! Result is -not- a unit vector, even if both ‘forward’ and ‘up’ are unit
1507 /// vectors.
1508 /// ### Examples
1509 /// ```
1510 /// use stereokit_rust::maths::Vec3;
1511 ///
1512 /// let forward = Vec3::new(0.0, 0.0, -1.0);
1513 /// let up = Vec3::new(0.0, 1.0, 0.0);
1514 /// let right = Vec3::perpendicular_right(forward, up);
1515 /// assert_eq!(right, Vec3::new(1.0, 0.0, 0.0));
1516 ///
1517 /// // The same with constants:
1518 /// let forward = Vec3::FORWARD;
1519 /// let up = Vec3::UP;
1520 /// let right = Vec3::perpendicular_right(forward, up);
1521 /// assert_eq!(right, Vec3::RIGHT);
1522 /// ```
1523 #[inline]
1524 pub fn perpendicular_right(forward: Self, up: Self) -> Self {
1525 Self::cross(forward, up)
1526 }
1527
1528 /// Returns a vector where each element is the absolute value of the corresponding element.
1529 /// <https://stereokit.net/Pages/StereoKit/Vec3/Abs.html>
1530 ///
1531 /// ### Examples
1532 /// ```
1533 /// use stereokit_rust::maths::Vec3;
1534 ///
1535 /// let v = Vec3::new(-1.0, 2.0, -3.0);
1536 /// assert_eq!(v.abs(), Vec3::new(1.0, 2.0, 3.0));
1537 /// ```
1538 #[inline]
1539 pub fn abs(&self) -> Self {
1540 Self { x: self.x.abs(), y: self.y.abs(), z: self.z.abs() }
1541 }
1542
1543 /// get an array
1544 ///
1545 /// ### Examples
1546 /// ```
1547 /// use stereokit_rust::maths::Vec3;
1548 ///
1549 /// let v = Vec3::new(1.0, 2.0, 3.0);
1550 /// assert_eq!(v.to_array(), [1.0, 2.0, 3.0]);
1551 ///```
1552 #[inline]
1553 pub const fn to_array(&self) -> [f32; 3] {
1554 [self.x, self.y, self.z]
1555 }
1556}
1557
1558impl Display for Vec3 {
1559 /// Mostly for debug purposes, this is a decent way to log or inspect the vector in debug mode.
1560 /// Looks like “[x, y, z]”
1561 /// <https://stereokit.net/Pages/StereoKit/Vec3/ToString.html>
1562 /// ### Examples
1563 /// ```
1564 /// use stereokit_rust::maths::Vec3;
1565 ///
1566 /// let v = Vec3::new(1.0, 2.0, 3.0);
1567 /// assert_eq!(v.to_string(), "[x:1, y:2, z:3]");
1568 /// ```
1569 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1570 write!(f, "[x:{}, y:{}, z:{}]", self.x, self.y, self.z)
1571 }
1572}
1573/// A component-wise vector division.
1574/// <https://stereokit.net/Pages/StereoKit/Vec3/op_Division.html>
1575impl Div<Vec3> for Vec3 {
1576 type Output = Self;
1577
1578 /// ### Examples
1579 /// ```
1580 /// use stereokit_rust::maths::Vec3;
1581 ///
1582 /// let v = Vec3::new(1.0, 2.0, 3.0) / Vec3::new(2.0, 2.0, 2.0);
1583 /// assert_eq!(v, Vec3::new(0.5, 1.0, 1.5));
1584 /// ```
1585 #[inline]
1586 fn div(self, rhs: Self) -> Self::Output {
1587 Self { x: self.x.div(rhs.x), y: self.y.div(rhs.y), z: self.z.div(rhs.z) }
1588 }
1589}
1590
1591/// A component-wise vector division.
1592/// <https://stereokit.net/Pages/StereoKit/Vec3/op_Division.html>
1593impl DivAssign<Vec3> for Vec3 {
1594 /// ### Examples
1595 /// ```
1596 /// use stereokit_rust::maths::Vec3;
1597 ///
1598 /// let mut v = Vec3::new(1.0, 2.0, 3.0);
1599 /// v /= Vec3::new(2.0, 2.0, 2.0);
1600 /// assert_eq!(v, Vec3::new(0.5, 1.0, 1.5));
1601 /// ```
1602 #[inline]
1603 fn div_assign(&mut self, rhs: Self) {
1604 self.x.div_assign(rhs.x);
1605 self.y.div_assign(rhs.y);
1606 self.z.div_assign(rhs.z);
1607 }
1608}
1609
1610/// A component-wise vector division.
1611/// <https://stereokit.net/Pages/StereoKit/Vec3/op_Division.html>
1612impl Div<f32> for Vec3 {
1613 type Output = Self;
1614
1615 /// ## Examples
1616 /// ```
1617 /// use stereokit_rust::maths::Vec3;
1618 ///
1619 /// let v = Vec3::new(1.0, 2.0, 3.0);
1620 /// let v = v / 2.0;
1621 /// assert_eq!(v, Vec3::new(0.5, 1.0, 1.5));
1622 /// ```
1623 #[inline]
1624 fn div(self, rhs: f32) -> Self::Output {
1625 Self { x: self.x.div(rhs), y: self.y.div(rhs), z: self.z.div(rhs) }
1626 }
1627}
1628
1629/// A component-wise vector division.
1630/// <https://stereokit.net/Pages/StereoKit/Vec3/op_Division.html>
1631impl DivAssign<f32> for Vec3 {
1632 /// ### Examples
1633 /// ```
1634 /// use stereokit_rust::maths::Vec3;
1635 ///
1636 /// let mut v = Vec3::new(1.0, 2.0, 3.0);
1637 /// v /= 2.0;
1638 /// assert_eq!(v, Vec3::new(0.5, 1.0, 1.5));
1639 /// ```
1640 #[inline]
1641 fn div_assign(&mut self, rhs: f32) {
1642 self.x.div_assign(rhs);
1643 self.y.div_assign(rhs);
1644 self.z.div_assign(rhs);
1645 }
1646}
1647
1648/// A component-wise vector division.
1649/// <https://stereokit.net/Pages/StereoKit/Vec3/op_Division.html>
1650impl Div<Vec3> for f32 {
1651 type Output = Vec3;
1652
1653 /// ### Examples
1654 /// ```
1655 /// use stereokit_rust::maths::Vec3;
1656 ///
1657 /// let v = Vec3::new(1.0, 2.0, 3.0);
1658 /// let v = v / Vec3::new(2.0, 2.0, 2.0);
1659 /// assert_eq!(v, Vec3::new(0.5, 1.0, 1.5));
1660 /// ```
1661 #[inline]
1662 fn div(self, rhs: Vec3) -> Self::Output {
1663 Vec3 { x: self.div(rhs.x), y: self.div(rhs.y), z: self.div(rhs.z) }
1664 }
1665}
1666
1667/// A component-wise vector multiplication, same thing as a non-uniform scale. NOT a dot or cross product! Commutative.
1668/// <https://stereokit.net/Pages/StereoKit/Vec3/op_Multiply.html>
1669impl Mul<Vec3> for Vec3 {
1670 type Output = Self;
1671
1672 /// ### Examples
1673 /// ```
1674 /// use stereokit_rust::maths::Vec3;
1675 ///
1676 /// let a = Vec3::new(1.0, 2.0, 3.0);
1677 /// let b = Vec3::new(4.0, 5.0, 6.0);
1678 /// let c = a * b;
1679 /// assert_eq!(c, Vec3::new(4.0, 10.0, 18.0));
1680 /// ```
1681 #[inline]
1682 fn mul(self, rhs: Self) -> Self::Output {
1683 Self { x: self.x.mul(rhs.x), y: self.y.mul(rhs.y), z: self.z.mul(rhs.z) }
1684 }
1685}
1686
1687/// A component-wise vector multiplication, same thing as a non-uniform scale. NOT a dot or cross product! Commutative.
1688/// <https://stereokit.net/Pages/StereoKit/Vec3/op_Multiply.html>
1689impl MulAssign<Vec3> for Vec3 {
1690 /// ### Examples
1691 /// ```
1692 /// use stereokit_rust::maths::Vec3;
1693 ///
1694 /// let mut a = Vec3::new(1.0, 2.0, 3.0);
1695 /// let b = Vec3::new(4.0, 5.0, 6.0);
1696 /// a *= b;
1697 /// assert_eq!(a, Vec3::new(4.0, 10.0, 18.0));
1698 /// ```
1699 #[inline]
1700 fn mul_assign(&mut self, rhs: Self) {
1701 self.x.mul_assign(rhs.x);
1702 self.y.mul_assign(rhs.y);
1703 self.z.mul_assign(rhs.z);
1704 }
1705}
1706
1707/// A component-wise vector multiplication, same thing as a non-uniform scale. NOT a dot or cross product! Commutative.
1708/// <https://stereokit.net/Pages/StereoKit/Vec3/op_Multiply.html>
1709impl Mul<f32> for Vec3 {
1710 type Output = Self;
1711
1712 /// ### Examples
1713 /// ```
1714 /// use stereokit_rust::maths::Vec3;
1715 ///
1716 /// let a = Vec3::new(1.0, 2.0, 3.0);
1717 /// let b = a * 2.0;
1718 /// assert_eq!(b, Vec3::new(2.0, 4.0, 6.0));
1719 /// ```
1720 #[inline]
1721 fn mul(self, rhs: f32) -> Self::Output {
1722 Self { x: self.x.mul(rhs), y: self.y.mul(rhs), z: self.z.mul(rhs) }
1723 }
1724}
1725
1726/// A component-wise vector multiplication, same thing as a non-uniform scale. NOT a dot or cross product! Commutative.
1727/// <https://stereokit.net/Pages/StereoKit/Vec3/op_Multiply.html>
1728impl MulAssign<f32> for Vec3 {
1729 /// ### Examples
1730 /// ```
1731 /// use stereokit_rust::maths::Vec3;
1732 ///
1733 /// let mut a = Vec3::new(1.0, 2.0, 3.0);
1734 /// a *= 2.0;
1735 /// assert_eq!(a, Vec3::new(2.0, 4.0, 6.0));
1736 /// ```
1737 #[inline]
1738 fn mul_assign(&mut self, rhs: f32) {
1739 self.x.mul_assign(rhs);
1740 self.y.mul_assign(rhs);
1741 self.z.mul_assign(rhs);
1742 }
1743}
1744
1745/// A component-wise vector multiplication, same thing as a non-uniform scale. NOT a dot or cross product! Commutative.
1746/// <https://stereokit.net/Pages/StereoKit/Vec3/op_Multiply.html>
1747impl Mul<Vec3> for f32 {
1748 type Output = Vec3;
1749
1750 /// ### Examples
1751 /// ```
1752 /// use stereokit_rust::maths::Vec3;
1753 ///
1754 /// let a = 2.0 * Vec3::new(1.0, 2.0, 3.0);
1755 /// let b = Vec3::new(2.0, 4.0, 6.0);
1756 /// assert_eq!(a, b);
1757 /// ```
1758 #[inline]
1759 fn mul(self, rhs: Vec3) -> Self::Output {
1760 Vec3 { x: self.mul(rhs.x), y: self.mul(rhs.y), z: self.mul(rhs.z) }
1761 }
1762}
1763
1764/// Adds matching components together. Commutative.
1765/// <https://stereokit.net/Pages/StereoKit/Vec3/op_Addition.html>
1766impl Add<Vec3> for Vec3 {
1767 type Output = Self;
1768
1769 /// ### Examples
1770 /// ```
1771 /// use stereokit_rust::maths::Vec3;
1772 ///
1773 /// let a = Vec3::new(1.0, 2.0, 3.0);
1774 /// let b = Vec3::new(4.0, 5.0, 6.0);
1775 /// let c = a + b;
1776 /// assert_eq!(c, Vec3::new(5.0, 7.0, 9.0));
1777 /// ```
1778 #[inline]
1779 fn add(self, rhs: Self) -> Self::Output {
1780 Self { x: self.x.add(rhs.x), y: self.y.add(rhs.y), z: self.z.add(rhs.z) }
1781 }
1782}
1783
1784/// Adds matching components together. Commutative.
1785/// <https://stereokit.net/Pages/StereoKit/Vec3/op_Addition.html>
1786impl AddAssign<Vec3> for Vec3 {
1787 /// ### Examples
1788 /// ```
1789 /// use stereokit_rust::maths::Vec3;
1790 ///
1791 /// let mut a = Vec3::new(1.0, 2.0, 3.0);
1792 /// let b = Vec3::new(4.0, 5.0, 6.0);
1793 /// a += b;
1794 /// assert_eq!(a, Vec3::new(5.0, 7.0, 9.0));
1795 /// ```
1796 #[inline]
1797 fn add_assign(&mut self, rhs: Self) {
1798 self.x.add_assign(rhs.x);
1799 self.y.add_assign(rhs.y);
1800 self.z.add_assign(rhs.z);
1801 }
1802}
1803
1804impl Sub<Vec3> for Vec3 {
1805 type Output = Self;
1806
1807 /// ## Examples
1808 /// ```
1809 /// use stereokit_rust::maths::Vec3;
1810 ///
1811 /// let a = Vec3::new(1.0, 2.0, 3.0);
1812 /// let b = Vec3::new(4.0, 5.0, 6.0);
1813 /// let c = a - b;
1814 /// assert_eq!(c, Vec3::new(-3.0, -3.0, -3.0));
1815 /// ```
1816 #[inline]
1817 fn sub(self, rhs: Self) -> Self::Output {
1818 Self { x: self.x.sub(rhs.x), y: self.y.sub(rhs.y), z: self.z.sub(rhs.z) }
1819 }
1820}
1821
1822/// Subtracts matching components from eachother. Not commutative.
1823/// <https://stereokit.net/Pages/StereoKit/Vec3/op_Subtraction.html>
1824impl SubAssign<Vec3> for Vec3 {
1825 /// ### Examples
1826 /// ```
1827 /// use stereokit_rust::maths::Vec3;
1828 ///
1829 /// let mut a = Vec3::new(1.0, 3.0, 1.0);
1830 /// let b = Vec3::new(0.5, 0.5, 0.5);
1831 /// a -= b;
1832 /// assert_eq!(a, Vec3::new(0.5, 2.5, 0.5));
1833 /// ```
1834 #[inline]
1835 fn sub_assign(&mut self, rhs: Vec3) {
1836 self.x.sub_assign(rhs.x);
1837 self.y.sub_assign(rhs.y);
1838 self.z.sub_assign(rhs.z);
1839 }
1840}
1841
1842/// Vector negation, returns a vector where each component has been negated.
1843/// <https://stereokit.net/Pages/StereoKit/Vec3/op_UnaryNegation.html>
1844impl Neg for Vec3 {
1845 type Output = Self;
1846
1847 /// ### Examples
1848 /// ```
1849 /// use stereokit_rust::maths::Vec3;
1850 ///
1851 /// let a = Vec3::new(1.0, 2.0, 3.0);
1852 /// let b = -a;
1853 /// assert_eq!(b, Vec3::new(-1.0, -2.0, -3.0));
1854 /// ```
1855 #[inline]
1856 fn neg(self) -> Self::Output {
1857 self * -1.0
1858 }
1859}
1860
1861/// A vector with 4 components: x, y, z, and w. Can be useful for things like shaders, where the registers are aligned
1862/// to 4 float vectors.
1863///
1864/// This is a wrapper on System.Numerics.Vector4, so it’s SIMD optimized, and can be cast to and from implicitly.
1865/// <https://stereokit.net/Pages/StereoKit/Vec4.html>
1866///
1867/// see also [`glam::Vec4`]
1868/// ### Examples
1869/// ```
1870/// use stereokit_rust::maths::Vec4;
1871///
1872/// let vec4 = Vec4::new(1.0, 2.0, 3.0, 4.0);
1873/// let vec4a = Vec4 { x: 1.0, y: 2.0, z:3.0, w:4.0 };
1874/// let vec4b = Vec4::X + Vec4::Y * 2.0;
1875/// let vec4c: Vec4 = [1.0, 2.0, 3.0, 4.0].into();
1876///
1877/// assert_eq!(vec4, vec4a);
1878/// assert_eq!(vec4a + vec4b, Vec4 { x: 2.0, y: 4.0, z: 3.0, w: 4.0 });
1879/// assert_eq!(vec4c, Vec4 { x: 1.0, y: 2.0, z: 3.0, w: 4.0 });
1880/// assert_eq!(vec4a.length_sq(), 30.0);
1881/// assert_eq!(Vec4::dot(Vec4::X, Vec4::Y), 0.0);
1882/// ```
1883#[derive(Debug, Default, Copy, Clone)]
1884#[repr(C)]
1885pub struct Vec4 {
1886 pub x: f32,
1887 pub y: f32,
1888 pub z: f32,
1889 pub w: f32,
1890}
1891impl From<glam::Vec4> for Vec4 {
1892 fn from(value: glam::Vec4) -> Self {
1893 Self { x: value.x, y: value.y, z: value.z, w: value.w }
1894 }
1895}
1896impl From<[f32; 4]> for Vec4 {
1897 fn from(val: [f32; 4]) -> Self {
1898 Vec4 { x: val[0], y: val[1], z: val[2], w: val[3] }
1899 }
1900}
1901
1902impl From<Vec4> for glam::Vec4 {
1903 fn from(value: Vec4) -> Self {
1904 Self::new(value.x, value.y, value.z, value.w)
1905 }
1906}
1907
1908/// Warning: Equality with a precision of 0.1 millimeter
1909impl PartialEq for Vec4 {
1910 /// Warning: Equality with a precision of 0.1 millimeter
1911 fn eq(&self, other: &Self) -> bool {
1912 ((self.x - other.x).abs() < 0.0001)
1913 && ((self.y - other.y).abs() < 0.0001)
1914 && ((self.z - other.z).abs() < 0.0001)
1915 && ((self.w - other.w).abs() < 0.0001)
1916 }
1917}
1918
1919impl Vec4 {
1920 /// all components to 0
1921 pub const ZERO: Vec4 = Vec4 { x: 0.0, y: 0.0, z: 0.0, w: 0.0 };
1922
1923 /// all components to 1
1924 pub const ONE: Vec4 = Vec4 { x: 1.0, y: 1.0, z: 1.0, w: 1.0 };
1925
1926 /// A normalized Vector that points down the X axis, this is the same as new Vec4(1,0,0,0).
1927 /// <https://stereokit.net/Pages/StereoKit/Vec4/UnitX.html>
1928 pub const X: Vec4 = Vec4 { x: 1.0, y: 0.0, z: 0.0, w: 0.0 };
1929
1930 /// A normalized Vector that points down the Y axis, this is the same as new Vec4(0,1,0,0).
1931 /// <https://stereokit.net/Pages/StereoKit/Vec4/UnitY.html>
1932 pub const Y: Vec4 = Vec4 { x: 0.0, y: 1.0, z: 0.0, w: 0.0 };
1933
1934 /// A normalized Vector that points down the Z axis, this is the same as new Vec4(0,0,1,0).
1935 /// <https://stereokit.net/Pages/StereoKit/Vec4/UnitZ.html>
1936 pub const Z: Vec4 = Vec4 { x: 0.0, y: 0.0, z: 1.0, w: 0.0 };
1937
1938 /// A normalized Vector that points down the W axis, this is the same as new Vec4(0,0,0,1).
1939 /// <https://stereokit.net/Pages/StereoKit/Vec4/UnitW.html>
1940 pub const W: Vec4 = Vec4 { x: 0.0, y: 0.0, z: 0.0, w: 1.0 };
1941
1942 /// A normalized Vector that points up the X axis, this is the same as new Vec4(1,0,0,0).
1943 pub const NEG_X: Vec4 = Vec4 { x: -1.0, y: 0.0, z: 0.0, w: 0.0 };
1944
1945 /// A normalized Vector that points up the Y axis, this is the same as new Vec4(0,1,0,0).
1946 pub const NEG_Y: Vec4 = Vec4 { x: 0.0, y: -1.0, z: 0.0, w: 0.0 };
1947
1948 /// A normalized Vector that points up the Z axis, this is the same as new Vec4(0,0,1,0).
1949 pub const NEG_Z: Vec4 = Vec4 { x: 0.0, y: 0.0, z: -1.0, w: 0.0 };
1950
1951 /// A normalized Vector that points up the W axis, this is the same as new Vec4(0,0,0,1).
1952 pub const NEG_W: Vec4 = Vec4 { x: 0.0, y: 0.0, z: 0.0, w: -1.0 };
1953
1954 /// <https://stereokit.net/Pages/StereoKit/Vec4/Vec4.html>
1955 #[inline]
1956 pub const fn new(x: f32, y: f32, z: f32, w: f32) -> Self {
1957 Self { x, y, z, w }
1958 }
1959
1960 /// This extracts the Vec2 from the X and Y axes.
1961 /// <https://stereokit.net/Pages/StereoKit/Vec4/XY.html>
1962 ///
1963 /// ### Examples
1964 /// ```
1965 /// use stereokit_rust::maths::{Vec2, Vec4};
1966 ///
1967 /// let v = Vec4::new(1.0, 2.0, 3.0, 4.0);
1968 /// let xy = v.xy();
1969 /// assert_eq!(xy, Vec2::new(1.0, 2.0));
1970 /// ```
1971 #[inline]
1972 pub fn xy(&self) -> Vec2 {
1973 Vec2::new(self.x, self.y)
1974 }
1975
1976 /// This extracts the Vec2 from the Y and Z axes.
1977 /// <https://stereokit.net/Pages/StereoKit/Vec4/YZ.html>
1978 ///
1979 /// ### Examples
1980 /// ```
1981 /// use stereokit_rust::maths::{Vec2, Vec4};
1982 ///
1983 /// let v = Vec4::new(1.0, 2.0, 3.0, 4.0);
1984 /// let yz = v.yz();
1985 /// assert_eq!(yz, Vec2::new(2.0, 3.0));
1986 /// ```
1987 #[inline]
1988 pub fn yz(&self) -> Vec2 {
1989 Vec2::new(self.y, self.z)
1990 }
1991
1992 /// This extracts the Vec2 from the X and Z axes.
1993 /// <https://stereokit.net/Pages/StereoKit/Vec4/XZ.html>
1994 ///
1995 /// ### Examples
1996 /// ```
1997 /// use stereokit_rust::maths::{Vec2, Vec4};
1998 ///
1999 /// let v = Vec4::new(1.0, 2.0, 3.0, 4.0);
2000 /// let xz = v.xz();
2001 /// assert_eq!(xz, Vec2::new(1.0, 3.0));
2002 /// ```
2003 #[inline]
2004 pub fn xz(&self) -> Vec2 {
2005 Vec2::new(self.x, self.z)
2006 }
2007
2008 /// This extracts the Vec2 from the Z and W axes.
2009 /// <https://stereokit.net/Pages/StereoKit/Vec4/ZW.html>
2010 ///
2011 /// ### Examples
2012 /// ```
2013 /// use stereokit_rust::maths::{Vec2, Vec4};
2014 ///
2015 /// let v = Vec4::new(1.0, 2.0, 3.0, 4.0);
2016 /// let zw = v.zw();
2017 /// assert_eq!(zw, Vec2::new(3.0, 4.0));
2018 /// ```
2019 #[inline]
2020 pub fn zw(&self) -> Vec2 {
2021 Vec2::new(self.z, self.w)
2022 }
2023
2024 /// This extracts a Vec3 from the X, Y, and Z axes.
2025 /// <https://stereokit.net/Pages/StereoKit/Vec4/XYZ.html>
2026 ///
2027 /// ### Examples
2028 /// ```
2029 /// use stereokit_rust::maths::{Vec3, Vec4};
2030 ///
2031 /// let v = Vec4::new(1.0, 2.0, 3.0, 4.0);
2032 /// let v3 = v.xyz();
2033 /// assert_eq!(v3, Vec3::new(1.0, 2.0, 3.0));
2034 /// ```
2035 #[inline]
2036 pub fn xyz(&self) -> Vec3 {
2037 Vec3::new(self.x, self.y, self.z)
2038 }
2039
2040 /// A Vec4 and a Quat are only really different by name and purpose. So, if you need to do Quat math with your
2041 /// Vec4, or visa versa, who am I to judge?
2042 /// <https://stereokit.net/Pages/StereoKit/Vec4/Quat.html>
2043 ///
2044 /// ### Examples
2045 /// ```
2046 /// use stereokit_rust::maths::{Vec4, Quat};
2047 ///
2048 /// let vec4 = Vec4::new(1.0, 2.0, 3.0, 4.0);
2049 /// let quat = vec4.get_as_quat();
2050 /// assert_eq!(quat, Quat::new(1.0, 2.0, 3.0, 4.0));
2051 /// ```
2052 #[inline]
2053 pub fn get_as_quat(&self) -> Quat {
2054 Quat { x: self.x, y: self.y, z: self.z, w: self.w }
2055 }
2056
2057 /// This is the squared length/magnitude of the vector! It skips the Sqrt call, and just gives you the squared
2058 /// version for speedy calculations that can work with it squared.
2059 /// <https://stereokit.net/Pages/StereoKit/Vec4.html>
2060 ///
2061 /// ### Examples
2062 /// ```
2063 /// use stereokit_rust::maths::Vec4;
2064 ///
2065 /// let v = Vec4::new(1.0, 2.0, 3.0, 4.0);
2066 /// assert_eq!(v.length_sq(), 30.0);
2067 /// ```
2068 #[inline]
2069 pub fn length_sq(&self) -> f32 {
2070 Self::dot(*self, *self)
2071 }
2072
2073 /// What’s a dot product do for 4D vectors, you might ask? Well, I’m no mathematician, so hopefully you are! I’ve
2074 /// never used it before. Whatever you’re doing with this function, it’s SIMD fast!
2075 /// <https://stereokit.net/Pages/StereoKit/Vec4/Dot.html>
2076 /// * `a` - The first vector.
2077 /// * `b` - The second vector.
2078 ///
2079 /// Returns the dot product of the two vectors.
2080 /// ### Examples
2081 /// ```
2082 /// use stereokit_rust::maths::Vec4;
2083 ///
2084 /// let a = Vec4::new(1.0, 2.0, 3.0, 4.0);
2085 /// let b = Vec4::new(5.0, 6.0, 7.0, 8.0);
2086 /// let result = Vec4::dot(a, b);
2087 /// assert_eq!(result, 70.0);
2088 /// ```
2089 #[inline]
2090 pub fn dot(a: Self, b: Self) -> f32 {
2091 (a.x * b.x) + (a.y * b.y) + (a.z * b.z) + (a.w * b.w)
2092 }
2093
2094 /// Blends (Linear Interpolation) between two vectors, based on a ‘blend’ value, where 0 is a, and 1 is b. Doesn’t
2095 /// clamp percent for you.
2096 /// <https://stereokit.net/Pages/StereoKit/Vec4/Lerp.html>
2097 /// * `a` - First item in the blend, or '0.0 blend.
2098 /// * `b` - Second item in the blend, or '1.0 blend.
2099 /// * `blend` - A blend value between 0 and 1. Can be outside this range, it’ll just interpolate outside of the a, b
2100 /// range.
2101 ///
2102 /// Returns an unclamped blend of a and b.
2103 /// ### Examples
2104 /// ```
2105 /// use stereokit_rust::maths::Vec4;
2106 /// let a = Vec4::new(0.0, 0.0, 0.0, 0.0);
2107 /// let b = Vec4::new(1.0, 1.0, 1.0, 1.0);
2108 /// let result = Vec4::lerp(a, b, 0.75);
2109 /// assert_eq!(result, Vec4::new(0.75, 0.75, 0.75, 0.75));
2110 /// ```
2111 #[inline]
2112 pub fn lerp(a: Self, b: Self, blend: f32) -> Self {
2113 a + ((b - a) * blend)
2114 }
2115
2116 /// Returns a vector where each element is the maximum value for each corresponding pair.
2117 /// <https://stereokit.net/Pages/StereoKit/Vec4/Max.html>
2118 /// * `a` - Order isn't important here.
2119 /// * `b` - Order isn't important here.
2120 ///
2121 /// Returns a vector where each element is the maximum value for each corresponding pair.
2122 /// #### Examples
2123 /// ```
2124 /// use stereokit_rust::maths::Vec4;
2125 ///
2126 /// let a = Vec4::new(1.0, 2.0, 3.0, 4.0);
2127 /// let b = Vec4::new(4.0, 3.0, 2.0, 1.0);
2128 /// let c = Vec4::max(a, b);
2129 /// assert_eq!(c, Vec4::new(4.0, 3.0, 3.0, 4.0));
2130 /// ```
2131 #[inline]
2132 pub fn max(a: Self, b: Self) -> Self {
2133 Self { x: f32::max(a.x, b.x), y: f32::max(a.y, b.y), z: f32::max(a.z, b.z), w: f32::max(a.w, b.w) }
2134 }
2135
2136 /// Returns a vector where each element is the minimum value for each corresponding pair.
2137 /// <https://stereokit.net/Pages/StereoKit/Vec4/Min.html>
2138 /// * `a` - Order isn't important here.
2139 /// * `b` - Order isn't important here.
2140 ///
2141 /// Returns a new vector with the minimum values.
2142 /// ### Examples
2143 /// ```
2144 /// use stereokit_rust::maths::Vec4;
2145 ///
2146 /// let a = Vec4::new(1.0, 2.0, 3.0, 4.0);
2147 /// let b = Vec4::new(4.0, 3.0, 2.0, 1.0);
2148 /// let c = Vec4::min(a, b);
2149 /// assert_eq!(c, Vec4::new(1.0, 2.0, 2.0, 1.0));
2150 /// ```
2151 #[inline]
2152 pub fn min(a: Self, b: Self) -> Self {
2153 Self { x: f32::min(a.x, b.x), y: f32::min(a.y, b.y), z: f32::min(a.z, b.z), w: f32::min(a.w, b.w) }
2154 }
2155}
2156
2157impl Display for Vec4 {
2158 /// Mostly for debug purposes, this is a decent way to log or inspect the vector in debug mode. Looks
2159 /// like “[x, y, z, w]”
2160 /// <https://stereokit.net/Pages/StereoKit/Vec4/ToString.html>
2161 ///
2162 /// ### Examples
2163 /// ```
2164 /// use stereokit_rust::maths::Vec4;
2165 ///
2166 /// let v = Vec4::new(1.0, 2.2, 3.0, 4.0);
2167 /// assert_eq!(format!("{}", v), "[x:1, y:2.2, z:3, w:4]");
2168 /// ```
2169 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2170 write!(f, "[x:{}, y:{}, z:{}, w:{}]", self.x, self.y, self.z, self.w)
2171 }
2172}
2173/// A component-wise vector division.
2174/// <https://stereokit.net/Pages/StereoKit/Vec4/op_Division.html>
2175impl Div<Vec4> for Vec4 {
2176 type Output = Self;
2177
2178 /// ### Examples
2179 /// ```
2180 /// use stereokit_rust::maths::Vec4;
2181 ///
2182 /// let a = Vec4::new(1.0, 2.0, 3.0, 4.0);
2183 /// let b = Vec4::new(2.0, 2.0, 2.0, 2.0);
2184 /// let c = a / b;
2185 /// assert_eq!(c, Vec4::new(0.5, 1.0, 1.5, 2.0));
2186 /// ```
2187 #[inline]
2188 fn div(self, rhs: Self) -> Self::Output {
2189 Self { x: self.x.div(rhs.x), y: self.y.div(rhs.y), z: self.z.div(rhs.z), w: self.w.div(rhs.w) }
2190 }
2191}
2192
2193/// A component-wise vector division.
2194/// <https://stereokit.net/Pages/StereoKit/Vec4/op_Division.html>
2195impl DivAssign<Vec4> for Vec4 {
2196 /// ### Examples
2197 /// ```
2198 /// use stereokit_rust::maths::*;
2199 ///
2200 /// let mut a = Vec4::new(1.0, 2.0, 3.0, 4.0);
2201 /// let b = Vec4::new(2.0, 2.0, 2.0, 2.0);
2202 /// a /= b;
2203 /// assert_eq!(a, Vec4::new(0.5, 1.0, 1.5, 2.0));
2204 /// ```
2205 #[inline]
2206 fn div_assign(&mut self, rhs: Self) {
2207 self.x.div_assign(rhs.x);
2208 self.y.div_assign(rhs.y);
2209 self.z.div_assign(rhs.z);
2210 self.w.div_assign(rhs.w);
2211 }
2212}
2213
2214/// A component-wise vector division.
2215/// <https://stereokit.net/Pages/StereoKit/Vec4/op_Division.html>
2216impl Div<f32> for Vec4 {
2217 type Output = Self;
2218
2219 /// ### Examples
2220 /// ```
2221 /// use stereokit_rust::maths::Vec4;
2222 ///
2223 /// let a = Vec4::new(1.0, 2.0, 3.0, 4.0);
2224 /// let b = a / 2.0;
2225 /// assert_eq!(b, Vec4::new(0.5, 1.0, 1.5, 2.0));
2226 /// ```
2227 #[inline]
2228 fn div(self, rhs: f32) -> Self::Output {
2229 Self { x: self.x.div(rhs), y: self.y.div(rhs), z: self.z.div(rhs), w: self.w.div(rhs) }
2230 }
2231}
2232
2233/// A component-wise vector division.
2234/// <https://stereokit.net/Pages/StereoKit/Vec4/op_Division.html>
2235impl DivAssign<f32> for Vec4 {
2236 /// ### Examples
2237 /// ```
2238 /// use stereokit_rust::maths::Vec4;
2239 ///
2240 /// let mut v = Vec4::new(1.0, 2.0, 3.0, 4.0);
2241 /// v /= 2.0;
2242 /// assert_eq!(v, Vec4::new(0.5, 1.0, 1.5, 2.0));
2243 /// ```
2244 #[inline]
2245 fn div_assign(&mut self, rhs: f32) {
2246 self.x.div_assign(rhs);
2247 self.y.div_assign(rhs);
2248 self.z.div_assign(rhs);
2249 self.w.div_assign(rhs);
2250 }
2251}
2252
2253/// A component-wise vector division.
2254/// <https://stereokit.net/Pages/StereoKit/Vec4/op_Division.html>
2255impl Div<Vec4> for f32 {
2256 type Output = Vec4;
2257
2258 /// ### Examples
2259 /// ```
2260 /// use stereokit_rust::maths::Vec4;
2261 ///
2262 /// let a = Vec4::new(1.0, 7.0, 3.0, 4.0);
2263 /// let b = a / 2.0;
2264 /// assert_eq!(b, Vec4::new(0.5, 3.5, 1.5, 2.0));
2265 /// ```
2266 #[inline]
2267 fn div(self, rhs: Vec4) -> Self::Output {
2268 Vec4 { x: self.div(rhs.x), y: self.div(rhs.y), z: self.div(rhs.z), w: self.div(rhs.w) }
2269 }
2270}
2271
2272/// A component-wise vector multiplication, same thing as a non-uniform scale. NOT a dot or cross product! Commutative.
2273/// <https://stereokit.net/Pages/StereoKit/Vec4/op_Multiply.html>
2274impl Mul<Vec4> for Vec4 {
2275 type Output = Self;
2276
2277 /// ### Examples
2278 /// ```
2279 /// use stereokit_rust::maths::Vec4;
2280 ///
2281 /// let a = Vec4::new(1.0, 2.0, 3.0, 5.0);
2282 /// let b = Vec4::new(2.0, 3.0, 4.0, 6.0);
2283 /// let c = a * b;
2284 /// assert_eq!(c, Vec4::new(2.0, 6.0, 12.0, 30.0));
2285 /// ```
2286 #[inline]
2287 fn mul(self, rhs: Self) -> Self::Output {
2288 Self { x: self.x.mul(rhs.x), y: self.y.mul(rhs.y), z: self.z.mul(rhs.z), w: self.w.mul(rhs.w) }
2289 }
2290}
2291
2292/// A component-wise vector multiplication, same thing as a non-uniform scale. NOT a dot or cross product! Commutative.
2293/// <https://stereokit.net/Pages/StereoKit/Vec4/op_Multiply.html>
2294impl MulAssign<Vec4> for Vec4 {
2295 /// ### Examples
2296 /// ```
2297 /// use stereokit_rust::maths::Vec4;
2298 ///
2299 /// let mut a = Vec4::new(1.0, 2.0, 3.0, 5.0);
2300 /// let b = Vec4::new(2.0, 3.0, 4.0, 6.0);
2301 /// a *= b;
2302 /// assert_eq!(a, Vec4::new(2.0, 6.0, 12.0, 30.0));
2303 /// ```
2304 #[inline]
2305 fn mul_assign(&mut self, rhs: Self) {
2306 self.x.mul_assign(rhs.x);
2307 self.y.mul_assign(rhs.y);
2308 self.z.mul_assign(rhs.z);
2309 self.w.mul_assign(rhs.w)
2310 }
2311}
2312
2313/// A component-wise vector multiplication, same thing as a non-uniform scale. NOT a dot or cross product! Commutative.
2314/// <https://stereokit.net/Pages/StereoKit/Vec4/op_Multiply.html>
2315impl Mul<f32> for Vec4 {
2316 type Output = Self;
2317
2318 /// ### Examples
2319 /// ```
2320 /// use stereokit_rust::maths::Vec4;
2321 ///
2322 /// let a = Vec4::new(1.0, 2.0, 3.0, 5.0);
2323 /// let b = a * 2.0;
2324 /// assert_eq!(b, Vec4::new(2.0, 4.0, 6.0, 10.0));
2325 /// ```
2326 #[inline]
2327 fn mul(self, rhs: f32) -> Self::Output {
2328 Self { x: self.x.mul(rhs), y: self.y.mul(rhs), z: self.z.mul(rhs), w: self.w.mul(rhs) }
2329 }
2330}
2331
2332/// A component-wise vector multiplication, same thing as a non-uniform scale. NOT a dot or cross product! Commutative.
2333/// <https://stereokit.net/Pages/StereoKit/Vec4/op_Multiply.html>
2334impl MulAssign<f32> for Vec4 {
2335 /// ### Examples
2336 /// ```
2337 /// use stereokit_rust::maths::Vec4;
2338 ///
2339 /// let mut a = Vec4::new(1.0, 2.0, 7.0, 5.0);
2340 /// a *= 2.0;
2341 /// assert_eq!(a, Vec4::new(2.0, 4.0, 14.0, 10.0));
2342 /// ```
2343 #[inline]
2344 fn mul_assign(&mut self, rhs: f32) {
2345 self.x.mul_assign(rhs);
2346 self.y.mul_assign(rhs);
2347 self.z.mul_assign(rhs);
2348 self.w.mul_assign(rhs);
2349 }
2350}
2351
2352/// A component-wise vector multiplication, same thing as a non-uniform scale. NOT a dot or cross product! Commutative.
2353/// <https://stereokit.net/Pages/StereoKit/Vec4/op_Multiply.html>
2354impl Mul<Vec4> for f32 {
2355 type Output = Vec4;
2356
2357 /// ### Examples
2358 /// ```
2359 /// use stereokit_rust::maths::Vec4;
2360 ///
2361 /// let a = 2.0;
2362 /// let b = Vec4::new(2.0, 3.0, 4.0, 6.0);
2363 /// let c = a * b;
2364 /// assert_eq!(c, Vec4::new(4.0, 6.0, 8.0, 12.0));
2365 /// ```
2366 #[inline]
2367 fn mul(self, rhs: Vec4) -> Self::Output {
2368 Vec4 { x: self.mul(rhs.x), y: self.mul(rhs.y), z: self.mul(rhs.z), w: self.mul(rhs.w) }
2369 }
2370}
2371
2372/// Adds matching components together. Commutative.
2373/// <https://stereokit.net/Pages/StereoKit/Vec4/op_Addition.html>
2374impl Add<Vec4> for Vec4 {
2375 type Output = Self;
2376
2377 /// ### Examples
2378 /// ```
2379 /// use stereokit_rust::maths::Vec4;
2380 ///
2381 /// let a = Vec4::new(1.0, 2.0, 3.0, 5.0);
2382 /// let b = Vec4::new(2.0, 3.0, 4.0, 6.0);
2383 /// let c = a + b;
2384 /// assert_eq!(c, Vec4::new(3.0, 5.0, 7.0, 11.0));
2385 /// ```
2386 #[inline]
2387 fn add(self, rhs: Self) -> Self::Output {
2388 Self { x: self.x.add(rhs.x), y: self.y.add(rhs.y), z: self.z.add(rhs.z), w: self.w.add(rhs.w) }
2389 }
2390}
2391
2392/// Adds matching components together. Commutative.
2393/// <https://stereokit.net/Pages/StereoKit/Vec4/op_Addition.html>
2394impl AddAssign<Vec4> for Vec4 {
2395 /// ### Examples
2396 /// ```
2397 /// use stereokit_rust::maths::Vec4;
2398 ///
2399 /// let mut v1 = Vec4::new(1.0, 2.0, 3.0, 4.0);
2400 /// let v2 = Vec4::new(5.0, 6.0, 7.0, 8.0);
2401 /// v1 += v2;
2402 /// assert_eq!(v1, Vec4::new(6.0, 8.0, 10.0, 12.0));
2403 /// ```
2404 #[inline]
2405 fn add_assign(&mut self, rhs: Self) {
2406 self.x.add_assign(rhs.x);
2407 self.y.add_assign(rhs.y);
2408 self.z.add_assign(rhs.z);
2409 self.w.add_assign(rhs.w);
2410 }
2411}
2412
2413impl Sub<Vec4> for Vec4 {
2414 type Output = Self;
2415
2416 /// ### Examples
2417 /// ```
2418 /// use stereokit_rust::maths::Vec4;
2419 ///
2420 /// let a = Vec4::new(1.0, 2.0, 3.0, 4.0);
2421 /// let b = Vec4::new(4.0, 3.0, 2.0, 1.0);
2422 /// let c = a - b;
2423 /// assert_eq!(c, Vec4::new(-3.0, -1.0, 1.0, 3.0));
2424 /// ```
2425 #[inline]
2426 fn sub(self, rhs: Self) -> Self::Output {
2427 Self { x: self.x.sub(rhs.x), y: self.y.sub(rhs.y), z: self.z.sub(rhs.z), w: self.w.sub(rhs.w) }
2428 }
2429}
2430
2431/// Subtracts matching components from eachother. Not commutative.
2432/// <https://stereokit.net/Pages/StereoKit/Vec4/op_Subtraction.html>
2433impl SubAssign<Vec4> for Vec4 {
2434 /// ### Examples
2435 /// ```
2436 /// use stereokit_rust::maths::Vec4;
2437 ///
2438 /// let mut v1 = Vec4::new(1.0, 2.0, 3.0, 4.0);
2439 /// let v2 = Vec4::new(1.0, 2.0, 3.0, 4.0);
2440 /// v1 -= v2;
2441 /// assert_eq!(v1, Vec4::new(0.0, 0.0, 0.0, 0.0));
2442 /// ```
2443 #[inline]
2444 fn sub_assign(&mut self, rhs: Vec4) {
2445 self.x.sub_assign(rhs.x);
2446 self.y.sub_assign(rhs.y);
2447 self.z.sub_assign(rhs.z);
2448 self.w.sub_assign(rhs.w);
2449 }
2450}
2451
2452/// Vector negation, returns a vector where each component has been negated.
2453/// <https://stereokit.net/Pages/StereoKit/Vec4/op_UnaryNegation.html>
2454impl Neg for Vec4 {
2455 type Output = Self;
2456
2457 /// ### Examples
2458 /// ```
2459 /// use stereokit_rust::maths::Vec4;
2460 ///
2461 /// let v = Vec4::new(1.0, 2.0, 3.0, 4.0);
2462 /// let neg_v = -v;
2463 /// assert_eq!(neg_v, Vec4::new(-1.0, -2.0, -3.0, -4.0));
2464 /// ```
2465 #[inline]
2466 fn neg(self) -> Self::Output {
2467 self * -1.0
2468 }
2469}
2470
2471/// Quaternions are efficient and robust mathematical objects for representing rotations! Understanding the details of
2472/// how a quaternion works is not generally necessary for using them effectively, so don’t worry too much if they seem
2473/// weird to you. They’re weird to me too.
2474///
2475/// If you’re interested in learning the details though, 3Blue1Brown and Ben Eater have an excellent interactive lesson
2476/// about them!
2477/// <https://stereokit.net/Pages/StereoKit/Quat.html>
2478///
2479/// see also [`glam::Quat`]
2480/// ### Examples
2481/// ```
2482/// use stereokit_rust::maths::{Quat, Vec3, Vec4};
2483///
2484/// let mut quat1 = Quat::new(0.0, 0.0, 0.0, 1.0);
2485/// let mut quat2 = Quat::from_angles(0.0, 90.0, 0.0);
2486/// let mut quat2b :Quat= [0.0, 90.0, 0.0].into();
2487/// let mut quat3 = Quat::look_at(Vec3::X, Vec3::ZERO, None);
2488/// let vec4_w: Vec4 = (quat2 - quat3).into();
2489///
2490/// // quat2 == quat3 but because of epsilon here is the demo:
2491/// assert_eq!(vec4_w.w, 1.0);
2492/// assert_eq!(vec4_w.length_sq(), 1.0);
2493/// assert_eq!(quat2b, quat2);
2494///
2495/// assert_eq!(quat1, Quat::IDENTITY);
2496/// assert_eq!(*quat1.normalize(), Quat::IDENTITY);
2497/// assert_eq!(*quat1.invert(), Quat::IDENTITY);
2498///
2499/// ```
2500#[repr(C)]
2501#[derive(Debug, Copy, Clone)]
2502pub struct Quat {
2503 pub x: f32,
2504 pub y: f32,
2505 pub z: f32,
2506 pub w: f32,
2507}
2508impl From<glam::Quat> for Quat {
2509 fn from(val: glam::Quat) -> Self {
2510 Quat { x: val.x, y: val.y, z: val.z, w: val.w }
2511 }
2512}
2513impl From<Quat> for glam::Quat {
2514 fn from(val: Quat) -> Self {
2515 Self::from_xyzw(val.x, val.y, val.z, val.w)
2516 }
2517}
2518impl From<glam::Vec4> for Quat {
2519 fn from(val: glam::Vec4) -> Self {
2520 Quat { x: val.x, y: val.y, z: val.z, w: val.w }
2521 }
2522}
2523impl From<Quat> for glam::Vec4 {
2524 fn from(val: Quat) -> Self {
2525 Self::new(val.x, val.y, val.z, val.w)
2526 }
2527}
2528impl From<[f32; 3]> for Quat {
2529 fn from(val: [f32; 3]) -> Self {
2530 Quat::from_angles(val[0], val[1], val[2])
2531 }
2532}
2533impl From<Vec4> for Quat {
2534 fn from(val: Vec4) -> Self {
2535 Quat { x: val.x, y: val.y, z: val.z, w: val.w }
2536 }
2537}
2538impl From<Quat> for Vec4 {
2539 fn from(val: Quat) -> Self {
2540 Self { x: val.x, y: val.y, z: val.z, w: val.w }
2541 }
2542}
2543
2544impl Default for Quat {
2545 // Identity quaternion (no rotation)
2546 fn default() -> Self {
2547 Quat::IDENTITY
2548 }
2549}
2550
2551/// Warning: Equality with a precision of 0.000001
2552impl PartialEq for Quat {
2553 /// Warning: Equality with a precision of 0.00001
2554 /// ### Example
2555 /// ```
2556 /// use stereokit_rust::maths::Quat;
2557 ///
2558 /// let q0 = Quat::new(1.00002, 2.0, 3.0, 4.0);
2559 /// let q1 = Quat::new(1.000001, 2.000001, 3.000001, 4.0);
2560 /// let q2 = Quat::new(1.0, 2.0, 3.0, 4.0);
2561 /// assert_ne!(q0, q1);
2562 /// assert_eq!(q1, q2);
2563 /// ```
2564 fn eq(&self, other: &Self) -> bool {
2565 ((self.x - other.x).abs() < 0.00001)
2566 && ((self.y - other.y).abs() < 0.00001)
2567 && ((self.z - other.z).abs() < 0.00001)
2568 && ((self.w - other.w).abs() < 0.00001)
2569 }
2570}
2571
2572unsafe extern "C" {
2573 pub fn quat_difference(a: *const Quat, b: *const Quat) -> Quat;
2574 pub fn quat_lookat(from: *const Vec3, at: *const Vec3) -> Quat;
2575 pub fn quat_lookat_up(from: *const Vec3, at: *const Vec3, up: *const Vec3) -> Quat;
2576 pub fn quat_from_angles(pitch_x_deg: f32, yaw_y_deg: f32, roll_z_deg: f32) -> Quat;
2577 pub fn quat_slerp(a: *const Quat, b: *const Quat, t: f32) -> Quat;
2578 pub fn quat_normalize(a: *const Quat) -> Quat;
2579 pub fn quat_inverse(a: *const Quat) -> Quat;
2580 pub fn quat_mul(a: *const Quat, b: *const Quat) -> Quat;
2581 pub fn quat_mul_vec(a: *const Quat, b: *const Vec3) -> Vec3;
2582 pub fn quat_to_axis_angle(a: Quat, out_axis: *mut Vec3, out_rotation_deg: *mut f32);
2583}
2584
2585impl Quat {
2586 /// This is the ‘multiply by one!’ of the quaternion rotation world. It’s basically a default, no rotation
2587 /// quaternion.
2588 /// <https://stereokit.net/Pages/StereoKit/Quat/Identity.html>
2589 pub const IDENTITY: Self = Self { x: 0.0, y: 0.0, z: 0.0, w: 1.0 };
2590
2591 /// This is a quaternion that represents a 180 degree rotation around the Y axis. It’s useful for
2592 /// representing a 180 degree turn in a 3D space, such as when you want to face the opposite direction.
2593 pub const Y_180: Self = Self { x: 0.0, y: 1.0, z: 0.0, w: 0.0 };
2594
2595 /// ZERO may be found when testing some [`crate::system::Input`], [`crate::system::Pointer`] or [`crate::system::Controller`]
2596 pub const ZERO: Self = Self { x: 0.0, y: 0.0, z: 0.0, w: 0.0 };
2597
2598 /// You may want to use static creation methods, like Quat::look_at, or Quat::IDENTITY instead of this one! Unless you
2599 /// know what you’re doing.
2600 /// <https://stereokit.net/Pages/StereoKit/Quat/Quat.html>
2601 #[inline]
2602 pub const fn new(x: f32, y: f32, z: f32, w: f32) -> Self {
2603 Self { x, y, z, w }
2604 }
2605
2606 /// Makes this Quat the reverse rotation! If this quat goes from A to B, the inverse will go from B to A.
2607 /// Costly, see get_inverse for a faster way to get this.
2608 /// <https://stereokit.net/Pages/StereoKit/Quat/Invert.html>
2609 ///
2610 /// see also [`Quat::get_inverse`] [`quat_inverse`]
2611 /// ### Examples
2612 /// ```
2613 /// use stereokit_rust::maths::Quat;
2614 ///
2615 /// let mut q = Quat::new(1.0, 2.0, 3.0, 4.0);
2616 /// q.invert();
2617 /// assert_eq!(q, Quat { x: -0.033333335, y: -0.06666667, z: -0.1, w: 0.13333334 });
2618 /// ```
2619 #[inline]
2620 pub fn invert(&mut self) -> &mut Self {
2621 let m = unsafe { quat_inverse(self) };
2622 self.x = m.x;
2623 self.y = m.y;
2624 self.z = m.z;
2625 self.w = m.w;
2626 self
2627 }
2628
2629 /// Return the conjugate
2630 /// ### Examples
2631 /// ```
2632 /// use stereokit_rust::maths::Quat;
2633 ///
2634 /// let mut q = Quat::new(1.0, 2.0, 3.0, 4.0);
2635 /// let q2 = q.conjugate();
2636 /// assert_eq!(q2, Quat { x: -1.0, y: -2.0, z: -3.0, w: 4.0 });
2637 /// ```
2638 #[inline]
2639 pub fn conjugate(&self) -> Self {
2640 Self { x: -self.x, y: -self.y, z: -self.z, w: self.w }
2641 }
2642
2643 /// Normalize this quaternion with the same orientation, and a length of 1.
2644 /// Costly, see get_normalized for a faster way to get this.
2645 /// <https://stereokit.net/Pages/StereoKit/Quat/Normalize.html>
2646 ///
2647 /// see also [`Quat::get_normalized`] [`quat_normalize`]
2648 /// ### Examples
2649 /// ```
2650 /// use stereokit_rust::maths::Quat;
2651 ///
2652 /// let mut q = Quat::new(1.0, 2.0, 3.0, 4.0);
2653 /// q.normalize();
2654 /// assert_eq!(q, Quat::new(0.18257419, 0.36514837, 0.54772256, 0.73029674));
2655 /// ```
2656 #[inline]
2657 pub fn normalize(&mut self) -> &mut Self {
2658 let m = unsafe { quat_normalize(self) };
2659 self.x = m.x;
2660 self.y = m.y;
2661 self.z = m.z;
2662 self.w = m.w;
2663 self
2664 }
2665
2666 /// Rotates a quaternion making it relative to another rotation while preserving it’s “Length”!
2667 /// <https://stereokit.net/Pages/StereoKit/Quat/Relative.html>
2668 /// * `to` - The relative quaternion.
2669 ///
2670 /// Returns this quaternion made relative to another rotation.
2671 /// see also [`quat_mul`]
2672 /// ### Examples
2673 /// ```
2674 /// use stereokit_rust::maths::Quat;
2675 ///
2676 /// let mut q = Quat::from_angles(0.0, 90.0, 0.0);
2677 /// assert_eq!(q, Quat { x: 0.0, y: 0.70710677, z: 0.0, w: 0.7071067 });
2678 ///
2679 /// let to = Quat::from_angles(0.0, 0.0, 90.0);
2680 /// q.relative(to);
2681 /// assert_eq!(q, Quat { x: 0.70710677, y: 0.0, z: 0.0, w: 0.7071067 });
2682 /// ```
2683 #[inline]
2684 pub fn relative(&mut self, to: Self) -> &mut Self {
2685 let m = to.mul(*self).mul(to.get_inverse());
2686 self.x = m.x;
2687 self.y = m.y;
2688 self.z = m.z;
2689 self.w = m.w;
2690 self
2691 }
2692
2693 /// This rotates a point around the origin by the Quat.
2694 /// <https://stereokit.net/Pages/StereoKit/Quat/Rotate.html>
2695 /// * `point` - The point to rotate around the origin.
2696 ///
2697 /// Returns the rotated point.
2698 /// see also [`quat_mul_vec`]
2699 /// ### Examples
2700 /// ```
2701 /// use stereokit_rust::maths::{Vec3, Quat};
2702 ///
2703 /// let q = Quat::from_angles(0.0, 90.0, 0.0);
2704 /// let point = Vec3::new(1.0, 0.0, 0.0);
2705 /// let rotated_point = q.rotate_point(point);
2706 /// assert_eq!(rotated_point, Vec3::new(0.0, 0.0, -1.0));
2707 /// ```
2708 #[inline]
2709 pub fn rotate_point(&self, point: Vec3) -> Vec3 {
2710 unsafe { quat_mul_vec(self, &point) }
2711 }
2712
2713 /// Get an array of the 3 angles in degrees of this Quat with x, y and z axis
2714 /// <https://stereokit.net/Pages/StereoKit/Quat.html>
2715 ///
2716 /// see also [`quat_to_axis_angle`]
2717 /// ### Examples
2718 /// ```
2719 /// use stereokit_rust::maths::{Quat, Vec3};
2720 ///
2721 /// let quat = Quat::from_angles(90.0, 180.0, -180.0);
2722 ///
2723 /// let angles: Vec3 = quat.to_angles_degrees().into();
2724 /// assert_eq!(angles, [-270.0, 0.0, 0.0].into());
2725 /// ```
2726 #[inline]
2727 pub fn to_angles_degrees(&self) -> [f32; 3] {
2728 let mut axis = Vec3::ZERO;
2729 let mut rotation: f32 = 0.0;
2730 unsafe { quat_to_axis_angle(*self, &mut axis, &mut rotation) };
2731 axis.normalize();
2732 [rotation * axis.x, rotation * axis.y, rotation * axis.z]
2733 }
2734
2735 /// Get an array of the 3 angles in radians of this Quat with x, y and z axis
2736 /// <https://stereokit.net/Pages/StereoKit/Quat.html>
2737 ///
2738 /// ### Examples
2739 /// ```
2740 /// use stereokit_rust::maths::{Quat, Vec3};
2741 ///
2742 /// let quat = Quat::from_angles(90.0, 0.0, 0.0);
2743 /// let angles = quat.to_angles();
2744 /// assert_eq!(angles, [1.5707964, 0.0, 0.0]);
2745 /// ```
2746 #[inline]
2747 pub fn to_angles(&self) -> [f32; 3] {
2748 self.to_angles_degrees().map(|x| x.to_radians())
2749 }
2750
2751 /// This rotates a point around the origin by the Quat.
2752 /// <https://stereokit.net/Pages/StereoKit/Quat/Rotate.html>
2753 /// * `a` - The Quat to use for rotation.
2754 /// * `point` - The point to rotate around the origin.
2755 ///
2756 /// Returns the rotated point.
2757 /// see also [`quat_mul_vec`] operator '*' [`Quat::rotate_point`]
2758 /// ### Examples
2759 /// ```
2760 /// use stereokit_rust::maths::{Vec3, Quat};
2761 ///
2762 /// let a = Quat::from_angles(0.0, 90.0, 0.0);
2763 /// let point = Vec3::new(1.0, 0.0, 0.0);
2764 /// let result1 = a * point;
2765 /// let result2 = Quat::rotate(a, point);
2766 /// let result3 = a.rotate_point(point);
2767 /// assert_eq!(result1, result2);
2768 /// assert_eq!(result2, result3);
2769 /// assert_eq!(result1, Vec3::new(0.0, 0.0, -1.0));
2770 /// ```
2771 #[inline]
2772 pub fn rotate(a: Quat, point: Vec3) -> Vec3 {
2773 unsafe { quat_mul_vec(&a, &point) }
2774 }
2775
2776 /// Creates a quaternion that goes from one rotation to another.
2777 /// <https://stereokit.net/Pages/StereoKit/Quat/Delta.html>
2778 /// * `from` - The origin rotation.
2779 /// * `to` - The target rotation.
2780 ///
2781 /// Returns the quaternion between from and to.
2782 /// see also `-` operator [`quat_difference`]
2783 /// ### Examples
2784 /// ```
2785 /// use stereokit_rust::maths::Quat;
2786 ///
2787 /// let from = Quat::from_angles(180.0, 0.0, 0.0);
2788 /// let to = Quat::from_angles(0.0, 180.0, 0.0);
2789 /// let delta = Quat::delta(from, to);
2790 /// assert_eq!(delta, Quat::from_angles(0.0, 0.0, 180.0));
2791 ///
2792 /// let delta_b = from - to;
2793 /// assert_eq!(delta_b, delta);
2794 /// ```
2795 #[inline]
2796 pub fn delta(from: Self, to: Self) -> Self {
2797 unsafe { quat_difference(&from, &to) }
2798 }
2799
2800 /// Creates a rotation that goes from one direction to another. Which is comes in handy when trying to roll
2801 /// something around with position data.
2802 /// <https://stereokit.net/Pages/StereoKit/Quat/Delta.html>
2803 /// * `from` - The origin direction.
2804 /// * `to` - The target direction.
2805 ///
2806 /// Returns the quaternion between the two directions.
2807 /// ### Examples
2808 /// ```
2809 /// use stereokit_rust::maths::{Quat, Vec3};
2810 ///
2811 /// let from = Vec3::new(1.0, 0.0, 0.0);
2812 /// let to = Vec3::new(0.0, 0.0, 1.0);
2813 /// let delta = Quat::delta_dir(from, to);
2814 /// assert_eq!(delta, Quat::from_angles(0.0, -90.0, 0.0));
2815 /// ```
2816 #[inline]
2817 pub fn delta_dir(from: Vec3, to: Vec3) -> Self {
2818 let c = Vec3::cross(from, to);
2819 let mut out = Quat { x: c.x, y: c.y, z: c.z, w: 1.0 + Vec3::dot(from, to) };
2820 *(out.normalize())
2821 }
2822
2823 /// Creates a Roll/Pitch/Yaw rotation (applied in that order) from the provided angles in degrees! There is also a
2824 /// From<[f32; 3]> for Quat implementation that does the same thing.
2825 /// <https://stereokit.net/Pages/StereoKit/Quat/FromAngles.html>
2826 /// * `pitch_x_deg` - The angle to rotate around the X-axis in degrees.
2827 /// * `yaw_y_deg` - The angle to rotate around the Y-axis in degrees.
2828 /// * `roll_z_deg` - The angle to rotate around the Z-axis in degrees.
2829 ///
2830 /// Returns a quaternion representing the given Roll/Pitch/Yaw rotation!
2831 /// see also [`quat_from_angles`] [`Quat::from`]
2832 /// ### Examples
2833 /// ```
2834 /// use stereokit_rust::maths::Quat;
2835 ///
2836 /// let quat = Quat::from_angles(45.0, 30.0, 60.0);
2837 /// let quat2: Quat = [45.0, 30.0, 60.0].into();
2838 /// assert_eq!(quat, quat2);
2839 ///
2840 /// let quat = Quat::from_angles(0.0, 180.0, 0.0);
2841 /// let quat2: Quat = Quat::Y_180;
2842 /// assert_eq!(quat, quat2);
2843 /// ```
2844 #[inline]
2845 pub fn from_angles(pitch_x_deg: f32, yaw_y_deg: f32, roll_z_deg: f32) -> Self {
2846 unsafe { quat_from_angles(pitch_x_deg, yaw_y_deg, roll_z_deg) }
2847 }
2848
2849 /// Creates a rotation that describes looking from a point, to another point! This is a great function for camera
2850 /// style rotation, or other facing behavior when you know where an object is, and where you want it to look at.
2851 /// This rotation works best when applied to objects that face Vec3.Forward in their resting/model space pose.
2852 /// <https://stereokit.net/Pages/StereoKit/Quat/LookAt.html>
2853 /// * `from` - Position of where the 'object' is.
2854 /// * `at` - The position you want the 'object' to look at.
2855 /// * `up` - Look From/At positions describe X and Y axis rotation well, but leave Z Axis/Roll
2856 /// undefined. Providing an upDirection vector helps to indicate roll around the From/At line. If None : up
2857 /// direction will be (0,1,0), to prevent roll.
2858 ///
2859 /// Returns a rotation that describes looking from a point, towards another point.
2860 /// see also [`quat_lookat`] [`quat_lookat_up`]
2861 /// ### Examples
2862 /// ```
2863 /// use stereokit_rust::maths::{Quat, Vec3};
2864 ///
2865 /// let from = Vec3::new(1.0, 0.0, 0.0);
2866 /// let at = Vec3::new(0.0, 0.0, 1.0);
2867 /// let up = Vec3::new(0.0, 1.0, 0.0);
2868 /// let quat = Quat::look_at(from, at, Some(up));
2869 /// assert_eq!(quat, Quat::from_angles(0.0, 135.0, 0.0));
2870 ///
2871 /// let quat = Quat::look_at(from, at, None);
2872 /// assert_eq!(quat, Quat::from_angles(0.0, 135.0, 0.0));
2873 /// ```
2874 #[inline]
2875 pub fn look_at<V: Into<Vec3>>(from: V, at: V, up: Option<Vec3>) -> Self {
2876 let from = from.into();
2877 let at = at.into();
2878 match up {
2879 Some(up) => unsafe { quat_lookat_up(&from, &at, &up) },
2880 None => unsafe { quat_lookat(&from, &at) },
2881 }
2882 }
2883
2884 /// Creates a rotation that describes looking towards a direction. This is great for quickly describing facing
2885 /// behavior! This rotation works best when applied to objects that face Vec3.Forward in their resting/model space
2886 /// pose.
2887 /// <https://stereokit.net/Pages/StereoKit/Quat/LookDir.html>
2888 /// * `direction` - The direction the rotation should be looking. Doesn't need to be normalized.
2889 ///
2890 /// Returns a rotation that describes looking towards a direction.
2891 /// see also [`quat_lookat`]
2892 /// ### Examples
2893 /// ```
2894 /// use stereokit_rust::maths::{Quat, Vec3};
2895 ///
2896 /// let direction = Vec3::new(1.0, 0.0, 0.0);
2897 /// let quat = Quat::look_dir(direction);
2898 /// assert_eq!(quat, Quat::from_angles(0.0, 270.0, 0.0));
2899 /// ```
2900 #[inline]
2901 pub fn look_dir<V: Into<Vec3>>(direction: V) -> Self {
2902 let direction = direction.into();
2903 unsafe { quat_lookat(&Vec3::ZERO, &direction) }
2904 }
2905
2906 /// Spherical Linear interpolation. Interpolates between two quaternions! Both Quats should be normalized/unit
2907 /// quaternions, or you may get unexpected results.
2908 /// <https://stereokit.net/Pages/StereoKit/Quat/Slerp.html>
2909 /// * `a` - Start quaternion, should be normalized/unit length.
2910 /// * `b` - End quaternion, should be normalized/unit length.
2911 /// * `slerp` - The interpolation amount! This’ll be a if 0, and b if 1. Unclamped.
2912 ///
2913 /// Returns a blend between the two quaternions!
2914 /// see also [`quat_slerp`]
2915 /// ### Examples
2916 /// ```
2917 /// use stereokit_rust::maths::Quat;
2918 ///
2919 /// let a = Quat::from_angles(0.0, 0.0, 0.0);
2920 /// let b = Quat::from_angles(0.0, 0.0, 90.0);
2921 /// let result = Quat::slerp(a, b, 0.25);
2922 /// assert_eq!(result, Quat::from_angles(0.0, 0.0, 22.5));
2923 /// ```
2924 #[inline]
2925 pub fn slerp(a: Self, b: Self, slerp: f32) -> Self {
2926 unsafe { quat_slerp(&a, &b, slerp) }
2927 }
2928
2929 /// The reverse rotation! If this quat goes from A to B, the inverse will go from B to A.
2930 /// <https://stereokit.net/Pages/StereoKit/Quat/Inverse.html>
2931 ///
2932 /// see also [`quat_inverse`]
2933 /// ### Examples
2934 /// ```
2935 /// use stereokit_rust::maths::Quat;
2936 ///
2937 /// let q = Quat::from_angles(90.0, 0.0, 0.0);
2938 /// let q_inv = q.get_inverse();
2939 /// assert_eq!(q_inv, Quat::from_angles(-90.0, 0.0, 0.0));
2940 /// ```
2941 #[inline]
2942 pub fn get_inverse(&self) -> Self {
2943 unsafe { quat_inverse(self) }
2944 }
2945
2946 /// A normalized quaternion has the same orientation, and a length of 1.
2947 /// <https://stereokit.net/Pages/StereoKit/Quat/Normalized.html>
2948 ///
2949 /// see also [`quat_normalize`]
2950 /// ### Examples
2951 /// ```
2952 /// use stereokit_rust::maths::Quat;
2953 ///
2954 /// let q = Quat::new(2.0, 0.0, 0.0, 0.0);
2955 /// let normalized = q.get_normalized();
2956 /// assert_eq!(normalized, Quat::new(1.0, 0.0, 0.0, 0.0));
2957 /// assert_eq!(normalized, Quat::from_angles(180.0, 0.0, 0.0));
2958 /// ```
2959 #[inline]
2960 pub fn get_normalized(&self) -> Self {
2961 unsafe { quat_normalize(self) }
2962 }
2963
2964 /// A Vec4 and a Quat are only really different by name and purpose. So, if you need to do Quat math with your
2965 /// Vec4, or visa versa, who am I to judge?
2966 /// <https://stereokit.net/Pages/StereoKit/Quat/Vec4.html>
2967 ///
2968 /// see also [`Quat::from`]
2969 /// ### Examples
2970 /// ```
2971 /// use stereokit_rust::maths::{Quat, Vec4};
2972 ///
2973 /// let quat = Quat::new(1.0, 2.0, 3.0, 4.0);
2974 /// let vec4 = Vec4::new(1.0, 2.0, 3.0, 4.0);
2975 /// assert_eq!(vec4, quat.get_as_vec4());
2976 /// assert_eq!(vec4, quat.into());
2977 /// assert_eq!(quat, vec4.into());
2978 /// ```
2979 #[inline]
2980 pub fn get_as_vec4(&self) -> Vec4 {
2981 Vec4 { x: self.x, y: self.y, z: self.z, w: self.w }
2982 }
2983
2984 /// This is the combination of rotations a and b. Note that order matters h
2985 /// <https://stereokit.net/Pages/StereoKit/Quat/op_Multiply.html>
2986 ///
2987 /// see also `*` operator [`quat_mul`]
2988 /// ### Examples
2989 /// ```
2990 /// use stereokit_rust::maths::Quat;
2991 ///
2992 /// let a = Quat::from_angles(180.0, 0.0, 0.0);
2993 /// let b = Quat::from_angles(0.0, 180.0, 0.0);
2994 /// let c = a * b;
2995 /// let d = a.mul(b);
2996 /// assert_eq!(c, Quat::from_angles(0.0, 0.0, -180.0));
2997 /// assert_eq!(d, Quat::from_angles(0.0, 0.0, -180.0));
2998 /// ```
2999 #[inline]
3000 pub fn mul(&self, rhs: Self) -> Self {
3001 unsafe { quat_mul(self, &rhs) }
3002 }
3003
3004 /// This rotates a point around the origin by the Quat.
3005 /// <https://stereokit.net/Pages/StereoKit/Quat/op_Multiply.html>
3006 ///
3007 /// see also `*` operator [`quat_mul_vec`]
3008 /// ### Examples
3009 /// ```
3010 /// use stereokit_rust::maths::{Quat, Vec3};
3011 ///
3012 /// let q = Quat::from_angles(0.0, 90.0, 0.0);
3013 /// let v = Vec3::new(1.0, 0.0, 0.0);
3014 /// let result = q.mul_vec3(v);
3015 /// assert_eq!(result, Vec3::new(0.0, 0.0, -1.0));
3016 ///
3017 /// let result_b = q * v;
3018 /// assert_eq!(result_b, result);
3019 /// ```
3020 #[inline]
3021 pub fn mul_vec3<V: Into<Vec3>>(&self, rhs: V) -> Vec3 {
3022 let rhs = rhs.into();
3023 unsafe { quat_mul_vec(self, &rhs) }
3024 }
3025
3026 /// get an array
3027 ///
3028 /// see also [`Quat::from`]
3029 /// ### Examples
3030 /// ```
3031 /// use stereokit_rust::maths::Quat;
3032 ///
3033 /// let q = Quat::new(1.0, 2.0, 3.0, 4.0);
3034 /// assert_eq!(q.to_array(), [1.0, 2.0, 3.0, 4.0]);
3035 /// ```
3036 #[inline]
3037 pub const fn to_array(&self) -> [f32; 4] {
3038 [self.x, self.y, self.z, self.w]
3039 }
3040}
3041
3042impl Display for Quat {
3043 /// Mostly for debug purposes, this is a decent way to log or inspect the vector in debug mode. Looks
3044 /// like “[x, y, z, w]”
3045 /// <https://stereokit.net/Pages/StereoKit/Quat/ToString.html>
3046 ///
3047 /// ### Examples
3048 /// ```
3049 /// use stereokit_rust::maths::Quat;
3050 ///
3051 /// let quat = Quat::new(1.0, 2.0, 3.3, 4.0);
3052 /// assert_eq!(format!("{}", quat), "[x:1, y:2, z:3.3, w:4]");
3053 /// ```
3054 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3055 write!(f, "[x:{}, y:{}, z:{}, w:{}]", self.x, self.y, self.z, self.w)
3056 }
3057}
3058
3059/// This is the combination of rotations a and b. Note that order matters h
3060/// <https://stereokit.net/Pages/StereoKit/Quat/op_Multiply.html>
3061///
3062/// see also [`quat_mul`]
3063impl Mul<Quat> for Quat {
3064 type Output = Self;
3065
3066 /// ### Examples
3067 /// ```
3068 /// use stereokit_rust::maths::Quat;
3069 ///
3070 /// let a = Quat::from_angles(180.0, 0.0, 0.0);
3071 /// let b = Quat::from_angles(0.0, 180.0, 0.0);
3072 /// let c = Quat::from_angles(0.0, 0.0, -180.0);
3073 /// assert_eq!(a * b, c);
3074 /// ```
3075 #[inline]
3076 fn mul(self, rhs: Self) -> Self::Output {
3077 unsafe { quat_mul(&self, &rhs) }
3078 }
3079}
3080
3081/// This is the combination of rotations a and b. Note that order matters h
3082/// <https://stereokit.net/Pages/StereoKit/Quat/op_Multiply.html>
3083///
3084/// see also [`quat_mul`]
3085impl MulAssign<Quat> for Quat {
3086 /// ### Examples
3087 /// ```
3088 /// use stereokit_rust::maths::Quat;
3089 ///
3090 /// let mut q = Quat::new(1.0, 0.0, 0.0, 0.0);
3091 /// let r = Quat::new(0.0, 1.0, 0.0, 0.0);
3092 /// q *= r;
3093 /// assert_eq!(q, Quat::new(0.0, 0.0, -1.0, 0.0));
3094 /// ```
3095 #[inline]
3096 fn mul_assign(&mut self, rhs: Quat) {
3097 *self = unsafe { quat_mul(self, &rhs) }
3098 }
3099}
3100
3101/// This rotates a point around the origin by the Quat.
3102/// <https://stereokit.net/Pages/StereoKit/Quat/op_Multiply.html>
3103///
3104/// see also [`quat_mul_vec`]
3105impl Mul<Vec3> for Quat {
3106 type Output = Vec3;
3107
3108 /// ### Examples
3109 /// ```
3110 /// use stereokit_rust::maths::{Quat, Vec3};
3111 ///
3112 /// let q = Quat::from_angles(0.0, 90.0, 0.0);
3113 /// let v = Vec3::new(1.0, 0.0, 0.0);
3114 /// assert_eq!(q * v, Vec3::new(0.0, 0.0, -1.0));
3115 /// ```
3116 fn mul(self, rhs: Vec3) -> Self::Output {
3117 unsafe { quat_mul_vec(&self, &rhs) }
3118 }
3119}
3120
3121/// Gets a Quat representing the rotation from a to b.
3122/// <https://stereokit.net/Pages/StereoKit/Quat/op_Subtraction.html>
3123/// see also QuatT::delta()
3124///
3125/// see also [`quat_difference`]
3126impl Sub<Quat> for Quat {
3127 type Output = Self;
3128
3129 /// ### Examples
3130 /// ```
3131 /// use stereokit_rust::maths::Quat;
3132 ///
3133 /// let from = Quat::from_angles(180.0, 0.0, 0.0);
3134 /// let to = Quat::from_angles(0.0, 180.0, 0.0);
3135 /// let delta = Quat::delta(from, to);
3136 /// assert_eq!(delta, Quat::from_angles(0.0, 0.0, 180.0));
3137 /// assert_eq!(from - to, delta);
3138 /// ```
3139 fn sub(self, rhs: Self) -> Self::Output {
3140 unsafe { quat_difference(&self, &rhs) }
3141 }
3142}
3143
3144/// A Matrix in StereoKit is a 4x4 grid of numbers that is used to represent a transformation for any sort of position
3145/// or vector! This is an oversimplification of what a matrix actually is, but it’s accurate in this case.
3146///
3147/// Matrices are really useful for transforms because you can chain together all sorts of transforms into a single
3148/// Matrix! A Matrix transform really shines when applied to many positions, as the more expensive operations get cached
3149/// within the matrix values.
3150///
3151/// Multiple matrix transforms can be combined by multiplying them. In StereoKit, to create a matrix that first scales
3152/// an object, followed by rotating it, and finally translating it you would use this order:
3153/// Matrix M = Matrix.S(...) * Matrix.R(...) * Matrix.T(...);
3154///
3155/// This order is related to the fact that StereoKit uses row-major order to store matrices. Note that in other 3D
3156/// frameworks and certain 3D math references you may find column-major matrices, which would need the reverse order
3157/// (i.e. TRS), so please keep this in mind when creating transformations.
3158///
3159/// Matrices are prominently used within shaders for mesh transforms!
3160/// <https://stereokit.net/Pages/StereoKit/Matrix.html>
3161///
3162/// see also [`glam::Mat4`]
3163/// ### Examples
3164/// ```
3165/// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
3166/// use stereokit_rust::{maths::{Vec3, Quat, Matrix}, model::Model};
3167///
3168/// let model = Model::from_file("center.glb", None).unwrap().copy();
3169/// let transform = Matrix::t_r_s(Vec3::NEG_Y * 0.7, [0.0, 155.0, 10.0], Vec3::ONE * 0.3);
3170///
3171/// filename_scr = "screenshots/matrix.jpeg";
3172/// test_screenshot!( // !!!! Get a proper main loop !!!!
3173/// model.draw(token, transform, None, None);
3174/// );
3175/// ```
3176/// <img src="https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/matrix.jpeg" alt="screenshot" width="200">
3177#[repr(C)]
3178#[derive(Copy, Clone)]
3179pub union Matrix {
3180 pub row: [Vec4; 4usize],
3181 pub m: [f32; 16usize],
3182}
3183
3184impl From<glam::Mat4> for Matrix {
3185 fn from(m: glam::Mat4) -> Self {
3186 Matrix { row: [m.x_axis.into(), m.y_axis.into(), m.z_axis.into(), m.w_axis.into()] }
3187 }
3188}
3189
3190impl From<[f32; 16]> for Matrix {
3191 fn from(s: [f32; 16]) -> Self {
3192 Self { m: s }
3193 }
3194}
3195
3196impl From<Pose> for Matrix {
3197 fn from(pose: Pose) -> Self {
3198 Self::t_r(pose.position, pose.orientation)
3199 }
3200}
3201
3202impl std::fmt::Debug for Matrix {
3203 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3204 write!(f, "{self}")
3205 }
3206}
3207
3208/// Warning: Equality with a precision of 0.1 millimeter
3209impl PartialEq for Matrix {
3210 /// Warning: Equality with a precision of 0.00001
3211 /// ### Examples
3212 /// ```
3213 /// use stereokit_rust::maths::Matrix;
3214 ///
3215 /// let matrix = Matrix::IDENTITY;
3216 /// assert_eq!(matrix, Matrix::IDENTITY);
3217 /// ```
3218 fn eq(&self, other: &Self) -> bool {
3219 unsafe {
3220 self.row[0] == other.row[0]
3221 && self.row[1] == other.row[1]
3222 && self.row[2] == other.row[2]
3223 && self.row[3] == other.row[3]
3224 }
3225 }
3226}
3227
3228unsafe extern "C" {
3229 pub fn pose_matrix_out(pose: *const Pose, out_result: *mut Matrix, scale: Vec3);
3230 pub fn matrix_inverse(a: *const Matrix, out_Matrix: *mut Matrix);
3231 pub fn matrix_invert(a: *const Matrix) -> Matrix;
3232 pub fn matrix_mul(a: *const Matrix, b: *const Matrix, out_Matrix: *mut Matrix);
3233 // Deprecated: pub fn matrix_mul_point(transform: *const Matrix, point: *const Vec3) -> Vec3;
3234 // Deprecated: pub fn matrix_mul_point4(transform: *const Matrix, point: *const Vec4) -> Vec4;
3235 pub fn matrix_mul_direction(transform: *const Matrix, direction: *const Vec3) -> Vec3;
3236 // Deprecated: pub fn matrix_mul_rotation(transform: *const Matrix, orientation: *const Quat) -> Quat;
3237 // Deprecated: pub fn matrix_mul_pose(transform: *const Matrix, pose: *const Pose) -> Pose;
3238 pub fn matrix_transform_pt(transform: Matrix, point: Vec3) -> Vec3;
3239 pub fn matrix_transform_pt4(transform: Matrix, point: Vec4) -> Vec4;
3240 pub fn matrix_transform_dir(transform: Matrix, direction: Vec3) -> Vec3;
3241 pub fn matrix_transform_ray(transform: Matrix, ray: Ray) -> Ray;
3242 pub fn matrix_transform_quat(transform: Matrix, rotation: Quat) -> Quat;
3243 pub fn matrix_transform_pose(transform: Matrix, pose: Pose) -> Pose;
3244 pub fn matrix_transpose(transform: Matrix) -> Matrix;
3245 pub fn matrix_to_angles(transform: *const Matrix) -> Vec3;
3246 pub fn matrix_trs(position: *const Vec3, orientation: *const Quat, scale: *const Vec3) -> Matrix;
3247 pub fn matrix_t(position: Vec3) -> Matrix;
3248 pub fn matrix_r(orientation: Quat) -> Matrix;
3249 pub fn matrix_s(scale: Vec3) -> Matrix;
3250 pub fn matrix_ts(position: Vec3, scale: Vec3) -> Matrix;
3251 pub fn matrix_trs_out(out_result: *mut Matrix, position: *const Vec3, orientation: *const Quat, scale: *const Vec3);
3252 pub fn matrix_perspective(fov_degrees: f32, aspect_ratio: f32, near_clip: f32, far_clip: f32) -> Matrix;
3253 pub fn matrix_orthographic(width: f32, height: f32, near_clip: f32, far_clip: f32) -> Matrix;
3254 pub fn matrix_decompose(
3255 transform: *const Matrix,
3256 out_position: *mut Vec3,
3257 out_scale: *mut Vec3,
3258 out_orientation: *mut Quat,
3259 ) -> Bool32T;
3260 pub fn matrix_extract_translation(transform: *const Matrix) -> Vec3;
3261 pub fn matrix_extract_scale(transform: *const Matrix) -> Vec3;
3262 pub fn matrix_extract_rotation(transform: *const Matrix) -> Quat;
3263 pub fn matrix_extract_pose(transform: *const Matrix) -> Pose;
3264}
3265
3266impl Matrix {
3267 /// Identity matrix made of [[Vec4::X, Vec4::Y, Vec4::Z, Vec4::W]]
3268 pub const IDENTITY: Matrix = Matrix { row: [Vec4::X, Vec4::Y, Vec4::Z, Vec4::W] };
3269
3270 /// Identity matrix rotated 180 degrees around the Y axis made of [[Vec4::NEG_X, Vec4::Y, Vec4::NEG_Z, Vec4::W]]
3271 /// This is mainly used for test screenshots, but it can be useful for other things too!
3272 pub const Y_180: Matrix = Matrix { row: [Vec4::NEG_X, Vec4::Y, Vec4::NEG_Z, Vec4::W] };
3273
3274 /// Null or Zero matrix made of [[Vec4::ZERO, Vec4::ZERO, Vec4::ZERO, Vec4::ZERO]]
3275 pub const NULL: Matrix = Matrix { row: [Vec4::ZERO, Vec4::ZERO, Vec4::ZERO, Vec4::ZERO] };
3276
3277 /// This creates a matrix used for projecting 3D geometry onto a 2D surface for rasterization. Orthographic
3278 /// projection matrices will preserve parallel lines. This is great for 2D scenes or content.
3279 /// <https://stereokit.net/Pages/StereoKit/Matrix/Orthographic.html>
3280 /// * `width` - in meters, of the area that will be projected.
3281 /// * `height` - The height, in meters, of the area that will be projected
3282 /// * `near_clip` - Anything closer than this distance (in meters) will be discarded. Must not be zero, and if you
3283 /// make this too small, you may experience glitching in your depth buffer.
3284 /// * `far_clip` - Anything further than this distance (in meters) will be discarded. For low resolution depth
3285 /// buffers, this should not be too far away, or you'll see bad z-fighting artifacts.
3286 ///
3287 /// Returns the final orthographic Matrix.
3288 /// ### Examples
3289 /// ```
3290 /// use stereokit_rust::maths::{Vec3, Matrix};
3291 ///
3292 /// let translate = Matrix::orthographic(1.0, 1.0, 0.1, 100.0);
3293 /// let point = Vec3::new(1.0, 2.0, 3.0);
3294 ///
3295 /// let projection = translate * point;
3296 /// assert_eq!(projection, Vec3 { x: 2.0, y: 4.0, z: -0.03103103 });
3297 /// ```
3298 /// see also [`matrix_orthographic`]
3299 #[inline]
3300 pub fn orthographic(width: f32, height: f32, near_clip: f32, far_clip: f32) -> Self {
3301 unsafe { matrix_orthographic(width, height, near_clip, far_clip) }
3302 }
3303
3304 /// This creates a matrix used for projecting 3D geometry onto a 2D surface for rasterization. Perspective
3305 /// projection matrices will cause parallel lines to converge at the horizon. This is great for normal looking
3306 /// content.
3307 /// <https://stereokit.net/Pages/StereoKit/Matrix/Perspective.html>
3308 /// * `fov_degrees` - This is the vertical field of view of the perspective matrix, units are in degrees.
3309 /// * `aspect_ratio` - The projection surface's width/height.
3310 /// * `near_clip` - Anything closer than this distance (in meters) will be discarded. Must not be zero, and if you
3311 /// make this too small, you may experience glitching in your depth buffer.
3312 /// * `far_clip` - Anything further than this distance (in meters) will be discarded. For low resolution depth
3313 /// buffers, this should not be too far away, or you'll see bad z-fighting artifacts.
3314 ///
3315 /// Returns the final perspective matrix.
3316 /// see also [`matrix_perspective`]
3317 /// ### Examples
3318 /// ```
3319 /// use stereokit_rust::maths::{Vec3, Matrix};
3320 ///
3321 /// let translate = Matrix::perspective(90.0, 1.0, 0.1, 100.0);
3322 /// let point = Vec3::new(1.0, 2.0, 3.0);
3323 ///
3324 /// let projection = translate * point;
3325 /// assert_eq!(projection, Vec3 { x: 72.946686, y: 145.89337, z: -3.1031032 });
3326 /// ```
3327 #[inline]
3328 pub fn perspective(fov_degrees: f32, aspect_ratio: f32, near_clip: f32, far_clip: f32) -> Self {
3329 unsafe { matrix_perspective(fov_degrees.to_radians(), aspect_ratio, near_clip, far_clip) }
3330 }
3331
3332 /// This creates a matrix used for projecting 3D geometry onto a 2D surface for rasterization. With the known camera
3333 /// intrinsics, you can replicate its perspective!
3334 /// <https://stereokit.net/Pages/StereoKit/Matrix/Perspective.html>
3335 /// * `image_resolution` - The resolution of the image. This should be the image's width and height in pixels.
3336 /// * `focal_length_px` - The focal length of camera in pixels, with image coordinates +X (pointing right) and +Y
3337 /// (pointing up).
3338 /// * `near_clip` - Anything closer than this distance (in meters) will be discarded. Must not be zero, and if you
3339 /// make this too small, you may experience glitching in your depth buffer.
3340 /// * `far_clip` - Anything further than this distance (in meters) will be discarded. For low resolution depth
3341 /// buffers, this should not be too far away, or you'll see bad z-fighting artifacts.
3342 ///
3343 /// Returns the final perspective matrix.
3344 /// Remarks: Think of the optical axis as an imaginary line that passes through the camera lens. In front of the
3345 /// camera lens, there's an image plane, perpendicular to the optical axis, where the image of the scene being
3346 /// captured is formed. Its distance is equal to the focal length of the camera from the center of the lens. Here,
3347 /// we find the ratio between the size of the image plane and distance from the camera in one unit distance and
3348 /// multiply it by the near clip distance to find a near plane that is parallel.
3349 ///
3350 /// see also [`matrix_perspective`]
3351 /// ### Examples
3352 /// ```
3353 /// use stereokit_rust::maths::{Vec2, Vec3, Matrix};
3354 ///
3355 /// let translate = Matrix::perspective_focal(Vec2::new(1.0, 1.0), 1.0, 0.1, 100.0);
3356 /// let point = Vec3::new(1.0, 2.0, 3.0);
3357 ///
3358 /// let projection = translate * point;
3359 /// assert_eq!(projection, Vec3 { x: 2.0, y: 4.0, z: -3.1031032 });
3360 /// ```
3361 #[inline]
3362 pub fn perspective_focal(image_resolution: Vec2, focal_length_px: f32, near_clip: f32, far_clip: f32) -> Self {
3363 let near_plane_dimensions = image_resolution / focal_length_px * near_clip;
3364
3365 let two_near = near_clip + near_clip;
3366 let f_range = far_clip / (near_clip - far_clip);
3367
3368 Self {
3369 m: [
3370 two_near / near_plane_dimensions.x,
3371 0.0,
3372 0.0,
3373 0.0,
3374 //
3375 0.0,
3376 two_near / near_plane_dimensions.y,
3377 0.0,
3378 0.0,
3379 //
3380 0.0,
3381 0.0,
3382 f_range,
3383 -1.0,
3384 //
3385 0.0,
3386 0.0,
3387 f_range * near_clip,
3388 0.0,
3389 ],
3390 }
3391 }
3392
3393 /// A transformation that describes one position looking at another point. This is particularly useful for
3394 /// describing camera transforms!
3395 /// <https://stereokit.net/Pages/StereoKit/Matrix/LookAt.html>
3396 ///
3397 /// see also [`matrix_r`]
3398 /// ### Examples
3399 /// ```
3400 /// use stereokit_rust::maths::{Vec3, Matrix};
3401 ///
3402 /// let from = Vec3::new(1.0, 0.0, 0.0);
3403 /// let at = Vec3::new(0.0, 0.0, 0.0);
3404 /// let up = Vec3::new(0.0, 1.0, 0.0);
3405 /// let transform = Matrix::look_at(from, at, Some(up));
3406 /// assert_eq!(transform, Matrix::from([
3407 /// 0.0, 0.0, 1.0, 0.0,
3408 /// 0.0, 1.0, 0.0, 0.0,
3409 /// 1.0, 0.0, 0.0, 0.0,
3410 /// 0.0, 0.0,-1.0, 1.0,
3411 /// ]));
3412 ///
3413 /// let transform_b = Matrix::look_at(from, at, None);
3414 /// assert_eq!(transform, transform_b);
3415 /// ```
3416 #[inline]
3417 pub fn look_at(from: Vec3, at: Vec3, up: Option<Vec3>) -> Self {
3418 let up = up.unwrap_or(Vec3::UP);
3419 let forward = (from - at).get_normalized();
3420 let right_v = Vec3::perpendicular_right(forward, up).get_normalized();
3421 let up_v = Vec3::perpendicular_right(right_v, forward).get_normalized();
3422 Self {
3423 m: [
3424 right_v.x,
3425 up_v.x,
3426 forward.x,
3427 0.0,
3428 //
3429 right_v.y,
3430 up_v.y,
3431 forward.y,
3432 0.0,
3433 //
3434 right_v.z,
3435 up_v.z,
3436 forward.z,
3437 0.0,
3438 //
3439 -Vec3::dot(from, right_v),
3440 -Vec3::dot(from, up_v),
3441 -Vec3::dot(from, forward),
3442 1.0,
3443 ],
3444 }
3445 }
3446
3447 /// Create a rotation matrix from a Quaternion. Consider using [`Matrix::update_r`] when you have to recalculate
3448 /// Matrix at each steps in main loop.
3449 /// <https://stereokit.net/Pages/StereoKit/Matrix/R.html>
3450 /// * `rotation` - The quaternion describing the rotation for this transform.
3451 ///
3452 /// returns a Matrix that will rotate by the provided Quaternion orientation.
3453 /// see also [`matrix_r`] [`Matrix::update_r`]
3454 /// ### Examples
3455 /// ```
3456 /// use stereokit_rust::maths::{Quat, Matrix};
3457 ///
3458 /// let rotation = Quat::from_angles(90.0, 0.0, 0.0);
3459 /// let matrix = Matrix::r(rotation);
3460 /// assert_eq!(matrix, Matrix::from([
3461 /// 1.0, 0.0, 0.0, 0.0,
3462 /// 0.0, 0.0, 1.0, 0.0,
3463 /// 0.0,-1.0, 0.0, 0.0,
3464 /// 0.0, 0.0, 0.0, 1.0,
3465 /// ]));
3466 ///
3467 /// let rotation = Quat::from_angles(0.0, 90.0, 0.0);
3468 /// let matrix = Matrix::r(rotation);
3469 /// assert_eq!(matrix, Matrix::from([
3470 /// 0.0, 0.0, -1.0, 0.0,
3471 /// 0.0, 1.0, 0.0, 0.0,
3472 /// 1.0, 0.0, 0.0, 0.0,
3473 /// 0.0, 0.0, 0.0, 1.0,
3474 /// ]));
3475 ///
3476 /// ```
3477 #[inline]
3478 pub fn r<Q: Into<Quat>>(rotation: Q) -> Self {
3479 unsafe { matrix_r(rotation.into()) }
3480 }
3481
3482 /// Create a rotation matrix from a Quaternion.
3483 /// <https://stereokit.net/Pages/StereoKit/Matrix/R.html>
3484 /// * `rotation` - The quaternion describing the rotation for this transform.
3485 ///
3486 /// see also [`matrix_trs_out`] [`Matrix::r`]
3487 /// ### Examples
3488 /// ```
3489 /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
3490 /// use stereokit_rust::{maths::{Vec3, Quat, Matrix}, mesh::Mesh, material::Material,
3491 /// util::Time};
3492 ///
3493 /// let mesh = Mesh::cube();
3494 /// let material = Material::pbr();
3495 ///
3496 /// let mut transform = Matrix::IDENTITY;
3497 /// let mut delta_rotate = 90.0;
3498 ///
3499 /// test_steps!( // !!!! Get a proper main loop !!!!
3500 /// delta_rotate = (delta_rotate + 10.0 * Time::get_stepf()) % 360.0;
3501 /// let rotation = Quat::from_angles(0.0, delta_rotate, 0.0);
3502 ///
3503 /// transform.update_r(&rotation);
3504 ///
3505 /// mesh.draw(token, &material, transform, None, None);
3506 /// assert_eq!(transform, Matrix::r(rotation));
3507 /// );
3508 #[inline]
3509 pub fn update_r(&mut self, rotation: &Quat) {
3510 unsafe { matrix_trs_out(self, &Vec3::ZERO, rotation, &Vec3::ONE) }
3511 }
3512
3513 /// Creates a scaling Matrix, where scale can be different on each axis (non-uniform).Consider using
3514 /// [`Matrix::update_s`] when you have to recalculate Matrix at each steps in main loop.
3515 /// <https://stereokit.net/Pages/StereoKit/Matrix/S.html>
3516 /// * `scale` - How much larger or smaller this transform makes things. Vec3::ONE is the default.
3517 ///
3518 /// Returns a non-uniform scaling matrix.
3519 /// see also [`matrix_s`] [`Matrix::update_s`]
3520 /// ### Examples
3521 /// ```
3522 /// use stereokit_rust::maths::{Vec3, Matrix};
3523 ///
3524 /// let scale = Matrix::s(Vec3::new(2.0, 3.0, 4.0));
3525 /// let point = Vec3::new(1.0, 1.0, 1.0);
3526 /// let scaled_point = scale * point;
3527 /// assert_eq!(scaled_point, Vec3::new(2.0, 3.0, 4.0));
3528 /// ```
3529 #[inline]
3530 pub fn s<V: Into<Vec3>>(scale: V) -> Self {
3531 unsafe { matrix_s(scale.into()) }
3532 }
3533
3534 /// Creates a scaling Matrix, where scale can be different on each axis (non-uniform).
3535 /// <https://stereokit.net/Pages/StereoKit/Matrix/S.html>
3536 /// * `scale` - How much larger or smaller this transform makes things. Vec3::ONE is the default.
3537 ///
3538 /// see also [`matrix_trs_out`] [`Matrix::s`]
3539 /// ### Examples
3540 /// ```
3541 /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
3542 /// use stereokit_rust::{maths::{Vec3, Quat, Matrix}, mesh::Mesh, material::Material,
3543 /// util::Time};
3544 ///
3545 /// let mesh = Mesh::cube();
3546 /// let material = Material::pbr();
3547 ///
3548 /// let mut transform = Matrix::IDENTITY;
3549 /// let mut delta_scale = 2.0;
3550 ///
3551 /// test_steps!( // !!!! Get a proper main loop !!!!
3552 /// let scale = Vec3::ONE * (delta_scale * Time::get_stepf()).cos();
3553 ///
3554 /// transform.update_s(&scale);
3555 ///
3556 /// mesh.draw(token, &material, transform, None, None);
3557 /// assert_eq!(transform, Matrix::s(scale));
3558 /// );
3559 /// ```
3560 #[inline]
3561 pub fn update_s(&mut self, scale: &Vec3) {
3562 unsafe { matrix_trs_out(self, &Vec3::ZERO, &Quat::IDENTITY, scale) }
3563 }
3564
3565 /// Translate. Creates a translation Matrix! Consider using [`Matrix::update_t`] when you have to recalculate
3566 /// Matrix at each steps in main loop.
3567 /// <https://stereokit.net/Pages/StereoKit/Matrix/T.html>
3568 /// * `translation` - Move an object by this amount.
3569 ///
3570 /// Returns a Matrix containing a simple translation!
3571 /// see also [`matrix_t`] [`Matrix::update_t`]
3572 /// ### Examples
3573 /// ```
3574 /// use stereokit_rust::maths::{Vec3, Matrix};
3575 ///
3576 /// let translation = Matrix::t(Vec3::new(1.0, 2.0, 3.0));
3577 /// let point = Vec3::new(0.0, 0.0, 0.0);
3578 /// let translated_point = translation * point;
3579 /// assert_eq!(translated_point, Vec3::new(1.0, 2.0, 3.0));
3580 /// ```
3581 #[inline]
3582 pub fn t<V: Into<Vec3>>(translation: V) -> Self {
3583 unsafe { matrix_t(translation.into()) }
3584 }
3585
3586 /// Translate. Creates a translation Matrix!
3587 /// <https://stereokit.net/Pages/StereoKit/Matrix/T.html>
3588 /// * `translation` - Move an object by this amount.
3589 ///
3590 /// see also [`matrix_trs_out`] [`Matrix::t`]
3591 /// ### Examples
3592 /// ```
3593 /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
3594 /// use stereokit_rust::{maths::{Vec3, Quat, Matrix}, mesh::Mesh, material::Material,
3595 /// util::Time};
3596 ///
3597 /// let mesh = Mesh::cube();
3598 /// let material = Material::pbr();
3599 ///
3600 /// let mut transform = Matrix::IDENTITY;
3601 /// let mut position = Vec3::ZERO;
3602 ///
3603 /// test_steps!( // !!!! Get a proper main loop !!!!
3604 /// position += Vec3::NEG_Z * Time::get_stepf();
3605 ///
3606 /// transform.update_t(&position);
3607 ///
3608 /// mesh.draw(token, &material, transform, None, None);
3609 /// assert_eq!(transform, Matrix::t(position));
3610 /// );
3611 /// ```
3612 #[inline]
3613 pub fn update_t(&mut self, translation: &Vec3) {
3614 unsafe { matrix_trs_out(self, translation, &Quat::IDENTITY, &Vec3::ONE) }
3615 }
3616
3617 /// Translate, Rotate. Creates a transform Matrix using these components!
3618 /// <https://stereokit.net/Pages/StereoKit/Matrix/TR.html>
3619 /// * `translation` - Move an object by this amount.
3620 /// * `rotation` - The quaternion describing the rotation for this transform.
3621 ///
3622 /// Returns a Matrix that combines translation and rotation information into a single Matrix!
3623 /// see also [`matrix_trs`]
3624 #[deprecated(since = "0.40.0", note = "please use Matrix::t_r or Matrix::update_t_r")]
3625 #[inline]
3626 pub fn tr(translation: &Vec3, rotation: &Quat) -> Self {
3627 unsafe { matrix_trs(translation, rotation, &Vec3::ONE) }
3628 }
3629
3630 /// Translate, Rotate. Creates a transform Matrix using these components! Consider using
3631 /// [`Matrix::update_t_r`] when you have to recalculate Matrix at each steps in main loop.
3632 /// <https://stereokit.net/Pages/StereoKit/Matrix/TR.html>
3633 /// * `translation` - Move an object by this amount.
3634 /// * `rotation` - The quaternion describing the rotation for this transform.
3635 ///
3636 /// Returns a Matrix that combines translation and rotation information into a single Matrix!
3637 /// see also [`matrix_trs`] [`Matrix::update_t_r`]
3638 /// ### Examples
3639 /// ```
3640 /// use stereokit_rust::maths::{Vec3, Matrix};
3641 ///
3642 /// let transform = Matrix::t_r([1.0, 2.0, 3.0], [0.0, 180.0, 0.0]);
3643 /// let point = Vec3::new(1.0, 1.0, 1.0);
3644 /// let transformed_point = transform * point;
3645 /// assert_eq!(transformed_point, Vec3::new(0.0, 3.0, 2.0));
3646 /// ```
3647 #[inline]
3648 pub fn t_r<V: Into<Vec3>, Q: Into<Quat>>(translation: V, rotation: Q) -> Self {
3649 unsafe { matrix_trs(&translation.into(), &rotation.into(), &Vec3::ONE) }
3650 }
3651
3652 /// Translate, Rotate. Creates a transform Matrix using these components!
3653 /// <https://stereokit.net/Pages/StereoKit/Matrix/TR.html>
3654 /// * `translation` - Move an object by this amount.
3655 /// * `rotation` - The quaternion describing the rotation for this transform.
3656 ///
3657 /// see also [`matrix_trs_out`] [`Matrix::t_r`]
3658 /// ### Examples
3659 /// ```
3660 /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
3661 /// use stereokit_rust::{maths::{Vec3, Quat, Matrix}, mesh::Mesh, material::Material,
3662 /// util::Time};
3663 ///
3664 /// let mesh = Mesh::cube();
3665 /// let material = Material::pbr();
3666 ///
3667 /// let mut transform = Matrix::IDENTITY;
3668 /// let mut position = Vec3::ZERO;
3669 /// let mut delta_rotate = 90.0;
3670 ///
3671 /// test_steps!( // !!!! Get a proper main loop !!!!
3672 /// position += Vec3::NEG_Z * Time::get_stepf();
3673 /// delta_rotate = (delta_rotate + 10.0 * Time::get_stepf()) % 360.0;
3674 /// let rotation = Quat::from_angles(0.0, delta_rotate, 0.0);
3675 ///
3676 /// transform.update_t_r(&position, &rotation);
3677 ///
3678 /// mesh.draw(token, &material, transform, None, None);
3679 /// assert_eq!(transform, Matrix::t_r(position, rotation));
3680 /// );
3681 #[inline]
3682 pub fn update_t_r(&mut self, translation: &Vec3, rotation: &Quat) {
3683 unsafe { matrix_trs_out(self, translation, rotation, &Vec3::ONE) }
3684 }
3685
3686 /// Translate, Scale. Creates a transform Matrix using these components!
3687 /// <https://stereokit.net/Pages/StereoKit/Matrix/TS.html>
3688 /// * `translation` - Move an object by this amount.
3689 /// * `scale` - How much larger or smaller this transform makes things. Vec3::ONE is the default.
3690 ///
3691 /// Returns a Matrix that combines translation and rotation information into a single Matrix!
3692 /// see also [`matrix_ts`]
3693 #[deprecated(since = "0.40.0", note = "please use Matrix::t_s or Matrix::update_t_s")]
3694 #[inline]
3695 pub fn ts<V: Into<Vec3>>(translation: V, scale: V) -> Self {
3696 unsafe { matrix_ts(translation.into(), scale.into()) }
3697 }
3698
3699 /// Translate, Scale. Creates a transform Matrix using these components! Consider using
3700 /// [`Matrix::update_t_s`] when you have to recalculate Matrix at each steps in main loop.
3701 /// <https://stereokit.net/Pages/StereoKit/Matrix/TS.html>
3702 /// * `translation` - Move an object by this amount.
3703 /// * `scale` - How much larger or smaller this transform makes things. Vec3::ONE is the default.
3704 ///
3705 /// Returns a Matrix that combines translation and rotation information into a single Matrix!
3706 /// see also [`matrix_ts`] [`Matrix::update_t_s`]
3707 /// ### Examples
3708 /// ```
3709 /// use stereokit_rust::maths::{Vec3, Matrix};
3710 ///
3711 /// let transform = Matrix::t_s([1.0, 2.0, 3.0], [2.0, 2.0, 2.0]);
3712 /// let point = Vec3::new(1.0, 1.0, 1.0);
3713 /// let transformed_point = transform * point;
3714 /// assert_eq!(transformed_point, Vec3::new(3.0, 4.0, 5.0));
3715 /// ```
3716 #[inline]
3717 pub fn t_s<V: Into<Vec3>>(translation: V, scale: V) -> Self {
3718 unsafe { matrix_ts(translation.into(), scale.into()) }
3719 }
3720
3721 /// Translate, Scale. Creates a transform Matrix using these components!
3722 /// <https://stereokit.net/Pages/StereoKit/Matrix/TS.html>
3723 /// * `translation` - Move an object by this amount.
3724 /// * `scale` - How much larger or smaller this transform makes things. Vec3::ONE is the default.
3725 ///
3726 /// Returns a Matrix that combines translation and rotation information into a single Matrix!
3727 /// see also [`matrix_trs_out`] [`Matrix::t_s`]
3728 /// ### Examples
3729 /// ```
3730 /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
3731 /// use stereokit_rust::{maths::{Vec3, Quat, Matrix}, mesh::Mesh, material::Material,
3732 /// util::Time};
3733 ///
3734 /// let mesh = Mesh::cube();
3735 /// let material = Material::pbr();
3736 ///
3737 /// let mut transform = Matrix::IDENTITY;
3738 /// let mut position = Vec3::ZERO;
3739 /// let mut delta_scale = 2.0;
3740 ///
3741 /// test_steps!( // !!!! Get a proper main loop !!!!
3742 /// position += Vec3::NEG_Z * Time::get_stepf();
3743 /// let scale = Vec3::ONE * (delta_scale * Time::get_stepf()).cos();
3744 ///
3745 /// transform.update_t_s(&position, &scale);
3746 ///
3747 /// mesh.draw(token, &material, transform, None, None);
3748 /// assert_eq!(transform, Matrix::t_s(position, scale));
3749 /// );
3750 /// ```
3751 #[inline]
3752 pub fn update_t_s(&mut self, translation: &Vec3, scale: &Vec3) {
3753 unsafe { matrix_trs_out(self, translation, &Quat::IDENTITY, scale) }
3754 }
3755
3756 /// Translate, Rotate, Scale. Creates a transform Matrix using all these components!
3757 /// <https://stereokit.net/Pages/StereoKit/Matrix/TRS.html>
3758 /// * `translation` - Move an object by this amount.
3759 /// * `rotation` - The quaternion describing the rotation for this transform.
3760 /// * `scale` - How much larger or smaller this transform makes things. Vec3::ONE is a good default.
3761 ///
3762 /// Returns a Matrix that combines translation, rotation and scale information into a single Matrix!
3763 /// see also [`matrix_trs`]
3764 #[deprecated(since = "0.40.0", note = "please use Matrix::t_r_s or Matrix::update_t_r_s")]
3765 #[inline]
3766 pub fn trs(translation: &Vec3, rotation: &Quat, scale: &Vec3) -> Self {
3767 unsafe { matrix_trs(translation, rotation, scale) }
3768 }
3769
3770 /// Translate, Rotate, Scale. Creates a transform Matrix using all these components! Consider using
3771 /// [`Matrix::update_t_r_s`] when you have to recalculate Matrix at each steps in main loop.
3772 /// <https://stereokit.net/Pages/StereoKit/Matrix/TRS.html>
3773 /// * `translation` - Move an object by this amount.
3774 /// * `rotation` - The quaternion describing the rotation for this transform.
3775 /// * `scale` - How much larger or smaller this transform makes things. Vec3::ONE is a good default.
3776 ///
3777 /// Returns a Matrix that combines translation, rotation and scale information into a single Matrix!
3778 /// see also [`matrix_trs`] [`Matrix::update_t_r_s`]
3779 /// ### Examples
3780 /// ```
3781 /// use stereokit_rust::maths::{Vec3, Matrix};
3782 ///
3783 /// let transform = Matrix::t_r_s([1.0, 2.0, 3.0], [0.0, 180.0, 0.0], [2.0, 2.0, 2.0]);
3784 /// let point = Vec3::new(1.0, 1.0, 1.0);
3785 /// let transformed_point = transform * point;
3786 /// assert_eq!(transformed_point, Vec3::new(-1.0, 4.0, 1.0));
3787 /// ```
3788 #[inline]
3789 pub fn t_r_s<V: Into<Vec3>, Q: Into<Quat>>(translation: V, rotation: Q, scale: V) -> Self {
3790 unsafe { matrix_trs(&translation.into(), &rotation.into(), &scale.into()) }
3791 }
3792
3793 /// Translate, Rotate, Scale. Creates a transform Matrix using all these components!
3794 /// <https://stereokit.net/Pages/StereoKit/Matrix/TRS.html>
3795 /// * `translation` - Move an object by this amount.
3796 /// * `rotation` - The quaternion describing the rotation for this transform.
3797 /// * `scale` - How much larger or smaller this transform makes things. Vec3::ONE is a good default.
3798 ///
3799 /// Returns a Matrix that combines translation, rotation and scale information into a single Matrix!
3800 /// see also [`matrix_trs_out`] [`Matrix::t_r_s`]
3801 /// ### Examples
3802 /// ```
3803 /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
3804 /// use stereokit_rust::{maths::{Vec3, Quat, Matrix}, mesh::Mesh, material::Material,
3805 /// util::Time};
3806 ///
3807 /// let mesh = Mesh::cube();
3808 /// let material = Material::pbr();
3809 ///
3810 /// let mut transform = Matrix::IDENTITY;
3811 /// let mut position = Vec3::ZERO;
3812 /// let mut delta_scale = 2.0;
3813 /// let mut delta_rotate = 90.0;
3814 ///
3815 /// test_steps!( // !!!! Get a proper main loop !!!!
3816 /// position += Vec3::NEG_Z * Time::get_stepf();
3817 /// delta_rotate = (delta_rotate + 10.0 * Time::get_stepf()) % 360.0;
3818 /// let rotation = Quat::from_angles(0.0, delta_rotate, 0.0);
3819 /// let scale = Vec3::ONE * (delta_scale * Time::get_stepf()).cos();
3820 ///
3821 /// transform.update_t_r_s(&position, &rotation, &scale);
3822 ///
3823 /// mesh.draw(token, &material, transform, None, None);
3824 /// assert_eq!(transform, Matrix::t_r_s(position, rotation, scale));
3825 /// );
3826 /// ```
3827 #[inline]
3828 pub fn update_t_r_s(&mut self, translation: &Vec3, rotation: &Quat, scale: &Vec3) {
3829 unsafe { matrix_trs_out(self, translation, rotation, scale) }
3830 }
3831
3832 /// Translate, Rotate, Scale. Update a transform Matrix using all these components!
3833 /// <https://stereokit.net/Pages/StereoKit/Matrix/TRS.html>
3834 /// * `translation` - Move an object by this amount.
3835 /// * `rotation` - The quaternion describing the rotation for this transform.
3836 /// * `scale` - How much larger or smaller this transform makes things. Vec3::ONE is a good default.
3837 ///
3838 /// see also [`matrix_trs_out`]
3839 #[deprecated(since = "0.40.0", note = "please use Matrix::update_t_r, Matrix::update_t_s or Matrix::update_t_r_s")]
3840 #[inline]
3841 #[allow(clippy::not_unsafe_ptr_arg_deref)]
3842 pub fn trs_to_pointer(translation: &Vec3, rotation: &Quat, scale: &Vec3, out_result: *mut Matrix) {
3843 unsafe { matrix_trs_out(out_result, translation, rotation, scale) }
3844 }
3845
3846 /// Inverts this Matrix! If the matrix takes a point from a -> b, then its inverse takes the point from b -> a.
3847 /// The Matrix is modified so use get_inverse* for performance gains
3848 /// <https://stereokit.net/Pages/StereoKit/Matrix/Invert.html>
3849 ///
3850 /// see also [`Matrix::get_inverse`] [`matrix_invert`]
3851 /// ### Examples
3852 /// ```
3853 /// use stereokit_rust::maths::{Vec3, Matrix};
3854 ///
3855 /// let mut transform = Matrix::t([1.0, 2.0, 3.0]);
3856 /// transform.invert();
3857 /// let point = Vec3::new(1.0, 2.0, 3.0);
3858 /// let transformed_point = transform * point;
3859 /// assert_eq!(transformed_point, Vec3::new(0.0, 0.0, 0.0));
3860 /// ```
3861 #[inline]
3862 pub fn invert(&mut self) -> &mut Self {
3863 let m = unsafe { matrix_invert(self) };
3864 unsafe {
3865 self.row[0] = m.row[0];
3866 self.row[1] = m.row[1];
3867 self.row[2] = m.row[2];
3868 self.row[3] = m.row[3];
3869 }
3870 self
3871 }
3872
3873 /// Transposes this Matrix! Transposing is like rotating the matrix 90 clockwise, or turning the rows into columns.
3874 /// This can be useful for inverting orthogonal matrices, or converting matrices for use in a math library that
3875 /// uses different conventions! The Matrix is modified so use get_transposed* for performance gains
3876 /// <https://stereokit.net/Pages/StereoKit/Matrix/Transpose.html>
3877 ///
3878 /// see also [`matrix_transpose`]
3879 /// ### Examples
3880 /// ```
3881 /// use stereokit_rust::maths::{Vec3, Matrix};
3882 ///
3883 /// let mut transform = Matrix::t([1.0, 2.0, 3.0]);
3884 /// assert_eq!(transform, Matrix::from([
3885 /// 1.0, 0.0, 0.0, 0.0,
3886 /// 0.0, 1.0, 0.0, 0.0,
3887 /// 0.0, 0.0, 1.0, 0.0,
3888 /// 1.0, 2.0, 3.0, 1.0,
3889 /// ]));
3890 ///
3891 /// transform.transpose();
3892 /// assert_eq!(transform, Matrix::from([
3893 /// 1.0, 0.0, 0.0, 1.0,
3894 /// 0.0, 1.0, 0.0, 2.0,
3895 /// 0.0, 0.0, 1.0, 3.0,
3896 /// 0.0, 0.0, 0.0, 1.0,
3897 /// ]));
3898 /// ```
3899 #[inline]
3900 pub fn transpose(&mut self) -> &mut Self {
3901 let m = unsafe { matrix_transpose(*self) };
3902 unsafe {
3903 self.row[0] = m.row[0];
3904 self.row[1] = m.row[1];
3905 self.row[2] = m.row[2];
3906 self.row[3] = m.row[3];
3907 }
3908 self
3909 }
3910
3911 /// Returns this transformation matrix to its original translation, rotation and scale components. Not exactly a
3912 /// cheap function. If this is not a transform matrix, there’s a chance this call will fail, and return false.
3913 /// <https://stereokit.net/Pages/StereoKit/Matrix/Decompose.html>
3914 /// Returns the tuple (position:Vec3, scale:Vec3, orientation:QuatT)
3915 ///
3916 /// see also [`matrix_decompose`] [`Matrix::decompose_to_ptr`]
3917 /// ### Examples
3918 /// ```
3919 /// use stereokit_rust::maths::{Matrix, Vec3, Quat};
3920 ///
3921 /// let position = Vec3::new(1.0, 2.0, 3.0);
3922 /// let orientation = Quat::from_angles(0.0, 90.0, 0.0);
3923 /// let scale = Vec3::new(2.0, 2.0, 2.0);
3924 /// let matrix = Matrix::t_r_s(position, orientation, scale);
3925 ///
3926 /// let (pos, sca, ori) = matrix.decompose().unwrap();
3927 /// assert_eq!(pos, position);
3928 /// assert_eq!(sca, scale);
3929 /// assert_eq!(ori, orientation);
3930 /// ```
3931 #[inline]
3932 pub fn decompose(&self) -> Option<(Vec3, Vec3, Quat)> {
3933 let position: *mut Vec3 = &mut Vec3 { x: 0.0, y: 0.0, z: 0.0 };
3934 let scale: *mut Vec3 = &mut Vec3 { x: 0.0, y: 0.0, z: 0.0 };
3935 let orientation: *mut Quat = &mut Quat { x: 0.0, y: 0.0, z: 0.0, w: 0.0 };
3936 match unsafe { matrix_decompose(self, position, scale, orientation) } {
3937 0 => None,
3938 _ => unsafe { Some((*position, *scale, *orientation)) },
3939 }
3940 }
3941
3942 /// Returns this transformation matrix to its original translation, rotation and scale components. Not exactly a
3943 /// cheap function. If this is not a transform matrix, there’s a chance this call will fail, and return false.
3944 /// <https://stereokit.net/Pages/StereoKit/Matrix/Decompose.html>
3945 /// * `out_position` - The translation component of the matrix.
3946 /// * `out_orientation` - The rotation component of the matrix, some lossiness may be encountered when
3947 /// composing/decomposing.
3948 /// * `out_scale` - The scale component of the matrix.
3949 ///
3950 /// see also [`matrix_decompose`]
3951 /// ### Examples
3952 /// ```
3953 /// use stereokit_rust::maths::{Matrix, Vec3, Quat};
3954 ///
3955 /// let position = Vec3::new(1.0, 2.0, 3.0);
3956 /// let orientation = Quat::from_angles(0.0, 90.0, 0.0);
3957 /// let scale = Vec3::new(2.0, 2.0, 2.0);
3958 /// let matrix = Matrix::t_r_s(position, orientation, scale);
3959 ///
3960 /// let mut pos = Vec3::ZERO;
3961 /// let mut sca = Vec3::ZERO;
3962 /// let mut ori = Quat::ZERO;
3963 ///
3964 /// matrix.decompose_to_ptr(&mut pos, &mut ori, &mut sca);
3965 /// assert_eq!(pos, position);
3966 /// assert_eq!(sca, scale);
3967 /// assert_eq!(ori, orientation);
3968 /// ```
3969 #[inline]
3970 pub fn decompose_to_ptr(&self, out_position: &mut Vec3, out_orientation: &mut Quat, out_scale: &mut Vec3) -> bool {
3971 unsafe { matrix_decompose(self, out_position, out_scale, out_orientation) != 0 }
3972 }
3973
3974 /// Transforms a point through the Matrix! This is basically just multiplying a vector (x,y,z,1) with the Matrix.
3975 /// <https://stereokit.net/Pages/StereoKit/Matrix/Transform.html>
3976 /// * `point` - The point to transform.
3977 ///
3978 /// Returns the point transformed by the Matrix.
3979 /// see also the '*' operator [`matrix_transform_pt`]
3980 /// ### Examples
3981 /// ```
3982 /// use stereokit_rust::maths::{Vec3, Matrix};
3983 ///
3984 /// let transform = Matrix::t([1.0, 2.0, 3.0]);
3985 /// let point = Vec3::new(1.0, 1.0, 1.0);
3986 /// let transformed_point = transform.transform_point(point);
3987 /// assert_eq!(transformed_point, Vec3::new(2.0, 3.0, 4.0));
3988 ///
3989 /// let transformed_point_b = transform * point;
3990 /// assert_eq!(transformed_point_b, transformed_point);
3991 /// ```
3992 #[inline]
3993 pub fn transform_point<V: Into<Vec3>>(&self, point: V) -> Vec3 {
3994 unsafe { matrix_transform_pt(*self, point.into()) }
3995 }
3996
3997 /// Shorthand to transform a ray though the Matrix! This properly transforms the position with the point transform
3998 /// method, and the direction with the direction transform method. Does not normalize, nor does it preserve a
3999 /// normalized direction if the Matrix contains scale data.
4000 /// <https://stereokit.net/Pages/StereoKit/Matrix/Transform.html>
4001 /// * `ray` - A ray you wish to transform from one space to another.
4002 ///
4003 /// Returns the Ray transformed by the Matrix.
4004 /// see also the `*` operator [`matrix_transform_ray`]
4005 /// ### Examples
4006 /// ```
4007 /// use stereokit_rust::maths::{Vec3, Matrix, Ray};
4008 ///
4009 /// let transform = Matrix::t([1.0, 2.0, 3.0]);
4010 /// let ray = Ray::new([0.0, 0.0, 0.0], [1.0, 0.0, 0.0]);
4011 /// let transformed_ray = transform.transform_ray(ray);
4012 /// assert_eq!(transformed_ray, Ray::new([1.0, 2.0, 3.0], [1.0, 0.0, 0.0]));
4013 ///
4014 /// let transformed_ray_b = transform * ray;
4015 /// assert_eq!(transformed_ray_b, transformed_ray);
4016 /// ```
4017 #[inline]
4018 pub fn transform_ray<R: Into<Ray>>(&self, ray: R) -> Ray {
4019 unsafe { matrix_transform_ray(*self, ray.into()) }
4020 }
4021
4022 /// Shorthand for transforming a Pose! This will transform the position of the Pose with the matrix, extract a
4023 /// rotation Quat from the matrix and apply that to the Pose’s orientation. Note that extracting a rotation Quat
4024 /// is an expensive operation, so if you’re doing it more than once, you should cache the rotation Quat and do this
4025 /// transform manually.
4026 /// <https://stereokit.net/Pages/StereoKit/Matrix/Transform.html>
4027 /// * `pose` - The original pose.
4028 ///
4029 /// Returns the transformed pose.
4030 /// see also the `*` operator [`matrix_transform_pose`]
4031 /// ### Examples
4032 /// ```
4033 /// use stereokit_rust::maths::{Pose, Vec3, Matrix};
4034 ///
4035 /// let transform = Matrix::t([1.0, 2.0, 3.0]);
4036 /// let pose = Pose::new([0.0, 0.0, 0.0], None);
4037 /// let transformed_pose = transform.transform_pose(pose);
4038 /// assert_eq!(transformed_pose, Pose::new([1.0, 2.0, 3.0], None));
4039 ///
4040 /// let transformed_pose_b = transform * pose;
4041 /// assert_eq!(transformed_pose_b, transformed_pose);
4042 /// ```
4043 #[inline]
4044 pub fn transform_pose<P: Into<Pose>>(&self, pose: P) -> Pose {
4045 unsafe { matrix_transform_pose(*self, pose.into()) }
4046 }
4047
4048 /// Shorthand for transforming a rotation! This will extract a rotation Quat from the matrix and apply that to the
4049 /// QuatT's orientation. Note that extracting a rotation Quat is an expensive operation, so if you’re doing it more
4050 /// than once, you should cache the rotation Quat and do this transform manually.
4051 /// <https://stereokit.net/Pages/StereoKit/Matrix/Transform.html>
4052 /// * `rotation` - The original rotation
4053 ///
4054 /// Return the transformed quat.
4055 /// see also the `*` operator [`matrix_transform_quat`]
4056 /// ### Examples
4057 /// ```
4058 /// use stereokit_rust::maths::{Quat, Matrix};
4059 ///
4060 /// let transform = Matrix::r([0.0, 90.0, 0.0]);
4061 /// let rotation = Quat::from_angles(0.0, 90.0, 0.0);
4062 /// let transformed_rotation = transform.transform_quat(rotation);
4063 /// assert_eq!(transformed_rotation, Quat::from_angles(0.0, 180.0, 0.0));
4064 ///
4065 /// let transformed_rotation_b = transform * rotation;
4066 /// assert_eq!(transformed_rotation_b, transformed_rotation);
4067 /// ```
4068 #[inline]
4069 pub fn transform_quat<Q: Into<Quat>>(&self, rotation: Q) -> Quat {
4070 unsafe { matrix_transform_quat(*self, rotation.into()) }
4071 }
4072
4073 /// Transforms a point through the Matrix, but excluding translation! This is great for transforming vectors that
4074 /// are -directions- rather than points in space. Use this to transform normals and directions. The same as
4075 /// multiplying (x,y,z,0) with the Matrix. Do not correspond to `*` operator !
4076 /// <https://stereokit.net/Pages/StereoKit/Matrix/TransformNormal.html>
4077 /// * `normal` - A direction vector to be transformed.
4078 ///
4079 /// Returns the direction transformed by the Matrix.
4080 /// see also [`matrix_transform_dir`]
4081 /// ### Examples
4082 /// ```
4083 /// use stereokit_rust::maths::{Vec3, Matrix};
4084 ///
4085 /// let transform = Matrix::r([0.0, 90.0, 0.0]);
4086 /// let normal = Vec3::new(1.0, 0.0, 0.0);
4087 /// let transformed_normal = transform.transform_normal(normal);
4088 /// assert_eq!(transformed_normal, Vec3::new(0.0, 0.0, -1.0));
4089 /// ```
4090 #[inline]
4091 pub fn transform_normal<V: Into<Vec3>>(&self, normal: V) -> Vec3 {
4092 unsafe { matrix_transform_dir(*self, normal.into()) }
4093 }
4094
4095 /// Creates an inverse matrix! If the matrix takes a point from a -> b, then its inverse takes the point
4096 /// from b -> a.
4097 /// <https://stereokit.net/Pages/StereoKit/Matrix/Inverse.html>
4098 ///
4099 /// see also [`matrix_inverse`]
4100 /// ### Examples
4101 /// ```
4102 /// use stereokit_rust::maths::{Vec3, Matrix};
4103 ///
4104 /// let transform = Matrix::t([1.0, 2.0, 3.0]);
4105 /// let inverse = transform.get_inverse();
4106 /// let point = Vec3::new(1.0, 2.0, 3.0);
4107 /// let transformed_point = inverse * point;
4108 /// assert_eq!(transformed_point, Vec3::new(0.0, 0.0, 0.0));
4109 /// ```
4110 #[inline]
4111 pub fn get_inverse(&self) -> Self {
4112 let out: *mut Matrix = &mut Matrix { row: [Vec4::ZERO, Vec4::ZERO, Vec4::ZERO, Vec4::ZERO] };
4113 unsafe {
4114 matrix_inverse(self, out);
4115 *out
4116 }
4117 }
4118
4119 /// Creates an inverse matrix! If the matrix takes a point from a -> b, then its inverse takes the point
4120 /// from b -> a.
4121 /// <https://stereokit.net/Pages/StereoKit/Matrix/Inverse.html>
4122 /// * `out` - The output matrix.
4123 ///
4124 /// see also [`matrix_inverse`]
4125 /// ### Examples
4126 /// ```
4127 /// use stereokit_rust::maths::{Vec3, Matrix};
4128 ///
4129 /// let transform = Matrix::t([1.0, 2.0, 3.0]);
4130 /// let mut inverse = Matrix::NULL;
4131 ///
4132 /// transform.get_inverse_to_ptr(&mut inverse);
4133 /// let point = Vec3::new(1.0, 2.0, 3.0);
4134 /// let transformed_point = inverse * point;
4135 /// assert_eq!(transformed_point, Vec3::new(0.0, 0.0, 0.0));
4136 /// ```
4137 #[inline]
4138 pub fn get_inverse_to_ptr(&self, out: &mut Matrix) {
4139 unsafe {
4140 matrix_inverse(self, out);
4141 }
4142 }
4143
4144 /// Extracts translation and rotation information from the transform matrix, and makes a Pose from it! Not exactly
4145 /// fast. This is backed by Decompose, so if you need any additional info, it’s better to just call Decompose instead.
4146 /// <https://stereokit.net/Pages/StereoKit/Matrix/Pose.html>
4147 ///
4148 /// see also [`matrix_extract_pose`]
4149 /// ### Examples
4150 /// ```
4151 /// use stereokit_rust::maths::{Vec3, Quat, Matrix, Pose};
4152 ///
4153 /// let matrix = Matrix::t_r(Vec3::new(1.0, 2.0, 3.0), [0.0, 0.0, 0.0]);
4154 ///
4155 /// let pose = matrix.get_pose();
4156 /// assert_eq!(pose.position, Vec3::new(1.0, 2.0, 3.0));
4157 /// assert_eq!(pose.orientation, Quat::IDENTITY)
4158 /// ```
4159 #[inline]
4160 pub fn get_pose(&self) -> Pose {
4161 unsafe { matrix_extract_pose(self) }
4162 }
4163
4164 /// A slow function that returns the rotation quaternion embedded in this transform matrix. This is backed by
4165 /// Decompose, so if you need any additional info, it’s better to just call Decompose instead.
4166 /// <https://stereokit.net/Pages/StereoKit/Matrix/Rotation.html>
4167 ///
4168 /// see also [`matrix_extract_rotation`]
4169 /// ### Examples
4170 /// ```
4171 /// use stereokit_rust::maths::{Vec3, Quat, Matrix};
4172 ///
4173 /// let matrix = Matrix::t_r(Vec3::new(1.0, 2.0, 3.0), [0.0, 90.0, 0.0]);
4174 ///
4175 /// let rotation = matrix.get_rotation();
4176 /// assert_eq!(rotation, Quat::from_angles(0.0, 90.0, 0.0))
4177 /// ```
4178 #[inline]
4179 pub fn get_rotation(&self) -> Quat {
4180 unsafe { matrix_extract_rotation(self) }
4181 }
4182
4183 /// Returns the scale embedded in this transform matrix. Not exactly cheap, requires 3 sqrt calls, but is cheaper
4184 /// than calling Decompose.
4185 /// <https://stereokit.net/Pages/StereoKit/Matrix/Scale.html>
4186 ///
4187 /// see also [`matrix_extract_scale`]
4188 /// ### Examples
4189 /// ```
4190 /// use stereokit_rust::maths::{Vec3, Matrix};
4191 ///
4192 /// let matrix = Matrix::t_s(Vec3::new(1.0, 2.0, 3.0), Vec3::new(2.0, 2.0, 2.0));
4193 ///
4194 /// let scale = matrix.get_scale();
4195 /// assert_eq!(scale, Vec3::new(2.0, 2.0, 2.0))
4196 /// ```
4197 #[inline]
4198 pub fn get_scale(&self) -> Vec3 {
4199 unsafe { matrix_extract_scale(self) }
4200 }
4201
4202 /// A fast getter that will return or set the translation component embedded in this transform matrix.
4203 /// <https://stereokit.net/Pages/StereoKit/Matrix/Translation.html>
4204 ///
4205 /// see also [`matrix_extract_translation`]
4206 /// ### Examples
4207 /// ```
4208 /// use stereokit_rust::maths::{Vec3, Matrix};
4209 ///
4210 /// let transform = Matrix::r([0.0, 90.0, 0.0]);
4211 /// let normal = Vec3::new(1.0, 0.0, 0.0);
4212 ///
4213 /// let transformed_normal = transform.transform_normal(normal);
4214 /// assert_eq!(transformed_normal, Vec3::new(0.0, 0.0, -1.0));
4215 /// ```
4216 #[inline]
4217 pub fn get_translation(&self) -> Vec3 {
4218 unsafe { matrix_extract_translation(self) }
4219 }
4220
4221 /// Creates a matrix that has been transposed! Transposing is like rotating the matrix 90 clockwise, or turning
4222 /// the rows into columns. This can be useful for inverting orthogonal matrices, or converting matrices for use
4223 /// in a math library that uses different conventions!
4224 /// <https://stereokit.net/Pages/StereoKit/Matrix/Transposed.html>
4225 ///
4226 /// see also [`matrix_transpose`]
4227 /// ### Examples
4228 /// ```
4229 /// use stereokit_rust::maths::{Vec3, Matrix};
4230 ///
4231 /// let transform = Matrix::t([1.0, 2.0, 3.0]);
4232 /// assert_eq!(transform, Matrix::from([
4233 /// 1.0, 0.0, 0.0, 0.0,
4234 /// 0.0, 1.0, 0.0, 0.0,
4235 /// 0.0, 0.0, 1.0, 0.0,
4236 /// 1.0, 2.0, 3.0, 1.0,
4237 /// ]));
4238 ///
4239 /// let transposed = transform.get_transposed();
4240 /// assert_eq!(transposed, Matrix::from([
4241 /// 1.0, 0.0, 0.0, 1.0,
4242 /// 0.0, 1.0, 0.0, 2.0,
4243 /// 0.0, 0.0, 1.0, 3.0,
4244 /// 0.0, 0.0, 0.0, 1.0,
4245 /// ]));
4246 /// ```
4247 #[inline]
4248 pub fn get_transposed(&self) -> Self {
4249 unsafe { matrix_transpose(*self) }
4250 }
4251}
4252
4253impl Display for Matrix {
4254 /// Mostly for debug purposes, this is a decent way to log or inspect the matrix in debug mode. Looks
4255 /// like “[, , , ]”
4256 ///
4257 /// ### Examples
4258 /// ```
4259 /// use stereokit_rust::maths::Matrix;
4260 ///
4261 /// let matrix = Matrix::from([
4262 /// 1.0, 2.0, 3.3, 4.0,
4263 /// 5.0, 6.0, 7.0, 8.0,
4264 /// 9.0, 10.0, 11.0, 12.0,
4265 /// 13.0, 14.0, 15.0, 16.0,
4266 /// ]);
4267 /// assert_eq!(format!("{}", matrix),
4268 /// "[\r\n [x:1, y:2, z:3.3, w:4],\r\n [x:5, y:6, z:7, w:8],\r\n [x:9, y:10, z:11, w:12],\r\n [x:13, y:14, z:15, w:16]]");
4269 /// ```
4270 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4271 unsafe { write!(f, "[\r\n {},\r\n {},\r\n {},\r\n {}]", self.row[0], self.row[1], self.row[2], self.row[3]) }
4272 }
4273}
4274/// Multiplies the vector by the Matrix! Since only a 1x4 vector can be multiplied against a 4x4 matrix, this uses ‘1’
4275/// for the 4th element, so the result will also include translation! To exclude translation,
4276/// use Matrix.transform_normal.
4277/// <https://stereokit.net/Pages/StereoKit/Matrix/op_Multiply.html>
4278///
4279/// see also [`matrix_transform_pt`]
4280impl Mul<Vec3> for Matrix {
4281 type Output = Vec3;
4282
4283 /// ### Examples
4284 /// ```
4285 /// use stereokit_rust::maths::{Vec3, Matrix};
4286 ///
4287 /// let transform = Matrix::t([1.0, 2.0, 3.0]);
4288 /// let point = Vec3::new(1.0, 1.0, 1.0);
4289 ///
4290 /// let transformed_point = transform * point;
4291 /// assert_eq!(transformed_point, Vec3::new(2.0, 3.0, 4.0));
4292 /// ```
4293 fn mul(self, rhs: Vec3) -> Self::Output {
4294 unsafe { matrix_transform_pt(self, rhs) }
4295 }
4296}
4297
4298/// Multiplies the vector by the Matrix! Since only a 1x4 vector can be multiplied against a 4x4 matrix, this uses ‘1’
4299/// for the 4th element, so the result will also include translation! To exclude translation,
4300/// use Matrix.transform_normal.
4301/// <https://stereokit.net/Pages/StereoKit/Matrix/op_Multiply.html>
4302///
4303/// see also [`matrix_transform_pt`]
4304impl MulAssign<Matrix> for Vec3 {
4305 /// ### Examples
4306 /// ```
4307 /// use stereokit_rust::maths::{Vec3, Matrix};
4308 ///
4309 /// let mut point = Vec3::new(1.0, 1.0, 1.0);
4310 /// let transform = Matrix::t([1.0, 2.0, 3.0]);
4311 ///
4312 /// point *= transform;
4313 /// assert_eq!(point, Vec3::new(2.0, 3.0, 4.0));
4314 /// ```
4315 fn mul_assign(&mut self, rhs: Matrix) {
4316 let res = unsafe { matrix_transform_pt(rhs, *self) };
4317 self.x = res.x;
4318 self.y = res.y;
4319 self.z = res.z;
4320 }
4321}
4322
4323/// Multiplies the vector by the Matrix! Since only a 1x4 vector can be multiplied against a 4x4 matrix, this uses ‘1’
4324/// for the 4th element, so the result will also include translation! To exclude translation,
4325/// use Matrix.transform_normal.
4326/// <https://stereokit.net/Pages/StereoKit/Matrix/op_Multiply.html>
4327///
4328/// see also [`matrix_transform_pt`]
4329impl Mul<Matrix> for Vec3 {
4330 type Output = Vec3;
4331
4332 /// ### Examples
4333 /// ```
4334 /// use stereokit_rust::maths::{Vec3, Matrix};
4335 ///
4336 /// let transform = Matrix::t([1.0, 2.0, 3.0]);
4337 /// let point = Vec3::new(1.0, 1.0, 1.0);
4338 ///
4339 /// let transformed_point = point * transform;
4340 /// assert_eq!(transformed_point, Vec3::new(2.0, 3.0, 4.0));
4341 /// ```
4342 fn mul(self, rhs: Matrix) -> Self::Output {
4343 unsafe { matrix_transform_pt(rhs, self) }
4344 }
4345}
4346
4347/// <https://stereokit.net/Pages/StereoKit/Matrix/op_Multiply.html>
4348///
4349/// see also [`matrix_transform_pt4`]
4350impl Mul<Vec4> for Matrix {
4351 type Output = Vec4;
4352
4353 /// ### Examples
4354 /// ```
4355 /// use stereokit_rust::maths::{Vec4, Matrix};
4356 ///
4357 /// let transform = Matrix::t([1.0, 2.0, 3.0]);
4358 /// let v4 = Vec4::new(1.0, 1.0, 1.0, 1.0);
4359 ///
4360 /// let transformed_v4 = transform * v4;
4361 /// assert_eq!(transformed_v4, Vec4::new(2.0, 3.0, 4.0, 1.0));
4362 /// ```
4363 fn mul(self, rhs: Vec4) -> Self::Output {
4364 unsafe { matrix_transform_pt4(self, rhs) }
4365 }
4366}
4367
4368/// <https://stereokit.net/Pages/StereoKit/Matrix/op_Multiply.html>
4369///
4370/// see also [`matrix_transform_pt4`]
4371impl MulAssign<Matrix> for Vec4 {
4372 /// ### Examples
4373 /// ```
4374 /// use stereokit_rust::maths::{Vec4, Matrix};
4375 ///
4376 /// let mut v4 = Vec4::new(1.0, 1.0, 1.0, 1.0);
4377 /// let transform = Matrix::t([1.0, 2.0, 3.0]);
4378 ///
4379 /// v4 *= transform;
4380 /// assert_eq!(v4, Vec4::new(2.0, 3.0, 4.0, 1.0));
4381 /// ```
4382 fn mul_assign(&mut self, rhs: Matrix) {
4383 let res = unsafe { matrix_transform_pt4(rhs, *self) };
4384 self.x = res.x;
4385 self.y = res.y;
4386 self.z = res.z;
4387 self.w = res.w
4388 }
4389}
4390
4391/// <https://stereokit.net/Pages/StereoKit/Matrix/op_Multiply.html>
4392///
4393/// see also [`matrix_transform_pt4`]
4394impl Mul<Matrix> for Vec4 {
4395 type Output = Vec4;
4396
4397 /// ### Examples
4398 /// ```
4399 /// use stereokit_rust::maths::{Vec4, Matrix};
4400 ///
4401 /// let transform = Matrix::t([1.0, 2.0, 3.0]);
4402 /// let v4 = Vec4::new(1.0, 1.0, 1.0, 1.0);
4403 ///
4404 /// let transformed_v4 = v4 * transform;
4405 /// assert_eq!(transformed_v4, Vec4::new(2.0, 3.0, 4.0, 1.0));
4406 /// ```
4407 fn mul(self, rhs: Matrix) -> Self::Output {
4408 unsafe { matrix_transform_pt4(rhs, self) }
4409 }
4410}
4411
4412/// Transforms a Ray by the Matrix! The position and direction are both multiplied by the matrix, accounting properly for
4413/// which should include translation, and which should not.
4414/// <https://stereokit.net/Pages/StereoKit/Matrix/op_Multiply.html>
4415///
4416/// see also [`matrix_transform_ray`]
4417impl Mul<Ray> for Matrix {
4418 type Output = Ray;
4419
4420 /// ### Examples
4421 /// ```
4422 /// use stereokit_rust::maths::{Vec3, Matrix, Ray};
4423 ///
4424 /// let transform = Matrix::t([1.0, 2.0, 3.0]);
4425 /// let ray = Ray::new([0.0, 0.0, 0.0], [1.0, 0.0, 0.0]);
4426 ///
4427 /// let transformed_ray = transform * ray;
4428 /// assert_eq!(transformed_ray, Ray::new([1.0, 2.0, 3.0], [1.0, 0.0, 0.0]));
4429 /// ```
4430 fn mul(self, rhs: Ray) -> Self::Output {
4431 unsafe { matrix_transform_ray(self, rhs) }
4432 }
4433}
4434
4435/// Transforms a Ray by the Matrix! The position and direction are both multiplied by the matrix, accounting properly for
4436/// which should include translation, and which should not.
4437/// <https://stereokit.net/Pages/StereoKit/Matrix/op_Multiply.html>
4438///
4439/// see also [`matrix_transform_ray`]
4440impl MulAssign<Matrix> for Ray {
4441 /// ```
4442 /// use stereokit_rust::maths::{Vec3, Matrix, Ray};
4443 ///
4444 /// let mut ray = Ray::new([0.0, 0.0, 0.0], [1.0, 0.0, 0.0]);
4445 /// let transform = Matrix::t([1.0, 2.0, 3.0]);
4446 ///
4447 /// ray *= transform;
4448 /// assert_eq!(ray, Ray::new([1.0, 2.0, 3.0], [1.0, 0.0, 0.0]));
4449 /// ```
4450 fn mul_assign(&mut self, rhs: Matrix) {
4451 let res = unsafe { matrix_transform_ray(rhs, *self) };
4452 self.position = res.position;
4453 self.direction = res.direction;
4454 }
4455}
4456
4457/// Transforms a Ray by the Matrix! The position and direction are both multiplied by the matrix, accounting properly for
4458/// which should include translation, and which should not.
4459/// <https://stereokit.net/Pages/StereoKit/Matrix/op_Multiply.html>
4460///
4461/// see also [`matrix_transform_ray`]
4462impl Mul<Matrix> for Ray {
4463 type Output = Ray;
4464
4465 /// ### Examples
4466 /// ```
4467 /// use stereokit_rust::maths::{Vec3, Matrix, Ray};
4468 ///
4469 /// let transform = Matrix::t([1.0, 2.0, 3.0]);
4470 /// let ray = Ray::new([0.0, 0.0, 0.0], [1.0, 0.0, 0.0]);
4471 ///
4472 /// let transformed_ray = ray * transform;
4473 /// assert_eq!(transformed_ray, Ray::new([1.0, 2.0, 3.0], [1.0, 0.0, 0.0]));
4474 /// ```
4475 fn mul(self, rhs: Matrix) -> Self::Output {
4476 unsafe { matrix_transform_ray(rhs, self) }
4477 }
4478}
4479
4480/// Transform an orientation by the Matrix.
4481/// <https://stereokit.net/Pages/StereoKit/Matrix/op_Multiply.html>
4482///
4483/// see also [`matrix_transform_quat`]
4484impl Mul<Quat> for Matrix {
4485 type Output = Quat;
4486
4487 /// ### Examples
4488 /// ```
4489 /// use stereokit_rust::maths::{Quat, Matrix};
4490 ///
4491 /// let transform = Matrix::r([0.0, 90.0, 0.0]);
4492 /// let rotation = Quat::from_angles(0.0, 0.0, 0.0);
4493 ///
4494 /// let transformed_rotation = transform * rotation;
4495 /// assert_eq!(transformed_rotation, Quat::from_angles(0.0, 90.0, 0.0));
4496 /// ```
4497 fn mul(self, rhs: Quat) -> Self::Output {
4498 unsafe { matrix_transform_quat(self, rhs) }
4499 }
4500}
4501
4502/// Transform an orientation by the Matrix.
4503/// <https://stereokit.net/Pages/StereoKit/Matrix/op_Multiply.html>
4504///
4505/// see also [`matrix_transform_quat`]
4506impl MulAssign<Matrix> for Quat {
4507 /// ### Examples
4508 /// ```
4509 /// use stereokit_rust::maths::{Quat, Matrix};
4510 ///
4511 /// let mut rotation = Quat::from_angles(0.0, 0.0, 0.0);
4512 /// let transform = Matrix::r([0.0, 90.0, 0.0]);
4513 ///
4514 /// rotation *= transform;
4515 /// assert_eq!(rotation, Quat::from_angles(0.0, 90.0, 0.0));
4516 /// ```
4517 fn mul_assign(&mut self, rhs: Matrix) {
4518 let res = unsafe { matrix_transform_quat(rhs, *self) };
4519 self.x = res.x;
4520 self.y = res.y;
4521 self.z = res.z;
4522 self.w = res.w
4523 }
4524}
4525
4526/// Transform an orientation by the Matrix.
4527/// <https://stereokit.net/Pages/StereoKit/Matrix/op_Multiply.html>
4528///
4529/// see also [`matrix_transform_quat`]
4530impl Mul<Matrix> for Quat {
4531 type Output = Quat;
4532
4533 /// ### Examples
4534 /// ```
4535 /// use stereokit_rust::maths::{Quat, Matrix};
4536 ///
4537 /// let transform = Matrix::r([0.0, 90.0, 0.0]);
4538 /// let rotation = Quat::from_angles(0.0, 0.0, 0.0);
4539 ///
4540 /// let transformed_rotation = rotation * transform;
4541 /// assert_eq!(transformed_rotation, Quat::from_angles(0.0, 90.0, 0.0));
4542 /// ```
4543 fn mul(self, rhs: Matrix) -> Self::Output {
4544 unsafe { matrix_transform_quat(rhs, self) }
4545 }
4546}
4547
4548/// Transforms a Pose by the Matrix! The position and orientation are both transformed by the matrix, accounting
4549/// properly for the Pose’s quaternion.
4550/// <https://stereokit.net/Pages/StereoKit/Matrix/op_Multiply.html>
4551///
4552/// see also [`matrix_transform_pose`]
4553impl Mul<Pose> for Matrix {
4554 type Output = Pose;
4555
4556 /// ### Examples
4557 /// ```
4558 /// use stereokit_rust::maths::{Pose, Vec3, Matrix};
4559 ///
4560 /// let transform = Matrix::t([1.0, 2.0, 3.0]);
4561 /// let pose = Pose::new([0.0, 0.0, 0.0], None);
4562 ///
4563 /// let transformed_pose = transform * pose;
4564 /// assert_eq!(transformed_pose, Pose::new([1.0, 2.0, 3.0], None));
4565 /// ```
4566 fn mul(self, rhs: Pose) -> Self::Output {
4567 unsafe { matrix_transform_pose(self, rhs) }
4568 }
4569}
4570
4571/// Transforms a Pose by the Matrix! The position and orientation are both transformed by the matrix, accounting
4572/// properly for the Pose’s quaternion.
4573/// <https://stereokit.net/Pages/StereoKit/Matrix/op_Multiply.html>
4574///
4575/// see also [`matrix_transform_pose`]
4576impl MulAssign<Matrix> for Pose {
4577 /// ### Examples
4578 /// ```
4579 /// use stereokit_rust::maths::{Pose, Vec3, Matrix};
4580 ///
4581 /// let mut pose = Pose::new([0.0, 0.0, 0.0], None);
4582 /// let transform = Matrix::t([1.0, 2.0, 3.0]);
4583 ///
4584 /// pose *= transform;
4585 /// assert_eq!(pose, Pose::new([1.0, 2.0, 3.0], None));
4586 /// ```
4587 fn mul_assign(&mut self, rhs: Matrix) {
4588 let res = unsafe { matrix_transform_pose(rhs, *self) };
4589 self.position = res.position;
4590 self.orientation = res.orientation;
4591 }
4592}
4593
4594/// Transforms a Pose by the Matrix! The position and orientation are both transformed by the matrix, accounting
4595/// properly for the Pose’s quaternion.
4596/// <https://stereokit.net/Pages/StereoKit/Matrix/op_Multiply.html>
4597///
4598/// see also [`matrix_transform_pose`]
4599impl Mul<Matrix> for Pose {
4600 type Output = Pose;
4601
4602 /// ### Examples
4603 /// ```
4604 /// use stereokit_rust::maths::{Pose, Vec3, Matrix};
4605 ///
4606 /// let transform = Matrix::t([1.0, 2.0, 3.0]);
4607 /// let pose = Pose::new([0.0, 0.0, 0.0], None);
4608 ///
4609 /// let transformed_pose = pose * transform;
4610 /// assert_eq!(transformed_pose, Pose::new([1.0, 2.0, 3.0], None));
4611 /// ```
4612 fn mul(self, rhs: Matrix) -> Self::Output {
4613 unsafe { matrix_transform_pose(rhs, self) }
4614 }
4615}
4616
4617/// Multiplies two matrices together! This is a great way to combine transform operations. Note that StereoKit’s
4618/// matrices are row-major, and multiplication order is important! To translate, then scale, multiply in order of
4619/// ‘translate * scale’.
4620/// <https://stereokit.net/Pages/StereoKit/Matrix/op_Multiply.html>
4621///
4622/// see also [`matrix_mul`]
4623impl Mul<Matrix> for Matrix {
4624 type Output = Self;
4625
4626 /// ### Examples
4627 /// ```
4628 /// use stereokit_rust::maths::{Vec3, Matrix};
4629 ///
4630 /// let transform_a = Matrix::t([1.0, 2.0, 3.0]);
4631 /// let transform_b = Matrix::s([2.0, 2.0, 2.0]);
4632 ///
4633 /// let transform_c = transform_a * transform_b;
4634 /// let point = Vec3::new(1.0, 1.0, 1.0);
4635 /// let transformed_point = transform_c * point;
4636 /// assert_eq!(transformed_point, Vec3::new(4.0, 6.0, 8.0));
4637 /// ```
4638 fn mul(self, rhs: Matrix) -> Self::Output {
4639 let out: *mut Matrix = &mut Matrix { row: [Vec4::ZERO, Vec4::ZERO, Vec4::ZERO, Vec4::ZERO] };
4640 unsafe {
4641 matrix_mul(&self, &rhs, out);
4642 *out
4643 }
4644 }
4645}
4646
4647/// Multiplies two matrices together! This is a great way to combine transform operations. Note that StereoKit’s
4648/// matrices are row-major, and multiplication order is important! To translate, then scale, multiply in order of
4649/// ‘translate * scale’.
4650/// <https://stereokit.net/Pages/StereoKit/Matrix/op_Multiply.html>
4651///
4652/// see also [`matrix_mul`]
4653impl MulAssign<Matrix> for Matrix {
4654 /// ### Examples
4655 /// ```
4656 /// use stereokit_rust::maths::{Vec3, Matrix};
4657 ///
4658 /// let mut transform_a = Matrix::t([1.0, 2.0, 3.0]);
4659 /// let transform_b = Matrix::s([2.0, 2.0, 2.0]);
4660 ///
4661 /// transform_a *= transform_b;
4662 /// let point = Vec3::new(1.0, 1.0, 1.0);
4663 /// let transformed_point = transform_a * point;
4664 /// assert_eq!(transformed_point, Vec3::new(4.0, 6.0, 8.0));
4665 /// ```
4666 fn mul_assign(&mut self, rhs: Matrix) {
4667 unsafe { matrix_mul(self, &rhs, self) };
4668 }
4669}
4670
4671/// Bounds is an axis aligned bounding box type that can be used for storing the sizes of objects, calculating
4672/// containment, intersections, and more!
4673///
4674/// While the constructor uses a center+dimensions for creating a bounds, don’t forget the static From* methods that
4675/// allow you to define a Bounds from different types of data!
4676/// <https://stereokit.net/Pages/StereoKit/Bounds.html>
4677///
4678/// ### Examples
4679/// ```
4680/// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
4681/// use stereokit_rust::{maths::{Vec3, Matrix, Pose}, model::Model, ui::Ui,
4682/// mesh::Mesh, material::Material, util::named_colors};
4683///
4684/// let model = Model::from_file("center.glb", None).unwrap().copy();
4685/// let cube = Mesh::cube();
4686/// let mut material_cube = Material::ui_box();
4687/// material_cube.color_tint(named_colors::GOLD)
4688/// .border_size(0.05);
4689///
4690/// let scale = 0.4;
4691/// let bounds = model.get_bounds() * scale;
4692/// let transform = Matrix::s(Vec3::ONE * scale);
4693/// let transform_cube = Matrix::t_s( bounds.center, bounds.dimensions);
4694/// let mut handle_pose =
4695/// Pose::new([0.0,-0.95,-0.65], Some([0.0, 140.0, 0.0].into()));
4696///
4697/// filename_scr = "screenshots/bounds.jpeg";
4698/// test_screenshot!( // !!!! Get a proper main loop !!!!
4699/// Ui::handle_begin( "Model Handle", &mut handle_pose,
4700/// bounds, false, None, None);
4701/// model.draw(token, transform, None, None);
4702/// cube.draw(token, &material_cube, transform_cube, None, None);
4703/// Ui::handle_end();
4704/// );
4705/// ```
4706/// <img src="https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/bounds.jpeg" alt="screenshot" width="200">
4707#[derive(Copy, Clone, Debug, Default, PartialEq)]
4708#[repr(C)]
4709pub struct Bounds {
4710 pub center: Vec3,
4711 pub dimensions: Vec3,
4712}
4713
4714/// AsRef
4715impl AsRef<Bounds> for Bounds {
4716 fn as_ref(&self) -> &Bounds {
4717 self
4718 }
4719}
4720
4721unsafe extern "C" {
4722 pub fn bounds_ray_intersect(bounds: Bounds, ray: Ray, out_pt: *mut Vec3) -> Bool32T;
4723 pub fn bounds_point_contains(bounds: Bounds, pt: Vec3) -> Bool32T;
4724 pub fn bounds_line_contains(bounds: Bounds, pt1: Vec3, pt2: Vec3) -> Bool32T;
4725 pub fn bounds_capsule_contains(bounds: Bounds, pt1: Vec3, pt2: Vec3, radius: f32) -> Bool32T;
4726 pub fn bounds_grow_to_fit_pt(bounds: Bounds, pt: Vec3) -> Bounds;
4727 pub fn bounds_grow_to_fit_box(bounds: Bounds, box_: Bounds, opt_box_transform: *const Matrix) -> Bounds;
4728 pub fn bounds_transform(bounds: Bounds, transform: Matrix) -> Bounds;
4729}
4730
4731impl Bounds {
4732 /// Creates a bounding box object!
4733 /// <https://stereokit.net/Pages/StereoKit/Bounds/Bounds.html>
4734 /// * center - The exact center of the box.
4735 /// * dimensions - The total size of the box, from one end to the other. This is the width, height, and depth of
4736 /// the Bounds.
4737 ///
4738 /// ### Examples
4739 /// ```
4740 /// use stereokit_rust::maths::{Vec3, Bounds};
4741 ///
4742 /// let bounds = Bounds::new([1.0, 2.0, 3.0], [4.0, 5.0, 6.0]);
4743 /// assert_eq!(bounds.center, Vec3::new(1.0, 2.0, 3.0));
4744 /// assert_eq!(bounds.dimensions, Vec3::new(4.0, 5.0, 6.0));
4745 /// ```
4746 #[inline]
4747 pub fn new<V: Into<Vec3>>(center: V, dimensions: V) -> Bounds {
4748 Bounds { center: center.into(), dimensions: dimensions.into() }
4749 }
4750
4751 /// Creates a bounding box object centered around zero!
4752 /// <https://stereokit.net/Pages/StereoKit/Bounds/Bounds.html>
4753 /// * dimensions - The total size of the box, from one end to the other. This is the width, height, and depth of
4754 /// the Bounds.
4755 ///
4756 /// ### Examples
4757 /// ```
4758 /// use stereokit_rust::maths::{Vec3, Bounds};
4759 ///
4760 /// let bounds = Bounds::bounds_centered( [4.0, 5.0, 6.0]);
4761 /// assert_eq!(bounds.center, Vec3::ZERO);
4762 /// assert_eq!(bounds.dimensions, Vec3::new(4.0, 5.0, 6.0));
4763 /// ```
4764 #[inline]
4765 pub fn bounds_centered(dimensions: impl Into<Vec3>) -> Bounds {
4766 Bounds { center: Vec3::ZERO, dimensions: dimensions.into() }
4767 }
4768
4769 /// Create a bounding box from a corner, plus box dimensions.
4770 /// <https://stereokit.net/Pages/StereoKit/Bounds/FromCorner.html>
4771 /// * bottom_left_back - The -X,-Y,-Z corner of the box.
4772 /// * dimensions - The dimensions of the bounding box.
4773 ///
4774 /// ### Examples
4775 /// ```
4776 /// use stereokit_rust::maths::{Vec3, Bounds};
4777 ///
4778 /// let bounds = Bounds::from_corner( Vec3::ZERO, [1.0, 2.0, 3.0].into());
4779 /// assert_eq!(bounds.center, [0.5, 1.0, 1.5].into());
4780 /// assert_eq!(bounds.dimensions, Vec3::new(1.0, 2.0, 3.0));
4781 /// ```
4782 #[inline]
4783 pub fn from_corner<V: Into<Vec3>>(bottom_left_back: V, dimensions: V) -> Bounds {
4784 let dim = dimensions.into();
4785 Bounds { center: bottom_left_back.into() + dim / 2.0, dimensions: dim }
4786 }
4787
4788 /// Create a bounding box between two corner points.
4789 /// <https://stereokit.net/Pages/StereoKit/Bounds/FromCorners.html>
4790 /// * bottom_left_back - The -X,-Y,-Z corner of the box.
4791 /// * top_right_front - The +X,+Y,+Z corner of the box.
4792 ///
4793 /// ### Examples
4794 /// ```
4795 /// use stereokit_rust::maths::{Vec3, Bounds};
4796 ///
4797 /// let bounds = Bounds::from_corners( Vec3::ZERO, Vec3::ONE);
4798 /// assert_eq!(bounds.center, Vec3::ONE / 2.0);
4799 /// assert_eq!(bounds.dimensions, Vec3::ONE);
4800 /// ```
4801 #[inline]
4802 pub fn from_corners<V: Into<Vec3>>(bottom_left_back: V, top_right_front: V) -> Bounds {
4803 let blb = bottom_left_back.into();
4804 let trf = top_right_front.into();
4805 Bounds { center: blb / 2.0 + trf / 2.0, dimensions: (trf - blb).abs() }
4806 }
4807
4808 /// Grow the Bounds to encapsulate the provided point. Returns the result, and does NOT modify the current bounds.
4809 /// <https://stereokit.net/Pages/StereoKit/Bounds/Grown.html>
4810 /// * pt - The point to encapsulate! This should be in the same space as the bounds.
4811 ///
4812 /// see also [`bounds_grow_to_fit_pt]
4813 /// ### Examples
4814 /// ```
4815 /// use stereokit_rust::maths::{Vec3, Bounds};
4816 ///
4817 /// let mut bounds = Bounds::from_corners( Vec3::ZERO, Vec3::ONE);
4818 /// bounds.grown_point(Vec3::new(1.0, 2.0, 3.0));
4819 /// assert_eq!(bounds.center, Vec3{ x: 0.5, y: 1.0, z: 1.5 });
4820 /// assert_eq!(bounds.dimensions, Vec3 { x: 1.0, y: 2.0, z: 3.0 });
4821 /// ```
4822 #[inline]
4823 pub fn grown_point(&mut self, pt: impl Into<Vec3>) -> &mut Self {
4824 let b = unsafe { bounds_grow_to_fit_pt(*self, pt.into()) };
4825 self.center = b.center;
4826 self.dimensions = b.dimensions;
4827 self
4828 }
4829
4830 /// Grow the Bounds to encapsulate the provided box after it has been transformed by the provided matrix transform.
4831 /// This will transform each corner of the box, and expand the bounds to encapsulate each point!
4832 /// <https://stereokit.net/Pages/StereoKit/Bounds/Grown.html>
4833 /// * box_ - the box to encapsulate! The corners of this box are transformed, and then used to grow the bounds.
4834 /// * opt_box_transform - to center use Matrix::IDENTITY
4835 ///
4836 /// see also [`bounds_grow_to_fit_box]
4837 /// see also [`bounds_grow_to_fit_pt]
4838 /// ### Examples
4839 /// ```
4840 /// use stereokit_rust::maths::{Vec3, Matrix, Bounds};
4841 ///
4842 /// let mut bounds = Bounds::from_corners( Vec3::ZERO, Vec3::ONE);
4843 /// let bounds_plus = Bounds::from_corners( Vec3::ONE, Vec3::ONE * 2.0);
4844 /// bounds.grown_box(bounds_plus, Matrix::IDENTITY);
4845 /// assert_eq!(bounds.center, Vec3::ONE);
4846 /// assert_eq!(bounds.dimensions, Vec3::ONE * 2.0);
4847 /// ```
4848 #[inline]
4849 pub fn grown_box<M: Into<Matrix>>(&mut self, box_: impl AsRef<Bounds>, opt_box_transform: M) -> &mut Self {
4850 let b = unsafe { bounds_grow_to_fit_box(*self, *(box_.as_ref()), &opt_box_transform.into()) };
4851 self.center = b.center;
4852 self.dimensions = b.dimensions;
4853 self
4854 }
4855
4856 /// Scale this bounds. It will scale the center as well as the dimensions! Modifies this bounds object.
4857 /// <https://stereokit.net/Pages/StereoKit/Bounds/Scale.html>
4858 /// * scale - The scale to apply.
4859 ///
4860 /// see also [Bounds::scale_vec] [Bounds::scaled] [Bounds::scaled_vec] and '/' '*' operator
4861 /// ### Examples
4862 /// ```
4863 /// use stereokit_rust::maths::{Vec3, Matrix, Bounds};
4864 ///
4865 /// let mut bounds = Bounds::from_corners( Vec3::ZERO, Vec3::ONE);
4866 /// bounds.scale(2.0);
4867 /// let bounds_plus = Bounds::from_corners( Vec3::ZERO, Vec3::ONE) * 2.0;
4868 ///
4869 /// assert_eq!(bounds.center, bounds_plus.center);
4870 /// assert_eq!(bounds.dimensions, bounds_plus.dimensions);
4871 /// ```
4872 #[inline]
4873 pub fn scale(&mut self, scale: f32) -> &mut Self {
4874 self.dimensions *= scale;
4875 self.center *= scale;
4876 self
4877 }
4878
4879 /// Scale this bounds. It will scale the center as well as the dimensions! Modifies this bounds object.
4880 /// <https://stereokit.net/Pages/StereoKit/Bounds/Scale.html>
4881 /// * scale - The scale to apply.
4882 ///
4883 /// see also [Bounds::scale] [Bounds::scaled_vec] [Bounds::scaled] and '/' '*' operator
4884 /// ### Examples
4885 /// ```
4886 /// use stereokit_rust::maths::{Vec3, Matrix, Bounds};
4887 ///
4888 /// let mut bounds = Bounds::from_corners( Vec3::ZERO, Vec3::ONE);
4889 /// bounds.scale_vec([1.0, 2.0, 3.0]);
4890 /// let bounds_plus = Bounds::from_corners( Vec3::ZERO, Vec3::ONE) * Vec3::new(1.0, 2.0, 3.0);
4891 ///
4892 /// assert_eq!(bounds.center, bounds_plus.center);
4893 /// assert_eq!(bounds.dimensions, bounds_plus.dimensions);
4894 /// ```
4895 #[inline]
4896 pub fn scale_vec(&mut self, scale: impl Into<Vec3>) -> &mut Self {
4897 let scale = scale.into();
4898 self.dimensions *= scale;
4899 self.center *= scale;
4900 self
4901 }
4902
4903 /// Does the Bounds contain the given point? This includes points that are on the surface of the Bounds.
4904 /// <https://stereokit.net/Pages/StereoKit/Bounds/Contains.html>
4905 /// * pt - A point in the same coordinate space as the Bounds.
4906 ///
4907 /// see also [`bounds_point_contains`]
4908 /// ### Examples
4909 /// ```
4910 /// use stereokit_rust::maths::{Vec3, Bounds, Matrix};
4911 ///
4912 /// // A cube of 1 meter per side at this position, aligned with x y and z axis.
4913 /// let box_transform = Matrix::t([10.0, 1.0, 2.0]);
4914 /// let box_bounds = Bounds::bounds_centered([1.0,1.0,1.0]);
4915 ///
4916 /// let inv = box_transform.get_inverse();
4917 /// let point1 = inv.transform_point([10.2, 1.3, 2.4]);
4918 /// let point2 = inv.transform_point([10.9, 1.8, 2.1]);
4919 /// let point3 = inv.transform_point([10.5, 2.01, 1.7]);
4920 /// let point4 = inv.transform_point([9.5, 0.7, 1.5]);
4921 ///
4922 /// assert!(box_bounds.contains_point(point1), "point1 should be inside");
4923 /// assert!(!box_bounds.contains_point(point2), "point2 should be outside");
4924 /// assert!(!box_bounds.contains_point(point3), "point3 should be outside");
4925 /// assert!(box_bounds.contains_point(point4), "point4 should be inside");
4926 ///
4927 /// assert!(box_bounds.contains_point([0.5, 0.5, 0.5]),
4928 /// "inverse point should be inside");
4929 /// ```
4930 #[inline]
4931 pub fn contains_point(&self, pt: impl Into<Vec3>) -> bool {
4932 unsafe { bounds_point_contains(*self, pt.into()) != 0 }
4933 }
4934
4935 /// Does the Bounds contain or intersects with the given line?
4936 /// <https://stereokit.net/Pages/StereoKit/Bounds/Contains.html>
4937 /// * line_pt1 - The first point on the line.
4938 /// * line_pt2 - The second point on the line.
4939 ///
4940 /// see also [`bounds_line_contains`]
4941 /// ### Examples
4942 /// ```
4943 /// use stereokit_rust::maths::{Vec3, Bounds, Matrix};
4944 ///
4945 /// // A cube of 1 meter per side at this position, aligned with x y and z axis.
4946 /// let box_transform = Matrix::t([10.0, 1.0, 2.0]);
4947 /// let box_bounds = Bounds::bounds_centered([1.0,1.0,1.0]);
4948 ///
4949 /// let inv = box_transform.get_inverse();
4950 /// let point1 = inv.transform_point([10.2, 1.3, 2.4]);
4951 /// let point2 = inv.transform_point([10.9, 1.8, 2.1]);
4952 /// let point3 = inv.transform_point([10.5, 2.01, 1.7]);
4953 /// let point4 = inv.transform_point([9.5, 0.7, 1.5]);
4954 ///
4955 /// assert!(box_bounds.contains_line(point1, point2), "point1-point2 should be inside");
4956 /// assert!(!box_bounds.contains_line(point2, point3), "point2-point3 should be outside");
4957 /// assert!(box_bounds.contains_line(point3, point4), "point3-point4 should be inside");
4958 /// assert!(box_bounds.contains_line(point4, point1), "point4-point1 should be inside");
4959 ///
4960 /// assert!(box_bounds.contains_line([0.1, 0.1, 0.1], [0.9, 0.9, 0.9]),
4961 /// "inverse line should be inside");
4962 /// ```
4963 #[inline]
4964 pub fn contains_line<V3: Into<Vec3>>(&self, line_pt1: V3, line_pt2: V3) -> bool {
4965 unsafe { bounds_line_contains(*self, line_pt1.into(), line_pt2.into()) != 0 }
4966 }
4967
4968 /// Does the bounds contain or intersect with the given capsule?
4969 /// <https://stereokit.net/Pages/StereoKit/Bounds/Contains.html>
4970 /// * pt1 - The first point of the capsule.
4971 /// * pt2 - The second point of the capsule.
4972 /// * radius - The radius of the capsule.
4973 ///
4974 /// see also [`bounds_capsule_contains`]
4975 /// ### Examples
4976 /// ```
4977 /// use stereokit_rust::maths::{Vec3, Bounds, Matrix};
4978 ///
4979 /// // A cube of 1 meter per side at this position, aligned with x y and z axis.
4980 /// let box_transform = Matrix::t([10.0, 1.0, 2.0]);
4981 /// let box_bounds = Bounds::bounds_centered([1.0,1.0,1.0]);
4982 ///
4983 /// let inv = box_transform.get_inverse();
4984 /// let point1 = inv.transform_point([10.2, 1.3, 2.4]);
4985 /// let point2 = inv.transform_point([10.9, 1.8, 2.1]);
4986 /// let point3 = inv.transform_point([10.5, 2.01, 1.7]);
4987 /// let point4 = inv.transform_point([9.5, 0.7, 1.5]);
4988 ///
4989 /// assert!(box_bounds.contains_capsule(point1, point2, 0.1), "point1-point2 should be inside");
4990 /// assert!(!box_bounds.contains_capsule(point2, point3, 0.1), "point2-point3 * 0.1 should be outside");
4991 /// assert!(box_bounds.contains_capsule(point2, point3, 0.4), "point2-point3 * 0.4 should be inside");
4992 /// assert!(box_bounds.contains_capsule(point3, point4, 0.1), "point3-point4 should be inside");
4993 /// assert!(box_bounds.contains_capsule(point4, point1, 0.1), "point4-point1 should be inside");
4994 ///
4995 /// assert!(box_bounds.contains_capsule([0.1, 0.1, 0.1], [0.9, 0.9, 0.9], 10.0),
4996 /// "inverse line * 10 should be inside");
4997 /// ```
4998 #[inline]
4999 pub fn contains_capsule<V3: Into<Vec3>>(&self, line_pt1: V3, line_pt2: V3, radius: f32) -> bool {
5000 unsafe { bounds_capsule_contains(*self, line_pt1.into(), line_pt2.into(), radius) != 0 }
5001 }
5002
5003 /// Calculate the intersection between a Ray, and these bounds. Returns false if no intersection occurred, and ‘at’
5004 /// will contain the nearest intersection point to the start of the ray if an intersection is found!
5005 /// <https://stereokit.net/Pages/StereoKit/Bounds/Intersect.html>
5006 /// * ray - Any Ray in the same coordinate space as the Bounds
5007 ///
5008 /// Returns the closest intersection point to the origin of the ray or None if there isn't an instersection
5009 /// see also [`bounds_ray_intersect`] same as [`Ray::intersect_bounds`]
5010 /// ### Examples
5011 /// ```
5012 /// use stereokit_rust::maths::{Vec3, Bounds, Matrix, Ray};
5013 ///
5014 /// // A cube of 1 meter per side at this position, aligned with x y and z axis.
5015 /// let box_transform = Matrix::t([10.0, 1.0, 2.0]);
5016 /// let box_bounds = Bounds::bounds_centered([1.0,1.0,1.0]);
5017 ///
5018 /// let inv = box_transform.get_inverse();
5019 /// let ray1 = inv.transform_ray(Ray::new([10.2, 1.3, 2.4],[0.0, 1.0, 0.0]));
5020 /// let ray2 = inv.transform_ray(Ray::new([10.9, 1.8, 2.6],[0.0, 0.0, 1.0]));
5021 /// let ray3 = inv.transform_ray(Ray::new([10.5, 2.0, 2.7],[1.0, 0.0, 1.0]));
5022 ///
5023 /// assert!(box_bounds.intersect(ray1).is_some(), "should be a point of contact");
5024 /// assert_eq!(box_bounds.intersect(ray2), None);
5025 /// assert_eq!(box_bounds.intersect(ray3), None);
5026 /// assert_eq!(box_bounds.intersect(Ray::new([1.1, 1.1, 1.1], [-1.9, -1.9, -1.9])),
5027 /// Some([0.5, 0.5, 0.5].into()));
5028 ///
5029 /// // We want the contact point for ray1
5030 /// let contact_point = box_bounds.intersect(ray1)
5031 /// .expect ("There should be a point of contact");
5032 ///
5033 /// let contact_point = box_transform.transform_point(contact_point);
5034 /// assert_eq!(contact_point, [10.2, 1.3, 2.4 ].into());
5035 /// ```
5036 #[inline]
5037 pub fn intersect<R: Into<Ray>>(&self, ray: R) -> Option<Vec3> {
5038 let mut pt = Vec3::default();
5039 let ray = ray.into();
5040 match unsafe { bounds_ray_intersect(*self, ray, &mut pt) != 0 } {
5041 true => Some(pt),
5042 false => None,
5043 }
5044 }
5045
5046 /// Scale the bounds. It will scale the center as well as the dimensions! Returns a new Bounds.
5047 /// equivalent to using multiply operator
5048 /// <https://stereokit.net/Pages/StereoKit/Bounds/Scaled.html>
5049 /// * scale - The scale to apply.
5050 ///
5051 /// see also [Bounds::scale] [Bounds::scaled_vec] [Bounds::scale_vec] and '/' '*' operator
5052 /// ### Examples
5053 /// ```
5054 /// use stereokit_rust::maths::{Vec3, Bounds};
5055 ///
5056 /// let mut bounds = Bounds::from_corners( Vec3::ZERO, Vec3::ONE);
5057 /// let bounds_scaled = bounds.scaled(2.0);
5058 /// let bounds_plus = Bounds::from_corners( Vec3::ZERO, Vec3::ONE) * 2.0;
5059 ///
5060 /// assert_eq!(*bounds.scale(2.0), bounds_scaled);
5061 /// assert_eq!(bounds_scaled.center, bounds_plus.center);
5062 /// assert_eq!(bounds_scaled.dimensions, bounds_plus.dimensions);
5063 /// ```
5064 #[inline]
5065 pub fn scaled(&self, scale: f32) -> Self {
5066 *self * scale
5067 }
5068
5069 /// Scale the bounds. It will scale the center as well as the dimensions! Returns a new Bounds.
5070 /// equivalent to using multiply operator
5071 /// <https://stereokit.net/Pages/StereoKit/Bounds/Scaled.html>
5072 /// * scale - The scale to apply.
5073 ///
5074 /// see also [Bounds::scale_vec] [Bounds::scale] [Bounds::scaled] and '/' '*' operator
5075 /// ### Examples
5076 /// ```
5077 /// use stereokit_rust::maths::{Vec3, Bounds};
5078 ///
5079 /// let bounds = Bounds::from_corners( Vec3::ZERO, Vec3::ONE);
5080 /// let bounds_scaled = bounds.scaled_vec([1.0, 2.0, 3.0]);
5081 /// let bounds_plus = Bounds::from_corners( Vec3::ZERO, Vec3::ONE) * Vec3::new(1.0, 2.0, 3.0);
5082 ///
5083 /// assert_eq!(bounds * Vec3::new(1.0, 2.0, 3.0), bounds_scaled);
5084 /// assert_eq!(bounds_scaled.center, bounds_plus.center);
5085 /// assert_eq!(bounds_scaled.dimensions, bounds_plus.dimensions);
5086 /// ```
5087 #[inline]
5088 pub fn scaled_vec(&self, scale: impl Into<Vec3>) -> Self {
5089 *self * scale.into()
5090 }
5091
5092 /// This returns a Bounds that encapsulates the transformed points of the current Bounds’s corners.
5093 /// Note that this will likely introduce a lot of extra empty volume in many cases, as the result is still always axis aligned.
5094 /// <https://stereokit.net/Pages/StereoKit/Bounds/Transformed.html>
5095 /// * transform - A transform Matrix for the current Bounds’s corners.
5096 ///
5097 /// see also [`bounds_transform]
5098 /// ### Examples
5099 ///```
5100 /// use stereokit_rust::maths::{Vec3, Bounds, Matrix};
5101 ///
5102 /// let matrix = Matrix::r([90.0, 90.0, 90.0]);
5103 /// let bounds = Bounds::bounds_centered([1.0, 1.0, 1.0]);
5104 /// let bounds_transformed = bounds.transformed(matrix);
5105 ///
5106 /// assert_eq!(bounds_transformed.dimensions, Vec3{x: 1.0000001, y: 0.99999994, z: 0.99999994});
5107 /// assert_eq!(bounds_transformed.center, Vec3{x:0.0, y:0.0, z:0.0})
5108 ///```
5109 #[inline]
5110 pub fn transformed(&self, transform: impl Into<Matrix>) -> Self {
5111 unsafe { bounds_transform(*self, transform.into()) }
5112 }
5113
5114 /// From the front, this is the Top (Y+), Left (X+), Center
5115 /// (Z0) of the bounds. Useful when working with UI layout bounds.
5116 /// <https://stereokit.net/Pages/StereoKit/Bounds/TLC.html>
5117 ///
5118 /// see also [Bounds::tlb]
5119 /// ### Examples
5120 ///```
5121 /// use stereokit_rust::maths::{Vec3, Bounds};
5122 ///
5123 /// let bounds = Bounds::bounds_centered([1.0, 1.0, 1.0]);
5124 ///
5125 /// assert_eq!(bounds.tlc(), Vec3{x:0.5, y:0.5, z: 0.0});
5126 ///```
5127 #[inline]
5128 pub fn tlc(&self) -> Vec3 {
5129 self.center + self.dimensions.xy0() / 2.0
5130 }
5131
5132 /// From the front, this is the Top (Y+), Left (X+), Back (Z+)
5133 /// of the bounds. Useful when working with UI layout bounds.
5134 /// <https://stereokit.net/Pages/StereoKit/Bounds/TLB.html>
5135 ///
5136 /// see also [Bounds::tlb]
5137 /// ### Examples
5138 ///```
5139 /// use stereokit_rust::maths::{Vec3, Bounds};
5140 ///
5141 /// let bounds = Bounds::bounds_centered([1.0, 1.0, 1.0]);
5142 ///
5143 /// assert_eq!(bounds.tlb(), Vec3{x:0.5, y:0.5, z: 0.5});
5144 ///```
5145 #[inline]
5146 pub fn tlb(&self) -> Vec3 {
5147 self.center + self.dimensions / 2.0
5148 }
5149}
5150
5151impl Display for Bounds {
5152 /// Creates a text description of the Bounds, in the format of “[center:X dimensions:X]”
5153 /// <https://stereokit.net/Pages/StereoKit/Bounds/ToString.html>
5154 ///
5155 /// ### Examples
5156 /// ```
5157 /// use stereokit_rust::maths::{Vec3, Bounds};
5158 ///
5159 /// let bounds = Bounds::new([1.1, 2.0, 3.0], [4.0, 5.0, 6.0]);
5160 /// assert_eq!(format!("{}", bounds),
5161 /// "[center:[x:1.1, y:2, z:3] dimensions:[x:4, y:5, z:6]]");
5162 /// ```
5163 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5164 write!(f, "[center:{} dimensions:{}]", self.center, self.dimensions)
5165 }
5166}
5167/// This operator will create a new Bounds that has been properly scaled up by the float. This does affect the center
5168/// position of the Bounds.
5169/// <https://stereokit.net/Pages/StereoKit/Bounds/op_Multiply.html>
5170impl Mul<f32> for Bounds {
5171 type Output = Bounds;
5172
5173 /// ### Examples
5174 /// ```
5175 /// use stereokit_rust::maths::{Vec3, Bounds};
5176 ///
5177 /// let bounds = Bounds::from_corners( Vec3::ZERO, Vec3::ONE);
5178 ///
5179 /// let bounds_scaled = bounds * 2.0;
5180 /// assert_eq!(bounds_scaled.center, Vec3::ONE);
5181 /// assert_eq!(bounds_scaled.dimensions, Vec3::new(2.0, 2.0, 2.0));
5182 /// ```
5183 fn mul(self, rhs: f32) -> Self::Output {
5184 Bounds { center: self.center * rhs, dimensions: self.dimensions * rhs }
5185 }
5186}
5187
5188/// This operator will create a new Bounds that has been properly scaled up by the float. This does affect the center
5189/// position of the Bounds.
5190/// <https://stereokit.net/Pages/StereoKit/Bounds/op_Multiply.html>
5191impl MulAssign<f32> for Bounds {
5192 /// ### Examples
5193 /// ```
5194 /// use stereokit_rust::maths::{Vec3, Bounds};
5195 ///
5196 /// let mut bounds = Bounds::from_corners( Vec3::ZERO, Vec3::ONE);
5197 ///
5198 /// bounds *= 2.0;
5199 /// assert_eq!(bounds.center, Vec3::ONE);
5200 /// assert_eq!(bounds.dimensions, Vec3::new(2.0, 2.0, 2.0));
5201 /// ```
5202 fn mul_assign(&mut self, rhs: f32) {
5203 self.center.mul_assign(rhs);
5204 self.dimensions.mul_assign(rhs);
5205 }
5206}
5207
5208/// This operator will create a new Bounds that has been properly scaled up by the float. This does affect the center
5209/// position of the Bounds.
5210/// <https://stereokit.net/Pages/StereoKit/Bounds/op_Multiply.html>
5211impl Mul<Bounds> for f32 {
5212 type Output = Bounds;
5213
5214 /// ### Examples
5215 /// ```
5216 /// use stereokit_rust::maths::{Vec3, Bounds};
5217 ///
5218 /// let bounds = Bounds::from_corners( Vec3::ZERO, Vec3::ONE);
5219 ///
5220 /// let bounds_scaled = 2.0 * bounds;
5221 /// assert_eq!(bounds_scaled.center, Vec3::ONE);
5222 /// assert_eq!(bounds_scaled.dimensions, Vec3::new(2.0, 2.0, 2.0));
5223 /// ```
5224 fn mul(self, rhs: Bounds) -> Self::Output {
5225 Bounds { center: rhs.center * self, dimensions: rhs.dimensions * self }
5226 }
5227}
5228
5229/// This operator will create a new Bounds that has been properly scaled up by the Vec3. This does affect the center
5230/// position of the Bounds.
5231/// <https://stereokit.net/Pages/StereoKit/Bounds/op_Multiply.html>
5232impl Mul<Vec3> for Bounds {
5233 type Output = Bounds;
5234
5235 /// ### Examples
5236 /// ```
5237 /// use stereokit_rust::maths::{Vec3, Bounds};
5238 ///
5239 /// let bounds = Bounds::from_corners( Vec3::ZERO, Vec3::ONE);
5240 ///
5241 /// let bounds_scaled = bounds * Vec3::new(1.0, 2.0, 3.0);
5242 /// assert_eq!(bounds_scaled.center, Vec3::new(0.5, 1.0, 1.5));
5243 /// assert_eq!(bounds_scaled.dimensions, Vec3::new(1.0, 2.0, 3.0));
5244 /// ```
5245 fn mul(self, rhs: Vec3) -> Self::Output {
5246 Bounds { center: self.center * rhs, dimensions: self.dimensions * rhs }
5247 }
5248}
5249
5250/// This operator will create a new Bounds that has been properly scaled up by the Vec3. This does affect the center
5251/// position of the Bounds.
5252/// <https://stereokit.net/Pages/StereoKit/Bounds/op_Multiply.html>
5253impl MulAssign<Vec3> for Bounds {
5254 /// ### Examples
5255 /// ```
5256 /// use stereokit_rust::maths::{Vec3, Bounds};
5257 ///
5258 /// let mut bounds = Bounds::from_corners( Vec3::ZERO, Vec3::ONE);
5259 ///
5260 /// bounds *= Vec3::new(1.0, 2.0, 3.0);
5261 /// assert_eq!(bounds.center, Vec3::new(0.5, 1.0, 1.5));
5262 /// assert_eq!(bounds.dimensions, Vec3::new(1.0, 2.0, 3.0));
5263 /// ```
5264 fn mul_assign(&mut self, rhs: Vec3) {
5265 self.center.mul_assign(rhs);
5266 self.dimensions.mul_assign(rhs);
5267 }
5268}
5269
5270/// Planes are really useful for collisions, intersections, and visibility testing!
5271///
5272/// This plane is stored using the ax + by + cz + d = 0 formula, where the normal is a,b,c, and the d is, well, d.
5273/// <https://stereokit.net/Pages/StereoKit/Plane.html>
5274/// ### Examples
5275/// ```
5276/// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
5277/// use stereokit_rust::{maths::{Vec3, Matrix, Plane},
5278/// mesh::Mesh, material::Material, util::named_colors};
5279///
5280/// let plane_mesh = Mesh::generate_plane_up([1.0,1.0], None, true);
5281/// let mut material_plane = Material::pbr();
5282///
5283/// let transform_wall = Matrix::t_r([-0.5, 0.0, 0.0],
5284/// [0.0, 0.0, 90.0]);
5285/// let transform_floor = Matrix::t([0.0, -0.5, 0.0]);
5286///
5287/// let wall = Plane::new (Vec3::X, 0.5);
5288/// let wall_b = Plane::from_point( [-0.5, -1.1, -1.1].into(), Vec3::X);
5289/// let wall_c = Plane::from_points([-0.5, -2.2, -2.2],
5290/// [-0.5, -3.3, -3.3],
5291/// [-0.5, -4.4, -14.4]);
5292///
5293/// assert_eq!(wall.closest(Vec3::Y), Vec3 {x:-0.5, y:1.0, z:0.0});
5294/// assert_eq!(wall_b.closest(Vec3::Y), Vec3 {x:-0.5, y:1.0, z:0.0});
5295/// assert_eq!(wall_c.closest(Vec3::Y), Vec3 {x:-0.5, y:1.0, z:0.0});
5296/// assert_eq!(wall, wall_b);
5297/// //assert_eq!(wall, wall_c); // differents but the same
5298///
5299/// filename_scr = "screenshots/plane.jpeg";
5300/// test_screenshot!( // !!!! Get a proper main loop !!!!
5301/// plane_mesh.draw(token, &material_plane, transform_wall, Some(named_colors::CYAN.into()), None);
5302/// plane_mesh.draw(token, &material_plane, transform_floor, Some(named_colors::BLACK.into()), None);
5303/// );
5304/// ```
5305/// <img src="https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/plane.jpeg" alt="screenshot" width="200">
5306#[derive(Copy, Clone, Debug, Default)]
5307#[repr(C)]
5308pub struct Plane {
5309 /// The direction the plane is facing.
5310 pub normal: Vec3,
5311 /// The distance/travel along the plane's normal from
5312 /// the origin to the surface of the plane.
5313 pub d: f32,
5314}
5315
5316/// AsRef
5317impl AsRef<Plane> for Plane {
5318 fn as_ref(&self) -> &Plane {
5319 self
5320 }
5321}
5322
5323/// Warning: Equality with a precision of 0.1 millimeter
5324impl PartialEq for Plane {
5325 /// Warning: Equality with a precision of 0.1 millimeter
5326 fn eq(&self, other: &Self) -> bool {
5327 self.normal == other.normal && self.d - other.d < 0.0001
5328 }
5329}
5330
5331unsafe extern "C" {
5332 pub fn plane_from_points(p1: Vec3, p2: Vec3, p3: Vec3) -> Plane;
5333 pub fn plane_from_ray(ray: Ray) -> Plane;
5334 pub fn plane_ray_intersect(plane: Plane, ray: Ray, out_pt: *mut Vec3) -> Bool32T;
5335 pub fn plane_line_intersect(plane: Plane, p1: Vec3, p2: Vec3, out_pt: *mut Vec3) -> Bool32T;
5336 pub fn plane_point_closest(plane: Plane, pt: Vec3) -> Vec3;
5337}
5338
5339impl Plane {
5340 /// Creates a Plane directly from the ax + by + cz + d = 0 formula!
5341 /// <https://stereokit.net/Pages/StereoKit/Plane/Plane.html>
5342 pub fn new<V: Into<Vec3>>(normal: V, d: f32) -> Plane {
5343 Plane { normal: normal.into(), d }
5344 }
5345
5346 /// Creates a plane from a normal, and any point on the plane!
5347 /// <https://stereokit.net/Pages/StereoKit/Plane/Plane.html>
5348 ///
5349 /// ## Examples
5350 /// ```
5351 /// use stereokit_rust::maths::{Plane,Vec3};
5352 /// let wall_x = Plane::from_point(Vec3::X*4.0, Vec3::X);
5353 /// assert_eq!(wall_x.d , -4.0);
5354 /// ````
5355 #[inline]
5356 pub fn from_point<V: Into<Vec3>>(point_on_plane: V, plane_normal: V) -> Plane {
5357 let p_o_p = point_on_plane.into();
5358 let normal = plane_normal.into();
5359 // let plane0 = Plane { normal, d: 0.0 };
5360 // let p0 = plane0.closest(p_o_p);
5361 //Plane { normal, d: Vec3::distance(p0, p_o_p) }
5362 Plane { normal, d: -Vec3::dot(p_o_p, normal) }
5363 }
5364
5365 /// Creates a plane from 3 points that are directly on that plane.
5366 /// Unstable as some normal with NaN values may be created if the points are aligned.
5367 ///
5368 /// <https://stereokit.net/Pages/StereoKit/Plane/Plane.html>
5369 ///
5370 /// ## Examples
5371 /// ```
5372 /// use stereokit_rust::maths::{Plane,Vec3};
5373 /// let ground = Plane::from_points([1.0, 1.5, 0.0],
5374 /// [0.0, 1.5, 1.0],
5375 /// [1.0, 1.5, 1.0]);
5376 /// assert_eq!(ground.d , 1.5);
5377 /// assert!(ground.normal.y + 1.0 < 0.0001);
5378 ///
5379 /// let wall_c = Plane::from_points([-0.5, -0.4, -1.0],
5380 /// [-0.5, 0.0, 3.0],
5381 /// [-0.5, 0.3, -4.0]);
5382 /// println! ("{:?}", wall_c);
5383 /// assert_eq!(wall_c.d , 0.5);
5384 /// assert!(wall_c.normal.x - 1.0 < 0.0001);
5385 /// ```
5386 #[deprecated(since = "0.4.0", note = "Unstable! use `Plane::from_point` or `Plane::new` instead")]
5387 #[inline]
5388 pub fn from_points<V: Into<Vec3>>(point_on_plane1: V, point_on_plane2: V, point_on_plane3: V) -> Plane {
5389 let p1 = point_on_plane1.into();
5390 let p2 = point_on_plane2.into();
5391 let p3 = point_on_plane3.into();
5392 let dir1 = p2 - p1;
5393 let dir2 = p2 - p3;
5394 let mut normal = Vec3::cross(dir1, dir2).get_normalized();
5395 if normal.z.is_nan() {
5396 let dir1 = p1 - p3;
5397 let dir2 = p1 - p2;
5398 normal = Vec3::cross(dir1, dir2).get_normalized();
5399 if normal.z.is_nan() {
5400 let dir1 = p3 - p1;
5401 let dir2 = p3 - p2;
5402 normal = Vec3::cross(dir1, dir2).get_normalized();
5403 }
5404 }
5405
5406 //let plane0 = Plane { normal, d: 0.0 };
5407 //let p0 = plane0.closest(p2);
5408 //Plane { normal, d: Vec3::distance(p0, p2) }
5409 Plane { normal, d: -Vec3::dot(p2, normal) }
5410
5411 // Do not save the problem : unsafe{plane_from_points(p1, p2, p3)}
5412 }
5413
5414 /// Finds the closest point on this plane to the given point!
5415 /// <https://stereokit.net/Pages/StereoKit/Plane/Closest.html>
5416 ///
5417 /// see also [`plane_point_closest`]
5418 /// ## Examples
5419 /// ```
5420 /// use stereokit_rust::maths::{Plane,Vec3};
5421 /// let plane = Plane{normal : Vec3::X , d: -4.0};
5422 /// let closest = plane.closest(Vec3::ZERO);
5423 /// assert_eq!(closest , (Vec3::X * 4.0));
5424 /// let plane = Plane::from_points(Vec3::X , Vec3::Z, Vec3::Y );
5425 /// assert_eq!(plane, Plane{normal : Vec3::ONE / (3.0_f32.sqrt()), d:-1.0/3.0_f32.sqrt()} );
5426 /// let closest = plane.closest(Vec3::ZERO);
5427 /// assert_eq!(closest , Vec3::new(0.3333333,0.3333333,0.3333333));
5428 /// ```
5429 #[inline]
5430 pub fn closest<V: Into<Vec3>>(&self, to: V) -> Vec3 {
5431 unsafe { plane_point_closest(*self, to.into()) }
5432 }
5433
5434 /// Checks the intersection of a ray with this plane!
5435 /// <https://stereokit.net/Pages/StereoKit/Plane/Intersect.html>
5436 /// * ray - The ray we're checking with.
5437 ///
5438 /// Returns the intersection point or None if there isn't an instersection
5439 /// see also [`plane_ray_intersect`] same as [`Ray::intersect_plane`]
5440 #[inline]
5441 pub fn intersect(&self, ray: Ray) -> Option<Vec3> {
5442 let mut pt = Vec3::default();
5443 match unsafe { plane_ray_intersect(*self, ray, &mut pt) != 0 } {
5444 true => Some(pt),
5445 false => None,
5446 }
5447 }
5448
5449 /// Checks the intersection of a line with this plane!
5450 /// <https://stereokit.net/Pages/StereoKit/Plane/Intersect.html>
5451 /// * line_start - Start of the line.
5452 /// * line_end - End of the line.
5453 ///
5454 /// Returns the intersection point or None if there isn't an instersection
5455 /// see also [`plane_line_intersect`]
5456 #[inline]
5457 pub fn intersect_line<V: Into<Vec3>>(&self, line_start: V, line_end: V) -> Option<Vec3> {
5458 let mut pt = Vec3::default();
5459 match unsafe { plane_line_intersect(*self, line_start.into(), line_end.into(), &mut pt) != 0 } {
5460 true => Some(pt),
5461 false => None,
5462 }
5463 }
5464}
5465
5466impl Display for Plane {
5467 /// Creates a text description of the Plane, in the format of “[normal:X distance:X]”
5468 /// ### Examples
5469 /// ```
5470 /// use stereokit_rust::maths::{Vec3, Plane};
5471 ///
5472 /// let plane = Plane::new([1.1, 2.0, 3.0], 4.0);
5473 /// assert_eq!(format!("{}", plane),
5474 /// "[normal:[x:1.1, y:2, z:3] distance:4]");
5475 /// ```
5476 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5477 write!(f, "[normal:{} distance:{}]", self.normal, self.d)
5478 }
5479}
5480
5481/// Pose represents a location and orientation in space, excluding scale! The default value of a Pose use
5482/// Pose.Identity .
5483/// <https://stereokit.net/Pages/StereoKit/Pose.html>
5484///
5485/// ### Examples
5486/// ```
5487/// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
5488/// use stereokit_rust::{ui::Ui, maths::{Vec3, Pose, Matrix}, model::Model };
5489///
5490/// let plane = Model::from_file("plane.glb", None).unwrap_or_default();
5491/// let bounds = plane.get_bounds();
5492/// let mut handle_pose = Pose::look_at(
5493/// [0.0, -5.5, -10.0], (Vec3::Z + Vec3::X) * 100.0);
5494///
5495/// let mut window_pose = Pose::new(
5496/// [0.0, 0.05, 0.90], Some([0.0, 200.0, 0.0].into()));
5497///
5498/// filename_scr = "screenshots/pose.jpeg";
5499/// test_screenshot!( // !!!! Get a proper main loop !!!!
5500/// Ui::handle_begin( "Model Handle", &mut handle_pose,
5501/// bounds, false, None, None);
5502/// plane.draw(token, Matrix::IDENTITY, None, None);
5503/// Ui::handle_end();
5504///
5505/// Ui::window_begin("My Window", &mut window_pose, None, None, None);
5506/// Ui::text("My Text", None, None, None, Some(0.14), None, None);
5507/// Ui::window_end();
5508/// );
5509/// ```
5510///
5511/// <img src="https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/pose.jpeg" alt="screenshot" width="200">
5512#[repr(C)]
5513#[derive(Debug, Copy, Clone, PartialEq)]
5514pub struct Pose {
5515 pub position: Vec3,
5516 pub orientation: Quat,
5517}
5518
5519impl From<Matrix> for Pose {
5520 fn from(matrix: Matrix) -> Self {
5521 matrix.get_pose()
5522 }
5523}
5524
5525impl Default for Pose {
5526 /// Position is Vec3::ZERO, and orientation is Quat::IDENTITY (no rotation)
5527 /// <https://stereokit.net/Pages/StereoKit/Pose/Identity.html>
5528 fn default() -> Self {
5529 Pose::IDENTITY
5530 }
5531}
5532
5533impl Pose {
5534 /// The default Pose: Origin with Quat::IDENTITY orientation.
5535 /// <https://stereokit.net/Pages/StereoKit/Pose/Identity.html>
5536 pub const IDENTITY: Pose = Pose { position: Vec3::new(0.0, 0.0, 0.0), orientation: Quat::IDENTITY };
5537
5538 /// Zero may be encountered when testing some [`crate::system::Input`] [`crate::system::Pointer`] and [`crate::system::Controller`]
5539 pub const ZERO: Pose = Pose { position: Vec3::new(0.0, 0.0, 0.0), orientation: Quat::ZERO };
5540
5541 /// Basic initialization constructor! Just copies in the provided values directly, and uses Identity for the
5542 /// orientation.
5543 /// <https://stereokit.net/Pages/StereoKit/Pose/Pose.html>
5544 ///
5545 /// ### Examples
5546 /// ```
5547 /// use stereokit_rust::maths::{Vec3, Pose};
5548 /// let mut handle_pose = Pose::new( [0.0, 0.05, 0.90], None);
5549 ///
5550 /// let mut window_pose = Pose::new(
5551 /// [0.0, 0.05, 0.90], Some([0.0, 180.0 * 4.0, 0.0].into()));
5552 ///
5553 /// assert_eq!(handle_pose, window_pose);
5554 #[inline]
5555 pub fn new(position: impl Into<Vec3>, orientation: Option<Quat>) -> Self {
5556 let orientation = orientation.unwrap_or(Quat::IDENTITY);
5557 Self { position: position.into(), orientation }
5558 }
5559
5560 /// Interpolates between two poses! It is unclamped, so values outside of (0,1) will extrapolate their position.
5561 /// <https://stereokit.net/Pages/StereoKit/Pose/Lerp.html>
5562 ///
5563 /// ### Examples
5564 /// ```
5565 /// use stereokit_rust::maths::{Vec3, Pose};
5566 ///
5567 /// let mut pose1 = Pose::new( Vec3::Y, None);
5568 /// let mut pose2 = Pose::new( Vec3::Y, Some([0.0, 45.0, 0.0].into()));
5569 /// let mut pose3 = Pose::new( Vec3::Y, Some([0.0, 90.0, 0.0].into()));
5570 ///
5571 /// assert_eq!(Pose::lerp(pose1, pose3, 0.5), pose2);
5572 #[inline]
5573 pub fn lerp(a: impl Into<Pose>, b: impl Into<Pose>, percent: f32) -> Self {
5574 let a = a.into();
5575 let b = b.into();
5576 Self {
5577 position: Vec3::lerp(a.position, b.position, percent),
5578 orientation: Quat::slerp(a.orientation, b.orientation, percent),
5579 }
5580 }
5581
5582 /// Creates a Pose that looks from one location in the direction of another location. This leaves “Up” as the +Y
5583 /// axis.
5584 /// <https://stereokit.net/Pages/StereoKit/Pose/LookAt.html>
5585 ///
5586 /// ### Examples
5587 /// ```
5588 /// use stereokit_rust::maths::{Vec3, Pose};
5589 ///
5590 /// let mut pose1 = Pose::look_at(Vec3::ZERO, Vec3::NEG_Z );
5591 /// assert_eq!(pose1, Pose::default());
5592 #[inline]
5593 pub fn look_at(from: impl Into<Vec3>, at: impl Into<Vec3>) -> Self {
5594 let from = from.into();
5595 let at = at.into();
5596 Self { position: from, orientation: Quat::look_at(from, at, None) }
5597 }
5598
5599 /// Converts this pose into a transform matrix.
5600 /// <https://stereokit.net/Pages/StereoKit/Pose/ToMatrix.html>
5601 /// * scale - Let you add a scale factor if needed.
5602 ///
5603 /// ### Examples
5604 /// ```
5605 /// use stereokit_rust::maths::{Vec3, Matrix, Pose};
5606 ///
5607 /// let pose1 = Pose::IDENTITY;
5608 ///
5609 /// assert_eq!(pose1.to_matrix(None), Matrix::IDENTITY);
5610 #[inline]
5611 pub fn to_matrix(&self, scale: Option<Vec3>) -> Matrix {
5612 match scale {
5613 Some(scale) => Matrix::t_r_s(self.position, self.orientation, scale),
5614 None => Matrix::t_r(self.position, self.orientation),
5615 }
5616 }
5617
5618 /// Converts this pose into the inverse of the Pose's transform matrix. This can be used to
5619 /// transform points from the space represented by the Pose into world space.
5620 /// <https://stereokit.net/Pages/StereoKit/Pose/ToMatrixInv.html>
5621 /// * scale - A scale vector! Vec3.One would be an identity scale.
5622 ///
5623 /// ### Examples
5624 /// ```
5625 /// use stereokit_rust::maths::{Vec3, Matrix, Pose};
5626 ///
5627 /// let pose1 = Pose::IDENTITY;
5628 ///
5629 /// assert_eq!(pose1.to_matrix_inv(None), Matrix::IDENTITY);
5630 ///
5631 /// assert_eq!(pose1.to_matrix_inv(Some(Vec3::new(0.5, 0.25, 0.125))),
5632 /// [2.0, 0.0, 0.0, 0.0,
5633 /// 0.0, 4.0, 0.0, 0.0,
5634 /// 0.0, 0.0, 8.0, 0.0,
5635 /// 0.0, 0.0, 0.0, 1.0].into());
5636 /// ```
5637 #[inline]
5638 pub fn to_matrix_inv(&self, scale: Option<Vec3>) -> Matrix {
5639 let inv_orientation = self.orientation.conjugate();
5640
5641 match scale {
5642 Some(scale) => {
5643 let inv_scale = 1.0 / scale;
5644
5645 let inv_transform = inv_orientation.rotate_point(-self.position * inv_scale);
5646
5647 Matrix::t_r_s(inv_transform, inv_orientation, inv_scale)
5648 }
5649 None => {
5650 let inv_transform = inv_orientation.rotate_point(-self.position);
5651 Matrix::t_r(inv_transform, inv_orientation)
5652 }
5653 }
5654 }
5655
5656 /// Calculates the forward direction from this pose. This is done by multiplying the orientation with
5657 /// Vec3::new(0, 0, -1). Remember that Forward points down the -Z axis!
5658 /// <https://stereokit.net/Pages/StereoKit/Pose/Forward.html>
5659 ///
5660 /// ### Examples
5661 /// ```
5662 /// use stereokit_rust::maths::{Vec3, Pose};
5663 ///
5664 /// let pose1 = Pose::default();
5665 /// assert_eq!(pose1.get_forward(), Vec3::NEG_Z);
5666 ///
5667 /// let pose2 = Pose::look_at(Vec3::new(1.0, 0.0, 0.0), Vec3::new(0.0, 0.0, 0.0));
5668 /// assert_eq!(pose2.get_forward(), Vec3::NEG_X);
5669 #[inline]
5670 pub fn get_forward(&self) -> Vec3 {
5671 self.orientation.mul_vec3(Vec3::FORWARD)
5672 }
5673
5674 /// This creates a ray starting at the Pose’s position, and pointing in the ‘Forward’ direction. The Ray
5675 /// direction is a unit vector/normalized.
5676 /// <https://stereokit.net/Pages/StereoKit/Pose/Ray.html>
5677 ///
5678 /// see also [`Ray`]
5679 /// ### Examples
5680 /// ```
5681 /// use stereokit_rust::maths::{Vec3, Pose, Ray};
5682 ///
5683 /// let pose1 = Pose::default();
5684 /// let ray_forward = Ray::new( Vec3::ZERO, Vec3::NEG_Z);
5685 /// assert_eq!(pose1.get_ray(), ray_forward);
5686 ///
5687 /// let pose2 = Pose::look_at(Vec3::new(1.0, 0.0, 0.0), Vec3::new(1.0, 2.0, 0.0));
5688 /// let ray_to_the_left = Ray::new(Vec3::X, Vec3::Y);
5689 /// assert_eq!(pose2.get_ray(), ray_to_the_left);
5690 #[inline]
5691 pub fn get_ray(&self) -> Ray {
5692 Ray { position: self.position, direction: self.orientation.mul_vec3(Vec3::FORWARD) }
5693 }
5694
5695 /// Calculates the right (+X) direction from this pose. This is done by multiplying the orientation with Vec3.Right.
5696 /// <https://stereokit.net/Pages/StereoKit/Pose/Right.html>
5697 ///
5698 /// ### Examples
5699 /// ```
5700 /// use stereokit_rust::maths::{Vec3, Pose, Ray};
5701 ///
5702 /// let pose1 = Pose::default();
5703 /// assert_eq!(pose1.get_right(), Vec3::X);
5704 ///
5705 /// let pose2 = Pose::look_at(Vec3::new(1.0, 0.0, 0.0), Vec3::new(1.0, 2.0, 3.0));
5706 /// assert_eq!(pose2.get_right(), Vec3::NEG_X);
5707 /// ```
5708 #[inline]
5709 pub fn get_right(&self) -> Vec3 {
5710 self.orientation.mul_vec3(Vec3::RIGHT)
5711 }
5712
5713 /// Calculates the up (+Y) direction from this pose. This is done by multiplying the orientation with Vec3.Up.
5714 /// <https://stereokit.net/Pages/StereoKit/Pose/Up.html>
5715 ///
5716 /// ### Examples
5717 /// ```
5718 /// use stereokit_rust::maths::{Vec3, Pose, Ray};
5719 ///
5720 /// let pose1 = Pose::default();
5721 /// assert_eq!(pose1.get_up(), Vec3::Y);
5722 ///
5723 /// let pose2 = Pose::look_at(Vec3::new(1.0, 0.0, 0.0), Vec3::new(2.0, 0.0, 3.0));
5724 /// assert_eq!(pose2.get_up(), Vec3::Y);
5725 /// ```
5726 #[inline]
5727 pub fn get_up(&self) -> Vec3 {
5728 self.orientation.mul_vec3(Vec3::UP)
5729 }
5730}
5731
5732impl Display for Pose {
5733 /// A string representation of the Pose, in the format of “position, Forward”. Mostly for debug visualization.
5734 /// <https://stereokit.net/Pages/StereoKit/Pose/ToString.html>
5735 /// ### Examples
5736 /// ```
5737 /// use stereokit_rust::maths::{Vec3, Pose};
5738 ///
5739 /// let pose = Pose::new([1.1, 2.0, 3.0], Some([0.0, 90.0, 0.0].into()));
5740 /// assert_eq!(format!("{}", pose),
5741 /// "[position:[x:1.1, y:2, z:3] forward:[x:0, y:0.70710677, z:0, w:0.7071067]]");
5742 /// ```
5743 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5744 write!(f, "[position:{} forward:{}]", self.position, self.orientation)
5745 }
5746}
5747
5748/// Represents a sphere in 3D space! Composed of a center point and a radius, can be used for raycasting, collision,
5749/// visibility, and other things!
5750/// <https://stereokit.net/Pages/StereoKit/Sphere.html>
5751///
5752/// ### Examples
5753/// ```
5754/// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
5755/// use stereokit_rust::{maths::{Vec3, Matrix, Sphere, Ray}, system::Lines,
5756/// mesh::Mesh, material::Material, util::named_colors};
5757///
5758/// let sphere = Sphere::new(Vec3::ZERO, 0.5);
5759/// let sphere_mesh = Mesh::generate_sphere(sphere.radius * 2.0, Some(12));
5760/// let mut material_sphere = Material::pbr().copy();
5761/// material_sphere.color_tint(named_colors::GOLD)
5762/// .border_size(0.05);
5763///
5764/// let scale = 0.1;
5765/// let transform = Matrix::t(sphere.center);
5766/// let ray_x = Ray::new(Vec3::X, Vec3::NEG_X);
5767/// let ray_y = Ray::new(Vec3::Y, Vec3::NEG_Y);
5768/// let contact_x = sphere.intersect(ray_x).expect("X Should be there");
5769/// let contact_y = sphere.intersect(ray_y).expect("Y Should be there");
5770///
5771/// assert_eq!(contact_x, Vec3::X * sphere.radius);
5772/// assert_eq!(contact_y, Vec3::Y * sphere.radius);
5773///
5774/// filename_scr = "screenshots/sphere.jpeg";
5775/// test_screenshot!( // !!!! Get a proper main loop !!!!
5776/// sphere_mesh.draw(token, &material_sphere, transform, None, None);
5777/// Lines::add_ray(token, ray_x, 0.30, named_colors::RED, None, 0.04);
5778/// Lines::add_ray(token, ray_y, 0.30, named_colors::GREEN, None, 0.04);
5779/// );
5780/// ```
5781/// <img src="https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/sphere.jpeg" alt="screenshot" width="200">
5782#[derive(Copy, Clone, Debug, Default, PartialEq)]
5783#[repr(C)]
5784pub struct Sphere {
5785 /// Center of the sphere
5786 pub center: Vec3,
5787 ///Distance from the center, to the surface of the sphere, in meters. Half the diameter.
5788 pub radius: f32,
5789}
5790/// AsRef
5791impl AsRef<Sphere> for Sphere {
5792 fn as_ref(&self) -> &Sphere {
5793 self
5794 }
5795}
5796
5797unsafe extern "C" {
5798 pub fn sphere_ray_intersect(sphere: Sphere, ray: Ray, out_pt: *mut Vec3) -> Bool32T;
5799 pub fn sphere_point_contains(sphere: Sphere, pt: Vec3) -> Bool32T;
5800}
5801
5802impl Sphere {
5803 /// Creates a Sphere directly from the ax + by + cz + d = 0 formula!
5804 /// <https://stereokit.net/Pages/StereoKit/Sphere.html>
5805 ///
5806 /// ### Examples
5807 /// ```
5808 /// use stereokit_rust::maths::{Vec3, Sphere};
5809 ///
5810 /// let sphere = Sphere::new(Vec3::ZERO, 0.5);
5811 /// let sphere_b = Sphere {center : Vec3::ZERO, radius : 0.5};
5812 ///
5813 /// assert_eq!(sphere, sphere_b);
5814 /// ```
5815 #[inline]
5816 pub fn new<V: Into<Vec3>>(center: V, radius: f32) -> Sphere {
5817 Sphere { center: center.into(), radius }
5818 }
5819
5820 /// A fast check to see if the given point is contained in or on a sphere!
5821 /// <https://stereokit.net/Pages/StereoKit/Sphere/Contains.html>
5822 ///
5823 /// see also [`sphere_point_contains`]
5824 /// ### Examples
5825 /// ```
5826 /// use stereokit_rust::maths::{Vec3, Sphere};
5827 ///
5828 /// let sphere = Sphere::new(Vec3::ZERO, 0.5);
5829 ///
5830 /// assert!(sphere.contains(Vec3::ONE * 0.28), "Should be contained");
5831 /// assert!(!sphere.contains(Vec3::ONE * 0.29), "Should not be contained");
5832 /// ```
5833 #[inline]
5834 pub fn contains<V: Into<Vec3>>(&self, point: V) -> bool {
5835 unsafe { sphere_point_contains(*self, point.into()) != 0 }
5836 }
5837
5838 /// Intersects a ray with this sphere, and finds if they intersect, and if so, where that intersection is!
5839 /// This only finds the closest intersection point to the origin of the ray.
5840 /// <https://stereokit.net/Pages/StereoKit/Sphere/Intersect.html>
5841 /// * ray - A ray to intersect with
5842 ///
5843 /// Returns the closest intersection point to the ray's origin. Or None it there is no intersection.
5844 /// see also [`sphere_ray_intersect`] same as [`Ray::intersect_sphere`]
5845 /// ### Examples
5846 /// ```
5847 /// use stereokit_rust::maths::{Vec3, Sphere, Ray};
5848 ///
5849 /// let sphere = Sphere::new(Vec3::ZERO, 0.5);
5850 ///
5851 /// assert_eq!(sphere.intersect(Ray::new(Vec3::Z, Vec3::NEG_Z)), Some(Vec3::Z * 0.5));
5852 /// assert_ne!(sphere.intersect(Ray::new(Vec3::Z, Vec3::Z)), None);
5853 /// ```
5854 #[inline]
5855 pub fn intersect(&self, ray: Ray) -> Option<Vec3> {
5856 let mut pt = Vec3::default();
5857 match unsafe { sphere_ray_intersect(*self, ray, &mut pt) != 0 } {
5858 true => Some(pt),
5859 false => None,
5860 }
5861 }
5862}
5863impl Display for Sphere {
5864 /// Creates a text description of the Sphere, in the format of “[center:X radius:X]”
5865 /// ### Examples
5866 /// ```
5867 /// use stereokit_rust::maths::{Vec3, Sphere};
5868 ///
5869 /// let sphere = Sphere::new([1.1, 2.0, 3.0], 4.0);
5870 /// assert_eq!(format!("{}", sphere),
5871 /// "[center:[x:1.1, y:2, z:3] radius:4]");
5872 /// ```
5873 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5874 write!(f, "[center:{} radius:{}]", self.center, self.radius)
5875 }
5876}
5877/// A pretty straightforward 2D rectangle, defined by the top left corner of the rectangle, and its width/height.
5878/// <https://stereokit.net/Pages/StereoKit/Rect.html>
5879#[derive(Debug, Copy, Clone, PartialEq)]
5880#[repr(C)]
5881pub struct Rect {
5882 /// The X axis position of the top left corner of the rectangle.
5883 pub x: f32,
5884 /// The Y axis position of the top left corner of the rectangle.
5885 pub y: f32,
5886 /// The width of the rectangle.
5887 pub width: f32,
5888 /// The height of the rectangle.
5889 pub height: f32,
5890}
5891
5892impl Default for Rect {
5893 fn default() -> Self {
5894 Self { x: 0.0, y: 0.0, width: 1.0, height: 1.0 }
5895 }
5896}
5897
5898impl Rect {
5899 /// Create a 2D rectangle, defined by the top left corner of the rectangle, and its width/height.
5900 /// <https://stereokit.net/Pages/StereoKit/Rect/Rect.html>
5901 ///
5902 /// ### Examples
5903 /// ```
5904 /// use stereokit_rust::maths::{Rect};
5905 ///
5906 /// let rect = Rect::new(0.0, 0.0, 1920.0, 1080.0);
5907 /// let rect_b = Rect {x:0.0, y:0.0, width:1920.0, height:1080.0};
5908 ///
5909 /// assert_eq!(rect, rect_b);
5910 /// ```
5911 pub const fn new(x: f32, y: f32, width: f32, height: f32) -> Self {
5912 Self { x, y, width, height }
5913 }
5914}
5915
5916/// A position and a direction indicating a ray through space! This is a great tool for intersection testing with
5917/// geometrical shapes.
5918/// <https://stereokit.net/Pages/StereoKit/Ray.html>
5919///
5920/// ### Examples
5921/// ```
5922/// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
5923/// use stereokit_rust::{maths::{Vec3, Matrix, Ray}, model::Model, system::Lines,
5924/// mesh::Mesh, material::Material, util::named_colors};
5925///
5926/// let point = Mesh::sphere();
5927/// let mut material_point =Material::unlit();
5928/// let model = Model::from_file("center.glb", None).unwrap().copy();
5929/// let cube = Mesh::cube();
5930/// let mut material_cube =Material::ui_box();
5931/// material_cube.color_tint(named_colors::GOLD)
5932/// .border_size(0.05);
5933///
5934/// let center = Vec3::new(0.0, -2.5, -2.5);
5935/// let bounds = model.get_bounds();
5936/// let transform = Matrix::t_r(center, [0.0, 220.0, 0.0]);
5937/// let transform_cube = Matrix::t_s( bounds.center, bounds.dimensions) * transform;
5938/// let inv = transform.get_inverse();
5939///
5940/// let ray_x = Ray::new(Vec3{x:4.0, y: 0.0, z: -2.5}, Vec3::NEG_X);
5941/// let inv_ray_x = inv.transform_ray(ray_x);
5942/// let inv_contact_x = bounds.intersect(inv_ray_x).expect("should be a point of contact");
5943/// let contact_x = transform.transform_point(inv_contact_x);
5944/// let transform_point_x = Matrix::t_s(contact_x, Vec3::ONE * 0.3);
5945///
5946/// filename_scr = "screenshots/ray.jpeg";
5947/// test_screenshot!( // !!!! Get a proper main loop !!!!
5948/// model.draw(token, transform, None, None);
5949/// cube.draw(token, &material_cube, transform_cube, None, None);
5950/// Lines::add_ray(token, ray_x, 1.5, named_colors::WHITE, None, 0.2);
5951/// point.draw(token, &material_point, transform_point_x, Some(named_colors::RED.into()), None );
5952/// );
5953/// ```
5954/// <img src="https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/ray.jpeg" alt="screenshot" width="200">
5955#[derive(Default, Debug, Copy, Clone, PartialEq)]
5956#[repr(C)]
5957pub struct Ray {
5958 /// The position or origin point of the Ray.
5959 pub position: Vec3,
5960 /// The direction the ray is facing, typically does not require being a unit vector, or normalized direction.
5961 pub direction: Vec3,
5962}
5963
5964unsafe extern "C" {
5965 pub fn ray_intersect_plane(ray: Ray, plane_pt: Vec3, plane_normal: Vec3, out_t: *mut f32) -> Bool32T;
5966 pub fn ray_from_mouse(screen_pixel_pos: Vec2, out_ray: *mut Ray) -> Bool32T;
5967 pub fn ray_point_closest(ray: Ray, pt: Vec3) -> Vec3;
5968}
5969
5970impl Ray {
5971 /// Ray Zero is the default
5972 pub const ZERO: Self = Ray { position: Vec3::ZERO, direction: Vec3::ZERO };
5973
5974 /// Basic initialization constructor! Just copies the parameters into the fields.
5975 /// <https://stereokit.net/Pages/StereoKit/Ray/Ray.html>
5976 /// * position - The position or origin point of the Ray.
5977 /// * direction - The direction the ray is facing, typically does not require being a unit vector, or normalized
5978 /// direction.
5979 ///
5980 /// ### Examples
5981 /// ```
5982 /// use stereokit_rust::maths::{Vec3, Ray};
5983 ///
5984 /// let ray = Ray::new(Vec3::ZERO, Vec3::ONE);
5985 /// let ray_b = Ray {position: Vec3::ZERO, direction: Vec3::ONE};
5986 ///
5987 /// assert_eq!(ray, ray_b);
5988 /// ```
5989 #[inline]
5990 pub fn new<V: Into<Vec3>>(pos: V, dir: V) -> Self {
5991 Self { position: pos.into(), direction: dir.into() }
5992 }
5993
5994 /// A convenience function that creates a ray from point a, towards point b. Resulting direction is not normalized.
5995 /// <https://stereokit.net/Pages/StereoKit/Ray/FromTo.html>
5996 /// * a - Ray starting point.
5997 /// * b - Location the ray is pointing towards.
5998 ///
5999 /// Returns a ray from point a to point b. Not normalized.
6000 ///
6001 /// ### Examples
6002 /// ```
6003 /// use stereokit_rust::maths::{Vec3, Ray};
6004 ///
6005 /// let ray = Ray::new(Vec3::ZERO, Vec3::ONE);
6006 /// let ray_b = Ray::from_to( Vec3::ZERO, Vec3::ONE);
6007 ///
6008 /// assert_eq!(ray, ray_b);
6009 /// ```
6010 #[inline]
6011 pub fn from_to<V: Into<Vec3>>(a: V, b: V) -> Ray {
6012 let position = a.into();
6013 let direction = b.into() - position;
6014 Ray { position, direction }
6015 }
6016
6017 /// Gets a point along the ray! This is basically just position + direction*percent. If Ray.direction is
6018 /// normalized, then percent is functionally distance, and can be used to find the point a certain distance
6019 /// out along the ray.
6020 /// <https://stereokit.net/Pages/StereoKit/Ray/At.html>
6021 /// * percent - How far along the ray should we get the point at? This is in multiples of self.direction's
6022 /// magnitude. If self.direction is normalized, this is functionally the distance.
6023 ///
6024 /// Returns the point at position + direction*percent
6025 ///
6026 /// ### Examples
6027 /// ```
6028 /// use stereokit_rust::maths::{Vec3, Ray};
6029 ///
6030 /// let ray = Ray::new(Vec3::ZERO, Vec3::ONE);
6031 ///
6032 /// assert_eq!(ray.get_at(3.0), Vec3::ONE * 3.0);
6033 /// ```
6034 #[inline]
6035 pub fn get_at(&self, percent: f32) -> Vec3 {
6036 self.position + self.direction * percent
6037 }
6038
6039 /// Calculates the point on the Ray that’s closest to the given point! This will be clamped if the point is behind
6040 /// the ray's origin.
6041 /// <https://stereokit.net/Pages/StereoKit/Ray/Closest.html>
6042 /// * to - Any point in the same coordinate space as the Ray.
6043 ///
6044 /// Returns the point on the ray that's closest to the given point.
6045 /// see also [`ray_point_closest`]
6046 ///
6047 /// ### Examples
6048 /// ```
6049 /// use stereokit_rust::maths::{Vec3, Plane, Ray};
6050 ///
6051 /// let ray = Ray::new(Vec3::ZERO, Vec3::ONE);
6052 ///
6053 /// assert_eq!(ray.closest(Vec3::Z), Vec3::ONE / 3.0);
6054 /// ```
6055 #[inline]
6056 pub fn closest<V: Into<Vec3>>(&self, to: V) -> Vec3 {
6057 unsafe { ray_point_closest(*self, to.into()) }
6058 }
6059
6060 /// Checks the intersection of this ray with a plane!
6061 /// <https://stereokit.net/Pages/StereoKit/Ray/Intersect.html>
6062 /// * plane - Any plane you want to intersect with.
6063 ///
6064 /// Returns intersection point if there's an intersection information or None if there's no intersection
6065 /// see also [`plane_ray_intersect`] same as [`Plane::intersect`]
6066 ///
6067 /// ### Examples
6068 /// ```
6069 /// use stereokit_rust::maths::{Vec3, Plane, Ray};
6070 ///
6071 /// let ray = Ray::new(Vec3::ZERO, Vec3::ONE);
6072 /// let plane = Plane::new(Vec3::NEG_Y, 2.5);
6073 ///
6074 /// assert_eq!(ray.intersect_plane(plane), Some(Vec3::ONE * 2.5));
6075 /// ```
6076 #[inline]
6077 pub fn intersect_plane(&self, plane: Plane) -> Option<Vec3> {
6078 let mut pt = Vec3::default();
6079 match unsafe { plane_ray_intersect(plane, *self, &mut pt) != 0 } {
6080 true => Some(pt),
6081 false => None,
6082 }
6083 }
6084
6085 /// Checks the intersection of this ray with a sphere!
6086 /// <https://stereokit.net/Pages/StereoKit/Ray/Intersect.html>
6087 /// * sphere - Any sphere you want to intersect with.
6088 ///
6089 /// Returns the closest intersection point to the ray origin if there's an intersection information or None if
6090 /// there's no intersection
6091 /// see also [`sphere_ray_intersect`] same as [`Sphere::intersect`]
6092 ///
6093 /// ### Examples
6094 /// ```
6095 /// use stereokit_rust::maths::{Vec3, Sphere, Ray};
6096 ///
6097 /// let ray = Ray::new(Vec3::ZERO, Vec3::ONE);
6098 /// let sphere = Sphere::new(Vec3::Y, 0.5);
6099 ///
6100 /// assert_eq!(ray.intersect_sphere(sphere), Some(Vec3::ONE * 0.5));
6101 /// ```
6102 #[inline]
6103 pub fn intersect_sphere(&self, sphere: Sphere) -> Option<Vec3> {
6104 let mut pt = Vec3::default();
6105 match unsafe { sphere_ray_intersect(sphere, *self, &mut pt) != 0 } {
6106 true => Some(pt),
6107 false => None,
6108 }
6109 }
6110
6111 /// Checks the intersection of this ray with a bounding box!
6112 /// <https://stereokit.net/Pages/StereoKit/Ray/Intersect.html>
6113 /// * bounds - Any bounds you want to intersect with.
6114 ///
6115 /// Returns the closest intersection point to the ray origin if there's an intersection information or None if
6116 /// there's no intersection
6117 /// see also [`bounds_ray_intersect`] same as [`Bounds::intersect`]
6118 /// ### Examples
6119 /// ```
6120 /// use stereokit_rust::maths::{Vec3, Bounds, Matrix, Ray};
6121 ///
6122 /// // A cube of 1 meter per side at this position, aligned with x y and z axis.
6123 /// let box_transform = Matrix::t([10.0, 1.0, 2.0]);
6124 /// let box_bounds = Bounds::bounds_centered([1.0,1.0,1.0]);
6125 ///
6126 /// let inv = box_transform.get_inverse();
6127 /// let ray1 = inv.transform_ray(Ray::new([10.2, 1.3, 2.4],[0.0, 1.0, 0.0]));
6128 /// let ray2 = inv.transform_ray(Ray::new([10.9, 1.8, 2.6],[0.0, 0.0, 1.0]));
6129 /// let ray3 = inv.transform_ray(Ray::new([10.5, 2.0, 2.7],[1.0, 0.0, 1.0]));
6130 ///
6131 /// assert!(ray1.intersect_bounds(box_bounds).is_some(), "should be a point of contact");
6132 /// assert_eq!(ray2.intersect_bounds(box_bounds), None);
6133 /// assert_eq!(ray3.intersect_bounds(box_bounds), None);
6134 ///
6135 /// // We want the contact point for ray1
6136 /// let contact_point = box_bounds.intersect(ray1)
6137 /// .expect ("There should be a point of contact");
6138 ///
6139 /// let contact_point = box_transform.transform_point(contact_point);
6140 /// assert_eq!(contact_point, [10.2, 1.3, 2.4 ].into());
6141 /// ```
6142 #[inline]
6143 pub fn intersect_bounds(&self, bounds: Bounds) -> Option<Vec3> {
6144 let mut pt = Vec3::default();
6145 match unsafe { bounds_ray_intersect(bounds, *self, &mut pt) != 0 } {
6146 true => Some(pt),
6147 false => None,
6148 }
6149 }
6150
6151 /// Checks the intersection point of this ray and a Mesh with collision data stored on the CPU. A mesh without
6152 /// collision data will always return false. Ray must be in model space, intersection point will be in model
6153 /// space too. You can use the inverse of the mesh’s world transform matrix to bring the ray into model space,
6154 /// see the example in the docs!
6155 /// <https://stereokit.net/Pages/StereoKit/Ray/Intersect.html>
6156 /// * mesh - A mesh containing collision data on the CPU. You can check this with mesh.get_keep_data().
6157 /// * cull - If None has default value of Cull::Back.
6158 ///
6159 /// Returns a tuple with
6160 /// - The intersection point of the ray and the mesh, if an intersection occurs. This is in model space, and must be
6161 /// transformed back into world space later.
6162 /// - The indice of the mesh where the intersection occurs.
6163 ///
6164 /// see also [`mesh_ray_intersect`] [`Ray::intersect_mesh_to_ptr`] same as [`Mesh::intersect`]
6165 /// ### Examples
6166 /// ```
6167 /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
6168 /// use stereokit_rust::{maths::{Vec3, Matrix, Quat, Ray}, system::Lines,
6169 /// util::{named_colors}, mesh::Mesh, material::{Material, Cull}};
6170 ///
6171 /// // Create Meshes
6172 /// let cube = Mesh::generate_cube(Vec3::ONE * 0.8, None);
6173 /// let sphere = Mesh::generate_sphere(1.0, Some(4));
6174 ///
6175 /// let material = Material::pbr().copy();
6176 /// let transform = Matrix::r(Quat::from_angles(40.0, 50.0, 20.0));
6177 /// let inv = transform.get_inverse();
6178 ///
6179 /// let ray = Ray::new([-3.0, 2.0, 0.5 ], [3.0, -2.0, -0.25]);
6180 /// let inv_ray = inv.transform_ray(ray);
6181 ///
6182 /// let (contact_sphere, ind_sphere) = inv_ray.intersect_mesh( &sphere, Some(Cull::Front))
6183 /// .expect("Ray should touch sphere");
6184 /// let (contact_cube, ind_cube) = inv_ray.intersect_mesh( &cube, Some(Cull::Back))
6185 /// .expect("Ray should touch cube");
6186 /// assert_eq!(ind_sphere, 672);
6187 /// assert_eq!(ind_cube, 9);
6188 ///
6189 /// let transform_contact_sphere = Matrix::t_s(
6190 /// transform.transform_point(contact_sphere), Vec3::ONE * 0.1);
6191 /// let transform_contact_cube = Matrix::t_s(
6192 /// transform.transform_point(contact_cube), Vec3::ONE * 0.1);
6193 ///
6194 /// filename_scr = "screenshots/intersect_meshes.jpeg";
6195 /// test_screenshot!( // !!!! Get a proper main loop !!!!
6196 /// cube.draw(token, &material, transform, Some(named_colors::CYAN.into()), None);
6197 /// sphere.draw(token, &material, transform, Some(named_colors::BLUE.into()), None);
6198 /// Lines::add_ray(token, ray, 2.2, named_colors::WHITE, None, 0.02);
6199 /// sphere.draw(token, &material, transform_contact_cube,
6200 /// Some(named_colors::YELLOW.into()), None );
6201 /// sphere.draw(token, &material, transform_contact_sphere,
6202 /// Some(named_colors::RED.into()), None );
6203 /// );
6204 /// ```
6205 /// <img src="https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/intersect_meshes.jpeg" alt="screenshot" width="200">
6206 #[inline]
6207 pub fn intersect_mesh(&self, mesh: &Mesh, cull: Option<Cull>) -> Option<(Vec3, VindT)> {
6208 let mut out_ray = Ray::default();
6209 let mut out_inds = 0;
6210 let cull = cull.unwrap_or(Cull::Back);
6211
6212 match unsafe { mesh_ray_intersect(mesh.0.as_ptr(), *self, cull, &mut out_ray, &mut out_inds) != 0 } {
6213 true => Some((out_ray.position, out_inds)),
6214 false => None,
6215 }
6216 }
6217
6218 /// Checks the intersection point of this ray and a Mesh with collision data stored on the CPU. A mesh without
6219 /// collision data will always return false. Ray must be in model space, intersection point will be in model
6220 /// space too. You can use the inverse of the mesh’s world transform matrix to bring the ray into model space,
6221 /// see the example in the docs!
6222 /// <https://stereokit.net/Pages/StereoKit/Ray/Intersect.html>
6223 /// * mesh - A mesh containing collision data on the CPU. You can check this with mesh.get_keep_data()
6224 /// * out_model_space_at - The intersection point and surface direction of the ray and the mesh, if an intersection
6225 /// occurs. This is in model space, and must be transformed back into world space later. Direction is not
6226 /// guaranteed to be normalized, especially if your own model->world transform contains scale/skew in it.
6227 /// * out_start_inds - The index of the first index of the triangle that was hit
6228 /// * cull - How should intersection work with respect to the direction the triangles are facing? Should we skip
6229 /// triangles that are facing away from the ray, or don't skip anything? A good default would be Cull.Back.
6230 /// If None has default value of Cull::Back.
6231 ///
6232 /// Returns true if an intersection occurs, false otherwise!
6233 /// see also [`mesh_ray_intersect`] [`Ray::intersect_mesh`] same as [`Mesh::intersect_to_ptr`]
6234 /// ### Examples
6235 /// ```
6236 /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
6237 /// use stereokit_rust::{maths::{Vec3, Matrix, Quat, Ray}, system::Lines,
6238 /// util::{named_colors}, mesh::Mesh, material::{Material, Cull}};
6239 ///
6240 /// // Create Meshes
6241 /// let cube = Mesh::generate_cube(Vec3::ONE * 0.8, None);
6242 /// let sphere = Mesh::generate_sphere(1.0, Some(4));
6243 ///
6244 /// let material = Material::pbr().copy();
6245 /// let transform = Matrix::r(Quat::from_angles(40.0, 50.0, 20.0));
6246 /// let inv = transform.get_inverse();
6247 ///
6248 /// let ray = Ray::new([-3.0, 2.0, 0.5 ], [3.0, -2.0, -0.25]);
6249 /// let inv_ray = inv.transform_ray(ray);
6250 ///
6251 /// let (mut contact_sphere_ray, mut ind_sphere) = (Ray::default(), 0u32);
6252 /// assert!(inv_ray.intersect_mesh_to_ptr(
6253 /// &sphere, Some(Cull::Front),
6254 /// &mut contact_sphere_ray, &mut ind_sphere)
6255 /// ,"Ray should touch sphere");
6256 ///
6257 /// let (mut contact_cube_ray, mut ind_cube) = (Ray::default(), 0u32);
6258 /// assert!( inv_ray.intersect_mesh_to_ptr(
6259 /// &cube, Some(Cull::Back),
6260 /// &mut contact_cube_ray, &mut ind_cube)
6261 /// ,"Ray should touch cube");
6262 ///
6263 /// assert_eq!(ind_sphere, 672);
6264 /// assert_eq!(ind_cube, 9);
6265 ///
6266 /// assert_eq!(transform.transform_ray(contact_sphere_ray),
6267 /// Ray { position: Vec3 { x: 0.36746234, y: -0.244975, z: 0.21937825 },
6268 /// direction: Vec3 { x: 0.58682406, y: -0.6427875, z: 0.49240398 }});
6269 /// assert_eq!(transform.transform_ray(contact_cube_ray),
6270 /// Ray { position: Vec3 { x: -0.39531866, y: 0.26354572, z: 0.2829433 },
6271 /// direction: Vec3 { x: -0.77243483, y: -0.2620026, z: 0.57853174 } });
6272 /// ```
6273 #[inline]
6274 #[allow(clippy::not_unsafe_ptr_arg_deref)]
6275 pub fn intersect_mesh_to_ptr(
6276 &self,
6277 mesh: &Mesh,
6278 cull: Option<Cull>,
6279 out_model_space_at: *mut Ray,
6280 out_start_inds: *mut u32,
6281 ) -> bool {
6282 let cull = cull.unwrap_or(Cull::Back);
6283 unsafe { mesh_ray_intersect(mesh.0.as_ptr(), *self, cull, out_model_space_at, out_start_inds) != 0 }
6284 }
6285
6286 /// Checks the intersection point of this ray and the Solid flagged Meshes in the Model’s visual nodes. Ray must
6287 /// be in model space, intersection point will be in model space too. You can use the inverse of the mesh’s world
6288 /// transform matrix to bring the ray into model space, see the example in the docs!
6289 /// <https://stereokit.net/Pages/StereoKit/Ray/Intersect.html>
6290 /// * model - Any Model that may or may not contain Solid flagged nodes, and Meshes with collision data.
6291 /// * cull - If None has default value of Cull::Back.
6292 ///
6293 /// Returns the intersection point of the ray and the model, if an intersection occurs. This is in model space, and
6294 /// must be transformed back into world space later.
6295 /// see also [`model_ray_intersect`] [`Ray::intersect_model_to_ptr`] same as [`Model::intersect`]
6296 /// ### Examples
6297 /// ```
6298 /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
6299 /// use stereokit_rust::{maths::{Vec3, Matrix, Ray}, model::Model, system::Lines,
6300 /// mesh::Mesh, material::{Material, Cull}, util::named_colors};
6301 ///
6302 /// let model = Model::from_file("center.glb", None).unwrap().copy();
6303 /// let transform = Matrix::t_r([0.0,-2.25,-2.00], [0.0, 140.0, 0.0]);
6304 ///
6305 /// let inv_ray = Ray::new([1.0, 2.0, -3.0], [-1.5, 2.0, 3.0]);
6306 ///
6307 /// let contact_model = inv_ray.intersect_model( &model, Some(Cull::Back))
6308 /// .expect("Ray should touch model");
6309 ///
6310 /// let ray = transform.transform_ray(inv_ray);
6311 /// let transform_contact_model = Matrix::t(transform.transform_point(contact_model));
6312 /// let point = Mesh::generate_sphere(0.2, Some(2));
6313 /// let material = Material::pbr();
6314 ///
6315 /// filename_scr = "screenshots/intersect_model.jpeg";
6316 /// test_screenshot!( // !!!! Get a proper main loop !!!!
6317 /// model.draw(token, transform, None, None);
6318 /// Lines::add_ray(token, ray, 1.2, named_colors::WHITE, None, 0.02);
6319 /// point.draw(token, &material, transform_contact_model,
6320 /// Some(named_colors::RED.into()), None );
6321 /// );
6322 /// ```
6323 /// <img src="https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/intersect_model.jpeg" alt="screenshot" width="200">
6324 #[inline]
6325 pub fn intersect_model(&self, model: &Model, cull: Option<Cull>) -> Option<Vec3> {
6326 let mut out_ray = Ray::default();
6327 let cull = cull.unwrap_or(Cull::Back);
6328
6329 match unsafe { model_ray_intersect(model.0.as_ptr(), *self, cull, &mut out_ray) != 0 } {
6330 true => Some(out_ray.position),
6331 false => None,
6332 }
6333 }
6334
6335 /// Checks the intersection point of this ray and the Solid flagged Meshes in the Model’s visual nodes. Ray must
6336 /// be in model space, intersection point will be in model space too. You can use the inverse of the mesh’s world
6337 /// transform matrix to bring the ray into model space, see the example in the docs!
6338 /// <https://stereokit.net/Pages/StereoKit/Ray/Intersect.html>
6339 /// * model - Any Model that may or may not contain Solid flagged nodes, and Meshes with collision data.
6340 /// * cull - If None has default value of Cull::Back.
6341 /// * out_model_space_at - The intersection point and surface direction of the ray and the model, if an intersection
6342 /// occurs. This is in model space, and must be transformed back into world space later. Direction is not
6343 /// guaranteed to be normalized, especially if your own model->world transform contains scale/skew in it.
6344 ///
6345 /// Returns - true if an intersection occurs, false otherwise!
6346 /// see also [`model_ray_intersect`] [`Ray::intersect_model`] same as [`Model::intersect_to_ptr`]
6347 /// ### Examples
6348 /// ```
6349 /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
6350 /// use stereokit_rust::{maths::{Vec3, Matrix, Ray}, model::Model,
6351 /// mesh::Mesh, material::{Material, Cull}, util::named_colors};
6352 ///
6353 /// let model = Model::from_file("center.glb", None).unwrap().copy();
6354 /// let transform = Matrix::t_r([0.0,-2.25,-2.00], [0.0, 140.0, 0.0]);
6355 ///
6356 /// let inv_ray = Ray::new([1.0, 2.0, -3.0], [-1.5, 2.0, 3.0]);
6357 ///
6358 /// let mut inv_contact_model_ray = Ray::default();
6359 /// assert!(inv_ray.intersect_model_to_ptr( &model, Some(Cull::Back), &mut inv_contact_model_ray)
6360 /// ,"Ray should touch model");
6361 ///
6362 /// let contact_model_ray = transform.transform_ray(inv_contact_model_ray);
6363 /// assert_eq!(contact_model_ray,
6364 /// Ray { position: Vec3 { x: -0.3688636, y: 1.2613544, z: -1.3526915 },
6365 /// direction: Vec3 { x: -0.4004621, y: -0.016381653, z: 0.9161662 } });
6366 #[inline]
6367 #[allow(clippy::not_unsafe_ptr_arg_deref)]
6368 pub fn intersect_model_to_ptr(&self, model: &Model, cull: Option<Cull>, out_model_space_at: *mut Ray) -> bool {
6369 let cull = cull.unwrap_or(Cull::Back);
6370 unsafe { model_ray_intersect(model.0.as_ptr(), *self, cull, out_model_space_at) != 0 }
6371 }
6372}
6373
6374impl Display for Ray {
6375 /// Creates a text description of the Ray, in the format of “[position:X direction:X]”
6376 /// <https://stereokit.net/Pages/StereoKit/Ray/ToString.html>
6377 /// ### Examples
6378 /// ```
6379 /// use stereokit_rust::maths::{Vec3, Ray};
6380 ///
6381 /// let ray = Ray::new([1.1, 2.0, 3.0], [4.0, 5.0, 6.0]);
6382 /// assert_eq!(format!("{}", ray),
6383 /// "[position:[x:1.1, y:2, z:3] direction:[x:4, y:5, z:6]]");
6384 /// ```
6385 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
6386 write!(f, "[position:{} direction:{}]", self.position, self.direction)
6387 }
6388}