1use crate::matrix::*;
30use crate::scalar::*;
31use crate::vector::*;
32
33#[repr(C)]
37#[derive(Debug, Clone, Copy, Default)]
38pub struct Dimension<T: Scalar> {
39 pub width: T,
40 pub height: T,
41}
42
43impl<T: Scalar> Dimension<T> {
44 pub fn new(width: T, height: T) -> Self {
45 Self { width, height }
46 }
47}
48
49#[repr(C)]
53#[derive(Debug, Clone, Copy, Default)]
54pub struct Rect<T: Scalar> {
55 pub x: T,
56 pub y: T,
57 pub width: T,
58 pub height: T,
59}
60
61impl<T: Scalar> Rect<T> {
62 pub fn new(x: T, y: T, width: T, height: T) -> Self {
63 Self {
64 x,
65 y,
66 width,
67 height,
68 }
69 }
70 pub fn from(min_vec: &Vector2<T>, max_vec: &Vector2<T>) -> Self {
71 let min_x = T::min(min_vec.x, max_vec.x);
72 let min_y = T::min(min_vec.y, max_vec.y);
73 let max_x = T::max(min_vec.x, max_vec.x);
74 let max_y = T::max(min_vec.y, max_vec.y);
75 Self {
76 x: min_x,
77 y: min_y,
78 width: max_x - min_x,
79 height: max_y - min_y,
80 }
81 }
82
83 pub fn min(&self) -> Vector2<T> {
84 Vector2::new(self.x, self.y)
85 }
86 pub fn max(&self) -> Vector2<T> {
87 Vector2::new(self.x + self.width, self.y + self.height)
88 }
89 pub fn intersect(&self, other: &Self) -> Option<Self> {
90 let smx = self.max();
91 let smn = self.min();
92 let omx = other.max();
93 let omn = other.min();
94
95 if smx.x < omn.x || smx.y < omn.y || smn.x > omx.x || smn.y > omx.y {
96 return None;
97 }
98
99 let min_vec = Vector2::max(&self.min(), &other.min());
100 let max_vec = Vector2::min(&self.max(), &other.max());
101 Some(Self::from(&min_vec, &max_vec))
102 }
103
104 pub fn contains(&self, p: &Vector2<T>) -> bool {
105 p.x >= self.x && p.y >= self.y && p.x <= self.x + self.width && p.y <= self.y + self.height
106 }
107}
108
109#[repr(C)]
113#[derive(Debug, Clone, Copy, Default)]
114pub struct Box3<T: Scalar> {
115 pub min: Vector3<T>,
116 pub max: Vector3<T>,
117}
118
119impl<T: Scalar> Box3<T> {
120 pub fn new(v0: &Vector3<T>, v1: &Vector3<T>) -> Self {
121 Self {
122 min: Vector3::min(v0, v1),
123 max: Vector3::max(v0, v1),
124 }
125 }
126 pub fn center(&self) -> Vector3<T> {
127 (self.max + self.min) * T::half()
128 }
129 pub fn extent(&self) -> Vector3<T> {
130 self.max - self.center()
131 }
132 pub fn overlap(&self, other: &Self) -> bool {
133 if self.max.x < other.min.x {
134 return false;
135 }
136 if self.max.y < other.min.y {
137 return false;
138 }
139 if self.max.z < other.min.z {
140 return false;
141 }
142
143 if self.min.x > other.max.x {
144 return false;
145 }
146 if self.min.x > other.max.x {
147 return false;
148 }
149 if self.min.x > other.max.x {
150 return false;
151 }
152 return true;
153 }
154
155 pub fn add(&self, p: &Vector3<T>) -> Self {
156 Self {
157 min: Vector3::min(&p, &self.min),
158 max: Vector3::max(&p, &self.max),
159 }
160 }
161
162 pub fn subdivide(&self) -> [Self; 8] {
163 let cube_table: [Vector3<i32>; 8] = [
164 Vector3::new(0, 1, 0),
165 Vector3::new(1, 1, 0),
166 Vector3::new(1, 1, 1),
167 Vector3::new(0, 1, 1),
168 Vector3::new(0, 0, 0),
169 Vector3::new(1, 0, 0),
170 Vector3::new(1, 0, 1),
171 Vector3::new(0, 0, 1),
172 ];
173
174 let ps: [Vector3<T>; 2] = [self.min, self.max];
175 let mut vs = [Vector3::zero(); 8];
176 for i in 0..8 {
177 vs[i] = Vector3::new(
178 ps[cube_table[i].x as usize].x,
179 ps[cube_table[i].y as usize].y,
180 ps[cube_table[i].z as usize].z,
181 );
182 }
183
184 let c = self.center();
185 let mut out = [Box3 {
186 min: Vector3::zero(),
187 max: Vector3::zero(),
188 }; 8];
189 for i in 0..8 {
190 out[i] = Self::new(&Vector3::min(&c, &vs[i]), &Vector3::max(&c, &vs[i]));
191 }
192 out
193 }
194}
195
196#[repr(C)]
200#[derive(Debug, Clone, Copy, Default)]
201pub struct Line<T: Scalar, V: Vector<T>> {
202 pub p: V, pub d: V, t: core::marker::PhantomData<T>,
205}
206
207impl<T: Scalar, V: Vector<T>> Line<T, V> {
208 pub fn new(p: &V, d: &V) -> Self {
209 Self {
210 p: *p,
211 d: *d,
212 t: core::marker::PhantomData,
213 }
214 }
215 pub fn from_start_end(s: &V, e: &V) -> Self {
216 Self {
217 p: *s,
218 d: *e - *s,
219 t: core::marker::PhantomData,
220 }
221 }
222 pub fn closest_point_on_line(&self, p: &V) -> (T, V) {
223 let p_dir = *p - self.p;
224
225 let d_sp = V::dot(&self.d, &p_dir);
226 let d_ss = V::dot(&self.d, &self.d);
227
228 let t = d_sp / d_ss;
229
230 (t, self.p + self.d * t)
231 }
232}
233
234impl<T: FloatScalar, V: FloatVector<T>> Line<T, V> {
235 pub fn normalize(&self) -> Self {
236 Self {
237 p: self.p,
238 d: FloatVector::normalize(&self.d),
239 t: core::marker::PhantomData,
240 }
241 }
242}
243
244pub fn shortest_segment3d_between_lines3d<T: FloatScalar>(
245 line0: &Line<T, Vector3<T>>,
246 line1: &Line<T, Vector3<T>>,
247 epsilon: T,
248) -> Option<Segment<T, Vector3<T>>> {
249 let s0 = line0.p;
250 let s1 = line1.p;
251
252 let d1 = line1.d;
253 let d0 = line0.d;
254
255 let normal = Vector3::normalize(&Vector3::cross(&d1, &d0));
256 let n0 = Vector3::normalize(&Vector3::cross(&normal, &d0));
257 let n1 = Vector3::normalize(&Vector3::cross(&normal, &d1));
258
259 let plane0 = Plane::new(&n0, &s0);
260 let plane1 = Plane::new(&n1, &s1);
261
262 let p1 = plane0.intersect_line(line1, epsilon);
263 let p0 = plane1.intersect_line(line0, epsilon);
264
265 match (p0, p1) {
266 (Some((_, s)), Some((_, e))) => Some(Segment::new(&s, &e)),
267 _ => None,
268 }
269}
270
271#[repr(C)]
275#[derive(Clone, Copy, Default)]
276pub struct Segment<T: Scalar, V: Vector<T>> {
277 pub s: V, pub e: V, t: core::marker::PhantomData<T>,
280}
281
282impl<T: Scalar, V: Vector<T>> Segment<T, V> {
283 pub fn new(s: &V, e: &V) -> Self {
284 Self {
285 s: *s,
286 e: *e,
287 t: core::marker::PhantomData,
288 }
289 }
290 pub fn closest_point_on_segment(&self, p: &V) -> (T, V) {
291 let dir = self.e - self.s;
292 let p_dir = *p - self.s;
293
294 let d_sp = V::dot(&dir, &p_dir);
295 let d_ss = V::dot(&dir, &dir);
296
297 if d_sp < T::zero() {
298 return (T::zero(), self.s);
299 } else if d_sp > d_ss {
300 return (T::one(), self.e);
301 }
302
303 let t = d_sp / d_ss;
304
305 (t, self.s + dir * t)
306 }
307}
308
309impl<T: FloatScalar, V: FloatVector<T>> Segment<T, V> {
310 pub fn distance(&self, p: &V) -> T {
311 let (_, p_on_seg) = self.closest_point_on_segment(p);
312 V::length(&(p_on_seg - *p))
313 }
314}
315
316#[repr(C)]
320#[derive(Clone, Copy, Default)]
321pub struct Ray<T: Scalar, V: Vector<T>> {
322 pub start: V,
323 pub direction: V,
324 t: core::marker::PhantomData<T>,
325}
326
327impl<T: FloatScalar, V: FloatVector<T>> Ray<T, V> {
328 pub fn new(start: &V, direction: &V) -> Self {
329 Self {
330 start: *start,
331 direction: V::normalize(direction),
332 t: core::marker::PhantomData,
333 }
334 }
335}
336
337impl<T: Scalar> Ray<T, Vector3<T>> {
338 pub fn intersect_plane(&self, p: &Plane<T>) -> Option<Vector3<T>> {
339 let n = p.normal();
340 let t: T = -(p.d + Vector3::dot(&n, &self.start)) / Vector3::dot(&n, &self.direction);
341 if t < T::zero() {
342 None
343 } else {
344 Some(self.direction * t + self.start)
345 }
346 }
347}
348
349#[repr(C)]
353#[derive(Clone, Copy, Default)]
354pub struct Sphere3<T: FloatScalar> {
355 pub center: Vector3<T>,
356 pub radius: T,
357}
358
359impl<T: FloatScalar> Sphere3<T> {
360 pub fn new(center: Vector3<T>, radius: T) -> Self {
361 Self {
362 center: center,
363 radius: radius,
364 }
365 }
366}
367
368#[repr(C)]
372#[derive(Clone, Copy, Default)]
373pub struct Tri3<T: FloatScalar> {
374 vertices: [Vector3<T>; 3],
375}
376
377impl<T: FloatScalar> Tri3<T> {
378 pub fn new(vertices: [Vector3<T>; 3]) -> Self {
379 Self { vertices: vertices }
380 }
381 pub fn vertices(&self) -> &[Vector3<T>; 3] {
382 &self.vertices
383 }
384
385 pub fn barycentric_coordinates(&self, pt: &Vector3<T>) -> Vector3<T> {
386 let v0 = self.vertices[0];
387 let v1 = self.vertices[1];
388 let v2 = self.vertices[2];
389 let vv1 = v1 - v0;
390 let vv2 = v2 - v0;
391 let vvc = Vector3::cross(&vv1, &vv2);
392 let m = Matrix3::new(
393 vv1.x, vv1.y, vv1.z, vv2.x, vv2.y, vv2.z, vvc.x, vvc.y, vvc.z,
394 );
395 let lambda = m.inverse() * *pt;
396 Vector3::new(T::one() - lambda.x - lambda.y, lambda.x, lambda.y)
397 }
398}
399
400#[repr(C)]
404#[derive(Clone, Copy, Default)]
405pub struct Plane<T: Scalar> {
406 a: T,
407 b: T,
408 c: T,
409 d: T,
410}
411
412impl<T: Scalar> Plane<T> {
413 pub fn normal(&self) -> Vector3<T> {
414 Vector3::new(self.a, self.b, self.c)
415 }
416 pub fn constant(&self) -> T {
417 self.d
418 }
419
420 pub fn intersect_ray(&self, r: &Ray<T, Vector3<T>>) -> Option<Vector3<T>> {
421 r.intersect_plane(self)
422 }
423
424 pub fn intersect_line(
425 &self,
426 line: &Line<T, Vector3<T>>,
427 epsilon: T,
428 ) -> Option<(T, Vector3<T>)> {
429 let s = line.p;
430 let dir = line.d;
431 let n = self.normal();
432
433 let denom = Vector3::dot(&n, &dir);
434 if denom.tabs() < epsilon {
435 None
436 } else {
437 let t = -(self.constant() + Vector3::dot(&n, &s)) / denom;
438 Some((t, dir * t + s))
439 }
440 }
441}
442
443impl<T: FloatScalar> Plane<T> {
444 pub fn new(n: &Vector3<T>, p: &Vector3<T>) -> Self {
445 let norm = Vector3::normalize(n);
446 let d = Vector3::dot(&norm, p);
447 Self {
448 a: norm.x,
449 b: norm.y,
450 c: norm.z,
451 d: -d,
452 }
453 }
454
455 pub fn from_tri(v0: &Vector3<T>, v1: &Vector3<T>, v2: &Vector3<T>) -> Self {
456 let n = tri_normal(v0, v1, v2);
457 Self::new(&n, v0)
458 }
459 pub fn from_quad(v0: &Vector3<T>, v1: &Vector3<T>, v2: &Vector3<T>, v3: &Vector3<T>) -> Self {
460 let n = quad_normal(v0, v1, v2, v3);
461 let c = (*v0 + *v1 + *v2 + *v3) * T::quarter();
462 Self::new(&n, &c)
463 }
464}
465
466#[repr(C)]
470#[derive(Clone, Copy, Default)]
471pub struct ParametricPlane<T: Scalar> {
472 pub center: Vector3<T>,
473 pub x_axis: Vector3<T>,
474 pub y_axis: Vector3<T>,
475}
476
477impl<T: FloatScalar> ParametricPlane<T> {
478 pub fn new(center: &Vector3<T>, x_axis: &Vector3<T>, y_axis: &Vector3<T>) -> Self {
479 Self {
480 center: *center,
481 x_axis: *x_axis,
482 y_axis: *y_axis,
483 }
484 }
485
486 pub fn plane(&self) -> Plane<T> {
487 Plane::new(&self.normal(), &self.center)
488 }
489
490 pub fn normal(&self) -> Vector3<T> {
491 Vector3::cross(&self.x_axis, &self.y_axis).normalize()
492 }
493
494 pub fn intersect_ray(&self, r: &Ray<T, Vector3<T>>) -> Option<Vector3<T>> {
495 r.intersect_plane(&self.plane())
496 }
497
498 pub fn intersect_line(
499 &self,
500 line: &Line<T, Vector3<T>>,
501 epsilon: T,
502 ) -> Option<(T, Vector3<T>)> {
503 self.plane().intersect_line(line, epsilon)
504 }
505
506 pub fn project(&self, v: &Vector3<T>) -> Vector2<T> {
507 let p = *v - self.center;
508 let x_coord = dot(&p, &self.x_axis) / dot(&self.x_axis, &self.x_axis);
509 let y_coord = dot(&p, &self.y_axis) / dot(&self.y_axis, &self.y_axis);
510 Vector2::new(x_coord, y_coord)
511 }
512}
513
514pub fn tri_normal<T: FloatScalar>(v0: &Vector3<T>, v1: &Vector3<T>, v2: &Vector3<T>) -> Vector3<T> {
518 let v10 = *v1 - *v0;
519 let v20 = *v2 - *v0;
520 Vector3::normalize(&Vector3::cross(&v10, &v20))
521}
522
523pub fn quad_normal<T: FloatScalar>(
527 v0: &Vector3<T>,
528 v1: &Vector3<T>,
529 v2: &Vector3<T>,
530 v3: &Vector3<T>,
531) -> Vector3<T> {
532 let v20 = *v2 - *v0;
533 let v31 = *v3 - *v1;
534 Vector3::normalize(&Vector3::cross(&v20, &v31))
535}
536
537#[cfg(test)]
538mod tests {
539 use super::*;
540 #[test]
541 pub fn test_barycentric() {
542 let v0 = Vector3::new(0.0, 0.0, 0.0);
543 let v1 = Vector3::new(0.0, 1.0, 0.0);
544 let v2 = Vector3::new(0.0, 0.0, 1.0);
545
546 let tri = Tri3::new([v0, v1, v2]);
547 let pp0 = tri.barycentric_coordinates(&v0);
548 assert!(f32::abs(pp0.x - 1.0) < 0.01);
549 assert!(f32::abs(pp0.y) < 0.01);
550 assert!(f32::abs(pp0.z) < 0.01);
551
552 let pp1 = tri.barycentric_coordinates(&v1);
553 assert!(f32::abs(pp1.x) < 0.01);
554 assert!(f32::abs(pp1.y - 1.0) < 0.01);
555 assert!(f32::abs(pp1.z) < 0.01);
556
557 let pp2 = tri.barycentric_coordinates(&v2);
558 assert!(f32::abs(pp2.x) < 0.01);
559 assert!(f32::abs(pp2.y) < 0.01);
560 assert!(f32::abs(pp2.z - 1.0) < 0.01);
561 }
562}