1pub mod num;
3
4pub mod vec;
6
7pub mod mat;
10
11pub mod quat;
13
14pub mod swizz;
16
17use num::*;
18use vec::*;
19use mat::*;
20use quat::*;
21
22#[cfg(feature = "short_types")]
24pub type Vec2f = Vec2<f32>;
25pub type Vec3f = Vec3<f32>;
26pub type Vec4f = Vec4<f32>;
27pub type Vec2d = Vec2<f64>;
28pub type Vec3d = Vec3<f64>;
29pub type Vec4d = Vec4<f64>;
30pub type Vec2i = Vec2<i32>;
31pub type Vec3i = Vec3<i32>;
32pub type Vec4i = Vec4<i32>;
33pub type Vec2u = Vec2<u32>;
34pub type Vec3u = Vec3<u32>;
35pub type Vec4u = Vec4<u32>;
36pub type Mat2f = Mat2<f32>;
37pub type Mat3f = Mat3<f32>;
38pub type Mat34f = Mat34<f32>;
39pub type Mat43f = Mat43<f32>;
40pub type Mat4f = Mat4<f32>;
41pub type Mat2d = Mat2<f64>;
42pub type Mat3d = Mat3<f64>;
43pub type Mat34d = Mat34<f64>;
44pub type Mat43d = Mat43<f64>;
45pub type Mat4d = Mat4<f64>;
46pub type Quatf = Quat<f32>;
47pub type Quatd = Quat<f64>;
48
49#[derive(PartialEq, Debug)]
51pub enum Classification {
52 Behind,
54 Infront,
56 Intersects,
58}
59
60pub fn min<T: Number, V: NumberOps<T>>(a: V, b: V) -> V {
62 V::min(a, b)
63}
64
65pub fn max<T: Number, V: NumberOps<T>>(a: V, b: V) -> V {
67 V::max(a, b)
68}
69
70pub fn min_max<T: Number, V: NumberOps<T> + Copy>(a: V, min_max: (V, V)) -> (V, V) {
72 (V::min(a, min_max.0), V::max(a, min_max.1))
73}
74
75pub fn clamp<T: Number, V: NumberOps<T>>(x: V, min: V, max: V) -> V {
77 V::clamp(x, min, max)
78}
79
80pub fn step<T: Number, V: NumberOps<T>>(a: V, b: V) -> V {
82 V::step(a, b)
83}
84
85pub fn signum<T: SignedNumber, V: SignedNumberOps<T>>(a: V) -> V {
87 V::signum(a)
88}
89
90pub fn copysign<T: Float, V: FloatOps<T>>(a: V, sign: T) -> V {
92 V::copysign(a, sign)
93}
94
95pub fn abs<T: SignedNumber, V: SignedNumberOps<T>>(a: V) -> V {
97 V::abs(a)
98}
99
100pub fn deg_to_rad<T: Float, V: FloatOps<T>>(a: V) -> V {
102 V::deg_to_rad(a)
103}
104
105pub fn rad_to_deg<T: Float, V: FloatOps<T>>(a: V) -> V {
107 V::rad_to_deg(a)
108}
109
110pub fn floor<T: Float, V: FloatOps<T>>(a: V) -> V {
112 V::floor(a)
113}
114
115pub fn ceil<T: Float, V: FloatOps<T>>(a: V) -> V {
117 V::ceil(a)
118}
119
120pub fn round<T: Float, V: FloatOps<T>>(a: V) -> V {
122 V::round(a)
123}
124
125pub fn approx<T: Float, V: FloatOps<T>>(a: V, b: V, eps: T) -> bool {
127 V::approx(a, b, eps)
128}
129
130pub fn sqrt<T: Float, V: FloatOps<T>>(a: V) -> V {
132 V::sqrt(a)
133}
134
135pub fn powi<T: Float, V: FloatOps<T>>(a: V, b: i32) -> V {
137 V::powi(a, b)
138}
139
140pub fn sqr<T: Float, V: FloatOps<T> + Base<T>>(a: V) -> V {
142 a * a
143}
144
145pub fn cube<T: Float, V: FloatOps<T> + Base<T>>(a: V) -> V {
147 a * a * a
148}
149
150pub fn powf<T: Float, V: FloatOps<T>>(a: V, b: T) -> V {
152 V::powf(a, b)
153}
154
155pub fn mad<T: Float, V: FloatOps<T>>(m: V, a: V, b: V) -> V {
157 V::mad(m, a, b)
158}
159
160pub fn fmod<T: Float, V: FloatOps<T>>(a: V, b: V) -> V {
162 V::fmod(a, b)
163}
164
165pub fn frac<T: Float, V: FloatOps<T>>(a: V) -> V {
167 V::frac(a)
168}
169
170pub fn trunc<T: Float, V: FloatOps<T>>(a: V) -> V {
172 V::trunc(a)
173}
174
175pub fn rsqrt<T: Float, V: FloatOps<T>>(a: V) -> V {
177 V::rsqrt(a)
178}
179
180pub fn recip<T: Float, V: FloatOps<T>>(a: V) -> V {
182 V::recip(a)
183}
184
185pub fn modf<T: Float, V: FloatOps<T>>(v: V) -> (V, V) {
187 V::modf(v)
188}
189
190pub fn lerp<T: Float, V: FloatOps<T>>(e0: V, e1: V, t: T) -> V {
192 V::lerp(e0, e1, t)
193}
194
195pub fn nlerp<T: Float, V: VecFloatOps<T> + Nlerp<T>>(e0: V, e1: V, t: T) -> V {
197 V::nlerp(e0, e1, t)
198}
199
200pub fn slerp<T: Float + NumberOps<T> + FloatOps<T>, V: Slerp<T>>(e0: V, e1: V, t: T) -> V {
202 V::slerp(e0, e1, t)
203}
204
205pub fn smoothstep<T: Float, V: FloatOps<T>>(e0: V, e1: V, t: T) -> V {
207 V::smoothstep(e0, e1, t)
208}
209
210pub fn saturate<T: Float, V: FloatOps<T>>(x: V) -> V {
212 V::saturate(x)
213}
214
215pub fn cross<T: Number, V: Cross<T>>(a: V, b: V) -> V {
217 V::cross(a, b)
218}
219
220pub fn scalar_triple<T: Number + SignedNumber, V: Triple<T>>(a: V, b: V, c: V) -> T {
222 V::scalar_triple(a, b, c)
223}
224
225pub fn vector_triple<T: Number + SignedNumber, V: Triple<T>>(a: V, b: V, c: V) -> V {
227 V::vector_triple(a, b, c)
228}
229
230pub fn perp<T: SignedNumber>(a: Vec2<T>) -> Vec2<T> {
232 Vec2 {
233 x: -a.y,
234 y: a.x
235 }
236}
237
238pub fn dot<T: Number, V: VecN<T>>(a: V, b: V) -> T {
240 V::dot(a, b)
241}
242
243pub fn length<T: Float, V: VecFloatOps<T>>(a: V) -> T {
245 V::length(a)
246}
247
248pub fn mag<T: Float, V: VecFloatOps<T>>(a: V) -> T {
250 V::mag(a)
251}
252
253pub fn mag2<T: Float, V: VecFloatOps<T>>(a: V) -> T {
255 V::mag2(a)
256}
257
258pub fn normalize<T: Float, V: VecFloatOps<T>>(a: V) -> V {
260 V::normalize(a)
261}
262
263pub fn chebyshev_normalize<T: Float, V: VecFloatOps<T> + VecN<T> + SignedNumberOps<T>>(a: V) -> V {
265 a / V::max_scalar(V::abs(a))
266}
267
268pub fn distance<T: Float, V: VecFloatOps<T>>(a: V, b: V) -> T {
270 V::distance(a, b)
271}
272
273pub fn dist<T: Float, V: VecFloatOps<T>>(a: V, b: V) -> T {
275 V::dist(a, b)
276}
277
278pub fn dist2<T: Float, V: VecFloatOps<T>>(a: V, b: V) -> T {
280 V::dist2(a, b)
281}
282
283pub fn barycentric<T: Float + NumberOps<T>, V: VecN<T> + VecFloatOps<T> + NumberOps<T>>(p: V, t1: V, t2: V, t3: V) -> (T, T, T) {
285 let x13 = t1 - t3;
286 let x23 = t2 - t3;
287 let x03 = p - t3;
288 let m13 = mag2(x13);
289 let m23 = mag2(x23);
290 let d = dot(x13, x23);
291 let invdet = T::one() / T::max(m13 * m23 - d * d, T::small_epsilon());
292 let a = dot(x13, x03);
293 let b = dot(x23, x03);
294 let u = invdet * (m23 * a - d * b);
295 let v = invdet * (m13 * b - d * a);
296 let w = T::one() - u - v;
297 (u, v, w)
298}
299
300pub fn azimuth_altitude_to_xyz<T: Float + FloatOps<T>>(azimuth: T, altitude: T) -> Vec3<T> {
302 let z = T::sin(altitude);
303 let hyp = T::cos(altitude);
304 let y = hyp * T::cos(azimuth);
305 let x = hyp * T::sin(azimuth);
306 Vec3::<T>::new(x, z, y)
307}
308
309pub fn focal_length_to_fov<T: Float + FloatOps<T> + Cast<T>>(focal_length: T, aperture_width: T) -> T {
311 T::two() * rad_to_deg(atan((aperture_width * T::from_f64(25.4)) / (T::two() * focal_length)))
312}
313
314pub fn fov_to_focal_length<T: Float + FloatOps<T> + Cast<T>>(fov: T, aperture_width: T) -> T {
316 (aperture_width * T::from_f64(25.4)) / (T::two() * tan(deg_to_rad(fov / T::two())))
317}
318
319pub fn xyz_to_azimuth_altitude<T: Float + FloatOps<T>>(xyz: Vec3<T>) -> (T, T) {
321 (T::atan2(xyz.y, xyz.x), T::atan2(xyz.z, sqrt(xyz.x * xyz.x + xyz.y * xyz.y)))
322}
323
324pub fn cos<T: Float, V: FloatOps<T>>(v: V) -> V {
326 V::cos(v)
327}
328
329pub fn sin<T: Float, V: FloatOps<T>>(v: V) -> V {
331 V::sin(v)
332}
333
334pub fn tan<T: Float, V: FloatOps<T>>(v: V) -> V {
336 V::tan(v)
337}
338
339pub fn acos<T: Float, V: FloatOps<T>>(v: V) -> V {
341 V::acos(v)
342}
343
344pub fn asin<T: Float, V: FloatOps<T>>(v: V) -> V {
346 V::asin(v)
347}
348
349pub fn atan<T: Float, V: FloatOps<T>>(v: V) -> V {
351 V::atan(v)
352}
353
354pub fn atan2<T: Float, V: FloatOps<T>>(y: V, x: V) -> V {
356 V::atan2(y, x)
357}
358
359pub fn cosh<T: Float, V: FloatOps<T>>(v: V) -> V {
361 V::cosh(v)
362}
363
364pub fn sinh<T: Float, V: FloatOps<T>>(v: V) -> V {
366 V::sinh(v)
367}
368
369pub fn tanh<T: Float, V: FloatOps<T>>(v: V) -> V {
371 V::tanh(v)
372}
373
374pub fn sin_cos<T: Float, V: FloatOps<T>>(v: V) -> (V, V) {
376 V::sin_cos(v)
377}
378
379pub fn exp<T: Float, V: FloatOps<T>>(v: V) -> V {
381 V::exp(v)
382}
383
384pub fn exp2<T: Float, V: FloatOps<T>>(v: V) -> V {
386 V::exp2(v)
387}
388
389pub fn log2<T: Float, V: FloatOps<T>>(v: V) -> V {
391 V::log2(v)
392}
393
394pub fn log10<T: Float, V: FloatOps<T>>(v: V) -> V {
396 V::log10(v)
397}
398
399pub fn log<T: Float, V: FloatOps<T>>(v: V, base: T) -> V {
401 V::log(v, base)
402}
403
404pub fn rotate_2d<T: Float + FloatOps<T>>(v: Vec2<T>, angle: T) -> Vec2<T> {
406 let c = cos(angle);
407 let s = sin(angle);
408 Vec2::new(c * v.x - s * v.y, s * v.x + c * v.y)
409}
410
411pub fn convex_hull_from_points<T: Float + SignedNumberOps<T> + NumberOps<T> + FloatOps<T>>(points: &Vec<Vec2<T>>) -> Vec<Vec2<T>> {
413 let mut cur = points[0];
415 let mut curi = 0;
416 for (i, item) in points.iter().enumerate().skip(1) {
417 if item.x > cur.x || (item.x == cur.x && item.y > cur.y) {
418 cur = *item;
420 curi = i;
421 }
422 }
423
424 let mut hull = vec![cur];
427 loop {
428 let mut rm = (curi+1)%points.len();
429 let mut x1 = points[rm];
430
431 for (i, item) in points.iter().enumerate() {
432 if i == curi {
433 continue;
434 }
435 let x2 = *item;
436 let v1 = x1 - cur;
437 let v2 = x2 - cur;
438 let z = v2.x * v1.y - v2.y * v1.x;
439 if z > T::zero() {
440 x1 = *item;
441 rm = i;
442 }
443 }
444
445 if approx(x1, hull[0], T::small_epsilon()) {
446 break;
447 }
448
449 cur = x1;
450 curi = rm;
451 hull.push(x1);
452 }
453 hull
454}
455
456pub fn plane_from_normal_and_point<T: SignedNumber>(x: Vec3<T>, n: Vec3<T>) -> Vec4<T> {
458 Vec4 {
459 x: n.x,
460 y: n.y,
461 z: n.z,
462 w: plane_distance(x, n)
463 }
464}
465
466pub fn get_triangle_normal<T: Float, V: VecFloatOps<T> + VecN<T> + Cross<T>>(t1: V, t2: V, t3: V) -> V {
468 normalize(cross(t2 - t1, t3 - t1))
469}
470
471pub fn project_to_ndc<T: Float>(p: Vec3<T>, view_projection: Mat4<T>) -> Vec3<T> {
473 let ndc = view_projection * Vec4::from((p, T::one()));
474 Vec3::from(ndc) / ndc.w
475}
476
477pub fn project_to_sc<T: Float + FloatOps<T>>(p: Vec3<T>, view_projection: Mat4<T>, viewport: Vec2<T>) -> Vec3<T> {
480 let ndc = project_to_ndc(p, view_projection);
481 let sc = ndc * T::point_five() + T::point_five();
482 Vec3::from((Vec2::<T>::from(sc) * viewport, sc.z))
483}
484
485pub fn project_to_sc_vdown<T: Float + FloatOps<T>>(p: Vec3<T>, view_projection: Mat4<T>, viewport: Vec2<T>) -> Vec2<T> {
488 let ndc = project_to_ndc(p, view_projection);
489 let sc = ndc * Vec3::new(T::point_five(), -T::point_five(), T::point_five()) + T::point_five();
490 Vec2::<T>::from(sc) * viewport
491}
492
493pub fn unproject_ndc<T: Float>(p: Vec3<T>, view_projection: Mat4<T>) -> Vec3<T> {
495 let inv = view_projection.inverse();
496 inv * p
497}
498
499pub fn unproject_sc<T: Float>(p: Vec3<T>, view_projection: Mat4<T>, viewport: Vec2<T>) -> Vec3<T> {
502 let ndc_xy = (Vec2::from(p) / viewport) * Vec2::from(T::two()) - Vec2::from(T::one());
503 let ndc = Vec3::from((ndc_xy, p.z));
504 unproject_ndc(ndc, view_projection)
505}
506
507pub fn unproject_sc_vdown<T: Float>(p: Vec3<T>, view_projection: Mat4<T>, viewport: Vec2<T>) -> Vec3<T> {
510 let ndc_xy = (Vec2::from(p) / viewport) * Vec2::new(T::two(), -T::two()) - Vec2::from(T::one());
511 let ndc = Vec3::from((ndc_xy, p.z));
512 unproject_ndc(ndc, view_projection)
513}
514
515pub fn plane_distance<T: SignedNumber, V: VecN<T>>(x: V, n: V) -> T {
517 -V::dot(x, n)
518}
519
520pub fn distance_on_line<T: Float, V: VecFloatOps<T> + VecN<T>>(p: V, l1: V, l2: V) -> T {
522 let v1 = p - l1;
523 let v2 = V::normalize(l2 - l1);
524 dot(v2, v1)
525}
526
527pub fn distance_on_ray<T: Float, V: VecFloatOps<T> + VecN<T>>(p: V, r0: V, rv: V) -> T {
529 dot(p - r0, rv)
530}
531
532pub fn point_plane_distance<T: SignedNumber, V: VecN<T>>( p: V, x: V, n: V) -> T {
534 V::dot(p, n) - V::dot(x, n)
535}
536
537pub fn point_line_segment_distance<T: Float + FloatOps<T>, V: VecFloatOps<T> + VecN<T>>(p: V, l1: V, l2: V) -> T {
539 let dx = l2 - l1;
540 let m2 = mag2(dx);
541 let s12 = saturate(dot(l2 - p, dx) / m2);
543 dist(p, l1 * s12 + l2 * (T::one() - s12))
545}
546
547pub fn point_aabb_distance<T: Float, V: VecN<T> + NumberOps<T> + VecFloatOps<T>>(p: V, aabb_min: V, aabb_max: V) -> T {
549 dist(closest_point_on_aabb(p, aabb_min, aabb_max), p)
550}
551
552pub fn point_sphere_distance<T: Float, V: VecN<T> + NumberOps<T> + VecFloatOps<T>>(p0: V, s0: V, r: T) -> T {
554 dist(p0, closest_point_on_sphere(p0, s0, r))
555}
556
557pub 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 {
559 let (w23, w31, w12) = barycentric(p, t1, t2, t3);
560 if w23 >= T::zero() && w31 >= T::zero() && w12 >= T::zero() {
561 dist(p, t1 * w23 + t2 * w31 + t3 * w12)
563 }
564 else {
565 if w23 > T::zero() {
567 T::min(point_line_segment_distance(p, t1, t2), point_line_segment_distance(p, t1, t3))
569 }
570 else if w31 > T::zero() {
571 T::min(point_line_segment_distance(p, t1, t2), point_line_segment_distance(p, t2, t3))
573 }
574 else {
575 T::min(point_line_segment_distance(p, t1, t3), point_line_segment_distance(p, t2, t3))
577 }
578 }
579}
580
581pub fn point_cone_distance<T: Float, V: VecN<T> + SignedVecN<T> + VecFloatOps<T>>(p: V, cp: V, cv: V, h: T, r: T) -> T {
583 dist(p, closest_point_on_cone(p, cp, cv, h, r))
584}
585
586pub fn point_convex_hull_distance<T: Float + FloatOps<T>>(p: Vec2<T>, hull: &Vec<Vec2<T>>) -> T {
588 dist(p, closest_point_on_polygon(p, hull))
589}
590
591pub fn point_polygon_distance<T: Float + FloatOps<T>>(p: Vec2<T>, hull: &Vec<Vec2<T>>) -> T {
593 dist(p, closest_point_on_polygon(p, hull))
594}
595
596pub 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 {
599 dist(p, closest_point_on_obb(p, mat))
600}
601
602pub fn closest_point_on_line_segment<T: Float, V: VecFloatOps<T> + VecN<T>>(p: V, l1: V, l2: V) -> V {
604 let v1 = p - l1;
605 let v2 = V::normalize(l2 - l1);
606 let t = V::dot(v2, v1);
607 if t < T::zero() {
608 l1
609 }
610 else if t > V::dist(l1, l2) {
611 l2
612 }
613 else {
614 l1 + (v2 * t)
615 }
616}
617
618pub fn closest_point_on_plane<T: SignedNumber, V: VecN<T> + SignedVecN<T>>(p: V, x: V, n: V) -> V {
620 p + n * -(V::dot(p, n) - V::dot(x, n))
621}
622
623pub fn closest_point_on_aabb<T: Float, V: NumberOps<T> + VecN<T>>(p: V, aabb_min: V, aabb_max: V) -> V {
625 V::min(V::max(p, aabb_min), aabb_max)
626}
627
628pub fn closest_point_on_sphere<T: Float, V: VecFloatOps<T> + VecN<T>>(p: V, s: V, r: T) -> V {
630 s + V::normalize(p - s) * r
631}
632
633pub fn closest_point_on_ray<T: Float, V: VecFloatOps<T> + VecN<T>>(p: V, r0: V, rv: V) -> V {
635 let v1 = p - r0;
636 let t = dot(v1, rv);
637 if t < T::zero() {
638 r0
639 }
640 else {
641 r0 + rv * t
642 }
643}
644
645pub 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 {
647 let invm = mat.inverse();
648 let tp = invm * p;
649 let cp = closest_point_on_aabb(tp, V::minus_one(), V::one());
650 mat * cp
651}
652
653pub 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 {
655 let (w23, w31, w12) = barycentric(p, t1, t2, t3);
656 if w23 >= T::zero() && w31 >= T::zero() && w12 >= T::zero() {
657 p
658 }
659 else {
660 if w23 > T::zero() {
662 let p1 = closest_point_on_line_segment(p, t1, t2);
664 let p2 = closest_point_on_line_segment(p, t1, t3);
665 if dist2(p, p1) < dist2(p, p2) {
666 p1
667 }
668 else {
669 p2
670 }
671 }
672 else if w31 > T::zero() {
673 let p1 = closest_point_on_line_segment(p, t1, t2);
675 let p2 = closest_point_on_line_segment(p, t2, t3);
676 if dist2(p, p1) < dist2(p, p2) {
677 p1
678 }
679 else {
680 p2
681 }
682 }
683 else {
684 let p1 = closest_point_on_line_segment(p, t1, t3);
686 let p2 = closest_point_on_line_segment(p, t2, t3);
687 if dist2(p, p1) < dist2(p, p2) {
688 p1
689 }
690 else {
691 p2
692 }
693 }
694 }
695}
696
697pub fn closest_point_on_cone<T: Float, V: VecN<T> + VecFloatOps<T>>(p: V, cp: V, cv: V, h: T, r: T) -> V {
699 let l2 = cp + cv * h;
701
702 let cplane = closest_point_on_plane(p, l2, cv);
704 let extent = l2 + normalize(cplane - l2) * r;
705
706 let e1 = closest_point_on_line_segment(p, cp, extent);
708 let e2 = closest_point_on_line_segment(p, l2, extent);
709
710 if dist2(p, e1) < dist2(p, e2) {
711 e1
712 }
713 else {
714 e2
715 }
716}
717
718pub fn closest_point_on_convex_hull<T: Float + FloatOps<T>>(p: Vec2<T>, hull: &Vec<Vec2<T>>) -> Vec2<T> {
720 closest_point_on_polygon(p, hull)
721}
722
723pub fn closest_point_on_polygon<T: Float + FloatOps<T>>(p: Vec2<T>, poly: &Vec<Vec2<T>>) -> Vec2<T> {
725 let ncp = poly.len();
726 let mut cp = Vec2::max_value();
727 let mut cd2 = T::max_value();
728 for i in 0..ncp {
729 let i2 = (i+1)%ncp;
730 let cpp = closest_point_on_line_segment(p, poly[i], poly[i2]);
731 let cppd2 = dist2(p, cpp);
732 if dist2(p, cpp) < cd2 {
733 cp = cpp;
734 cd2 = cppd2;
735 }
736 }
737 cp
738}
739
740pub fn point_inside_aabb<T: Float, V: VecN<T> + VecFloatOps<T>>(p: V, aabb_min: V, aabb_max: V) -> bool {
742 for i in 0..V::len() {
743 if p[i] < aabb_min[i] || p[i] > aabb_max[i] {
744 return false;
745 }
746 }
747 true
748}
749
750pub fn point_inside_sphere<T: Float, V: VecFloatOps<T> + VecN<T>>(p: V, s: V, r: T) -> bool {
752 dist2(p, s) < r * r
753}
754
755pub 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 {
757 let invm = mat.inverse();
758 let tp = invm * p;
759 point_inside_aabb(tp, V::minus_one(), V::one())
760}
761
762pub 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 {
764 let (w23, w31, w12) = barycentric(p, t1, t2, t3);
765 w23 >= T::zero() && w31 >= T::zero() && w12 >= T::zero()
766}
767
768pub 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 {
770 let l2 = cp + cv * h;
771 let dh = distance_on_line(p, cp, l2) / h;
772 let x0 = closest_point_on_line_segment(p, cp, l2);
773 let d = dist(x0, p);
774 d < dh * r && dh < T::one()
775}
776
777pub fn point_inside_convex_hull<T: Float>(p: Vec2<T>, hull: &Vec<Vec2<T>>) -> bool {
779 let ncp = hull.len();
780 for i in 0..ncp {
781 let i2 = (i+1)%ncp;
782 let p1 = hull[i];
783 let p2 = hull[i2];
784 let v1 = p2 - p1;
785 let v2 = p - p1;
786 let z = v1.x * v2.y - v2.x - v1.y;
787 if z > T::zero() {
788 return false;
789 }
790 }
791 true
792}
793
794pub fn point_inside_polygon<T: Float>(p: Vec2<T>, poly: &Vec<Vec2<T>>) -> bool {
796 let npol = poly.len();
799 let mut c = false;
800 let mut j = npol-1;
801 for i in 0..npol {
802 if (((poly[i].y <= p.y) && (p.y < poly[j].y)) || ((poly[j].y <= p.y) && (p.y < poly[i].y))) &&
803 (p.x < (poly[j].x - poly[i].x) * (p.y - poly[i].y) / (poly[j].y - poly[i].y) + poly[i].x) {
804 c = !c;
805 }
806 j = i
807 }
808 c
809}
810
811pub fn point_inside_frustum<T: Number>(p: Vec3<T>, planes: &[Vec4<T>; 6]) -> bool {
813 for plane in planes.iter().take(6) {
814 let d = dot(p, Vec3::from(*plane)) + plane.w;
815 if d > T::zero() {
816 return false;
817 }
818 }
819 true
820}
821
822pub fn point_vs_plane<T: SignedNumber + SignedNumberOps<T>>(p: Vec3<T>, x: Vec3<T>, n: Vec3<T>) -> Classification {
824 let pd = plane_distance(x, n);
825 let d = dot(n, p) + pd;
826 if d < T::zero() {
827 Classification::Behind
828 }
829 else if d > T::zero() {
830 Classification::Infront
831 }
832 else {
833 Classification::Intersects
834 }
835}
836
837pub fn aabb_vs_plane<T: SignedNumber + SignedNumberOps<T>>(aabb_min: Vec3<T>, aabb_max: Vec3<T>, x: Vec3<T>, n: Vec3<T>) -> Classification {
839 let e = (aabb_max - aabb_min) / T::two();
840 let centre = aabb_min + e;
841 let radius = abs(n.x * e.x) + abs(n.y * e.y) + abs(n.z * e.z);
842 let pd = plane_distance(x, n);
843 let d = dot(n, centre) + pd;
844 if d > radius {
845 Classification::Infront
846 }
847 else if d < -radius {
848 Classification::Behind
849 }
850 else {
851 Classification::Intersects
852 }
853}
854
855pub fn sphere_vs_plane<T: SignedNumber + SignedNumberOps<T>>(s: Vec3<T>, r: T, x: Vec3<T>, n: Vec3<T>) -> Classification {
857 let pd = plane_distance(x, n);
858 let d = dot(n, s) + pd;
859 if d > r {
860 Classification::Infront
861 }
862 else if d < -r {
863 Classification::Behind
864 }
865 else {
866 Classification::Intersects
867 }
868}
869
870pub 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 {
872 let pd = plane_distance(x, n);
873 let d1 = dot(n, c1) + pd;
876 let r1 = if d1 > r {
877 Classification::Infront
878 }
879 else if d1 < -r {
880 Classification::Behind
881 }
882 else {
883 Classification::Intersects
884 };
885 let d2 = dot(n, c2) + pd;
887 let r2 = if d2 > r {
888 Classification::Infront
889 }
890 else if d2 < -r {
891 Classification::Behind
892 }
893 else {
894 Classification::Intersects
895 };
896 if r1 == r2 {
897 r1
899 }
900 else {
901 Classification::Intersects
903 }
904}
905
906pub 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 {
909 let l2 = cp + cv * h;
910 let pd = plane_distance(x, n);
911 let d1 = dot(n, cp) + pd;
913 let perp = normalize(cross(cross(n, cv), cv));
915 let extent = l2 + perp * r;
916 let extent2 = l2 + perp * -r;
917 let d2 = dot(n, extent) + pd;
918 let d3 = dot(n, extent2) + pd;
919 if d1 < T::zero() && d2 < T::zero() && d3 < T::zero() {
920 Classification::Behind
921 }
922 else if d1 > T::zero() && d2 > T::zero() && d3 > T::zero() {
923 Classification::Infront
924 }
925 else {
926 Classification::Intersects
927 }
928}
929
930pub fn ray_vs_plane<T: Float + SignedNumberOps<T>>(r0: Vec3<T>, rv: Vec3<T>, x: Vec3<T>, n: Vec3<T>) -> Option<Vec3<T>> {
932 let t = -(dot(r0, n) - dot(x, n)) / dot(rv, n);
933 if t < T::zero() {
934 None
935 }
936 else {
937 Some(r0 + rv * t)
938 }
939}
940
941pub fn line_vs_plane<T: Float + SignedNumberOps<T>>(l0: Vec3<T>, lv: Vec3<T>, x: Vec3<T>, n: Vec3<T>) -> Option<Vec3<T>> {
943 let r = dot(lv, n);
944 if r == T::zero() {
945 None
946 }
947 else {
948 let t = -(dot(l0, n) - dot(x, n)) / dot(lv, n);
949 Some(l0 + lv * t)
950 }
951}
952
953pub 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>> {
955 let ll = l2-l1;
956 let m = mag(ll);
957 let lv = ll / m;
958 let t = -(dot(l1, n) - dot(x, n)) / dot(lv, n);
959 if t < T::zero() || t > m {
960 None
961 }
962 else {
963 Some(l1 + lv * t)
964 }
965}
966
967pub fn sphere_vs_sphere<T: Float, V: VecN<T> + VecFloatOps<T>>(s1: V, r1: T, s2: V, r2: T) -> bool {
969 let d2 = dist2(s1, s2);
970 let r22 = r1 + r2;
971 d2 < r22 * r22
972}
973
974pub 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 {
976 let cp = closest_point_on_line_segment(s1, c0, c1);
977 let r2 = sqr(r1 + cr);
978 dist2(s1, cp) < r2
979}
980
981pub fn aabb_vs_sphere<T: Float, V: VecN<T> + VecFloatOps<T> + NumberOps<T>>(aabb_min: V, aabb_max: V, s: V, r: T) -> bool {
983 let cp = closest_point_on_aabb(s, aabb_min, aabb_max);
984 dist2(cp, s) < r * r
985}
986
987pub fn aabb_vs_aabb<T: Number, V: VecN<T> + NumberOps<T>>(aabb_min1: V, aabb_max1: V, aabb_min2: V, aabb_max2: V) -> bool {
989 for i in 0..V::len() {
990 if aabb_max1[i] < aabb_min2[i] || aabb_min1[i] > aabb_max2[i] {
991 return false;
992 }
993 }
994 true
995}
996
997pub 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 {
999 let corners = [
1001 Vec3::<T>::new(-T::one(), -T::one(), -T::one()),
1002 Vec3::<T>::new( T::one(), -T::one(), -T::one()),
1003 Vec3::<T>::new( T::one(), T::one(), -T::one()),
1004 Vec3::<T>::new(-T::one(), T::one(), T::one()),
1005 Vec3::<T>::new(-T::one(), -T::one(), T::one()),
1006 Vec3::<T>::new( T::one(), -T::one(), T::one()),
1007 Vec3::<T>::new( T::one(), T::one(), T::one()),
1008 Vec3::<T>::new(-T::one(), T::one(), T::one()),
1009 ];
1010
1011 let verts0 = vec![
1013 aabb_min,
1014 Vec3::<T>::new(aabb_min.x, aabb_min.y, aabb_max.z),
1015 Vec3::<T>::new(aabb_max.x, aabb_min.y, aabb_min.z),
1016 Vec3::<T>::new(aabb_max.x, aabb_min.y, aabb_max.z),
1017 Vec3::<T>::new(aabb_min.x, aabb_max.y, aabb_min.z),
1018 Vec3::<T>::new(aabb_min.x, aabb_max.y, aabb_max.z),
1019 Vec3::<T>::new(aabb_max.x, aabb_max.y, aabb_min.z),
1020 aabb_max
1021 ];
1022
1023 let mut verts1 = Vec::new();
1025 for corner in corners {
1026 verts1.push(obb * corner);
1027 }
1028
1029 gjk_3d(verts0, verts1)
1030}
1031
1032pub 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 {
1035 let cp = closest_point_on_obb(s, obb);
1037 dist2(s, cp) < r * r
1038}
1039
1040pub 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 {
1042 let corners = [
1044 Vec3::<T>::new(-T::one(), -T::one(), -T::one()),
1045 Vec3::<T>::new( T::one(), -T::one(), -T::one()),
1046 Vec3::<T>::new( T::one(), T::one(), -T::one()),
1047 Vec3::<T>::new(-T::one(), T::one(), T::one()),
1048 Vec3::<T>::new(-T::one(), -T::one(), T::one()),
1049 Vec3::<T>::new( T::one(), -T::one(), T::one()),
1050 Vec3::<T>::new( T::one(), T::one(), T::one()),
1051 Vec3::<T>::new(-T::one(), T::one(), T::one()),
1052 ];
1053
1054 let mut verts0 = Vec::new();
1056 for corner in corners {
1057 verts0.push(obb0 * corner);
1058 }
1059
1060 let mut verts1 = Vec::new();
1061 for corner in corners {
1062 verts1.push(obb1 * corner);
1063 }
1064
1065 gjk_3d(verts0, verts1)
1066}
1067
1068pub 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 {
1070 let r2 = (cr0 + cr1) * (cr0 + cr1);
1072
1073 if let Some((start, end)) = shortest_line_segment_between_line_segments(cp0, cp1, cp2, cp3) {
1075 let d = dist2(start, end);
1076 d < r2
1077 }
1078 else {
1079 let l0 = normalize(cp1 - cp0);
1082 let t0 = dot(cp2 - cp0, l0);
1083 let ip0 = cp0 + l0 * t0;
1084 let d = dist2(cp2, ip0);
1085
1086 if d < r2 {
1088 let l1 = normalize(cp3 - cp2);
1089 let t1 = dot(cp0 - cp2, l1);
1090
1091 if t0 >= T::zero() && t0*t0 < dist2(cp1, cp0) {
1093 true
1094 }
1095 else {
1096 t1 > T::zero() && t1*t1 < dist2(cp2, cp3)
1097 }
1098 }
1099 else {
1100 false
1101 }
1102 }
1103}
1104
1105pub 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> {
1107 let oc = r0 - s0;
1108 let a = dot(rv, rv);
1109 let b = T::two() * dot(oc, rv);
1110 let c = dot(oc,oc) - r*r;
1111 let discriminant = b*b - T::four()*a*c;
1112 let hit = discriminant > T::zero();
1113 if !hit {
1114 None
1115 }
1116 else {
1117 let t1 = (-b - sqrt(discriminant)) / (T::two()*a);
1118 let t2 = (-b + sqrt(discriminant)) / (T::two()*a);
1119 let t = if t1 > T::zero() && t2 > T::zero() {
1120 min(t1, t2)
1121 }
1122 else if t1 > T::zero() {
1123 t1
1124 }
1125 else {
1126 t2
1127 };
1128 Some(r0 + rv * t)
1129 }
1130}
1131
1132pub fn ray_vs_aabb<T: Number + NumberOps<T>, V: VecN<T>>(r0: V, rv: V, aabb_min: V, aabb_max: V) -> Option<V> {
1134 let dirfrac = V::one() / rv;
1137 let tx = (aabb_min[0] - r0[0]) * dirfrac[0];
1138 let tm = (aabb_max[0] - r0[0]) * dirfrac[0];
1139 let mut tmin = min(tx, tm);
1140 let mut tmax = max(tx, tm);
1141 for i in 0..V::len() {
1142 let t1 = (aabb_min[i] - r0[i]) * dirfrac[i];
1143 let t2 = (aabb_max[i] - r0[i]) * dirfrac[i];
1144 tmin = max(min(t1, t2), tmin);
1145 tmax = min(max(t1, t2), tmax);
1146 }
1147
1148 if tmax < T::zero() || tmin > tmax {
1149 None
1152 }
1153 else {
1154 Some(r0 + rv * tmin)
1156 }
1157}
1158
1159pub fn ray_vs_obb<T: Float + NumberOps<T>,
1161 V: VecFloatOps<T> + NumberOps<T> + SignedNumberOps<T> + VecN<T> + SignedVecN<T>,
1162 M: MatTranslate<V> + MatInverse<T> + MatRotate3D<T, V> + MatN<T, V>
1163 + Into<Mat3<T>> + Copy>
1164 (r0: V, rv: V, mat: M) -> Option<V> where Mat3<T> : MatN<T, V> {
1165 let invm = mat.inverse();
1166 let tr1 = invm * r0;
1167 let rotm : Mat3<T> = invm.into();
1168 let trv = rotm * rv;
1169 let ip = ray_vs_aabb(tr1, normalize(trv), -V::one(), V::one());
1170 ip.map(|ip| mat * ip)
1171}
1172
1173pub fn ray_vs_triangle<T: Float>(r0: Vec3<T>, rv: Vec3<T>, t0: Vec3<T>, t1: Vec3<T>, t2: Vec3<T>) -> Option<Vec3<T>> {
1175 let edge1 = t1 - t0;
1178 let edge2 = t2 - t0;
1179 let h = cross(rv, edge2);
1180 let a = dot(edge1, h);
1181 if a > T::small_epsilon() && a < T::small_epsilon() {
1182 None
1184 }
1185 else {
1186 let f = T::one() / a;
1187 let s = r0 - t0;
1188 let u = f * dot(s, h);
1189 if u < T::zero() || u > T::one() {
1190 None
1191 }
1192 else {
1193 let q = cross(s, edge1);
1194 let v = f * dot(rv, q);
1195 if v < T::zero() || u + v > T::one() {
1196 None
1197 }
1198 else {
1199 let t = f * dot(edge2, q);
1201 if t > T::zero() {
1202 Some(r0 + rv * t)
1203 }
1204 else {
1205 None
1207 }
1208 }
1209 }
1210 }
1211}
1212
1213pub 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> {
1215 let seg = shortest_line_segment_between_line_and_line_segment(r0, r0 + rv, c0, c1);
1217 let mut ipc = V::max_value();
1218 let mut bc = false;
1219 if let Some((l0, l1)) = seg {
1220 if dist2(l0, l1) < sqr(cr) {
1222 let a = c0;
1225 let b = c1;
1226 let v = rv;
1227 let r = cr;
1228
1229 let ab = b - a;
1230 let ao = r0 - a;
1231 let aoxab = cross(ao, ab);
1232 let vxab = cross(v, ab);
1233 let ab2 = dot(ab, ab);
1234
1235 let aa = dot(vxab, vxab);
1236 let bb = T::two() * dot(vxab, aoxab);
1237 let cc = dot(aoxab, aoxab) - (r*r * ab2);
1238 let dd = bb * bb - T::four() * aa * cc;
1239
1240 if dd >= T::zero() {
1241 let t = (-bb - sqrt(dd)) / (T::two() * aa);
1242 if t >= T::zero() {
1243 ipc = r0 + rv * t;
1245 let ipd = distance_on_line(ipc, a, b);
1247 if ipd >= T::zero() && ipd <= dist(a, b) {
1248 bc = true;
1249 }
1250 }
1251 }
1252 }
1253 }
1254
1255 let bs1 = ray_vs_sphere(r0, rv, c0, cr);
1258 let bs2 = ray_vs_sphere(r0, rv, c1, cr);
1259
1260 let ips1 = if let Some(ip) = bs1 {
1262 ip
1263 }
1264 else {
1265 V::max_value()
1266 };
1267
1268 let ips2 = if let Some(ip) = bs2 {
1269 ip
1270 }
1271 else {
1272 V::max_value()
1273 };
1274
1275 let ips : [V; 3] = [ips1, ips2, ipc];
1277 let bips : [bool; 3] = [bs1.is_some(), bs2.is_some(), bc];
1278
1279 let mut iclosest = -1;
1280 let mut dclosest = T::max_value();
1281 for i in 0..3 {
1282 if bips[i] {
1283 let dd = distance_on_line(ips[i], r0, r0 + rv);
1284 if dd < dclosest {
1285 iclosest = i as i32;
1286 dclosest = dd;
1287 }
1288 }
1289 }
1290
1291 if iclosest != -1 {
1293 Some(ips[iclosest as usize])
1294 }
1295 else {
1296 None
1297 }
1298}
1299
1300pub 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>> {
1303 let a = c0;
1306 let b = c1;
1307 let v = rv;
1308 let r = cr;
1309
1310 let ab = b - a;
1311 let ao = r0 - a;
1312 let aoxab = cross(ao, ab);
1313 let vxab = cross(v, ab);
1314 let ab2 = dot(ab, ab);
1315
1316 let aa = dot(vxab, vxab);
1317 let bb = T::two() * dot(vxab, aoxab);
1318 let cc = dot(aoxab, aoxab) - (r*r * ab2);
1319 let dd = bb * bb - T::four() * aa * cc;
1320
1321 if dd >= T::zero() {
1322 let t = (-bb - sqrt(dd)) / (T::two() * aa);
1323 if t >= T::zero() {
1324 let ipc = r0 + rv * t;
1326 let ipd = distance_on_line(ipc, a, b);
1328 if ipd >= T::zero() && ipd <= dist(a, b) {
1329 return Some(ipc);
1330 }
1331 }
1332 }
1333
1334 let ip_top = ray_vs_plane(r0, rv, c0, normalize(c0 - c1));
1336 let ip_bottom = ray_vs_plane(r0, rv, c1, normalize(c1 - c0));
1337 let r2 = r*r;
1338
1339 let mut btop = false;
1340 if let Some(ip_top) = ip_top {
1341 if dist2(ip_top, c0) < r2 {
1342 btop = true;
1343 }
1344 }
1345
1346 if let Some(ip_bottom) = ip_bottom {
1347 if dist2(ip_bottom, c1) < r2 {
1348 if btop {
1349 if let Some(ip_top) = ip_top {
1350 let d1 = distance_on_line(ip_top, r0, r0 + rv);
1351 let d2 = distance_on_line(ip_bottom, r0, r0 + rv);
1352 if d2 < d1 {
1353 return Some(ip_bottom);
1354 }
1355 }
1356 }
1357 else {
1358 return Some(ip_bottom);
1359 }
1360 }
1361 }
1362
1363 if btop {
1364 if let Some(ip_top) = ip_top {
1365 return Some(ip_top);
1366 }
1367 }
1368
1369
1370 None
1371}
1372
1373pub fn sphere_vs_frustum<T: Number>(s: Vec3<T>, r: T, planes: &[Vec4<T>; 6]) -> bool {
1375 for p in planes.iter().take(6) {
1376 let d = dot(s, Vec3::from(*p)) + p.w;
1377 if d > r {
1378 return false;
1379 }
1380 }
1381 true
1382}
1383
1384pub fn aabb_vs_frustum<T: SignedNumber + SignedNumberOps<T>>(aabb_pos: Vec3<T>, aabb_extent: Vec3<T>, planes: &[Vec4<T>; 6]) -> bool {
1386 let mut inside = true;
1387 for p in planes.iter().take(6) {
1388 let pn = Vec3::from(*p);
1389 let sign_flip = Vec3::signum(pn) * T::minus_one();
1390 let pd = p.w;
1391 let d2 = dot(aabb_pos + aabb_extent * sign_flip, pn);
1392 if d2 > -pd {
1393 inside = false;
1394 }
1395 }
1396 inside
1397}
1398
1399pub 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>> {
1401 let da = l2 - l1;
1402 let db = s2 - s1;
1403 let dc = s1 - l1;
1404 if dot(dc, cross(da, db)) != T::zero() {
1405 None
1407 }
1408 else {
1409 let s = dot(cross(dc, db), cross(da, db)) / mag2(cross(da, db));
1410 if s >= T::zero() && s <= T::one() {
1411 let ip = l1 + da * s;
1412 let t = distance_on_line(ip, s1, s2) / dist(s1, s2);
1413 if t >= T::zero() && t <= T::one() {
1414 Some(ip)
1415 }
1416 else {
1417 None
1418 }
1419 }
1420 else {
1421 None
1422 }
1423 }
1424}
1425
1426pub 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>> {
1428 let da = l2 - l1;
1429 let db = s2 - s1;
1430 let dc = s1 - l1;
1431 if dot(dc, cross(da, db)) != T::zero() {
1432 None
1434 }
1435 else {
1436 let s = dot(cross(dc, db), cross(da, db)) / mag2(cross(da, db));
1437 let ip = l1 + da * s;
1438 let t = distance_on_line(ip, s1, s2) / dist(s1, s2);
1439 if t >= T::zero() && t <= T::one() {
1440 Some(ip)
1441 }
1442 else {
1443 None
1444 }
1445 }
1446}
1447
1448pub 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>> {
1450 let da = l2 - l1;
1451 let db = rv;
1452 let dc = r0 - l1;
1453 if dot(dc, cross(da, db)) != T::zero() {
1454 None
1456 }
1457 else {
1458 let s = dot(cross(dc, db), cross(da, db)) / mag2(cross(da, db));
1459 let ip = l1 + da * s;
1460 let t = distance_on_ray(ip, r0, rv);
1461 if s >= T::zero() && s <= T::one() && t >= T::zero() {
1462 Some(ip)
1463 }
1464 else {
1465 None
1466 }
1467 }
1468}
1469
1470pub 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)> {
1472 let p13 = p1 - p3;
1475 let p43 = p4 - p3;
1476
1477 if approx(abs(p43), V::zero(), T::small_epsilon()) {
1478 return None;
1479 }
1480
1481 let p21 = p2 - p1;
1482 if approx(abs(p21), V::zero(), T::small_epsilon()) {
1483 return None;
1484 }
1485
1486 let d1343 = dot(p13, p43);
1487 let d4321 = dot(p43, p21);
1488 let d1321 = dot(p13, p21);
1489 let d4343 = dot(p43, p43);
1490 let d2121 = dot(p21, p21);
1491
1492 let denom = d2121 * d4343 - d4321 * d4321;
1493 if abs(denom) < T::small_epsilon() {
1494 return None;
1495 }
1496
1497 let numer = d1343 * d4321 - d1321 * d4343;
1498 let mua = saturate(numer / denom);
1499 let mub = saturate((d1343 + d4321 * mua) / d4343);
1500
1501 Some((
1502 p1 + (p21 * mua),
1503 p3 + (p43 * mub)
1504 ))
1505}
1506
1507pub 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)> {
1509 let p13 = p1 - p3;
1512 let p43 = p4 - p3;
1513
1514 if approx(abs(p43), V::zero(), T::small_epsilon()) {
1515 return None;
1516 }
1517
1518 let p21 = p2 - p1;
1519 if approx(abs(p21), V::zero(), T::small_epsilon()) {
1520 return None;
1521 }
1522
1523 let d1343 = dot(p13, p43);
1524 let d4321 = dot(p43, p21);
1525 let d1321 = dot(p13, p21);
1526 let d4343 = dot(p43, p43);
1527 let d2121 = dot(p21, p21);
1528
1529 let denom = d2121 * d4343 - d4321 * d4321;
1530 if abs(denom) < T::small_epsilon() {
1531 return None;
1532 }
1533
1534 let numer = d1343 * d4321 - d1321 * d4343;
1535 let mua = numer / denom;
1536 let mub = (d1343 + d4321 * mua) / d4343;
1537
1538 Some((
1539 p1 + (p21 * mua),
1540 p3 + (p43 * mub)
1541 ))
1542}
1543
1544pub 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)> {
1546 let p13 = p1 - p3;
1549 let p43 = p4 - p3;
1550
1551 if approx(abs(p43), V::zero(), T::small_epsilon()) {
1552 return None;
1553 }
1554
1555 let p21 = p2 - p1;
1556 if approx(abs(p21), V::zero(), T::small_epsilon()) {
1557 return None;
1558 }
1559
1560 let d1343 = dot(p13, p43);
1561 let d4321 = dot(p43, p21);
1562 let d1321 = dot(p13, p21);
1563 let d4343 = dot(p43, p43);
1564 let d2121 = dot(p21, p21);
1565
1566 let denom = d2121 * d4343 - d4321 * d4321;
1567 if abs(denom) < T::small_epsilon() {
1568 return None;
1569 }
1570
1571 let numer = d1343 * d4321 - d1321 * d4343;
1572 let mua = numer / denom;
1573 let mub = saturate((d1343 + d4321 * mua) / d4343);
1574
1575 Some((
1576 p1 + (p21 * mua),
1577 p3 + (p43 * mub)
1578 ))
1579}
1580
1581pub fn almost_identity<T: Number + Float>(x: T, m: T, n: T) -> T {
1583 let a = T::two()*n - m;
1585 let b = T::two()*m - T::three()*n;
1586 let t = x/m;
1587 if x > m {
1588 x
1589 }
1590 else {
1591 (a*t + b)*t*t + n
1592 }
1593}
1594
1595pub fn integral_smoothstep<T: Number + Float + FloatOps<T>>(x: T, t: T) -> T {
1597 if x > t {
1599 x - t/T::two()
1600 }
1601 else {
1602 x*x*x*(T::one()-x*T::point_five()/t)/t/t
1603 }
1604}
1605
1606pub fn exp_impulse<T: Number + Float, X: Base<T> + FloatOps<T>>(k: X, x: X) -> X {
1608 let h = k * x;
1610 h * X::exp(X::one() - h)
1611}
1612
1613pub fn quad_impulse<T: Number + Float + Base<T> + FloatOps<T>>(k: T, x: T) -> T {
1615 T::two() * T::sqrt(k) * x / (T::one()+k*x*x)
1617}
1618
1619pub fn poly_impulse<T: Number + Float + Base<T> + FloatOps<T>>(k: T, x: T, n: T) -> T {
1621 let one = T::one();
1623 (n/(n-one))* T::powf((n-one)*k,one/n)*x/(one+k*T::powf(x,n))
1624}
1625
1626pub fn exp_sustained_impulse<T: SignedNumber + Float, X: Base<T> + FloatOps<T> + SignedNumberOps<T> + Ord>(x: X, f: X, k: X) -> X {
1628 let s = X::max(x-f, X::zero());
1630 X::min(x*x/(f*f), X::one() + (X::two()/f)*s*X::exp(-k*s))
1631}
1632
1633pub fn cubic_pulse<X: Float + SignedNumberOps<X>>(c: X, w: X, x: X) -> X {
1635 let mut x = abs(x - c);
1637 if x > w {
1638 X::zero()
1639 }
1640 else {
1641 x /= w;
1642 X::one() - x * x*(X::three() - X::two()*x)
1643 }
1644}
1645
1646pub fn exp_step<T: SignedNumber + Float, X: Base<T> + FloatOps<T> + SignedNumberOps<T>>(x: X, k: X, n: T) -> X {
1648 X::exp(-k * X::powf(x, n))
1650}
1651
1652pub fn gain<T: SignedNumber + Float + FloatOps<T>>(x: T, k: T) -> T {
1654 let y = if x < T::point_five() {
1656 x
1657 }
1658 else {
1659 T::one()-x
1660 };
1661 let a = T::point_five()*T::powf(T::two()*(y), k);
1662 if x < T::point_five() {
1663 a
1664 }
1665 else {
1666 T::one() - a
1667 }
1668}
1669
1670pub fn parabola<T: SignedNumber + Float, X: Base<T> + FloatOps<T> + SignedNumberOps<T>>(x: X, k: T) -> X {
1672 powf(X::four() * x * (X::one() - x), k)
1674}
1675
1676pub fn pcurve<T: SignedNumber + Float + Base<T> + FloatOps<T>>(x: T, a: T, b: T) -> T {
1678 let k = powf(a + b, a + b) / (powf(a, a) * powf(b, b));
1680 k * powf(x, a) * powf(T::one() - x, b)
1681}
1682
1683pub fn sinc<T: SignedNumber + Float, X: Base<T> + FloatOps<T> + SignedNumberOps<T>>(x: X, k: X) -> X {
1685 let a = X::zero() * (k*x-X::one());
1687 X::sin(a)/a
1688}
1689
1690pub fn rgb_to_hsv<T: Float + SignedNumberOps<T> + Cast<T>>(rgb: Vec3<T>) -> Vec3<T> {
1692 let mut r = rgb.x;
1695 let mut g = rgb.y;
1696 let mut b = rgb.z;
1697
1698 let mut k = T::zero();
1699 if g < b {
1700 std::mem::swap(&mut g, &mut b);
1701 k = T::minus_one();
1702 }
1703
1704 if r < g {
1705 std::mem::swap(&mut r, &mut g);
1706 k = -T::two() / T::from_f64(6.0) - k;
1707 }
1708
1709 let chroma = r - if g < b { g } else { b };
1710
1711 Vec3 {
1712 x: abs(k + (g - b) / (T::from_f64(6.0) * chroma + T::small_epsilon())),
1713 y: chroma / (r + T::small_epsilon()),
1714 z: r
1715 }
1716}
1717
1718pub fn hsv_to_rgb<T: Float + FloatOps<T> + Cast<T>>(hsv: Vec3<T>) -> Vec3<T> {
1720 let h = hsv.x;
1722 let s = hsv.y;
1723 let v = hsv.z;
1724
1725 if s == T::zero() {
1726 return Vec3 {
1728 x: v,
1729 y: v,
1730 z: v
1731 };
1732 }
1733
1734 let h = T::fmod(h, T::one()) / T::from_f64(0.16666666666);
1735 let i = h.as_i32();
1736 let f = h - floor(h);
1737 let p = v * (T::one() - s);
1738 let q = v * (T::one() - s * f);
1739 let t = v * (T::one() - s * (T::one() - f));
1740
1741 match i {
1742 0 => {
1743 Vec3::new(v, t, p)
1744 }
1745 1 => {
1746 Vec3::new(q, v, p)
1747 }
1748 2 => {
1749 Vec3::new(p, v, t)
1750 }
1751 3 => {
1752 Vec3::new(p, q, v)
1753 }
1754 4 => {
1755 Vec3::new(t, p, v)
1756 }
1757 _ => {
1758 Vec3::new(v, p, q)
1759 }
1760 }
1761}
1762
1763pub fn rgba8_to_vec4<T: Float + FloatOps<T> + Cast<T>>(rgba: u32) -> Vec4<T> {
1765 let one_over_255 = T::from_f32(1.0 / 255.0);
1766 Vec4 {
1767 x: T::from_u32((rgba >> 24) & 0xff) * one_over_255,
1768 y: T::from_u32((rgba >> 16) & 0xff) * one_over_255,
1769 z: T::from_u32((rgba >> 8) & 0xff) * one_over_255,
1770 w: T::from_u32(rgba & 0xff) * one_over_255
1771 }
1772}
1773
1774pub fn vec4_to_rgba8<T: Float + Cast<T>>(v: Vec4<T>) -> u32 {
1776 let mut rgba : u32 = 0;
1777 let x = T::from_f32(255.0);
1778 rgba |= (v[0] * x).as_u32() << 24;
1779 rgba |= (v[1] * x).as_u32() << 16;
1780 rgba |= (v[2] * x).as_u32() << 8;
1781 rgba |= (v[3] * x).as_u32();
1782 rgba
1783}
1784
1785pub fn smooth_start2<T: Float, X: Base<T>>(t: X, b: X, c: X, d: X) -> X {
1787 let t = t/d;
1788 c * t*t + b
1789}
1790
1791pub fn smooth_start3<T: Float, X: Base<T>>(t: X, b: X, c: X, d: X) -> X {
1793 let t = t/d;
1794 c * t*t*t + b
1795}
1796
1797pub fn smooth_start4<T: Float, X: Base<T>>(t: X, b: X, c: X, d: X) -> X {
1799 let t = t/d;
1800 c * t*t*t*t + b
1801}
1802
1803pub fn smooth_start5<T: Float, X: Base<T>>(t: X, b: X, c: X, d: X) -> X {
1805 let t = t/d;
1806 c * t*t*t*t*t + b
1807}
1808
1809pub fn smooth_stop2<T: Float, X: Base<T> + SignedNumberOps<T>>(t: X, b: X, c: X, d: X) -> X {
1811 let t = t/d;
1812 -c * t * (t - X::two()) + b
1813}
1814
1815pub fn smooth_stop3<T: Float, X: Base<T> + SignedNumberOps<T>>(t: X, b: X, c: X, d: X) -> X {
1817 let t = t/d;
1818 c * (t*t*t + X::one()) + b
1819}
1820
1821pub fn smooth_stop4<T: Float, X: Base<T> + SignedNumberOps<T>>(t: X, b: X, c: X, d: X) -> X {
1823 let t = t/d;
1824 c * (t*t*t*t + X::one()) + b
1825}
1826
1827pub fn smooth_stop5<T: Float, X: Base<T> + SignedNumberOps<T>>(t: X, b: X, c: X, d: X) -> X {
1829 let t = t/d;
1830 c * (t*t*t*t*t + X::one()) + b
1831}
1832
1833pub fn cubic_interpolate<T: Float, V: VecN<T> + NumberOps<T> + VecFloatOps<T>>(p1: V, p2: V, p3: V, p4: V, t: T) -> V {
1835 p1 * (T::one() - t) * (T::one() - t) * (T::one() - t) +
1836 p2 * T::three() * t * (T::one() - t) * (T::one() - t) +
1837 p3 * T::three() * t * t * (T::one() - t) +
1838 p4 * t * t * t
1839}
1840
1841pub fn cubic_tangent<T: Float, V: VecN<T> + NumberOps<T> + VecFloatOps<T>>(p1: V, p2: V, p3: V, p4: V, t: T) -> V {
1843 p1 * (-T::one() + T::two() * t - t * t) +
1844 p2 * (T::one() - T::four() * t + T::three() * t * t) +
1845 p3 * (T::two() * t - T::three() * t * t) +
1846 p4 * (t * t)
1847}
1848
1849pub fn morton_xy(x: u64, y: u64) -> u64 {
1851 let mut x = x;
1852 x = (x | (x << 16)) & 0x0000FFFF0000FFFF;
1853 x = (x | (x << 8)) & 0x00FF00FF00FF00FF;
1854 x = (x | (x << 4)) & 0x0F0F0F0F0F0F0F0F;
1855 x = (x | (x << 2)) & 0x3333333333333333;
1856 x = (x | (x << 1)) & 0x5555555555555555;
1857
1858 let mut y = y;
1859 y = (y | (y << 16)) & 0x0000FFFF0000FFFF;
1860 y = (y | (y << 8)) & 0x00FF00FF00FF00FF;
1861 y = (y | (y << 4)) & 0x0F0F0F0F0F0F0F0F;
1862 y = (y | (y << 2)) & 0x3333333333333333;
1863 y = (y | (y << 1)) & 0x5555555555555555;
1864
1865 x | (y << 1)
1866}
1867
1868pub fn morton_xyz(x: u64, y: u64, z: u64) -> u64 {
1870 let mut x = x;
1871 x = (x | (x << 16)) & 0xFFFF00000000FFFF;
1872 x = (x | (x << 8)) & 0xF00F00F00F00F;
1873 x = (x | (x << 4)) & 0x30C30C30C30C30C3;
1874 x = (x | (x << 2)) & 0x9249249249249249;
1875
1876 let mut y = y;
1877 y = (y | (y << 16)) & 0xFFFF00000000FFFF;
1878 y = (y | (y << 8)) & 0xF00F00F00F00F;
1879 y = (y | (y << 4)) & 0x30C30C30C30C30C3;
1880 y = (y | (y << 2)) & 0x9249249249249249;
1881
1882 let mut z = z;
1883 z = (z | (z << 16)) & 0xFFFF00000000FFFF;
1884 z = (z | (z << 8)) & 0xF00F00F00F00F;
1885 z = (z | (z << 4)) & 0x30C30C30C30C30C3;
1886 z = (z | (z << 2)) & 0x9249249249249249;
1887
1888 x | (y << 1) | (z << 2)
1889}
1890
1891pub fn morton_1(x: u64) -> u64 {
1893 let mut x = x & 0x5555555555555555;
1894 x = (x | (x >> 1)) & 0x3333333333333333;
1895 x = (x | (x >> 2)) & 0x0F0F0F0F0F0F0F0F;
1896 x = (x | (x >> 4)) & 0x00FF00FF00FF00FF;
1897 x = (x | (x >> 8)) & 0x0000FFFF0000FFFF;
1898 x = (x | (x >> 16)) & 0x00000000FFFFFFFF;
1899 x
1900}
1901
1902pub fn morton_2(x: u64) -> u64 {
1904 let mut x = x & 0x9249249249249249;
1905 x = (x | (x >> 2)) & 0x30C30C30C30C30C3;
1906 x = (x | (x >> 4)) & 0xF00F00F00F00F;
1907 x = (x | (x >> 8)) & 0xFF0000FF0000FF;
1908 x = (x | (x >> 16)) & 0xFFFF00000000FFFF;
1909 x = (x | (x >> 32)) & 0x00000000FFFFFFFF;
1910 x
1911}
1912
1913pub fn morton_to_xy(d: u64) -> (u64, u64) {
1915 (morton_1(d), morton_1(d >> 1))
1916}
1917
1918pub fn morton_to_xyz(d: u64) -> (u64, u64, u64) {
1920 (morton_2(d), morton_2(d >> 1), morton_2(d >> 2))
1921}
1922
1923pub fn map_to_range<T: Float, X: Base<T>>(v: X, in_start: X, in_end: X, out_start: X, out_end: X) -> X {
1925 let slope = X::one() * (out_end - out_start) / (in_end - in_start);
1926 out_start + slope * (v - in_start)
1927}
1928
1929pub fn gjk_mesh_support_function<T: Float + FloatOps<T> + NumberOps<T> + SignedNumberOps<T>, V: VecN<T> + VecFloatOps<T> + SignedNumberOps<T> + FloatOps<T>> (convex0: &Vec<V>, convex1: &Vec<V>, dir: V) -> V {
1931 let furthest_point = |dir: V, vertices: &Vec<V>| -> V {
1932 let mut fd = -T::max_value();
1933 let mut fv = vertices[0];
1934 for v in vertices {
1935 let d = dot(dir, *v);
1936 if d > fd {
1937 fv = *v;
1938 fd = d;
1939 }
1940 }
1941 fv
1942 };
1943
1944 let fp0 = furthest_point(dir, convex0);
1946 let fp1 = furthest_point(-dir, convex1);
1947 fp0 - fp1
1948}
1949
1950fn 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 {
1952 match simplex.len() {
1953 2 => {
1954 let a = simplex[1];
1955 let b = simplex[0];
1956 let ab = b - a;
1957 let ao = -a;
1958
1959 *dir = vector_triple(ab, ao, ab);
1960
1961 false
1962 },
1963 3 => {
1964 let a = simplex[2];
1965 let b = simplex[1];
1966 let c = simplex[0];
1967
1968 let ab = b - a;
1969 let ac = c - a;
1970 let ao = -a;
1971
1972 let abperp = vector_triple(ac, ab, ab);
1973 let acperp = vector_triple(ab, ac, ac);
1974
1975 if dot(abperp, ao) > T::zero() {
1976 simplex.remove(0);
1977 *dir = abperp;
1978 false
1979 }
1980 else if dot(acperp, ao) > T::zero() {
1981 simplex.remove(1);
1982 *dir = acperp;
1983 false
1984 }
1985 else {
1986 true
1987 }
1988 }
1989 _ => {
1990 panic!("we should always have 2 or 3 points in the simplex!");
1991 }
1992 }
1993}
1994
1995pub 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 {
1997 let mut dir = V::unit_x();
2001 let support = gjk_mesh_support_function(&convex0, &convex1, dir);
2002 dir = normalize(-support);
2003
2004 let mut simplex = vec![support];
2006
2007 let max_iters = 32;
2008 for _i in 0..max_iters {
2009 let a = gjk_mesh_support_function(&convex0, &convex1, dir);
2010
2011 if dot(a, dir) < T::zero() {
2012 return false;
2013 }
2014 simplex.push(a);
2015
2016 if handle_simplex_2d(&mut simplex, &mut dir) {
2017 return true;
2018 }
2019 }
2020
2021 false
2023}
2024
2025pub 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 {
2027 gjk_2d(convex0, convex1)
2028}
2029
2030fn 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 {
2032 match simplex.len() {
2033 2 => {
2034 let a = simplex[1];
2035 let b = simplex[0];
2036
2037 let ab = b - a;
2038 let ao = -a;
2039
2040 *dir = vector_triple(ab, ao, ab);
2041
2042 false
2043 },
2044 3 => {
2045 let a = simplex[2];
2046 let b = simplex[1];
2047 let c = simplex[0];
2048
2049 let ab = b - a;
2050 let ac = c - a;
2051 let ao = -a;
2052
2053 *dir = cross(ac, ab);
2054
2055 if dot(*dir, ao) < T::zero() {
2057 *dir = -*dir;
2058 }
2059
2060 false
2061 },
2062 4 => {
2063 let a = simplex[3];
2064 let b = simplex[2];
2065 let c = simplex[1];
2066 let d = simplex[0];
2067
2068 let centre = (a+b+c+d) / T::four();
2069
2070 let ab = b - a;
2071 let ac = c - a;
2072 let ad = d - a;
2073 let ao = -a;
2074
2075 let mut abac = cross(ab, ac);
2076 let mut acad = cross(ac, ad);
2077 let mut adab = cross(ad, ab);
2078
2079 let centre_abc = (a + b + c) / T::three();
2081 let centre_acd = (a + c + d) / T::three();
2082 let centre_adb = (a + d + b) / T::three();
2083
2084 if dot(centre - centre_abc, abac) > T::zero() {
2085 abac = -abac;
2086 }
2087
2088 if dot(centre - centre_acd, acad) > T::zero() {
2089 acad = -acad;
2090 }
2091
2092 if dot(centre - centre_adb, adab) > T::zero() {
2093 adab = -adab;
2094 }
2095
2096 if dot(abac, ao) > T::zero() {
2097 simplex.remove(0);
2099 *dir = abac;
2100 false
2101 }
2102 else if dot(acad, ao) > T::zero() {
2103 simplex.remove(1);
2105 *dir = acad;
2106 false
2107 }
2108 else if dot(adab, ao) > T::zero() {
2109 simplex.remove(2);
2111 *dir = adab;
2112 false
2113 }
2114 else {
2115 true
2116 }
2117 },
2118 _ => {
2119 panic!("we should always have 2, 3 or 4 points in the simplex!");
2120 }
2121 }
2122}
2123
2124pub 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 {
2126 let mut dir = V::unit_x();
2130 let support = gjk_mesh_support_function(&convex0, &convex1, dir);
2131 dir = normalize(-support);
2132
2133 let mut simplex = vec![support];
2135
2136 let max_iters = 32;
2137 for _i in 0..max_iters {
2138 let a = gjk_mesh_support_function(&convex0, &convex1, dir);
2139
2140 if dot(a, dir) < T::zero() {
2141 return false;
2142 }
2143 simplex.push(a);
2144
2145 if handle_simplex_3d(&mut simplex, &mut dir) {
2146 return true;
2147 }
2148 }
2149
2150 false
2152}
2153
2154pub mod prelude {
2156 #[doc(hidden)]
2157 pub use crate::{
2158 vec::*,
2160 mat::*,
2161 num::*,
2162 quat::*,
2163 swizz::*,
2164
2165 Vec2f, Vec3f, Vec4f,
2167 Mat2f, Mat3f, Mat34f, Mat4f,
2168 Quatf,
2169
2170 *,
2172 };
2173}
2174
2175