1use crate::matrix::*;
54use crate::scalar::*;
55use crate::vector::*;
56use num_traits::{Zero, One};
57
58#[repr(C)]
60#[derive(Debug, Clone, Copy, Default)]
61pub struct Dimension<T: Scalar> {
62 pub width: T,
63 pub height: T,
64}
65
66impl<T: Scalar> Dimension<T> {
67 pub fn new(width: T, height: T) -> Self {
69 Self { width, height }
70 }
71}
72
73#[repr(C)]
77#[derive(Debug, Clone, Copy, Default)]
78pub struct Rect<T: Scalar> {
79 pub x: T,
80 pub y: T,
81 pub width: T,
82 pub height: T,
83}
84
85impl<T: Scalar> Rect<T> {
86 pub fn new(x: T, y: T, width: T, height: T) -> Self {
88 Self {
89 x,
90 y,
91 width,
92 height,
93 }
94 }
95 pub fn from(min_vec: &Vector2<T>, max_vec: &Vector2<T>) -> Self {
99 let min_x = T::min(min_vec.x, max_vec.x);
100 let min_y = T::min(min_vec.y, max_vec.y);
101 let max_x = T::max(min_vec.x, max_vec.x);
102 let max_y = T::max(min_vec.y, max_vec.y);
103 Self {
104 x: min_x,
105 y: min_y,
106 width: max_x - min_x,
107 height: max_y - min_y,
108 }
109 }
110
111 pub fn min(&self) -> Vector2<T> {
113 Vector2::new(self.x, self.y)
114 }
115 pub fn max(&self) -> Vector2<T> {
117 Vector2::new(self.x + self.width, self.y + self.height)
118 }
119 pub fn intersect(&self, other: &Self) -> Option<Self> {
123 let smx = self.max();
124 let smn = self.min();
125 let omx = other.max();
126 let omn = other.min();
127
128 if smx.x < omn.x || smx.y < omn.y || smn.x > omx.x || smn.y > omx.y {
129 return None;
130 }
131
132 let min_vec = Vector2::max(&self.min(), &other.min());
133 let max_vec = Vector2::min(&self.max(), &other.max());
134 Some(Self::from(&min_vec, &max_vec))
135 }
136
137 pub fn contains(&self, p: &Vector2<T>) -> bool {
139 p.x >= self.x && p.y >= self.y && p.x <= self.x + self.width && p.y <= self.y + self.height
140 }
141}
142
143#[repr(C)]
147#[derive(Debug, Clone, Copy, Default)]
148pub struct Box3<T: Scalar> {
149 pub min: Vector3<T>,
150 pub max: Vector3<T>,
151}
152
153impl<T: Scalar> Box3<T> {
154 pub fn new(v0: &Vector3<T>, v1: &Vector3<T>) -> Self {
158 Self {
159 min: Vector3::min(v0, v1),
160 max: Vector3::max(v0, v1),
161 }
162 }
163 pub fn center(&self) -> Vector3<T> {
165 (self.max + self.min) * T::half()
166 }
167 pub fn extent(&self) -> Vector3<T> {
169 self.max - self.center()
170 }
171 pub fn overlap(&self, other: &Self) -> bool {
173 if self.max.x < other.min.x {
174 return false;
175 }
176 if self.max.y < other.min.y {
177 return false;
178 }
179 if self.max.z < other.min.z {
180 return false;
181 }
182
183 if self.min.x > other.max.x {
184 return false;
185 }
186 if self.min.x > other.max.x {
187 return false;
188 }
189 if self.min.x > other.max.x {
190 return false;
191 }
192 return true;
193 }
194
195 pub fn add(&self, p: &Vector3<T>) -> Self {
197 Self {
198 min: Vector3::min(&p, &self.min),
199 max: Vector3::max(&p, &self.max),
200 }
201 }
202
203 pub fn subdivide(&self) -> [Self; 8] {
207 let cube_table: [Vector3<i32>; 8] = [
208 Vector3::new(0, 1, 0),
209 Vector3::new(1, 1, 0),
210 Vector3::new(1, 1, 1),
211 Vector3::new(0, 1, 1),
212 Vector3::new(0, 0, 0),
213 Vector3::new(1, 0, 0),
214 Vector3::new(1, 0, 1),
215 Vector3::new(0, 0, 1),
216 ];
217
218 let ps: [Vector3<T>; 2] = [self.min, self.max];
219 let mut vs = [Vector3::zero(); 8];
220 for i in 0..8 {
221 vs[i] = Vector3::new(
222 ps[cube_table[i].x as usize].x,
223 ps[cube_table[i].y as usize].y,
224 ps[cube_table[i].z as usize].z,
225 );
226 }
227
228 let c = self.center();
229 let mut out = [Box3 {
230 min: Vector3::zero(),
231 max: Vector3::zero(),
232 }; 8];
233 for i in 0..8 {
234 out[i] = Self::new(&Vector3::min(&c, &vs[i]), &Vector3::max(&c, &vs[i]));
235 }
236 out
237 }
238}
239
240#[repr(C)]
244#[derive(Debug, Clone, Copy, Default)]
245pub struct Line<T: Scalar, V: Vector<T>> {
246 pub p: V, pub d: V, t: core::marker::PhantomData<T>,
249}
250
251impl<T: Scalar, V: Vector<T>> Line<T, V> {
252 pub fn new(p: &V, d: &V) -> Self {
254 Self {
255 p: *p,
256 d: *d,
257 t: core::marker::PhantomData,
258 }
259 }
260 pub fn from_start_end(s: &V, e: &V) -> Self {
264 Self {
265 p: *s,
266 d: *e - *s,
267 t: core::marker::PhantomData,
268 }
269 }
270 pub fn closest_point_on_line(&self, p: &V) -> (T, V) {
276 let p_dir = *p - self.p;
277
278 let d_sp = V::dot(&self.d, &p_dir);
279 let d_ss = V::dot(&self.d, &self.d);
280
281 let t = d_sp / d_ss;
282
283 (t, self.p + self.d * t)
284 }
285}
286
287impl<T: FloatScalar, V: FloatVector<T>> Line<T, V> {
288 pub fn normalize(&self) -> Self {
290 Self {
291 p: self.p,
292 d: FloatVector::normalize(&self.d),
293 t: core::marker::PhantomData,
294 }
295 }
296}
297
298pub fn shortest_segment3d_between_lines3d<T: FloatScalar>(
302 line0: &Line<T, Vector3<T>>,
303 line1: &Line<T, Vector3<T>>,
304 epsilon: T,
305) -> Option<Segment<T, Vector3<T>>> {
306 let s0 = line0.p;
307 let s1 = line1.p;
308
309 let d1 = line1.d;
310 let d0 = line0.d;
311
312 let normal = Vector3::normalize(&Vector3::cross(&d1, &d0));
313 let n0 = Vector3::normalize(&Vector3::cross(&normal, &d0));
314 let n1 = Vector3::normalize(&Vector3::cross(&normal, &d1));
315
316 let plane0 = Plane::new(&n0, &s0);
317 let plane1 = Plane::new(&n1, &s1);
318
319 let p1 = plane0.intersect_line(line1, epsilon);
320 let p0 = plane1.intersect_line(line0, epsilon);
321
322 match (p0, p1) {
323 (Some((_, s)), Some((_, e))) => Some(Segment::new(&s, &e)),
324 _ => None,
325 }
326}
327
328#[repr(C)]
330#[derive(Clone, Copy, Default)]
331pub struct Segment<T: Scalar, V: Vector<T>> {
332 pub s: V, pub e: V, t: core::marker::PhantomData<T>,
335}
336
337impl<T: Scalar, V: Vector<T>> Segment<T, V> {
338 pub fn new(s: &V, e: &V) -> Self {
340 Self {
341 s: *s,
342 e: *e,
343 t: core::marker::PhantomData,
344 }
345 }
346 pub fn closest_point_on_segment(&self, p: &V) -> (T, V) {
352 let dir = self.e - self.s;
353 let p_dir = *p - self.s;
354
355 let d_sp = V::dot(&dir, &p_dir);
356 let d_ss = V::dot(&dir, &dir);
357
358 if d_sp < <T as Zero>::zero() {
359 return (<T as Zero>::zero(), self.s);
360 } else if d_sp > d_ss {
361 return (<T as One>::one(), self.e);
362 }
363
364 let t = d_sp / d_ss;
365
366 (t, self.s + dir * t)
367 }
368}
369
370impl<T: FloatScalar, V: FloatVector<T>> Segment<T, V> {
371 pub fn distance(&self, p: &V) -> T {
373 let (_, p_on_seg) = self.closest_point_on_segment(p);
374 V::length(&(p_on_seg - *p))
375 }
376}
377
378#[repr(C)]
382#[derive(Clone, Copy, Default)]
383pub struct Ray<T: Scalar, V: Vector<T>> {
384 pub start: V,
385 pub direction: V,
386 t: core::marker::PhantomData<T>,
387}
388
389impl<T: FloatScalar, V: FloatVector<T>> Ray<T, V> {
390 pub fn new(start: &V, direction: &V) -> Self {
392 Self {
393 start: *start,
394 direction: V::normalize(direction),
395 t: core::marker::PhantomData,
396 }
397 }
398}
399
400impl<T: Scalar> Ray<T, Vector3<T>> {
401 pub fn intersect_plane(&self, p: &Plane<T>) -> Option<Vector3<T>> {
406 let n = p.normal();
407 let t: T = -(p.d + Vector3::dot(&n, &self.start)) / Vector3::dot(&n, &self.direction);
408 if t < <T as Zero>::zero() {
409 None
410 } else {
411 Some(self.direction * t + self.start)
412 }
413 }
414}
415
416#[repr(C)]
420#[derive(Clone, Copy, Default)]
421pub struct Sphere3<T: FloatScalar> {
422 pub center: Vector3<T>,
423 pub radius: T,
424}
425
426impl<T: FloatScalar> Sphere3<T> {
427 pub fn new(center: Vector3<T>, radius: T) -> Self {
428 Self {
429 center: center,
430 radius: radius,
431 }
432 }
433}
434
435#[repr(C)]
439#[derive(Clone, Copy, Default)]
440pub struct Tri3<T: FloatScalar> {
441 vertices: [Vector3<T>; 3],
442}
443
444impl<T: FloatScalar> Tri3<T> {
445 pub fn new(vertices: [Vector3<T>; 3]) -> Self {
446 Self { vertices: vertices }
447 }
448 pub fn vertices(&self) -> &[Vector3<T>; 3] {
449 &self.vertices
450 }
451
452 pub fn barycentric_coordinates(&self, pt: &Vector3<T>) -> Vector3<T> {
453 let v0 = self.vertices[0];
454 let v1 = self.vertices[1];
455 let v2 = self.vertices[2];
456 let vv1 = v1 - v0;
457 let vv2 = v2 - v0;
458 let vvc = Vector3::cross(&vv1, &vv2);
459 let m = Matrix3::new(
460 vv1.x, vv1.y, vv1.z, vv2.x, vv2.y, vv2.z, vvc.x, vvc.y, vvc.z,
461 );
462 let lambda = m.inverse() * (*pt - v0);
463 Vector3::new(<T as One>::one() - lambda.x - lambda.y, lambda.x, lambda.y)
464 }
465}
466
467#[repr(C)]
471#[derive(Clone, Copy, Default)]
472pub struct Plane<T: Scalar> {
473 a: T,
474 b: T,
475 c: T,
476 d: T,
477}
478
479impl<T: Scalar> Plane<T> {
480 pub fn normal(&self) -> Vector3<T> {
481 Vector3::new(self.a, self.b, self.c)
482 }
483 pub fn constant(&self) -> T {
484 self.d
485 }
486
487 pub fn intersect_ray(&self, r: &Ray<T, Vector3<T>>) -> Option<Vector3<T>> {
488 r.intersect_plane(self)
489 }
490
491 pub fn intersect_line(
495 &self,
496 line: &Line<T, Vector3<T>>,
497 epsilon: T,
498 ) -> Option<(T, Vector3<T>)> {
499 let s = line.p;
500 let dir = line.d;
501 let n = self.normal();
502
503 let denom = Vector3::dot(&n, &dir);
504 if denom.tabs() < epsilon {
505 None
506 } else {
507 let t = -(self.constant() + Vector3::dot(&n, &s)) / denom;
508 Some((t, dir * t + s))
509 }
510 }
511}
512
513impl<T: FloatScalar> Plane<T> {
514 pub fn new(n: &Vector3<T>, p: &Vector3<T>) -> Self {
515 let norm = Vector3::normalize(n);
516 let d = Vector3::dot(&norm, p);
517 Self {
518 a: norm.x,
519 b: norm.y,
520 c: norm.z,
521 d: -d,
522 }
523 }
524
525 pub fn from_tri(v0: &Vector3<T>, v1: &Vector3<T>, v2: &Vector3<T>) -> Self {
526 let n = tri_normal(v0, v1, v2);
527 Self::new(&n, v0)
528 }
529 pub fn from_quad(v0: &Vector3<T>, v1: &Vector3<T>, v2: &Vector3<T>, v3: &Vector3<T>) -> Self {
530 let n = quad_normal(v0, v1, v2, v3);
531 let c = (*v0 + *v1 + *v2 + *v3) * T::quarter();
532 Self::new(&n, &c)
533 }
534}
535
536#[repr(C)]
540#[derive(Clone, Copy, Default)]
541pub struct ParametricPlane<T: Scalar> {
542 pub center: Vector3<T>,
543 pub x_axis: Vector3<T>,
544 pub y_axis: Vector3<T>,
545}
546
547impl<T: FloatScalar> ParametricPlane<T> {
548 pub fn new(center: &Vector3<T>, x_axis: &Vector3<T>, y_axis: &Vector3<T>) -> Self {
549 Self {
550 center: *center,
551 x_axis: *x_axis,
552 y_axis: *y_axis,
553 }
554 }
555
556 pub fn plane(&self) -> Plane<T> {
557 Plane::new(&self.normal(), &self.center)
558 }
559
560 pub fn normal(&self) -> Vector3<T> {
562 Vector3::cross(&self.x_axis, &self.y_axis).normalize()
563 }
564
565 pub fn intersect_ray(&self, r: &Ray<T, Vector3<T>>) -> Option<Vector3<T>> {
566 r.intersect_plane(&self.plane())
567 }
568
569 pub fn intersect_line(
570 &self,
571 line: &Line<T, Vector3<T>>,
572 epsilon: T,
573 ) -> Option<(T, Vector3<T>)> {
574 self.plane().intersect_line(line, epsilon)
575 }
576
577 pub fn project(&self, v: &Vector3<T>) -> Vector2<T> {
578 let p = *v - self.center;
579 let x_coord = dot(&p, &self.x_axis) / dot(&self.x_axis, &self.x_axis);
580 let y_coord = dot(&p, &self.y_axis) / dot(&self.y_axis, &self.y_axis);
581 Vector2::new(x_coord, y_coord)
582 }
583}
584
585pub fn tri_normal<T: FloatScalar>(v0: &Vector3<T>, v1: &Vector3<T>, v2: &Vector3<T>) -> Vector3<T> {
589 let v10 = *v1 - *v0;
590 let v20 = *v2 - *v0;
591 Vector3::normalize(&Vector3::cross(&v10, &v20))
592}
593
594pub fn quad_normal<T: FloatScalar>(
598 v0: &Vector3<T>,
599 v1: &Vector3<T>,
600 v2: &Vector3<T>,
601 v3: &Vector3<T>,
602) -> Vector3<T> {
603 let v20 = *v2 - *v0;
604 let v31 = *v3 - *v1;
605 Vector3::normalize(&Vector3::cross(&v20, &v31))
606}
607
608#[cfg(test)]
609mod tests {
610 use super::*;
611 #[test]
612 pub fn test_barycentric() {
613 let v0 = Vector3::new(0.0, 0.0, 0.0);
614 let v1 = Vector3::new(0.0, 1.0, 0.0);
615 let v2 = Vector3::new(0.0, 0.0, 1.0);
616
617 let tri = Tri3::new([v0, v1, v2]);
618 let pp0 = tri.barycentric_coordinates(&v0);
619 assert!(f32::abs(pp0.x - 1.0) < 0.01);
620 assert!(f32::abs(pp0.y) < 0.01);
621 assert!(f32::abs(pp0.z) < 0.01);
622
623 let pp1 = tri.barycentric_coordinates(&v1);
624 assert!(f32::abs(pp1.x) < 0.01);
625 assert!(f32::abs(pp1.y - 1.0) < 0.01);
626 assert!(f32::abs(pp1.z) < 0.01);
627
628 let pp2 = tri.barycentric_coordinates(&v2);
629 assert!(f32::abs(pp2.x) < 0.01);
630 assert!(f32::abs(pp2.y) < 0.01);
631 assert!(f32::abs(pp2.z - 1.0) < 0.01);
632 }
633
634 #[test]
635 pub fn test_barycentric_translated() {
636 let v0 = Vector3::new(1.0, 2.0, 3.0);
638 let v1 = Vector3::new(4.0, 2.0, 3.0);
639 let v2 = Vector3::new(1.0, 5.0, 3.0);
640
641 let tri = Tri3::new([v0, v1, v2]);
642
643 let pp0 = tri.barycentric_coordinates(&v0);
645 assert!(f32::abs(pp0.x - 1.0) < 0.001);
646 assert!(f32::abs(pp0.y) < 0.001);
647 assert!(f32::abs(pp0.z) < 0.001);
648
649 let pp1 = tri.barycentric_coordinates(&v1);
650 assert!(f32::abs(pp1.x) < 0.001);
651 assert!(f32::abs(pp1.y - 1.0) < 0.001);
652 assert!(f32::abs(pp1.z) < 0.001);
653
654 let pp2 = tri.barycentric_coordinates(&v2);
655 assert!(f32::abs(pp2.x) < 0.001);
656 assert!(f32::abs(pp2.y) < 0.001);
657 assert!(f32::abs(pp2.z - 1.0) < 0.001);
658
659 let center = (v0 + v1 + v2) / 3.0;
661 let pp_center = tri.barycentric_coordinates(¢er);
662 assert!(f32::abs(pp_center.x - 1.0/3.0) < 0.001);
663 assert!(f32::abs(pp_center.y - 1.0/3.0) < 0.001);
664 assert!(f32::abs(pp_center.z - 1.0/3.0) < 0.001);
665
666 assert!(f32::abs((pp_center.x + pp_center.y + pp_center.z) - 1.0) < 0.001);
668 }
669
670 #[test]
671 pub fn test_barycentric_edge_midpoints() {
672 let v0 = Vector3::new(0.0, 0.0, 0.0);
673 let v1 = Vector3::new(2.0, 0.0, 0.0);
674 let v2 = Vector3::new(0.0, 2.0, 0.0);
675
676 let tri = Tri3::new([v0, v1, v2]);
677
678 let mid01 = (v0 + v1) / 2.0;
680 let pp_mid01 = tri.barycentric_coordinates(&mid01);
681 assert!(f32::abs(pp_mid01.x - 0.5) < 0.001);
682 assert!(f32::abs(pp_mid01.y - 0.5) < 0.001);
683 assert!(f32::abs(pp_mid01.z) < 0.001);
684
685 let mid02 = (v0 + v2) / 2.0;
687 let pp_mid02 = tri.barycentric_coordinates(&mid02);
688 assert!(f32::abs(pp_mid02.x - 0.5) < 0.001);
689 assert!(f32::abs(pp_mid02.y) < 0.001);
690 assert!(f32::abs(pp_mid02.z - 0.5) < 0.001);
691
692 let mid12 = (v1 + v2) / 2.0;
694 let pp_mid12 = tri.barycentric_coordinates(&mid12);
695 assert!(f32::abs(pp_mid12.x) < 0.001);
696 assert!(f32::abs(pp_mid12.y - 0.5) < 0.001);
697 assert!(f32::abs(pp_mid12.z - 0.5) < 0.001);
698 }
699
700 #[test]
701 pub fn test_barycentric_interpolation() {
702 let v0 = Vector3::new(1.0, 0.0, 0.0);
704 let v1 = Vector3::new(0.0, 1.0, 0.0);
705 let v2 = Vector3::new(0.0, 0.0, 1.0);
706
707 let tri = Tri3::new([v0, v1, v2]);
708
709 let test_point = Vector3::new(0.2, 0.3, 0.5);
711 let bary = tri.barycentric_coordinates(&test_point);
712
713 let reconstructed = v0 * bary.x + v1 * bary.y + v2 * bary.z;
715
716 assert!(f32::abs(reconstructed.x - test_point.x) < 0.001);
717 assert!(f32::abs(reconstructed.y - test_point.y) < 0.001);
718 assert!(f32::abs(reconstructed.z - test_point.z) < 0.001);
719 }
720}