1use super::{EPSILON, Float, Vec2, approx_eq, lerp};
4use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
5
6#[derive(Debug, Clone, Copy, PartialEq, Default)]
8#[repr(C)]
9pub struct Vec3 {
10 pub x: Float,
12 pub y: Float,
14 pub z: Float,
16}
17
18impl Vec3 {
19 pub const ZERO: Self = Self {
21 x: 0.0,
22 y: 0.0,
23 z: 0.0,
24 };
25
26 pub const ONE: Self = Self {
28 x: 1.0,
29 y: 1.0,
30 z: 1.0,
31 };
32
33 pub const X: Self = Self {
35 x: 1.0,
36 y: 0.0,
37 z: 0.0,
38 };
39
40 pub const Y: Self = Self {
42 x: 0.0,
43 y: 1.0,
44 z: 0.0,
45 };
46
47 pub const Z: Self = Self {
49 x: 0.0,
50 y: 0.0,
51 z: 1.0,
52 };
53
54 pub const NEG_X: Self = Self {
56 x: -1.0,
57 y: 0.0,
58 z: 0.0,
59 };
60
61 pub const NEG_Y: Self = Self {
63 x: 0.0,
64 y: -1.0,
65 z: 0.0,
66 };
67
68 pub const NEG_Z: Self = Self {
70 x: 0.0,
71 y: 0.0,
72 z: -1.0,
73 };
74
75 #[inline]
77 #[must_use]
78 pub const fn new(x: Float, y: Float, z: Float) -> Self {
79 Self { x, y, z }
80 }
81
82 #[inline]
84 #[must_use]
85 pub const fn splat(value: Float) -> Self {
86 Self {
87 x: value,
88 y: value,
89 z: value,
90 }
91 }
92
93 #[inline]
95 #[must_use]
96 pub const fn from_array(arr: [Float; 3]) -> Self {
97 Self {
98 x: arr[0],
99 y: arr[1],
100 z: arr[2],
101 }
102 }
103
104 #[inline]
106 #[must_use]
107 pub const fn to_array(self) -> [Float; 3] {
108 [self.x, self.y, self.z]
109 }
110
111 #[inline]
113 #[must_use]
114 pub const fn from_vec2(v: Vec2, z: Float) -> Self {
115 Self { x: v.x, y: v.y, z }
116 }
117
118 #[inline]
120 #[must_use]
121 pub const fn xy(self) -> Vec2 {
122 Vec2 {
123 x: self.x,
124 y: self.y,
125 }
126 }
127
128 #[inline]
130 #[must_use]
131 pub const fn xz(self) -> Vec2 {
132 Vec2 {
133 x: self.x,
134 y: self.z,
135 }
136 }
137
138 #[inline]
140 #[must_use]
141 pub const fn yz(self) -> Vec2 {
142 Vec2 {
143 x: self.y,
144 y: self.z,
145 }
146 }
147
148 #[inline]
150 #[must_use]
151 pub fn dot(self, other: Self) -> Float {
152 self.x * other.x + self.y * other.y + self.z * other.z
153 }
154
155 #[inline]
157 #[must_use]
158 pub fn cross(self, other: Self) -> Self {
159 Self {
160 x: self.y * other.z - self.z * other.y,
161 y: self.z * other.x - self.x * other.z,
162 z: self.x * other.y - self.y * other.x,
163 }
164 }
165
166 #[inline]
168 #[must_use]
169 pub fn length_squared(self) -> Float {
170 self.dot(self)
171 }
172
173 #[inline]
175 #[must_use]
176 pub fn length(self) -> Float {
177 self.length_squared().sqrt()
178 }
179
180 #[inline]
182 #[must_use]
183 pub fn normalize(self) -> Self {
184 let len = self.length();
185 if len > EPSILON {
186 self / len
187 } else {
188 Self::ZERO
189 }
190 }
191
192 #[inline]
194 #[must_use]
195 pub fn try_normalize(self) -> Option<Self> {
196 let len = self.length();
197 if len > EPSILON {
198 Some(self / len)
199 } else {
200 None
201 }
202 }
203
204 #[inline]
206 #[must_use]
207 pub fn distance(self, other: Self) -> Float {
208 (self - other).length()
209 }
210
211 #[inline]
213 #[must_use]
214 pub fn distance_squared(self, other: Self) -> Float {
215 (self - other).length_squared()
216 }
217
218 #[inline]
220 #[must_use]
221 pub fn lerp(self, other: Self, t: Float) -> Self {
222 Self {
223 x: lerp(self.x, other.x, t),
224 y: lerp(self.y, other.y, t),
225 z: lerp(self.z, other.z, t),
226 }
227 }
228
229 #[inline]
231 #[must_use]
232 pub fn min(self, other: Self) -> Self {
233 Self {
234 x: self.x.min(other.x),
235 y: self.y.min(other.y),
236 z: self.z.min(other.z),
237 }
238 }
239
240 #[inline]
242 #[must_use]
243 pub fn max(self, other: Self) -> Self {
244 Self {
245 x: self.x.max(other.x),
246 y: self.y.max(other.y),
247 z: self.z.max(other.z),
248 }
249 }
250
251 #[inline]
253 #[must_use]
254 pub fn abs(self) -> Self {
255 Self {
256 x: self.x.abs(),
257 y: self.y.abs(),
258 z: self.z.abs(),
259 }
260 }
261
262 #[inline]
264 #[must_use]
265 pub fn angle_between(self, other: Self) -> Float {
266 let denom = (self.length_squared() * other.length_squared()).sqrt();
267 if denom < EPSILON {
268 0.0
269 } else {
270 (self.dot(other) / denom).clamp(-1.0, 1.0).acos()
271 }
272 }
273
274 #[inline]
276 #[must_use]
277 pub fn approx_eq(self, other: Self) -> bool {
278 approx_eq(self.x, other.x) && approx_eq(self.y, other.y) && approx_eq(self.z, other.z)
279 }
280
281 #[inline]
283 #[must_use]
284 pub fn reflect(self, normal: Self) -> Self {
285 self - normal * (2.0 * self.dot(normal))
286 }
287
288 #[inline]
290 #[must_use]
291 pub fn project(self, onto: Self) -> Self {
292 let denom = onto.length_squared();
293 if denom < EPSILON {
294 Self::ZERO
295 } else {
296 onto * (self.dot(onto) / denom)
297 }
298 }
299
300 #[inline]
302 #[must_use]
303 pub fn floor(self) -> Self {
304 Self {
305 x: self.x.floor(),
306 y: self.y.floor(),
307 z: self.z.floor(),
308 }
309 }
310
311 #[inline]
313 #[must_use]
314 pub fn ceil(self) -> Self {
315 Self {
316 x: self.x.ceil(),
317 y: self.y.ceil(),
318 z: self.z.ceil(),
319 }
320 }
321}
322
323impl Add for Vec3 {
324 type Output = Self;
325
326 #[inline]
327 fn add(self, other: Self) -> Self {
328 Self {
329 x: self.x + other.x,
330 y: self.y + other.y,
331 z: self.z + other.z,
332 }
333 }
334}
335
336impl AddAssign for Vec3 {
337 #[inline]
338 fn add_assign(&mut self, other: Self) {
339 self.x += other.x;
340 self.y += other.y;
341 self.z += other.z;
342 }
343}
344
345impl Sub for Vec3 {
346 type Output = Self;
347
348 #[inline]
349 fn sub(self, other: Self) -> Self {
350 Self {
351 x: self.x - other.x,
352 y: self.y - other.y,
353 z: self.z - other.z,
354 }
355 }
356}
357
358impl SubAssign for Vec3 {
359 #[inline]
360 fn sub_assign(&mut self, other: Self) {
361 self.x -= other.x;
362 self.y -= other.y;
363 self.z -= other.z;
364 }
365}
366
367impl Mul<Float> for Vec3 {
368 type Output = Self;
369
370 #[inline]
371 fn mul(self, scalar: Float) -> Self {
372 Self {
373 x: self.x * scalar,
374 y: self.y * scalar,
375 z: self.z * scalar,
376 }
377 }
378}
379
380impl Mul<Vec3> for Float {
381 type Output = Vec3;
382
383 #[inline]
384 fn mul(self, vec: Vec3) -> Vec3 {
385 vec * self
386 }
387}
388
389impl MulAssign<Float> for Vec3 {
390 #[inline]
391 fn mul_assign(&mut self, scalar: Float) {
392 self.x *= scalar;
393 self.y *= scalar;
394 self.z *= scalar;
395 }
396}
397
398impl Mul for Vec3 {
399 type Output = Self;
400
401 #[inline]
402 fn mul(self, other: Self) -> Self {
403 Self {
404 x: self.x * other.x,
405 y: self.y * other.y,
406 z: self.z * other.z,
407 }
408 }
409}
410
411impl Div<Float> for Vec3 {
412 type Output = Self;
413
414 #[inline]
415 fn div(self, scalar: Float) -> Self {
416 Self {
417 x: self.x / scalar,
418 y: self.y / scalar,
419 z: self.z / scalar,
420 }
421 }
422}
423
424impl DivAssign<Float> for Vec3 {
425 #[inline]
426 fn div_assign(&mut self, scalar: Float) {
427 self.x /= scalar;
428 self.y /= scalar;
429 self.z /= scalar;
430 }
431}
432
433impl Neg for Vec3 {
434 type Output = Self;
435
436 #[inline]
437 fn neg(self) -> Self {
438 Self {
439 x: -self.x,
440 y: -self.y,
441 z: -self.z,
442 }
443 }
444}
445
446impl From<[Float; 3]> for Vec3 {
447 #[inline]
448 fn from(arr: [Float; 3]) -> Self {
449 Self::from_array(arr)
450 }
451}
452
453impl From<Vec3> for [Float; 3] {
454 #[inline]
455 fn from(v: Vec3) -> Self {
456 v.to_array()
457 }
458}
459
460impl From<(Float, Float, Float)> for Vec3 {
461 #[inline]
462 fn from((x, y, z): (Float, Float, Float)) -> Self {
463 Self { x, y, z }
464 }
465}
466
467#[cfg(test)]
468mod tests {
469 use super::*;
470
471 #[test]
472 fn test_new() {
473 let v = Vec3::new(1.0, 2.0, 3.0);
474 assert_eq!(v.x, 1.0);
475 assert_eq!(v.y, 2.0);
476 assert_eq!(v.z, 3.0);
477 }
478
479 #[test]
480 fn test_constants() {
481 assert!(Vec3::ZERO.approx_eq(Vec3::new(0.0, 0.0, 0.0)));
482 assert!(Vec3::ONE.approx_eq(Vec3::new(1.0, 1.0, 1.0)));
483 assert!(Vec3::X.approx_eq(Vec3::new(1.0, 0.0, 0.0)));
484 assert!(Vec3::Y.approx_eq(Vec3::new(0.0, 1.0, 0.0)));
485 assert!(Vec3::Z.approx_eq(Vec3::new(0.0, 0.0, 1.0)));
486 }
487
488 #[test]
489 fn test_splat() {
490 let v = Vec3::splat(5.0);
491 assert!(v.approx_eq(Vec3::new(5.0, 5.0, 5.0)));
492 }
493
494 #[test]
495 fn test_from_vec2() {
496 let v2 = Vec2::new(1.0, 2.0);
497 let v3 = Vec3::from_vec2(v2, 3.0);
498 assert!(v3.approx_eq(Vec3::new(1.0, 2.0, 3.0)));
499 }
500
501 #[test]
502 fn test_swizzle() {
503 let v = Vec3::new(1.0, 2.0, 3.0);
504 assert!(v.xy().approx_eq(Vec2::new(1.0, 2.0)));
505 assert!(v.xz().approx_eq(Vec2::new(1.0, 3.0)));
506 assert!(v.yz().approx_eq(Vec2::new(2.0, 3.0)));
507 }
508
509 #[test]
510 fn test_dot() {
511 let a = Vec3::new(1.0, 2.0, 3.0);
512 let b = Vec3::new(4.0, 5.0, 6.0);
513 assert!(approx_eq(a.dot(b), 32.0)); }
515
516 #[test]
517 fn test_cross() {
518 let a = Vec3::X;
519 let b = Vec3::Y;
520 assert!(a.cross(b).approx_eq(Vec3::Z));
521 assert!(b.cross(a).approx_eq(Vec3::NEG_Z));
522 }
523
524 #[test]
525 fn test_length() {
526 let v = Vec3::new(2.0, 3.0, 6.0);
527 assert!(approx_eq(v.length_squared(), 49.0));
528 assert!(approx_eq(v.length(), 7.0));
529 }
530
531 #[test]
532 fn test_normalize() {
533 let v = Vec3::new(0.0, 3.0, 4.0);
534 let n = v.normalize();
535 assert!(approx_eq(n.length(), 1.0));
536 assert!(n.approx_eq(Vec3::new(0.0, 0.6, 0.8)));
537 }
538
539 #[test]
540 fn test_normalize_zero() {
541 let v = Vec3::ZERO;
542 assert!(v.normalize().approx_eq(Vec3::ZERO));
543 assert!(v.try_normalize().is_none());
544 }
545
546 #[test]
547 fn test_distance() {
548 let a = Vec3::ZERO;
549 let b = Vec3::new(2.0, 3.0, 6.0);
550 assert!(approx_eq(a.distance(b), 7.0));
551 }
552
553 #[test]
554 fn test_lerp() {
555 let a = Vec3::ZERO;
556 let b = Vec3::new(10.0, 20.0, 30.0);
557 assert!(a.lerp(b, 0.0).approx_eq(a));
558 assert!(a.lerp(b, 1.0).approx_eq(b));
559 assert!(a.lerp(b, 0.5).approx_eq(Vec3::new(5.0, 10.0, 15.0)));
560 }
561
562 #[test]
563 fn test_min_max() {
564 let a = Vec3::new(1.0, 4.0, 2.0);
565 let b = Vec3::new(3.0, 2.0, 5.0);
566 assert!(a.min(b).approx_eq(Vec3::new(1.0, 2.0, 2.0)));
567 assert!(a.max(b).approx_eq(Vec3::new(3.0, 4.0, 5.0)));
568 }
569
570 #[test]
571 fn test_reflect() {
572 let v = Vec3::new(1.0, -1.0, 0.0);
573 let n = Vec3::Y;
574 let r = v.reflect(n);
575 assert!(r.approx_eq(Vec3::new(1.0, 1.0, 0.0)));
576 }
577
578 #[test]
579 fn test_project() {
580 let v = Vec3::new(3.0, 4.0, 0.0);
581 let onto = Vec3::X;
582 assert!(v.project(onto).approx_eq(Vec3::new(3.0, 0.0, 0.0)));
583 }
584
585 #[test]
586 fn test_angle_between() {
587 let a = Vec3::X;
588 let b = Vec3::Y;
589 assert!(approx_eq(
590 a.angle_between(b),
591 std::f32::consts::FRAC_PI_2 as Float
592 ));
593 }
594
595 #[test]
596 fn test_add() {
597 let a = Vec3::new(1.0, 2.0, 3.0);
598 let b = Vec3::new(4.0, 5.0, 6.0);
599 assert!((a + b).approx_eq(Vec3::new(5.0, 7.0, 9.0)));
600 }
601
602 #[test]
603 fn test_sub() {
604 let a = Vec3::new(4.0, 5.0, 6.0);
605 let b = Vec3::new(1.0, 2.0, 3.0);
606 assert!((a - b).approx_eq(Vec3::new(3.0, 3.0, 3.0)));
607 }
608
609 #[test]
610 fn test_mul_scalar() {
611 let v = Vec3::new(1.0, 2.0, 3.0);
612 assert!((v * 2.0).approx_eq(Vec3::new(2.0, 4.0, 6.0)));
613 assert!((2.0 * v).approx_eq(Vec3::new(2.0, 4.0, 6.0)));
614 }
615
616 #[test]
617 fn test_div() {
618 let v = Vec3::new(2.0, 4.0, 6.0);
619 assert!((v / 2.0).approx_eq(Vec3::new(1.0, 2.0, 3.0)));
620 }
621
622 #[test]
623 fn test_neg() {
624 let v = Vec3::new(1.0, -2.0, 3.0);
625 assert!((-v).approx_eq(Vec3::new(-1.0, 2.0, -3.0)));
626 }
627
628 #[test]
629 fn test_floor_ceil() {
630 let v = Vec3::new(1.5, -2.3, 3.7);
631 assert!(v.floor().approx_eq(Vec3::new(1.0, -3.0, 3.0)));
632 assert!(v.ceil().approx_eq(Vec3::new(2.0, -2.0, 4.0)));
633 }
634}