1pub mod num;
22
23pub mod vec;
25
26pub mod mat;
29
30pub mod quat;
32
33pub mod swizz;
35
36use num::*;
37use vec::*;
38use mat::*;
39use quat::*;
40
41#[cfg(feature = "short_types")]
43pub type Vec2f = Vec2<f32>;
44
45#[cfg(feature = "short_types")]
46pub type Vec3f = Vec3<f32>;
47
48#[cfg(feature = "short_types")]
49pub type Vec4f = Vec4<f32>;
50
51#[cfg(feature = "short_types")]
52pub type Vec2d = Vec2<f64>;
53
54#[cfg(feature = "short_types")]
55pub type Vec3d = Vec3<f64>;
56
57#[cfg(feature = "short_types")]
58pub type Vec4d = Vec4<f64>;
59
60#[cfg(feature = "short_types")]
61pub type Vec2i = Vec2<i32>;
62
63#[cfg(feature = "short_types")]
64pub type Vec3i = Vec3<i32>;
65
66#[cfg(feature = "short_types")]
67pub type Vec4i = Vec4<i32>;
68
69#[cfg(feature = "short_types")]
70pub type Vec2u = Vec2<u32>;
71
72#[cfg(feature = "short_types")]
73pub type Vec3u = Vec3<u32>;
74
75#[cfg(feature = "short_types")]
76pub type Vec4u = Vec4<u32>;
77
78#[cfg(feature = "short_types")]
79pub type Mat2f = Mat2<f32>;
80
81#[cfg(feature = "short_types")]
82pub type Mat3f = Mat3<f32>;
83
84#[cfg(feature = "short_types")]
85pub type Mat34f = Mat34<f32>;
86
87#[cfg(feature = "short_types")]
88pub type Mat43f = Mat43<f32>;
89
90#[cfg(feature = "short_types")]
91pub type Mat4f = Mat4<f32>;
92
93#[cfg(feature = "short_types")]
94pub type Mat2d = Mat2<f64>;
95
96#[cfg(feature = "short_types")]
97pub type Mat3d = Mat3<f64>;
98
99#[cfg(feature = "short_types")]
100pub type Mat34d = Mat34<f64>;
101
102#[cfg(feature = "short_types")]
103pub type Mat43d = Mat43<f64>;
104
105#[cfg(feature = "short_types")]
106pub type Mat4d = Mat4<f64>;
107
108#[cfg(feature = "short_types")]
109pub type Quatf = Quat<f32>;
110
111#[cfg(feature = "short_types")]
112pub type Quatd = Quat<f64>;
113
114#[derive(PartialEq, Debug)]
116pub enum Classification {
117 Behind,
119 Infront,
121 Intersects,
123}
124
125pub fn min<T: Number, V: NumberOps<T>>(a: V, b: V) -> V {
127 V::min(a, b)
128}
129
130pub fn max<T: Number, V: NumberOps<T>>(a: V, b: V) -> V {
132 V::max(a, b)
133}
134
135pub fn min_max<T: Number, V: NumberOps<T> + Copy>(a: V, min_max: (V, V)) -> (V, V) {
137 (V::min(a, min_max.0), V::max(a, min_max.1))
138}
139
140pub fn clamp<T: Number, V: NumberOps<T>>(x: V, min: V, max: V) -> V {
142 V::clamp(x, min, max)
143}
144
145pub fn step<T: Number, V: NumberOps<T>>(a: V, b: V) -> V {
147 V::step(a, b)
148}
149
150pub fn signum<T: SignedNumber, V: SignedNumberOps<T>>(a: V) -> V {
152 V::signum(a)
153}
154
155pub fn copysign<T: Float, V: FloatOps<T>>(a: V, sign: T) -> V {
157 V::copysign(a, sign)
158}
159
160pub fn abs<T: SignedNumber, V: SignedNumberOps<T>>(a: V) -> V {
162 V::abs(a)
163}
164
165pub fn deg_to_rad<T: Float, V: FloatOps<T>>(a: V) -> V {
167 V::deg_to_rad(a)
168}
169
170pub fn rad_to_deg<T: Float, V: FloatOps<T>>(a: V) -> V {
172 V::rad_to_deg(a)
173}
174
175pub fn floor<T: Float, V: FloatOps<T>>(a: V) -> V {
177 V::floor(a)
178}
179
180pub fn ceil<T: Float, V: FloatOps<T>>(a: V) -> V {
182 V::ceil(a)
183}
184
185pub fn round<T: Float, V: FloatOps<T>>(a: V) -> V {
187 V::round(a)
188}
189
190pub fn approx<T: Float, V: FloatOps<T>>(a: V, b: V, eps: T) -> bool {
192 V::approx(a, b, eps)
193}
194
195pub fn sqrt<T: Float, V: FloatOps<T>>(a: V) -> V {
197 V::sqrt(a)
198}
199
200pub fn powi<T: Float, V: FloatOps<T>>(a: V, b: i32) -> V {
202 V::powi(a, b)
203}
204
205pub fn sqr<T: Float, V: FloatOps<T> + Base<T>>(a: V) -> V {
207 a * a
208}
209
210pub fn cube<T: Float, V: FloatOps<T> + Base<T>>(a: V) -> V {
212 a * a * a
213}
214
215pub fn powf<T: Float, V: FloatOps<T>>(a: V, b: T) -> V {
217 V::powf(a, b)
218}
219
220pub fn mad<T: Float, V: FloatOps<T>>(m: V, a: V, b: V) -> V {
222 V::mad(m, a, b)
223}
224
225pub fn fmod<T: Float, V: FloatOps<T>>(a: V, b: V) -> V {
227 V::fmod(a, b)
228}
229
230pub fn frac<T: Float, V: FloatOps<T>>(a: V) -> V {
232 V::frac(a)
233}
234
235pub fn trunc<T: Float, V: FloatOps<T>>(a: V) -> V {
237 V::trunc(a)
238}
239
240pub fn rsqrt<T: Float, V: FloatOps<T>>(a: V) -> V {
242 V::rsqrt(a)
243}
244
245pub fn recip<T: Float, V: FloatOps<T>>(a: V) -> V {
247 V::recip(a)
248}
249
250pub fn modf<T: Float, V: FloatOps<T>>(v: V) -> (V, V) {
252 V::modf(v)
253}
254
255pub fn lerp<T: Float, V: Lerp<T>>(e0: V, e1: V, t: T) -> V {
257 V::lerp(e0, e1, t)
258}
259
260pub fn nlerp<T: Float, V: Nlerp<T>>(e0: V, e1: V, t: T) -> V {
262 V::nlerp(e0, e1, t)
263}
264
265pub fn slerp<T: Float + NumberOps<T> + FloatOps<T>, V: Slerp<T>>(e0: V, e1: V, t: T) -> V {
267 V::slerp(e0, e1, t)
268}
269
270pub fn smoothstep<T: Float, V: FloatOps<T>>(e0: V, e1: V, t: T) -> V {
272 V::smoothstep(e0, e1, t)
273}
274
275pub fn saturate<T: Float, V: FloatOps<T>>(x: V) -> V {
277 V::saturate(x)
278}
279
280pub fn cross<T: Number, V: Cross<T>>(a: V, b: V) -> V {
282 V::cross(a, b)
283}
284
285pub fn scalar_triple<T: Number + SignedNumber, V: Triple<T>>(a: V, b: V, c: V) -> T {
287 V::scalar_triple(a, b, c)
288}
289
290pub fn vector_triple<T: Number + SignedNumber, V: Triple<T>>(a: V, b: V, c: V) -> V {
292 V::vector_triple(a, b, c)
293}
294
295pub fn perp<T: SignedNumber>(a: Vec2<T>) -> Vec2<T> {
297 Vec2 {
298 x: -a.y,
299 y: a.x
300 }
301}
302
303pub fn dot<T: Number, V: Dot<T>>(a: V, b: V) -> T {
305 V::dot(a, b)
306}
307
308pub fn length<T: Float, V: Magnitude<T>>(a: V) -> T {
310 V::length(a)
311}
312
313pub fn mag<T: Float, V: Magnitude<T>>(a: V) -> T {
315 V::mag(a)
316}
317
318pub fn mag2<T: Float, V: Magnitude<T>>(a: V) -> T {
320 V::mag2(a)
321}
322
323pub fn normalize<T: Float, V: Magnitude<T>>(a: V) -> V {
325 V::normalize(a)
326}
327
328pub fn chebyshev_normalize<T: Float, V: VecFloatOps<T> + VecN<T> + SignedNumberOps<T>>(a: V) -> V {
330 a / V::max_scalar(V::abs(a))
331}
332
333pub fn distance<T: Float, V: VecFloatOps<T>>(a: V, b: V) -> T {
335 V::distance(a, b)
336}
337
338pub fn dist<T: Float, V: VecFloatOps<T>>(a: V, b: V) -> T {
340 V::dist(a, b)
341}
342
343pub fn dist2<T: Float, V: VecFloatOps<T>>(a: V, b: V) -> T {
345 V::dist2(a, b)
346}
347
348pub fn barycentric<T: Float + NumberOps<T>, V: VecN<T> + VecFloatOps<T> + NumberOps<T>>(p: V, t1: V, t2: V, t3: V) -> (T, T, T) {
350 let x13 = t1 - t3;
351 let x23 = t2 - t3;
352 let x03 = p - t3;
353 let m13 = mag2(x13);
354 let m23 = mag2(x23);
355 let d = dot(x13, x23);
356 let invdet = T::one() / T::max(m13 * m23 - d * d, T::small_epsilon());
357 let a = dot(x13, x03);
358 let b = dot(x23, x03);
359 let u = invdet * (m23 * a - d * b);
360 let v = invdet * (m13 * b - d * a);
361 let w = T::one() - u - v;
362 (u, v, w)
363}
364
365pub fn azimuth_altitude_to_xyz<T: Float + FloatOps<T>>(azimuth: T, altitude: T) -> Vec3<T> {
367 let z = T::sin(altitude);
368 let hyp = T::cos(altitude);
369 let y = hyp * T::cos(azimuth);
370 let x = hyp * T::sin(azimuth);
371 Vec3::<T>::new(x, z, y)
372}
373
374pub fn focal_length_to_fov<T: Float + FloatOps<T> + Cast<T>>(focal_length: T, aperture_width: T) -> T {
376 T::two() * rad_to_deg(atan((aperture_width * T::from_f64(25.4)) / (T::two() * focal_length)))
377}
378
379pub fn fov_to_focal_length<T: Float + FloatOps<T> + Cast<T>>(fov: T, aperture_width: T) -> T {
381 (aperture_width * T::from_f64(25.4)) / (T::two() * tan(deg_to_rad(fov / T::two())))
382}
383
384pub fn xyz_to_azimuth_altitude<T: Float + FloatOps<T>>(xyz: Vec3<T>) -> (T, T) {
386 (T::atan2(xyz.y, xyz.x), T::atan2(xyz.z, sqrt(xyz.x * xyz.x + xyz.y * xyz.y)))
387}
388
389pub fn cos<T: Float, V: FloatOps<T>>(v: V) -> V {
391 V::cos(v)
392}
393
394pub fn sin<T: Float, V: FloatOps<T>>(v: V) -> V {
396 V::sin(v)
397}
398
399pub fn tan<T: Float, V: FloatOps<T>>(v: V) -> V {
401 V::tan(v)
402}
403
404pub fn acos<T: Float, V: FloatOps<T>>(v: V) -> V {
406 V::acos(v)
407}
408
409pub fn asin<T: Float, V: FloatOps<T>>(v: V) -> V {
411 V::asin(v)
412}
413
414pub fn atan<T: Float, V: FloatOps<T>>(v: V) -> V {
416 V::atan(v)
417}
418
419pub fn atan2<T: Float, V: FloatOps<T>>(y: V, x: V) -> V {
421 V::atan2(y, x)
422}
423
424pub fn cosh<T: Float, V: FloatOps<T>>(v: V) -> V {
426 V::cosh(v)
427}
428
429pub fn sinh<T: Float, V: FloatOps<T>>(v: V) -> V {
431 V::sinh(v)
432}
433
434pub fn tanh<T: Float, V: FloatOps<T>>(v: V) -> V {
436 V::tanh(v)
437}
438
439pub fn sin_cos<T: Float, V: FloatOps<T>>(v: V) -> (V, V) {
441 V::sin_cos(v)
442}
443
444pub fn exp<T: Float, V: FloatOps<T>>(v: V) -> V {
446 V::exp(v)
447}
448
449pub fn exp2<T: Float, V: FloatOps<T>>(v: V) -> V {
451 V::exp2(v)
452}
453
454pub fn log2<T: Float, V: FloatOps<T>>(v: V) -> V {
456 V::log2(v)
457}
458
459pub fn log10<T: Float, V: FloatOps<T>>(v: V) -> V {
461 V::log10(v)
462}
463
464pub fn log<T: Float, V: FloatOps<T>>(v: V, base: T) -> V {
466 V::log(v, base)
467}
468
469pub fn rotate_2d<T: Float + FloatOps<T>>(v: Vec2<T>, angle: T) -> Vec2<T> {
471 let c = cos(angle);
472 let s = sin(angle);
473 Vec2::new(c * v.x - s * v.y, s * v.x + c * v.y)
474}
475
476pub fn convex_hull_from_points<T: Float + SignedNumberOps<T> + NumberOps<T> + FloatOps<T>>(points: &[Vec2<T>]) -> Vec<Vec2<T>> {
478 let mut cur = points[0];
480 let mut curi = 0;
481 for (i, item) in points.iter().enumerate().skip(1) {
482 if item.x > cur.x || (item.x == cur.x && item.y > cur.y) {
483 cur = *item;
485 curi = i;
486 }
487 }
488
489 let mut hull = vec![cur];
492 loop {
493 let mut rm = (curi+1)%points.len();
494 let mut x1 = points[rm];
495
496 for (i, item) in points.iter().enumerate() {
497 if i == curi {
498 continue;
499 }
500 let x2 = *item;
501 let v1 = x1 - cur;
502 let v2 = x2 - cur;
503 let z = v2.x * v1.y - v2.y * v1.x;
504 if z > T::zero() {
505 x1 = *item;
506 rm = i;
507 }
508 }
509
510 if approx(x1, hull[0], T::small_epsilon()) {
511 break;
512 }
513
514 cur = x1;
515 curi = rm;
516 hull.push(x1);
517 }
518 hull
519}
520
521pub fn plane_from_normal_and_point<T: SignedNumber>(x: Vec3<T>, n: Vec3<T>) -> Vec4<T> {
523 Vec4 {
524 x: n.x,
525 y: n.y,
526 z: n.z,
527 w: plane_distance(x, n)
528 }
529}
530
531pub fn get_triangle_normal<T: Float, V: VecFloatOps<T> + VecN<T> + Cross<T>>(t1: V, t2: V, t3: V) -> V {
533 normalize(cross(t2 - t1, t3 - t1))
534}
535
536pub fn project_to_ndc<T: Float>(p: Vec3<T>, view_projection: Mat4<T>) -> Vec3<T> {
538 let ndc = view_projection * Vec4::from((p, T::one()));
539 Vec3::from(ndc) / ndc.w
540}
541
542pub fn project_to_sc<T: Float + FloatOps<T>>(p: Vec3<T>, view_projection: Mat4<T>, viewport: Vec2<T>) -> Vec3<T> {
545 let ndc = project_to_ndc(p, view_projection);
546 let sc = ndc * T::point_five() + T::point_five();
547 Vec3::from((Vec2::<T>::from(sc) * viewport, sc.z))
548}
549
550pub fn project_to_sc_vdown<T: Float + FloatOps<T>>(p: Vec3<T>, view_projection: Mat4<T>, viewport: Vec2<T>) -> Vec2<T> {
553 let ndc = project_to_ndc(p, view_projection);
554 let sc = ndc * Vec3::new(T::point_five(), -T::point_five(), T::point_five()) + T::point_five();
555 Vec2::<T>::from(sc) * viewport
556}
557
558pub fn unproject_ndc<T: Float>(p: Vec3<T>, view_projection: Mat4<T>) -> Vec3<T> {
560 let inv = view_projection.inverse();
561 inv * p
562}
563
564pub fn unproject_sc<T: Float>(p: Vec3<T>, view_projection: Mat4<T>, viewport: Vec2<T>) -> Vec3<T> {
567 let ndc_xy = (Vec2::from(p) / viewport) * Vec2::from(T::two()) - Vec2::from(T::one());
568 let ndc = Vec3::from((ndc_xy, p.z));
569 unproject_ndc(ndc, view_projection)
570}
571
572pub fn unproject_sc_vdown<T: Float>(p: Vec3<T>, view_projection: Mat4<T>, viewport: Vec2<T>) -> Vec3<T> {
575 let ndc_xy = (Vec2::from(p) / viewport) * Vec2::new(T::two(), -T::two()) - Vec2::from(T::one());
576 let ndc = Vec3::from((ndc_xy, p.z));
577 unproject_ndc(ndc, view_projection)
578}
579
580pub fn plane_distance<T: SignedNumber, V: VecN<T>>(x: V, n: V) -> T {
582 -V::dot(x, n)
583}
584
585pub fn distance_on_line<T: Float, V: VecFloatOps<T> + VecN<T>>(p: V, l1: V, l2: V) -> T {
587 let v1 = p - l1;
588 let v2 = V::normalize(l2 - l1);
589 dot(v2, v1)
590}
591
592pub fn distance_on_ray<T: Float, V: VecFloatOps<T> + VecN<T>>(p: V, r0: V, rv: V) -> T {
594 dot(p - r0, rv)
595}
596
597pub fn point_plane_distance<T: SignedNumber, V: VecN<T>>( p: V, x: V, n: V) -> T {
599 V::dot(p, n) - V::dot(x, n)
600}
601
602pub fn point_line_segment_distance<T: Float + FloatOps<T>, V: VecFloatOps<T> + VecN<T>>(p: V, l1: V, l2: V) -> T {
604 let dx = l2 - l1;
605 let m2 = mag2(dx);
606 let s12 = saturate(dot(l2 - p, dx) / m2);
608 dist(p, l1 * s12 + l2 * (T::one() - s12))
610}
611
612pub fn point_aabb_distance<T: Float, V: VecN<T> + NumberOps<T> + VecFloatOps<T>>(p: V, aabb_min: V, aabb_max: V) -> T {
614 dist(closest_point_on_aabb(p, aabb_min, aabb_max), p)
615}
616
617pub fn point_sphere_distance<T: Float, V: VecN<T> + NumberOps<T> + VecFloatOps<T>>(p0: V, s0: V, r: T) -> T {
619 dist(p0, closest_point_on_sphere(p0, s0, r))
620}
621
622pub fn point_triangle_distance<T: Float + FloatOps<T> + NumberOps<T>, V: VecN<T> + NumberOps<T> + VecFloatOps<T>>(p: V, t1: V, t2: V, t3: V) -> T {
624 let (w23, w31, w12) = barycentric(p, t1, t2, t3);
625 if w23 >= T::zero() && w31 >= T::zero() && w12 >= T::zero() {
626 dist(p, t1 * w23 + t2 * w31 + t3 * w12)
628 }
629 else {
630 if w23 > T::zero() {
632 T::min(point_line_segment_distance(p, t1, t2), point_line_segment_distance(p, t1, t3))
634 }
635 else if w31 > T::zero() {
636 T::min(point_line_segment_distance(p, t1, t2), point_line_segment_distance(p, t2, t3))
638 }
639 else {
640 T::min(point_line_segment_distance(p, t1, t3), point_line_segment_distance(p, t2, t3))
642 }
643 }
644}
645
646pub fn point_cone_distance<T: Float, V: VecN<T> + SignedVecN<T> + VecFloatOps<T>>(p: V, cp: V, cv: V, h: T, r: T) -> T {
648 dist(p, closest_point_on_cone(p, cp, cv, h, r))
649}
650
651pub fn point_convex_hull_distance<T: Float + FloatOps<T>>(p: Vec2<T>, hull: &[Vec2<T>]) -> T {
653 dist(p, closest_point_on_polygon(p, hull))
654}
655
656pub fn point_polygon_distance<T: Float + FloatOps<T>>(p: Vec2<T>, hull: &[Vec2<T>]) -> T {
658 dist(p, closest_point_on_polygon(p, hull))
659}
660
661pub fn point_obb_distance<T: Float, V: VecFloatOps<T> + NumberOps<T> + SignedNumberOps<T> + VecN<T> + SignedVecN<T>, M: MatTranslate<V> + MatInverse<T> + MatN<T, V>>(p: V, mat: M) -> T {
664 dist(p, closest_point_on_obb(p, mat))
665}
666
667pub fn closest_point_on_line_segment<T: Float, V: VecFloatOps<T> + VecN<T>>(p: V, l1: V, l2: V) -> V {
669 let v1 = p - l1;
670 let v2 = V::normalize(l2 - l1);
671 let t = V::dot(v2, v1);
672 if t < T::zero() {
673 l1
674 }
675 else if t > V::dist(l1, l2) {
676 l2
677 }
678 else {
679 l1 + (v2 * t)
680 }
681}
682
683pub fn closest_point_on_plane<T: SignedNumber, V: VecN<T> + SignedVecN<T>>(p: V, x: V, n: V) -> V {
685 p + n * -(V::dot(p, n) - V::dot(x, n))
686}
687
688pub fn closest_point_on_aabb<T: Float, V: NumberOps<T> + VecN<T>>(p: V, aabb_min: V, aabb_max: V) -> V {
690 V::min(V::max(p, aabb_min), aabb_max)
691}
692
693pub fn closest_point_on_sphere<T: Float, V: VecFloatOps<T> + VecN<T>>(p: V, s: V, r: T) -> V {
695 s + V::normalize(p - s) * r
696}
697
698pub fn closest_point_on_ray<T: Float, V: VecFloatOps<T> + VecN<T>>(p: V, r0: V, rv: V) -> V {
700 let v1 = p - r0;
701 let t = dot(v1, rv);
702 if t < T::zero() {
703 r0
704 }
705 else {
706 r0 + rv * t
707 }
708}
709
710pub fn closest_point_on_obb<T: Float, V: VecFloatOps<T> + NumberOps<T> + SignedNumberOps<T> + VecN<T> + SignedVecN<T>, M: MatTranslate<V> + MatInverse<T> + MatN<T, V>>(p: V, mat: M) -> V {
712 let invm = mat.inverse();
713 let tp = invm * p;
714 let cp = closest_point_on_aabb(tp, V::minus_one(), V::one());
715 mat * cp
716}
717
718pub fn closest_point_on_triangle<T: Float + FloatOps<T> + NumberOps<T>, V: VecN<T> + NumberOps<T> + VecFloatOps<T>>(p: V, t1: V, t2: V, t3: V) -> V {
720 let (w23, w31, w12) = barycentric(p, t1, t2, t3);
721 if w23 >= T::zero() && w31 >= T::zero() && w12 >= T::zero() {
722 p
723 }
724 else {
725 if w23 > T::zero() {
727 let p1 = closest_point_on_line_segment(p, t1, t2);
729 let p2 = closest_point_on_line_segment(p, t1, t3);
730 if dist2(p, p1) < dist2(p, p2) {
731 p1
732 }
733 else {
734 p2
735 }
736 }
737 else if w31 > T::zero() {
738 let p1 = closest_point_on_line_segment(p, t1, t2);
740 let p2 = closest_point_on_line_segment(p, t2, t3);
741 if dist2(p, p1) < dist2(p, p2) {
742 p1
743 }
744 else {
745 p2
746 }
747 }
748 else {
749 let p1 = closest_point_on_line_segment(p, t1, t3);
751 let p2 = closest_point_on_line_segment(p, t2, t3);
752 if dist2(p, p1) < dist2(p, p2) {
753 p1
754 }
755 else {
756 p2
757 }
758 }
759 }
760}
761
762pub fn closest_point_on_cone<T: Float, V: VecN<T> + VecFloatOps<T>>(p: V, cp: V, cv: V, h: T, r: T) -> V {
764 let l2 = cp + cv * h;
766
767 let cplane = closest_point_on_plane(p, l2, cv);
769 let extent = l2 + normalize(cplane - l2) * r;
770
771 let e1 = closest_point_on_line_segment(p, cp, extent);
773 let e2 = closest_point_on_line_segment(p, l2, extent);
774
775 if dist2(p, e1) < dist2(p, e2) {
776 e1
777 }
778 else {
779 e2
780 }
781}
782
783pub fn closest_point_on_convex_hull<T: Float + FloatOps<T>>(p: Vec2<T>, hull: &[Vec2<T>]) -> Vec2<T> {
785 closest_point_on_polygon(p, hull)
786}
787
788pub fn closest_point_on_polygon<T: Float + FloatOps<T>>(p: Vec2<T>, poly: &[Vec2<T>]) -> Vec2<T> {
790 let ncp = poly.len();
791 let mut cp = Vec2::max_value();
792 let mut cd2 = T::max_value();
793 for i in 0..ncp {
794 let i2 = (i+1)%ncp;
795 let cpp = closest_point_on_line_segment(p, poly[i], poly[i2]);
796 let cppd2 = dist2(p, cpp);
797 if dist2(p, cpp) < cd2 {
798 cp = cpp;
799 cd2 = cppd2;
800 }
801 }
802 cp
803}
804
805pub fn point_inside_aabb<T: Float, V: VecN<T> + VecFloatOps<T>>(p: V, aabb_min: V, aabb_max: V) -> bool {
807 for i in 0..V::len() {
808 if p[i] < aabb_min[i] || p[i] > aabb_max[i] {
809 return false;
810 }
811 }
812 true
813}
814
815pub fn point_inside_sphere<T: Float, V: VecFloatOps<T> + VecN<T>>(p: V, s: V, r: T) -> bool {
817 dist2(p, s) < r * r
818}
819
820pub fn point_inside_obb<T: Float, V: VecFloatOps<T> + NumberOps<T> + SignedNumberOps<T> + VecN<T> + SignedVecN<T>, M: MatTranslate<V> + MatInverse<T> + MatN<T, V>>(p: V, mat: M) -> bool {
822 let invm = mat.inverse();
823 let tp = invm * p;
824 point_inside_aabb(tp, V::minus_one(), V::one())
825}
826
827pub fn point_inside_triangle<T: Float + FloatOps<T> + NumberOps<T>, V: VecN<T> + NumberOps<T> + VecFloatOps<T>>(p: V, t1: V, t2: V, t3: V) -> bool {
829 let (w23, w31, w12) = barycentric(p, t1, t2, t3);
830 w23 >= T::zero() && w31 >= T::zero() && w12 >= T::zero()
831}
832
833pub fn point_inside_cone<T: Float + FloatOps<T> + NumberOps<T>, V: VecN<T> + VecFloatOps<T>>(p: V, cp: V, cv: V, h: T, r: T) -> bool {
835 let l2 = cp + cv * h;
836 let dh = distance_on_line(p, cp, l2) / h;
837 let x0 = closest_point_on_line_segment(p, cp, l2);
838 let d = dist(x0, p);
839 d < dh * r && dh < T::one()
840}
841
842pub fn point_inside_convex_hull<T: Float>(p: Vec2<T>, hull: &[Vec2<T>]) -> bool {
844 let ncp = hull.len();
845 for i in 0..ncp {
846 let i2 = (i+1)%ncp;
847 let p1 = hull[i];
848 let p2 = hull[i2];
849 let v1 = p2 - p1;
850 let v2 = p - p1;
851 let z = v1.x * v2.y - v2.x * v1.y;
852 if z > T::zero() {
853 return false;
854 }
855 }
856 true
857}
858
859pub fn point_inside_polygon<T: Float>(p: Vec2<T>, poly: &[Vec2<T>]) -> bool {
861 let npol = poly.len();
864 let mut c = false;
865 let mut j = npol-1;
866 for i in 0..npol {
867 if (((poly[i].y <= p.y) && (p.y < poly[j].y)) || ((poly[j].y <= p.y) && (p.y < poly[i].y))) &&
868 (p.x < (poly[j].x - poly[i].x) * (p.y - poly[i].y) / (poly[j].y - poly[i].y) + poly[i].x) {
869 c = !c;
870 }
871 j = i
872 }
873 c
874}
875
876pub fn point_inside_frustum<T: Number>(p: Vec3<T>, planes: &[Vec4<T>; 6]) -> bool {
878 for plane in planes.iter().take(6) {
879 let d = dot(p, Vec3::from(*plane)) + plane.w;
880 if d > T::zero() {
881 return false;
882 }
883 }
884 true
885}
886
887pub fn point_vs_plane<T: SignedNumber + SignedNumberOps<T>>(p: Vec3<T>, x: Vec3<T>, n: Vec3<T>) -> Classification {
889 let pd = plane_distance(x, n);
890 let d = dot(n, p) + pd;
891 if d < T::zero() {
892 Classification::Behind
893 }
894 else if d > T::zero() {
895 Classification::Infront
896 }
897 else {
898 Classification::Intersects
899 }
900}
901
902pub fn aabb_vs_plane<T: SignedNumber + SignedNumberOps<T>>(aabb_min: Vec3<T>, aabb_max: Vec3<T>, x: Vec3<T>, n: Vec3<T>) -> Classification {
904 let e = (aabb_max - aabb_min) / T::two();
905 let centre = aabb_min + e;
906 let radius = abs(n.x * e.x) + abs(n.y * e.y) + abs(n.z * e.z);
907 let pd = plane_distance(x, n);
908 let d = dot(n, centre) + pd;
909 if d > radius {
910 Classification::Infront
911 }
912 else if d < -radius {
913 Classification::Behind
914 }
915 else {
916 Classification::Intersects
917 }
918}
919
920pub fn sphere_vs_plane<T: SignedNumber + SignedNumberOps<T>>(s: Vec3<T>, r: T, x: Vec3<T>, n: Vec3<T>) -> Classification {
922 let pd = plane_distance(x, n);
923 let d = dot(n, s) + pd;
924 if d > r {
925 Classification::Infront
926 }
927 else if d < -r {
928 Classification::Behind
929 }
930 else {
931 Classification::Intersects
932 }
933}
934
935pub fn capsule_vs_plane<T: Float + FloatOps<T> + SignedNumber + SignedNumberOps<T>>(c1: Vec3<T>, c2: Vec3<T>, r: T, x: Vec3<T>, n: Vec3<T>) -> Classification {
937 let pd = plane_distance(x, n);
938 let d1 = dot(n, c1) + pd;
941 let r1 = if d1 > r {
942 Classification::Infront
943 }
944 else if d1 < -r {
945 Classification::Behind
946 }
947 else {
948 Classification::Intersects
949 };
950 let d2 = dot(n, c2) + pd;
952 let r2 = if d2 > r {
953 Classification::Infront
954 }
955 else if d2 < -r {
956 Classification::Behind
957 }
958 else {
959 Classification::Intersects
960 };
961 if r1 == r2 {
962 r1
964 }
965 else {
966 Classification::Intersects
968 }
969}
970
971pub fn cone_vs_plane<T: Float + SignedNumberOps<T>, V: VecN<T> + Cross<T> + Dot<T> + SignedVecN<T> + VecFloatOps<T>>(cp: V, cv: V, h: T, r: T, x: V, n: V) -> Classification {
974 let l2 = cp + cv * h;
975 let pd = plane_distance(x, n);
976 let d1 = dot(n, cp) + pd;
978 let perp = normalize(cross(cross(n, cv), cv));
980 let extent = l2 + perp * r;
981 let extent2 = l2 + perp * -r;
982 let d2 = dot(n, extent) + pd;
983 let d3 = dot(n, extent2) + pd;
984 if d1 < T::zero() && d2 < T::zero() && d3 < T::zero() {
985 Classification::Behind
986 }
987 else if d1 > T::zero() && d2 > T::zero() && d3 > T::zero() {
988 Classification::Infront
989 }
990 else {
991 Classification::Intersects
992 }
993}
994
995pub fn ray_vs_plane<T: Float + SignedNumberOps<T>>(r0: Vec3<T>, rv: Vec3<T>, x: Vec3<T>, n: Vec3<T>) -> Option<Vec3<T>> {
997 let t = -(dot(r0, n) - dot(x, n)) / dot(rv, n);
998 if t < T::zero() {
999 None
1000 }
1001 else {
1002 Some(r0 + rv * t)
1003 }
1004}
1005
1006pub fn line_vs_plane<T: Float + SignedNumberOps<T>>(l0: Vec3<T>, lv: Vec3<T>, x: Vec3<T>, n: Vec3<T>) -> Option<Vec3<T>> {
1008 let r = dot(lv, n);
1009 if r == T::zero() {
1010 None
1011 }
1012 else {
1013 let t = -(dot(l0, n) - dot(x, n)) / dot(lv, n);
1014 Some(l0 + lv * t)
1015 }
1016}
1017
1018pub fn line_segment_vs_plane<T: Float + FloatOps<T> + SignedNumber + SignedNumberOps<T>>(l1: Vec3<T>, l2: Vec3<T>, x: Vec3<T>, n: Vec3<T>) -> Option<Vec3<T>> {
1020 let ll = l2-l1;
1021 let m = mag(ll);
1022 let lv = ll / m;
1023 let t = -(dot(l1, n) - dot(x, n)) / dot(lv, n);
1024 if t < T::zero() || t > m {
1025 None
1026 }
1027 else {
1028 Some(l1 + lv * t)
1029 }
1030}
1031
1032pub fn sphere_vs_sphere<T: Float, V: VecN<T> + VecFloatOps<T>>(s1: V, r1: T, s2: V, r2: T) -> bool {
1034 let d2 = dist2(s1, s2);
1035 let r22 = r1 + r2;
1036 d2 < r22 * r22
1037}
1038
1039pub fn sphere_vs_capsule<T: Float + FloatOps<T>, V: VecN<T> + VecFloatOps<T> + FloatOps<T>>(s1: V, r1: T, c0: V, c1: V, cr: T) -> bool {
1041 let cp = closest_point_on_line_segment(s1, c0, c1);
1042 let r2 = sqr(r1 + cr);
1043 dist2(s1, cp) < r2
1044}
1045
1046pub fn aabb_vs_sphere<T: Float, V: VecN<T> + VecFloatOps<T> + NumberOps<T>>(aabb_min: V, aabb_max: V, s: V, r: T) -> bool {
1048 let cp = closest_point_on_aabb(s, aabb_min, aabb_max);
1049 dist2(cp, s) < r * r
1050}
1051
1052pub fn aabb_vs_aabb<T: Number, V: VecN<T> + NumberOps<T>>(aabb_min1: V, aabb_max1: V, aabb_min2: V, aabb_max2: V) -> bool {
1054 for i in 0..V::len() {
1055 if aabb_max1[i] < aabb_min2[i] || aabb_min1[i] > aabb_max2[i] {
1056 return false;
1057 }
1058 }
1059 true
1060}
1061
1062pub fn aabb_vs_obb<T: Number + Float + SignedNumber + SignedNumberOps<T> + NumberOps<T> + FloatOps<T>, V: VecN<T> + NumberOps<T> + FloatOps<T> + Triple<T> + Cross<T>, M: MatTranslate<V> + MatInverse<T> + MatRotate3D<T, V> + MatN<T, V> + std::ops::Mul<Vec3<T>, Output=Vec3<T>>>(aabb_min: Vec3<T>, aabb_max: Vec3<T>, obb: M) -> bool {
1064 let corners = [
1066 Vec3::<T>::new(-T::one(), -T::one(), -T::one()),
1067 Vec3::<T>::new( T::one(), -T::one(), -T::one()),
1068 Vec3::<T>::new( T::one(), T::one(), -T::one()),
1069 Vec3::<T>::new(-T::one(), T::one(), -T::one()),
1070 Vec3::<T>::new(-T::one(), -T::one(), T::one()),
1071 Vec3::<T>::new( T::one(), -T::one(), T::one()),
1072 Vec3::<T>::new( T::one(), T::one(), T::one()),
1073 Vec3::<T>::new(-T::one(), T::one(), T::one()),
1074 ];
1075
1076 let verts0 = vec![
1078 aabb_min,
1079 Vec3::<T>::new(aabb_min.x, aabb_min.y, aabb_max.z),
1080 Vec3::<T>::new(aabb_max.x, aabb_min.y, aabb_min.z),
1081 Vec3::<T>::new(aabb_max.x, aabb_min.y, aabb_max.z),
1082 Vec3::<T>::new(aabb_min.x, aabb_max.y, aabb_min.z),
1083 Vec3::<T>::new(aabb_min.x, aabb_max.y, aabb_max.z),
1084 Vec3::<T>::new(aabb_max.x, aabb_max.y, aabb_min.z),
1085 aabb_max
1086 ];
1087
1088 let mut verts1 = Vec::new();
1090 for corner in corners {
1091 verts1.push(obb * corner);
1092 }
1093
1094 gjk_3d(verts0, verts1)
1095}
1096
1097pub fn sphere_vs_obb<T: Float, V: VecN<T> + VecFloatOps<T> + NumberOps<T> + SignedNumberOps<T>, M: MatTranslate<V> + MatInverse<T> + MatRotate3D<T, V> + MatN<T, V>>(s: V, r: T, obb: M) -> bool {
1100 let cp = closest_point_on_obb(s, obb);
1102 dist2(s, cp) < r * r
1103}
1104
1105pub fn obb_vs_obb<T: Number + Float + SignedNumber + SignedNumberOps<T> + NumberOps<T> + FloatOps<T>, V: VecN<T> + NumberOps<T> + FloatOps<T> + Triple<T> + Cross<T>, M: MatTranslate<V> + MatInverse<T> + MatRotate3D<T, V> + MatN<T, V> + std::ops::Mul<Vec3<T>, Output=Vec3<T>>>(obb0: M, obb1: M) -> bool {
1107 let corners = [
1109 Vec3::<T>::new(-T::one(), -T::one(), -T::one()),
1110 Vec3::<T>::new( T::one(), -T::one(), -T::one()),
1111 Vec3::<T>::new( T::one(), T::one(), -T::one()),
1112 Vec3::<T>::new(-T::one(), T::one(), -T::one()),
1113 Vec3::<T>::new(-T::one(), -T::one(), T::one()),
1114 Vec3::<T>::new( T::one(), -T::one(), T::one()),
1115 Vec3::<T>::new( T::one(), T::one(), T::one()),
1116 Vec3::<T>::new(-T::one(), T::one(), T::one()),
1117 ];
1118
1119 let mut verts0 = Vec::new();
1121 for corner in corners {
1122 verts0.push(obb0 * corner);
1123 }
1124
1125 let mut verts1 = Vec::new();
1126 for corner in corners {
1127 verts1.push(obb1 * corner);
1128 }
1129
1130 gjk_3d(verts0, verts1)
1131}
1132
1133pub fn capsule_vs_capsule<T: Float + FloatOps<T> + SignedNumberOps<T>, V: VecN<T> + VecFloatOps<T> + FloatOps<T> + SignedNumberOps<T>>(cp0: V, cp1: V, cr0: T, cp2: V, cp3: V, cr1: T) -> bool {
1135 let r2 = (cr0 + cr1) * (cr0 + cr1);
1137
1138 if let Some((start, end)) = shortest_line_segment_between_line_segments(cp0, cp1, cp2, cp3) {
1140 let d = dist2(start, end);
1141 d < r2
1142 }
1143 else {
1144 let l0 = normalize(cp1 - cp0);
1147 let t0 = dot(cp2 - cp0, l0);
1148 let ip0 = cp0 + l0 * t0;
1149 let d = dist2(cp2, ip0);
1150
1151 if d < r2 {
1153 let l1 = normalize(cp3 - cp2);
1154 let t1 = dot(cp0 - cp2, l1);
1155
1156 if t0 >= T::zero() && t0*t0 < dist2(cp1, cp0) {
1158 true
1159 }
1160 else {
1161 t1 > T::zero() && t1*t1 < dist2(cp2, cp3)
1162 }
1163 }
1164 else {
1165 false
1166 }
1167 }
1168}
1169
1170pub fn ray_vs_sphere<T: Float + FloatOps<T> + NumberOps<T>, V: VecN<T> + VecFloatOps<T>>(r0: V, rv: V, s0: V, r: T) -> Option<V> {
1172 let oc = r0 - s0;
1173 let a = dot(rv, rv);
1174 let b = T::two() * dot(oc, rv);
1175 let c = dot(oc,oc) - r*r;
1176 let discriminant = b*b - T::four()*a*c;
1177 let hit = discriminant > T::zero();
1178 if !hit {
1179 None
1180 }
1181 else {
1182 let t1 = (-b - sqrt(discriminant)) / (T::two()*a);
1183 let t2 = (-b + sqrt(discriminant)) / (T::two()*a);
1184 let t = if t1 > T::zero() && t2 > T::zero() {
1185 min(t1, t2)
1186 }
1187 else if t1 > T::zero() {
1188 t1
1189 }
1190 else {
1191 t2
1192 };
1193 Some(r0 + rv * t)
1194 }
1195}
1196
1197pub fn ray_vs_aabb<T: Number + NumberOps<T>, V: VecN<T>>(r0: V, rv: V, aabb_min: V, aabb_max: V) -> Option<V> {
1199 let dirfrac = V::one() / rv;
1202 let tx = (aabb_min[0] - r0[0]) * dirfrac[0];
1203 let tm = (aabb_max[0] - r0[0]) * dirfrac[0];
1204 let mut tmin = min(tx, tm);
1205 let mut tmax = max(tx, tm);
1206 for i in 0..V::len() {
1207 let t1 = (aabb_min[i] - r0[i]) * dirfrac[i];
1208 let t2 = (aabb_max[i] - r0[i]) * dirfrac[i];
1209 tmin = max(min(t1, t2), tmin);
1210 tmax = min(max(t1, t2), tmax);
1211 }
1212
1213 if tmax < T::zero() || tmin > tmax {
1214 None
1217 }
1218 else {
1219 Some(r0 + rv * tmin)
1221 }
1222}
1223
1224pub fn ray_vs_obb<T: Float + NumberOps<T>,
1226 V: VecFloatOps<T> + NumberOps<T> + SignedNumberOps<T> + VecN<T> + SignedVecN<T>,
1227 M: MatTranslate<V> + MatInverse<T> + MatRotate3D<T, V> + MatN<T, V>
1228 + Into<Mat3<T>> + Copy>
1229 (r0: V, rv: V, mat: M) -> Option<V> where Mat3<T> : MatN<T, V> {
1230 let invm = mat.inverse();
1231 let tr1 = invm * r0;
1232 let rotm : Mat3<T> = invm.into();
1233 let trv = rotm * rv;
1234 let ip = ray_vs_aabb(tr1, normalize(trv), -V::one(), V::one());
1235 ip.map(|ip| mat * ip)
1236}
1237
1238pub fn ray_vs_triangle<T: Float>(r0: Vec3<T>, rv: Vec3<T>, t0: Vec3<T>, t1: Vec3<T>, t2: Vec3<T>) -> Option<Vec3<T>> {
1240 let edge1 = t1 - t0;
1243 let edge2 = t2 - t0;
1244 let h = cross(rv, edge2);
1245 let a = dot(edge1, h);
1246 if a > -T::small_epsilon() && a < T::small_epsilon() {
1247 None
1249 }
1250 else {
1251 let f = T::one() / a;
1252 let s = r0 - t0;
1253 let u = f * dot(s, h);
1254 if u < T::zero() || u > T::one() {
1255 None
1256 }
1257 else {
1258 let q = cross(s, edge1);
1259 let v = f * dot(rv, q);
1260 if v < T::zero() || u + v > T::one() {
1261 None
1262 }
1263 else {
1264 let t = f * dot(edge2, q);
1266 if t > T::zero() {
1267 Some(r0 + rv * t)
1268 }
1269 else {
1270 None
1272 }
1273 }
1274 }
1275 }
1276}
1277
1278pub fn ray_vs_capsule<T: Float + FloatOps<T> + NumberOps<T> + SignedNumberOps<T>, V: VecN<T> + Cross<T> + VecFloatOps<T> + SignedNumberOps<T> + FloatOps<T>>(r0: V, rv: V, c0: V, c1: V, cr: T) -> Option<V> {
1280 let seg = shortest_line_segment_between_line_and_line_segment(r0, r0 + rv, c0, c1);
1282 let mut ipc = V::max_value();
1283 let mut bc = false;
1284 if let Some((l0, l1)) = seg {
1285 if dist2(l0, l1) < sqr(cr) {
1287 let a = c0;
1290 let b = c1;
1291 let v = rv;
1292 let r = cr;
1293
1294 let ab = b - a;
1295 let ao = r0 - a;
1296 let aoxab = cross(ao, ab);
1297 let vxab = cross(v, ab);
1298 let ab2 = dot(ab, ab);
1299
1300 let aa = dot(vxab, vxab);
1301 let bb = T::two() * dot(vxab, aoxab);
1302 let cc = dot(aoxab, aoxab) - (r*r * ab2);
1303 let dd = bb * bb - T::four() * aa * cc;
1304
1305 if dd >= T::zero() {
1306 let t = (-bb - sqrt(dd)) / (T::two() * aa);
1307 if t >= T::zero() {
1308 ipc = r0 + rv * t;
1310 let ipd = distance_on_line(ipc, a, b);
1312 if ipd >= T::zero() && ipd <= dist(a, b) {
1313 bc = true;
1314 }
1315 }
1316 }
1317 }
1318 }
1319
1320 let bs1 = ray_vs_sphere(r0, rv, c0, cr);
1323 let bs2 = ray_vs_sphere(r0, rv, c1, cr);
1324
1325 let ips1 = if let Some(ip) = bs1 {
1327 ip
1328 }
1329 else {
1330 V::max_value()
1331 };
1332
1333 let ips2 = if let Some(ip) = bs2 {
1334 ip
1335 }
1336 else {
1337 V::max_value()
1338 };
1339
1340 let ips : [V; 3] = [ips1, ips2, ipc];
1342 let bips : [bool; 3] = [bs1.is_some(), bs2.is_some(), bc];
1343
1344 let mut iclosest = -1;
1345 let mut dclosest = T::max_value();
1346 for i in 0..3 {
1347 if bips[i] {
1348 let dd = distance_on_line(ips[i], r0, r0 + rv);
1349 if dd < dclosest {
1350 iclosest = i as i32;
1351 dclosest = dd;
1352 }
1353 }
1354 }
1355
1356 if iclosest != -1 {
1358 Some(ips[iclosest as usize])
1359 }
1360 else {
1361 None
1362 }
1363}
1364
1365pub fn ray_vs_cylinder<T: Float + FloatOps<T> + NumberOps<T> + SignedNumberOps<T>>(r0: Vec3<T>, rv: Vec3<T>, c0: Vec3<T>, c1: Vec3<T>, cr: T) -> Option<Vec3<T>> {
1368 let a = c0;
1371 let b = c1;
1372 let v = rv;
1373 let r = cr;
1374
1375 let ab = b - a;
1376 let ao = r0 - a;
1377 let aoxab = cross(ao, ab);
1378 let vxab = cross(v, ab);
1379 let ab2 = dot(ab, ab);
1380
1381 let aa = dot(vxab, vxab);
1382 let bb = T::two() * dot(vxab, aoxab);
1383 let cc = dot(aoxab, aoxab) - (r*r * ab2);
1384 let dd = bb * bb - T::four() * aa * cc;
1385
1386 if dd >= T::zero() {
1387 let t = (-bb - sqrt(dd)) / (T::two() * aa);
1388 if t >= T::zero() {
1389 let ipc = r0 + rv * t;
1391 let ipd = distance_on_line(ipc, a, b);
1393 if ipd >= T::zero() && ipd <= dist(a, b) {
1394 return Some(ipc);
1395 }
1396 }
1397 }
1398
1399 let ip_top = ray_vs_plane(r0, rv, c0, normalize(c0 - c1));
1401 let ip_bottom = ray_vs_plane(r0, rv, c1, normalize(c1 - c0));
1402 let r2 = r*r;
1403
1404 let mut btop = false;
1405 if let Some(ip_top) = ip_top {
1406 if dist2(ip_top, c0) < r2 {
1407 btop = true;
1408 }
1409 }
1410
1411 if let Some(ip_bottom) = ip_bottom {
1412 if dist2(ip_bottom, c1) < r2 {
1413 if btop {
1414 if let Some(ip_top) = ip_top {
1415 let d1 = distance_on_line(ip_top, r0, r0 + rv);
1416 let d2 = distance_on_line(ip_bottom, r0, r0 + rv);
1417 if d2 < d1 {
1418 return Some(ip_bottom);
1419 }
1420 }
1421 }
1422 else {
1423 return Some(ip_bottom);
1424 }
1425 }
1426 }
1427
1428 if btop {
1429 if let Some(ip_top) = ip_top {
1430 return Some(ip_top);
1431 }
1432 }
1433
1434
1435 None
1436}
1437
1438pub fn sphere_vs_frustum<T: Number>(s: Vec3<T>, r: T, planes: &[Vec4<T>; 6]) -> bool {
1440 for p in planes.iter().take(6) {
1441 let d = dot(s, Vec3::from(*p)) + p.w;
1442 if d > r {
1443 return false;
1444 }
1445 }
1446 true
1447}
1448
1449pub fn aabb_vs_frustum<T: SignedNumber + SignedNumberOps<T>>(aabb_pos: Vec3<T>, aabb_extent: Vec3<T>, planes: &[Vec4<T>; 6]) -> bool {
1451 let mut inside = true;
1452 for p in planes.iter().take(6) {
1453 let pn = Vec3::from(*p);
1454 let sign_flip = Vec3::signum(pn) * T::minus_one();
1455 let pd = p.w;
1456 let d2 = dot(aabb_pos + aabb_extent * sign_flip, pn);
1457 if d2 > -pd {
1458 inside = false;
1459 }
1460 }
1461 inside
1462}
1463
1464pub fn line_segment_vs_line_segment<T: Float + SignedNumberOps<T> + FloatOps<T>>(l1: Vec3<T>, l2: Vec3<T>, s1: Vec3<T>, s2: Vec3<T>) -> Option<Vec3<T>> {
1466 let da = l2 - l1;
1467 let db = s2 - s1;
1468 let dc = s1 - l1;
1469 if dot(dc, cross(da, db)) != T::zero() {
1470 None
1472 }
1473 else {
1474 let s = dot(cross(dc, db), cross(da, db)) / mag2(cross(da, db));
1475 if s >= T::zero() && s <= T::one() {
1476 let ip = l1 + da * s;
1477 let t = distance_on_line(ip, s1, s2) / dist(s1, s2);
1478 if t >= T::zero() && t <= T::one() {
1479 Some(ip)
1480 }
1481 else {
1482 None
1483 }
1484 }
1485 else {
1486 None
1487 }
1488 }
1489}
1490
1491pub fn line_vs_line<T: Float + SignedNumberOps<T> + FloatOps<T>>(l1: Vec3<T>, l2: Vec3<T>, s1: Vec3<T>, s2: Vec3<T>) -> Option<Vec3<T>> {
1493 let da = l2 - l1;
1494 let db = s2 - s1;
1495 let dc = s1 - l1;
1496 if dot(dc, cross(da, db)) != T::zero() {
1497 None
1499 }
1500 else {
1501 let s = dot(cross(dc, db), cross(da, db)) / mag2(cross(da, db));
1502 let ip = l1 + da * s;
1503 let t = distance_on_line(ip, s1, s2) / dist(s1, s2);
1504 if t >= T::zero() && t <= T::one() {
1505 Some(ip)
1506 }
1507 else {
1508 None
1509 }
1510 }
1511}
1512
1513pub fn ray_vs_line_segment<T: Float + SignedNumberOps<T> + FloatOps<T>>(r0: Vec3<T>, rv: Vec3<T>, l1: Vec3<T>, l2: Vec3<T>) -> Option<Vec3<T>> {
1515 let da = l2 - l1;
1516 let db = rv;
1517 let dc = r0 - l1;
1518 if dot(dc, cross(da, db)) != T::zero() {
1519 None
1521 }
1522 else {
1523 let s = dot(cross(dc, db), cross(da, db)) / mag2(cross(da, db));
1524 let ip = l1 + da * s;
1525 let t = distance_on_ray(ip, r0, rv);
1526 if s >= T::zero() && s <= T::one() && t >= T::zero() {
1527 Some(ip)
1528 }
1529 else {
1530 None
1531 }
1532 }
1533}
1534
1535pub fn shortest_line_segment_between_line_segments<T: Float + SignedNumberOps<T> + FloatOps<T>, V: VecN<T> + SignedNumberOps<T> + FloatOps<T> + Dot<T>>(p1: V, p2: V, p3: V, p4: V) -> Option<(V, V)> {
1537 let p13 = p1 - p3;
1540 let p43 = p4 - p3;
1541
1542 if approx(abs(p43), V::zero(), T::small_epsilon()) {
1543 return None;
1544 }
1545
1546 let p21 = p2 - p1;
1547 if approx(abs(p21), V::zero(), T::small_epsilon()) {
1548 return None;
1549 }
1550
1551 let d1343 = dot(p13, p43);
1552 let d4321 = dot(p43, p21);
1553 let d1321 = dot(p13, p21);
1554 let d4343 = dot(p43, p43);
1555 let d2121 = dot(p21, p21);
1556
1557 let denom = d2121 * d4343 - d4321 * d4321;
1558 if abs(denom) < T::small_epsilon() {
1559 return None;
1560 }
1561
1562 let numer = d1343 * d4321 - d1321 * d4343;
1563 let mua = saturate(numer / denom);
1564 let mub = saturate((d1343 + d4321 * mua) / d4343);
1565
1566 Some((
1567 p1 + (p21 * mua),
1568 p3 + (p43 * mub)
1569 ))
1570}
1571
1572pub fn shortest_line_segment_between_lines<T: Float + SignedNumberOps<T> + FloatOps<T>, V: VecN<T> + SignedNumberOps<T> + FloatOps<T> + Dot<T>>(p1: V, p2: V, p3: V, p4: V) -> Option<(V, V)> {
1574 let p13 = p1 - p3;
1577 let p43 = p4 - p3;
1578
1579 if approx(abs(p43), V::zero(), T::small_epsilon()) {
1580 return None;
1581 }
1582
1583 let p21 = p2 - p1;
1584 if approx(abs(p21), V::zero(), T::small_epsilon()) {
1585 return None;
1586 }
1587
1588 let d1343 = dot(p13, p43);
1589 let d4321 = dot(p43, p21);
1590 let d1321 = dot(p13, p21);
1591 let d4343 = dot(p43, p43);
1592 let d2121 = dot(p21, p21);
1593
1594 let denom = d2121 * d4343 - d4321 * d4321;
1595 if abs(denom) < T::small_epsilon() {
1596 return None;
1597 }
1598
1599 let numer = d1343 * d4321 - d1321 * d4343;
1600 let mua = numer / denom;
1601 let mub = (d1343 + d4321 * mua) / d4343;
1602
1603 Some((
1604 p1 + (p21 * mua),
1605 p3 + (p43 * mub)
1606 ))
1607}
1608
1609pub fn shortest_line_segment_between_line_and_line_segment<T: Float + SignedNumberOps<T> + FloatOps<T>, V: VecN<T> + SignedNumberOps<T> + FloatOps<T> + Dot<T>>(p1: V, p2: V, p3: V, p4: V) -> Option<(V, V)> {
1611 let p13 = p1 - p3;
1614 let p43 = p4 - p3;
1615
1616 if approx(abs(p43), V::zero(), T::small_epsilon()) {
1617 return None;
1618 }
1619
1620 let p21 = p2 - p1;
1621 if approx(abs(p21), V::zero(), T::small_epsilon()) {
1622 return None;
1623 }
1624
1625 let d1343 = dot(p13, p43);
1626 let d4321 = dot(p43, p21);
1627 let d1321 = dot(p13, p21);
1628 let d4343 = dot(p43, p43);
1629 let d2121 = dot(p21, p21);
1630
1631 let denom = d2121 * d4343 - d4321 * d4321;
1632 if abs(denom) < T::small_epsilon() {
1633 return None;
1634 }
1635
1636 let numer = d1343 * d4321 - d1321 * d4343;
1637 let mua = numer / denom;
1638 let mub = saturate((d1343 + d4321 * mua) / d4343);
1639
1640 Some((
1641 p1 + (p21 * mua),
1642 p3 + (p43 * mub)
1643 ))
1644}
1645
1646pub fn almost_identity<T: Number + Float>(x: T, m: T, n: T) -> T {
1648 let a = T::two()*n - m;
1650 let b = T::two()*m - T::three()*n;
1651 let t = x/m;
1652 if x > m {
1653 x
1654 }
1655 else {
1656 (a*t + b)*t*t + n
1657 }
1658}
1659
1660pub fn integral_smoothstep<T: Number + Float + FloatOps<T>>(x: T, t: T) -> T {
1662 if x > t {
1664 x - t/T::two()
1665 }
1666 else {
1667 x*x*x*(T::one()-x*T::point_five()/t)/t/t
1668 }
1669}
1670
1671pub fn exp_impulse<T: Number + Float, X: Base<T> + FloatOps<T>>(k: X, x: X) -> X {
1673 let h = k * x;
1675 h * X::exp(X::one() - h)
1676}
1677
1678pub fn quad_impulse<T: Number + Float + Base<T> + FloatOps<T>>(k: T, x: T) -> T {
1680 T::two() * T::sqrt(k) * x / (T::one()+k*x*x)
1682}
1683
1684pub fn poly_impulse<T: Number + Float + Base<T> + FloatOps<T>>(k: T, x: T, n: T) -> T {
1686 let one = T::one();
1688 (n/(n-one))* T::powf((n-one)*k,one/n)*x/(one+k*T::powf(x,n))
1689}
1690
1691pub fn exp_sustained_impulse<T: SignedNumber + Float, X: Base<T> + FloatOps<T> + SignedNumberOps<T> + NumberOps<T>>(x: X, f: X, k: X) -> X {
1693 let s = X::max(x-f, X::zero());
1695 X::min(x*x/(f*f), X::one() + (X::two()/f)*s*X::exp(-k*s))
1696}
1697
1698pub fn cubic_pulse<X: Float + SignedNumberOps<X>>(c: X, w: X, x: X) -> X {
1700 let mut x = abs(x - c);
1702 if x > w {
1703 X::zero()
1704 }
1705 else {
1706 x /= w;
1707 X::one() - x * x*(X::three() - X::two()*x)
1708 }
1709}
1710
1711pub fn exp_step<T: SignedNumber + Float, X: Base<T> + FloatOps<T> + SignedNumberOps<T>>(x: X, k: X, n: T) -> X {
1713 X::exp(-k * X::powf(x, n))
1715}
1716
1717pub fn gain<T: SignedNumber + Float + FloatOps<T>>(x: T, k: T) -> T {
1719 let y = if x < T::point_five() {
1721 x
1722 }
1723 else {
1724 T::one()-x
1725 };
1726 let a = T::point_five()*T::powf(T::two()*(y), k);
1727 if x < T::point_five() {
1728 a
1729 }
1730 else {
1731 T::one() - a
1732 }
1733}
1734
1735pub fn parabola<T: SignedNumber + Float, X: Base<T> + FloatOps<T> + SignedNumberOps<T>>(x: X, k: T) -> X {
1737 powf(X::four() * x * (X::one() - x), k)
1739}
1740
1741pub fn pcurve<T: SignedNumber + Float + Base<T> + FloatOps<T>>(x: T, a: T, b: T) -> T {
1743 let k = powf(a + b, a + b) / (powf(a, a) * powf(b, b));
1745 k * powf(x, a) * powf(T::one() - x, b)
1746}
1747
1748pub fn sinc<T: SignedNumber + Float, X: Base<T> + FloatOps<T> + SignedNumberOps<T>>(x: X, k: X) -> X {
1750 let a = X::pi() * (k*x-X::one());
1752 X::sin(a)/a
1753}
1754
1755pub fn rgb_to_hsv<T: Float + SignedNumberOps<T> + Cast<T>>(rgb: Vec3<T>) -> Vec3<T> {
1757 let mut r = rgb.x;
1760 let mut g = rgb.y;
1761 let mut b = rgb.z;
1762
1763 let mut k = T::zero();
1764 if g < b {
1765 std::mem::swap(&mut g, &mut b);
1766 k = T::minus_one();
1767 }
1768
1769 if r < g {
1770 std::mem::swap(&mut r, &mut g);
1771 k = -T::two() / T::from_f64(6.0) - k;
1772 }
1773
1774 let chroma = r - if g < b { g } else { b };
1775
1776 Vec3 {
1777 x: abs(k + (g - b) / (T::from_f64(6.0) * chroma + T::small_epsilon())),
1778 y: chroma / (r + T::small_epsilon()),
1779 z: r
1780 }
1781}
1782
1783pub fn hsv_to_rgb<T: Float + FloatOps<T> + Cast<T>>(hsv: Vec3<T>) -> Vec3<T> {
1785 let h = hsv.x;
1787 let s = hsv.y;
1788 let v = hsv.z;
1789
1790 if s == T::zero() {
1791 return Vec3 {
1793 x: v,
1794 y: v,
1795 z: v
1796 };
1797 }
1798
1799 let h = T::fmod(h, T::one()) / T::from_f64(0.16666666666);
1800 let i = h.as_i32();
1801 let f = h - floor(h);
1802 let p = v * (T::one() - s);
1803 let q = v * (T::one() - s * f);
1804 let t = v * (T::one() - s * (T::one() - f));
1805
1806 match i {
1807 0 => {
1808 Vec3::new(v, t, p)
1809 }
1810 1 => {
1811 Vec3::new(q, v, p)
1812 }
1813 2 => {
1814 Vec3::new(p, v, t)
1815 }
1816 3 => {
1817 Vec3::new(p, q, v)
1818 }
1819 4 => {
1820 Vec3::new(t, p, v)
1821 }
1822 _ => {
1823 Vec3::new(v, p, q)
1824 }
1825 }
1826}
1827
1828pub fn rgba8_to_vec4<T: Float + FloatOps<T> + Cast<T>>(rgba: u32) -> Vec4<T> {
1830 let one_over_255 = T::from_f32(1.0 / 255.0);
1831 Vec4 {
1832 x: T::from_u32((rgba >> 24) & 0xff) * one_over_255,
1833 y: T::from_u32((rgba >> 16) & 0xff) * one_over_255,
1834 z: T::from_u32((rgba >> 8) & 0xff) * one_over_255,
1835 w: T::from_u32(rgba & 0xff) * one_over_255
1836 }
1837}
1838
1839pub fn vec4_to_rgba8<T: Float + Cast<T>>(v: Vec4<T>) -> u32 {
1841 let mut rgba : u32 = 0;
1842 let x = T::from_f32(255.0);
1843 rgba |= (v[0] * x).as_u32() << 24;
1844 rgba |= (v[1] * x).as_u32() << 16;
1845 rgba |= (v[2] * x).as_u32() << 8;
1846 rgba |= (v[3] * x).as_u32();
1847 rgba
1848}
1849
1850pub fn smooth_start2<T: Float, X: Base<T>>(t: X, b: X, c: X, d: X) -> X {
1852 let t = t/d;
1853 c * t*t + b
1854}
1855
1856pub fn smooth_start3<T: Float, X: Base<T>>(t: X, b: X, c: X, d: X) -> X {
1858 let t = t/d;
1859 c * t*t*t + b
1860}
1861
1862pub fn smooth_start4<T: Float, X: Base<T>>(t: X, b: X, c: X, d: X) -> X {
1864 let t = t/d;
1865 c * t*t*t*t + b
1866}
1867
1868pub fn smooth_start5<T: Float, X: Base<T>>(t: X, b: X, c: X, d: X) -> X {
1870 let t = t/d;
1871 c * t*t*t*t*t + b
1872}
1873
1874pub fn smooth_stop2<T: Float, X: Base<T> + SignedNumberOps<T>>(t: X, b: X, c: X, d: X) -> X {
1876 let t = t/d;
1877 -c * t * (t - X::two()) + b
1878}
1879
1880pub fn smooth_stop3<T: Float, X: Base<T> + SignedNumberOps<T>>(t: X, b: X, c: X, d: X) -> X {
1882 let t = t/d;
1883 c * (t*t*t + X::one()) + b
1884}
1885
1886pub fn smooth_stop4<T: Float, X: Base<T> + SignedNumberOps<T>>(t: X, b: X, c: X, d: X) -> X {
1888 let t = t/d;
1889 c * (t*t*t*t + X::one()) + b
1890}
1891
1892pub fn smooth_stop5<T: Float, X: Base<T> + SignedNumberOps<T>>(t: X, b: X, c: X, d: X) -> X {
1894 let t = t/d;
1895 c * (t*t*t*t*t + X::one()) + b
1896}
1897
1898pub fn cubic_interpolate<T: Float, V: VecN<T> + NumberOps<T> + VecFloatOps<T>>(p1: V, p2: V, p3: V, p4: V, t: T) -> V {
1900 p1 * (T::one() - t) * (T::one() - t) * (T::one() - t) +
1901 p2 * T::three() * t * (T::one() - t) * (T::one() - t) +
1902 p3 * T::three() * t * t * (T::one() - t) +
1903 p4 * t * t * t
1904}
1905
1906pub fn cubic_tangent<T: Float, V: VecN<T> + NumberOps<T> + VecFloatOps<T>>(p1: V, p2: V, p3: V, p4: V, t: T) -> V {
1908 p1 * (-T::one() + T::two() * t - t * t) +
1909 p2 * (T::one() - T::four() * t + T::three() * t * t) +
1910 p3 * (T::two() * t - T::three() * t * t) +
1911 p4 * (t * t)
1912}
1913
1914pub fn morton_xy(x: u64, y: u64) -> u64 {
1916 let mut x = x;
1917 x = (x | (x << 16)) & 0x0000FFFF0000FFFF;
1918 x = (x | (x << 8)) & 0x00FF00FF00FF00FF;
1919 x = (x | (x << 4)) & 0x0F0F0F0F0F0F0F0F;
1920 x = (x | (x << 2)) & 0x3333333333333333;
1921 x = (x | (x << 1)) & 0x5555555555555555;
1922
1923 let mut y = y;
1924 y = (y | (y << 16)) & 0x0000FFFF0000FFFF;
1925 y = (y | (y << 8)) & 0x00FF00FF00FF00FF;
1926 y = (y | (y << 4)) & 0x0F0F0F0F0F0F0F0F;
1927 y = (y | (y << 2)) & 0x3333333333333333;
1928 y = (y | (y << 1)) & 0x5555555555555555;
1929
1930 x | (y << 1)
1931}
1932
1933pub fn morton_xyz(x: u64, y: u64, z: u64) -> u64 {
1935 let mut x = x;
1936 x = (x | (x << 16)) & 0xFFFF00000000FFFF;
1937 x = (x | (x << 8)) & 0xF00F00F00F00F;
1938 x = (x | (x << 4)) & 0x30C30C30C30C30C3;
1939 x = (x | (x << 2)) & 0x9249249249249249;
1940
1941 let mut y = y;
1942 y = (y | (y << 16)) & 0xFFFF00000000FFFF;
1943 y = (y | (y << 8)) & 0xF00F00F00F00F;
1944 y = (y | (y << 4)) & 0x30C30C30C30C30C3;
1945 y = (y | (y << 2)) & 0x9249249249249249;
1946
1947 let mut z = z;
1948 z = (z | (z << 16)) & 0xFFFF00000000FFFF;
1949 z = (z | (z << 8)) & 0xF00F00F00F00F;
1950 z = (z | (z << 4)) & 0x30C30C30C30C30C3;
1951 z = (z | (z << 2)) & 0x9249249249249249;
1952
1953 x | (y << 1) | (z << 2)
1954}
1955
1956pub fn morton_1(x: u64) -> u64 {
1958 let mut x = x & 0x5555555555555555;
1959 x = (x | (x >> 1)) & 0x3333333333333333;
1960 x = (x | (x >> 2)) & 0x0F0F0F0F0F0F0F0F;
1961 x = (x | (x >> 4)) & 0x00FF00FF00FF00FF;
1962 x = (x | (x >> 8)) & 0x0000FFFF0000FFFF;
1963 x = (x | (x >> 16)) & 0x00000000FFFFFFFF;
1964 x
1965}
1966
1967pub fn morton_2(x: u64) -> u64 {
1969 let mut x = x & 0x9249249249249249;
1970 x = (x | (x >> 2)) & 0x30C30C30C30C30C3;
1971 x = (x | (x >> 4)) & 0xF00F00F00F00F;
1972 x = (x | (x >> 8)) & 0xFF0000FF0000FF;
1973 x = (x | (x >> 16)) & 0xFFFF00000000FFFF;
1974 x = (x | (x >> 32)) & 0x00000000FFFFFFFF;
1975 x
1976}
1977
1978pub fn morton_to_xy(d: u64) -> (u64, u64) {
1980 (morton_1(d), morton_1(d >> 1))
1981}
1982
1983pub fn morton_to_xyz(d: u64) -> (u64, u64, u64) {
1985 (morton_2(d), morton_2(d >> 1), morton_2(d >> 2))
1986}
1987
1988pub fn map_to_range<T: Float, X: Base<T>>(v: X, in_start: X, in_end: X, out_start: X, out_end: X) -> X {
1990 let slope = X::one() * (out_end - out_start) / (in_end - in_start);
1991 out_start + slope * (v - in_start)
1992}
1993
1994pub fn gjk_mesh_support_function<T: Float + FloatOps<T> + NumberOps<T> + SignedNumberOps<T>, V: VecN<T> + VecFloatOps<T> + SignedNumberOps<T> + FloatOps<T>> (convex0: &[V], convex1: &[V], dir: V) -> V {
1996 let furthest_point = |dir: V, vertices: &[V]| -> V {
1997 let mut fd = -T::max_value();
1998 let mut fv = vertices[0];
1999 for v in vertices {
2000 let d = dot(dir, *v);
2001 if d > fd {
2002 fv = *v;
2003 fd = d;
2004 }
2005 }
2006 fv
2007 };
2008
2009 let fp0 = furthest_point(dir, convex0);
2011 let fp1 = furthest_point(-dir, convex1);
2012 fp0 - fp1
2013}
2014
2015fn handle_simplex_2d<T: Float + FloatOps<T> + NumberOps<T> + SignedNumber + SignedNumberOps<T>, V: VecN<T> + VecFloatOps<T> + Triple<T>> (simplex: &mut Vec<V>, dir: &mut V) -> bool {
2017 match simplex.len() {
2018 2 => {
2019 let a = simplex[1];
2020 let b = simplex[0];
2021 let ab = b - a;
2022 let ao = -a;
2023
2024 *dir = vector_triple(ab, ao, ab);
2025
2026 false
2027 },
2028 3 => {
2029 let a = simplex[2];
2030 let b = simplex[1];
2031 let c = simplex[0];
2032
2033 let ab = b - a;
2034 let ac = c - a;
2035 let ao = -a;
2036
2037 let abperp = vector_triple(ac, ab, ab);
2038 let acperp = vector_triple(ab, ac, ac);
2039
2040 if dot(abperp, ao) > T::zero() {
2041 simplex.remove(0);
2042 *dir = abperp;
2043 false
2044 }
2045 else if dot(acperp, ao) > T::zero() {
2046 simplex.remove(1);
2047 *dir = acperp;
2048 false
2049 }
2050 else {
2051 true
2052 }
2053 }
2054 _ => {
2055 panic!("we should always have 2 or 3 points in the simplex!");
2056 }
2057 }
2058}
2059
2060pub fn gjk_2d<T: Float + FloatOps<T> + NumberOps<T> + SignedNumber + SignedNumberOps<T>, V: VecN<T> + FloatOps<T> + SignedNumberOps<T> + VecFloatOps<T> + Triple<T>>(convex0: Vec<V>, convex1: Vec<V>) -> bool {
2062 let mut dir = V::unit_x();
2066 let support = gjk_mesh_support_function(&convex0, &convex1, dir);
2067 dir = normalize(-support);
2068
2069 let mut simplex = vec![support];
2071
2072 let max_iters = 32;
2073 for _i in 0..max_iters {
2074 let a = gjk_mesh_support_function(&convex0, &convex1, dir);
2075
2076 if dot(a, dir) < T::zero() {
2077 return false;
2078 }
2079 simplex.push(a);
2080
2081 if handle_simplex_2d(&mut simplex, &mut dir) {
2082 return true;
2083 }
2084 }
2085
2086 false
2088}
2089
2090pub fn convex_hull_vs_convex_hull<T: Float + FloatOps<T> + NumberOps<T> + SignedNumber + SignedNumberOps<T>, V: VecN<T> + FloatOps<T> + SignedNumberOps<T> + VecFloatOps<T> + Triple<T>>(convex0: Vec<V>, convex1: Vec<V>) -> bool {
2092 gjk_2d(convex0, convex1)
2093}
2094
2095fn handle_simplex_3d<T: Float + FloatOps<T> + NumberOps<T> + SignedNumber + SignedNumberOps<T>, V: VecN<T> + VecFloatOps<T> + Triple<T> + Cross<T>> (simplex: &mut Vec<V>, dir: &mut V) -> bool {
2097 match simplex.len() {
2098 2 => {
2099 let a = simplex[1];
2100 let b = simplex[0];
2101
2102 let ab = b - a;
2103 let ao = -a;
2104
2105 *dir = vector_triple(ab, ao, ab);
2106
2107 false
2108 },
2109 3 => {
2110 let a = simplex[2];
2111 let b = simplex[1];
2112 let c = simplex[0];
2113
2114 let ab = b - a;
2115 let ac = c - a;
2116 let ao = -a;
2117
2118 *dir = cross(ac, ab);
2119
2120 if dot(*dir, ao) < T::zero() {
2122 *dir = -*dir;
2123 }
2124
2125 false
2126 },
2127 4 => {
2128 let a = simplex[3];
2129 let b = simplex[2];
2130 let c = simplex[1];
2131 let d = simplex[0];
2132
2133 let centre = (a+b+c+d) / T::four();
2134
2135 let ab = b - a;
2136 let ac = c - a;
2137 let ad = d - a;
2138 let ao = -a;
2139
2140 let mut abac = cross(ab, ac);
2141 let mut acad = cross(ac, ad);
2142 let mut adab = cross(ad, ab);
2143
2144 let centre_abc = (a + b + c) / T::three();
2146 let centre_acd = (a + c + d) / T::three();
2147 let centre_adb = (a + d + b) / T::three();
2148
2149 if dot(centre - centre_abc, abac) > T::zero() {
2150 abac = -abac;
2151 }
2152
2153 if dot(centre - centre_acd, acad) > T::zero() {
2154 acad = -acad;
2155 }
2156
2157 if dot(centre - centre_adb, adab) > T::zero() {
2158 adab = -adab;
2159 }
2160
2161 if dot(abac, ao) > T::zero() {
2162 simplex.remove(0);
2164 *dir = abac;
2165 false
2166 }
2167 else if dot(acad, ao) > T::zero() {
2168 simplex.remove(1);
2170 *dir = acad;
2171 false
2172 }
2173 else if dot(adab, ao) > T::zero() {
2174 simplex.remove(2);
2176 *dir = adab;
2177 false
2178 }
2179 else {
2180 true
2181 }
2182 },
2183 _ => {
2184 panic!("we should always have 2, 3 or 4 points in the simplex!");
2185 }
2186 }
2187}
2188
2189pub fn gjk_3d<T: Float + FloatOps<T> + NumberOps<T> + SignedNumber + SignedNumberOps<T>, V: VecN<T> + FloatOps<T> + SignedNumberOps<T> + VecFloatOps<T> + Triple<T> + Cross<T>>(convex0: Vec<V>, convex1: Vec<V>) -> bool {
2191 let mut dir = V::unit_x();
2195 let support = gjk_mesh_support_function(&convex0, &convex1, dir);
2196 dir = normalize(-support);
2197
2198 let mut simplex = vec![support];
2200
2201 let max_iters = 32;
2202 for _i in 0..max_iters {
2203 let a = gjk_mesh_support_function(&convex0, &convex1, dir);
2204
2205 if dot(a, dir) < T::zero() {
2206 return false;
2207 }
2208 simplex.push(a);
2209
2210 if handle_simplex_3d(&mut simplex, &mut dir) {
2211 return true;
2212 }
2213 }
2214
2215 false
2217}
2218
2219pub mod prelude {
2221 #[doc(hidden)]
2222 pub use crate::{
2223 vec::*,
2225 mat::*,
2226 num::*,
2227 quat::*,
2228 swizz::*,
2229
2230 Vec2f, Vec3f, Vec4f,
2232 Mat2f, Mat3f, Mat34f, Mat4f,
2233 Quatf,
2234
2235 *,
2237 };
2238}
2239
2240