1use super::toi_proxy::ToiProxy;
7use crate::math::{Pose, Real, Vector};
8
9#[derive(Copy, Clone, Debug, Default)]
11pub struct SimplexCache {
12 #[cfg(feature = "dim3")]
14 pub metric: Real,
15 pub count: u8,
17 pub index_a: [u32; 3],
19 pub index_b: [u32; 3],
21}
22
23#[derive(Copy, Clone, Debug, Default)]
26pub struct ProxyDistanceOutput {
27 pub point_a: Vector,
29 pub point_b: Vector,
31 pub normal: Vector,
33 pub distance: Real,
35 pub iterations: u32,
37}
38
39#[derive(Copy, Clone, Default)]
40struct SimplexVertex {
41 wa: Vector,
42 wb: Vector,
43 w: Vector,
44 a: Real,
45 index_a: u32,
46 index_b: u32,
47}
48
49fn cache_is_valid(cache: &SimplexCache, proxy_a: &ToiProxy, proxy_b: &ToiProxy) -> bool {
50 let (na, nb) = (proxy_a.points().len() as u32, proxy_b.points().len() as u32);
51 cache.count <= 3
52 && cache.index_a[..cache.count as usize]
53 .iter()
54 .all(|i| *i < na)
55 && cache.index_b[..cache.count as usize]
56 .iter()
57 .all(|i| *i < nb)
58}
59
60#[cfg(feature = "dim2")]
66pub fn proxy_distance(
67 pos12: &Pose,
68 proxy_a: &ToiProxy,
69 proxy_b: &ToiProxy,
70 use_radii: bool,
71 cache: &mut SimplexCache,
72) -> ProxyDistanceOutput {
73 let points_a = proxy_a.points();
74 let points_b = proxy_b.points();
75 let point_b_in_a = |i: u32| pos12.transform_point(points_b[i as usize]);
76
77 let mut output = ProxyDistanceOutput::default();
78
79 let mut simplex = [SimplexVertex::default(); 3];
81 let mut count = if cache_is_valid(cache, proxy_a, proxy_b) {
82 cache.count as usize
83 } else {
84 0
85 };
86 for (i, v) in simplex.iter_mut().enumerate().take(count) {
87 v.index_a = cache.index_a[i];
88 v.index_b = cache.index_b[i];
89 v.wa = points_a[v.index_a as usize];
90 v.wb = point_b_in_a(v.index_b);
91 v.w = v.wa - v.wb;
92 v.a = -1.0;
94 }
95
96 if count == 0 {
97 let v = &mut simplex[0];
98 v.index_a = 0;
99 v.index_b = 0;
100 v.wa = points_a[0];
101 v.wb = point_b_in_a(0);
102 v.w = v.wa - v.wb;
103 v.a = 1.0;
104 count = 1;
105 }
106
107 let mut non_unit_normal = Vector::ZERO;
108 let mut save_a = [0u32; 3];
109 let mut save_b = [0u32; 3];
110
111 const MAX_ITERATIONS: u32 = 20;
113 let mut iteration = 0;
114 while iteration < MAX_ITERATIONS {
115 let save_count = count;
117 for i in 0..save_count {
118 save_a[i] = simplex[i].index_a;
119 save_b[i] = simplex[i].index_b;
120 }
121
122 let d = match count {
123 1 => -simplex[0].w,
124 2 => solve_simplex2(&mut simplex, &mut count),
125 3 => solve_simplex3(&mut simplex, &mut count),
126 _ => unreachable!(),
127 };
128
129 if count == 3 {
131 let (pa, pb) = witness_points(&simplex, count);
132 output.point_a = pa;
133 output.point_b = pb;
134 output.iterations = iteration;
135 return output;
136 }
137
138 if d.dot(d) < Real::EPSILON * Real::EPSILON {
141 let (pa, pb) = witness_points(&simplex, count);
142 output.point_a = pa;
143 output.point_b = pb;
144 output.iterations = iteration;
145 return output;
146 }
147
148 non_unit_normal = d;
149
150 let index_a = proxy_a.support(d);
153 let index_b = proxy_b.support(pos12.rotation.inverse_transform_vector(-d));
154 let vertex = &mut simplex[count];
155 vertex.index_a = index_a;
156 vertex.wa = points_a[index_a as usize];
157 vertex.index_b = index_b;
158 vertex.wb = point_b_in_a(index_b);
159 vertex.w = vertex.wa - vertex.wb;
160
161 iteration += 1;
163
164 let duplicate = (0..save_count).any(|i| index_a == save_a[i] && index_b == save_b[i]);
166 if duplicate {
167 break;
168 }
169
170 count += 1;
172 }
173
174 let normal = non_unit_normal.normalize_or_zero();
175 let (pa, pb) = witness_points(&simplex, count);
176 output.normal = normal;
177 output.distance = pa.distance(pb);
178 output.point_a = pa;
179 output.point_b = pb;
180 output.iterations = iteration;
181
182 cache.count = count as u8;
184 for (i, v) in simplex.iter().enumerate().take(count) {
185 cache.index_a[i] = v.index_a;
186 cache.index_b[i] = v.index_b;
187 }
188
189 if use_radii {
191 let radius_a = proxy_a.radius;
192 let radius_b = proxy_b.radius;
193 output.distance = (output.distance - radius_a - radius_b).max(0.0);
194
195 output.point_a += radius_a * normal;
198 output.point_b -= radius_b * normal;
199 }
200
201 output
202}
203
204#[cfg(feature = "dim2")]
205fn witness_points(simplex: &[SimplexVertex; 3], count: usize) -> (Vector, Vector) {
206 match count {
207 1 => (simplex[0].wa, simplex[0].wb),
208 2 => (
209 simplex[0].a * simplex[0].wa + simplex[1].a * simplex[1].wa,
210 simplex[0].a * simplex[0].wb + simplex[1].a * simplex[1].wb,
211 ),
212 3 => {
213 let pa = simplex[0].a * simplex[0].wa
214 + simplex[1].a * simplex[1].wa
215 + simplex[2].a * simplex[2].wa;
216 (pa, pa)
217 }
218 _ => unreachable!(),
219 }
220}
221
222#[cfg(feature = "dim2")]
224fn solve_simplex2(simplex: &mut [SimplexVertex; 3], count: &mut usize) -> Vector {
225 let w1 = simplex[0].w;
226 let w2 = simplex[1].w;
227 let e12 = w2 - w1;
228
229 let d12_2 = -w1.dot(e12);
231 if d12_2 <= 0.0 {
232 simplex[0].a = 1.0;
234 *count = 1;
235 return -w1;
236 }
237
238 let d12_1 = w2.dot(e12);
240 if d12_1 <= 0.0 {
241 simplex[1].a = 1.0;
243 *count = 1;
244 simplex[0] = simplex[1];
245 return -w2;
246 }
247
248 let inv_d12 = 1.0 / (d12_1 + d12_2);
250 simplex[0].a = d12_1 * inv_d12;
251 simplex[1].a = d12_2 * inv_d12;
252 *count = 2;
253 let s = (w1 + w2).perp_dot(e12);
255 Vector::new(-s * e12.y, s * e12.x)
256}
257
258#[cfg(feature = "dim2")]
259fn solve_simplex3(simplex: &mut [SimplexVertex; 3], count: &mut usize) -> Vector {
260 let w1 = simplex[0].w;
261 let w2 = simplex[1].w;
262 let w3 = simplex[2].w;
263
264 let e12 = w2 - w1;
266 let w1e12 = w1.dot(e12);
267 let w2e12 = w2.dot(e12);
268 let d12_1 = w2e12;
269 let d12_2 = -w1e12;
270
271 let e13 = w3 - w1;
273 let w1e13 = w1.dot(e13);
274 let w3e13 = w3.dot(e13);
275 let d13_1 = w3e13;
276 let d13_2 = -w1e13;
277
278 let e23 = w3 - w2;
280 let w2e23 = w2.dot(e23);
281 let w3e23 = w3.dot(e23);
282 let d23_1 = w3e23;
283 let d23_2 = -w2e23;
284
285 let n123 = e12.perp_dot(e13);
287 let d123_1 = n123 * w2.perp_dot(w3);
288 let d123_2 = n123 * w3.perp_dot(w1);
289 let d123_3 = n123 * w1.perp_dot(w2);
290
291 if d12_2 <= 0.0 && d13_2 <= 0.0 {
293 simplex[0].a = 1.0;
294 *count = 1;
295 return -w1;
296 }
297
298 if d12_1 > 0.0 && d12_2 > 0.0 && d123_3 <= 0.0 {
300 let inv_d12 = 1.0 / (d12_1 + d12_2);
301 simplex[0].a = d12_1 * inv_d12;
302 simplex[1].a = d12_2 * inv_d12;
303 *count = 2;
304 let s = (w1 + w2).perp_dot(e12);
305 return Vector::new(-s * e12.y, s * e12.x);
306 }
307
308 if d13_1 > 0.0 && d13_2 > 0.0 && d123_2 <= 0.0 {
310 let inv_d13 = 1.0 / (d13_1 + d13_2);
311 simplex[0].a = d13_1 * inv_d13;
312 simplex[2].a = d13_2 * inv_d13;
313 *count = 2;
314 simplex[1] = simplex[2];
315 let s = (w1 + w3).perp_dot(e13);
316 return Vector::new(-s * e13.y, s * e13.x);
317 }
318
319 if d12_1 <= 0.0 && d23_2 <= 0.0 {
321 simplex[1].a = 1.0;
322 *count = 1;
323 simplex[0] = simplex[1];
324 return -w2;
325 }
326
327 if d13_1 <= 0.0 && d23_1 <= 0.0 {
329 simplex[2].a = 1.0;
330 *count = 1;
331 simplex[0] = simplex[2];
332 return -w3;
333 }
334
335 if d23_1 > 0.0 && d23_2 > 0.0 && d123_1 <= 0.0 {
337 let inv_d23 = 1.0 / (d23_1 + d23_2);
338 simplex[1].a = d23_1 * inv_d23;
339 simplex[2].a = d23_2 * inv_d23;
340 *count = 2;
341 simplex[0] = simplex[2];
342 let s = (w2 + w3).perp_dot(e23);
343 return Vector::new(-s * e23.y, s * e23.x);
344 }
345
346 let inv_d123 = 1.0 / (d123_1 + d123_2 + d123_3);
348 simplex[0].a = d123_1 * inv_d123;
349 simplex[1].a = d123_2 * inv_d123;
350 simplex[2].a = d123_3 * inv_d123;
351 *count = 3;
352
353 Vector::ZERO
355}
356
357#[cfg(feature = "dim3")]
360const MAX_GJK_ITERATIONS: u32 = 32;
361
362#[cfg(feature = "dim3")]
363fn barycentric_coords_edge(a: Vector, b: Vector) -> [Real; 3] {
364 let ab = b - a;
365 [b.dot(ab), -a.dot(ab), ab.dot(ab)]
367}
368
369#[cfg(feature = "dim3")]
370fn barycentric_coords_tri(a: Vector, b: Vector, c: Vector) -> [Real; 4] {
371 let ab = b - a;
372 let ac = c - a;
373
374 let b_x_c = b.cross(c);
375 let c_x_a = c.cross(a);
376 let a_x_b = a.cross(b);
377
378 let ab_x_ac = ab.cross(ac);
379
380 [
382 b_x_c.dot(ab_x_ac),
383 c_x_a.dot(ab_x_ac),
384 a_x_b.dot(ab_x_ac),
385 ab_x_ac.dot(ab_x_ac),
386 ]
387}
388
389#[cfg(feature = "dim3")]
390fn scalar_triple_product(a: Vector, b: Vector, c: Vector) -> Real {
391 a.cross(b).dot(c)
392}
393
394#[cfg(feature = "dim3")]
395fn barycentric_coords_tet(a: Vector, b: Vector, c: Vector, d: Vector) -> [Real; 5] {
396 let ab = b - a;
397 let ac = c - a;
398 let ad = d - a;
399
400 let divisor = scalar_triple_product(ab, ac, ad);
402 let sign = if divisor < 0.0 { -1.0 } else { 1.0 };
403
404 [
405 sign * scalar_triple_product(b, c, d),
406 sign * scalar_triple_product(a, d, c),
407 sign * scalar_triple_product(a, b, d),
408 sign * scalar_triple_product(a, c, b),
409 sign * divisor,
410 ]
411}
412
413#[cfg(feature = "dim3")]
414fn simplex_metric(simplex: &[SimplexVertex; 4], count: usize) -> Real {
415 match count {
416 1 => 0.0,
417 2 => simplex[0].w.distance(simplex[1].w),
418 3 => {
419 let a = simplex[0].w;
420 let b = simplex[1].w;
421 let c = simplex[2].w;
422 (b - a).cross(c - a).length() / 2.0
423 }
424 4 => {
425 let a = simplex[0].w;
426 let b = simplex[1].w;
427 let c = simplex[2].w;
428 let d = simplex[3].w;
429 scalar_triple_product(b - a, c - a, d - a) / 6.0
430 }
431 _ => unreachable!(),
432 }
433}
434
435#[cfg(feature = "dim3")]
436fn witness_points3(simplex: &[SimplexVertex; 4], count: usize) -> (Vector, Vector) {
437 let vs = simplex;
438 match count {
439 1 => (vs[0].wa, vs[0].wb),
440 2 => (
441 vs[0].a * vs[0].wa + vs[1].a * vs[1].wa,
442 vs[0].a * vs[0].wb + vs[1].a * vs[1].wb,
443 ),
444 3 => (
445 vs[0].a * vs[0].wa + vs[1].a * vs[1].wa + vs[2].a * vs[2].wa,
446 vs[0].a * vs[0].wb + vs[1].a * vs[1].wb + vs[2].a * vs[2].wb,
447 ),
448 4 => {
449 let sum =
451 vs[0].a * vs[0].wa + vs[1].a * vs[1].wa + vs[2].a * vs[2].wa + vs[3].a * vs[3].wa;
452 (sum, sum)
453 }
454 _ => unreachable!(),
455 }
456}
457
458#[cfg(feature = "dim3")]
460fn solve_simplex2_3d(simplex: &mut [SimplexVertex; 4], count: &mut usize) -> bool {
461 let a = simplex[0].w;
462 let b = simplex[1].w;
463 let ab = b - a;
464
465 let divisor = ab.dot(ab);
466 let u = b.dot(ab);
467 let v = -a.dot(ab);
468
469 if v <= 0.0 {
471 *count = 1;
472 simplex[0].a = 1.0;
473 return true;
474 }
475
476 if u <= 0.0 {
478 *count = 1;
479 simplex[0] = simplex[1];
480 simplex[0].a = 1.0;
481 return true;
482 }
483
484 if divisor <= 0.0 {
486 return false;
487 }
488
489 let denominator = 1.0 / divisor;
490 simplex[0].a = denominator * u;
491 simplex[1].a = denominator * v;
492 true
493}
494
495#[cfg(feature = "dim3")]
496fn solve_simplex3_3d(simplex: &mut [SimplexVertex; 4], count: &mut usize) -> bool {
497 let v1 = simplex[0];
498 let v2 = simplex[1];
499 let v3 = simplex[2];
500
501 let w_ab = barycentric_coords_edge(v1.w, v2.w);
502 let w_bc = barycentric_coords_edge(v2.w, v3.w);
503 let w_ca = barycentric_coords_edge(v3.w, v1.w);
504
505 if w_ab[1] <= 0.0 && w_ca[0] <= 0.0 {
507 *count = 1;
508 simplex[0] = v1;
509 simplex[0].a = 1.0;
510 return true;
511 }
512
513 if w_bc[1] <= 0.0 && w_ab[0] <= 0.0 {
515 *count = 1;
516 simplex[0] = v2;
517 simplex[0].a = 1.0;
518 return true;
519 }
520
521 if w_ca[1] <= 0.0 && w_bc[0] <= 0.0 {
523 *count = 1;
524 simplex[0] = v3;
525 simplex[0].a = 1.0;
526 return true;
527 }
528
529 let w_abc = barycentric_coords_tri(v1.w, v2.w, v3.w);
530
531 if w_abc[2] <= 0.0 && w_ab[0] > 0.0 && w_ab[1] > 0.0 {
533 *count = 2;
534 simplex[0] = v1;
535 simplex[1] = v2;
536 let divisor = w_ab[2];
537 if divisor <= 0.0 {
538 return false;
539 }
540 simplex[0].a = w_ab[0] / divisor;
541 simplex[1].a = w_ab[1] / divisor;
542 return true;
543 }
544
545 if w_abc[0] <= 0.0 && w_bc[0] > 0.0 && w_bc[1] > 0.0 {
547 *count = 2;
548 simplex[0] = v2;
549 simplex[1] = v3;
550 let divisor = w_bc[2];
551 if divisor <= 0.0 {
552 return false;
553 }
554 simplex[0].a = w_bc[0] / divisor;
555 simplex[1].a = w_bc[1] / divisor;
556 return true;
557 }
558
559 if w_abc[1] <= 0.0 && w_ca[0] > 0.0 && w_ca[1] > 0.0 {
561 *count = 2;
562 simplex[0] = v3;
563 simplex[1] = v1;
564 let divisor = w_ca[2];
565 if divisor <= 0.0 {
566 return false;
567 }
568 simplex[0].a = w_ca[0] / divisor;
569 simplex[1].a = w_ca[1] / divisor;
570 return true;
571 }
572
573 let divisor = w_abc[3];
575 if divisor <= 0.0 {
576 return false;
577 }
578
579 simplex[0].a = w_abc[0] / divisor;
581 simplex[1].a = w_abc[1] / divisor;
582 simplex[2].a = w_abc[2] / divisor;
583 true
584}
585
586#[cfg(feature = "dim3")]
587fn solve_simplex4_3d(simplex: &mut [SimplexVertex; 4], count: &mut usize) -> bool {
588 let vertex_a = simplex[0];
589 let vertex_b = simplex[1];
590 let vertex_c = simplex[2];
591 let vertex_d = simplex[3];
592
593 let w_ab = barycentric_coords_edge(vertex_a.w, vertex_b.w);
594 let w_ac = barycentric_coords_edge(vertex_a.w, vertex_c.w);
595 let w_ad = barycentric_coords_edge(vertex_a.w, vertex_d.w);
596 let w_bc = barycentric_coords_edge(vertex_b.w, vertex_c.w);
597 let w_cd = barycentric_coords_edge(vertex_c.w, vertex_d.w);
598 let w_db = barycentric_coords_edge(vertex_d.w, vertex_b.w);
599
600 if w_ab[1] <= 0.0 && w_ac[1] <= 0.0 && w_ad[1] <= 0.0 {
602 *count = 1;
603 simplex[0] = vertex_a;
604 simplex[0].a = 1.0;
605 return true;
606 }
607
608 if w_ab[0] <= 0.0 && w_db[0] <= 0.0 && w_bc[1] <= 0.0 {
610 *count = 1;
611 simplex[0] = vertex_b;
612 simplex[0].a = 1.0;
613 return true;
614 }
615
616 if w_ac[0] <= 0.0 && w_bc[0] <= 0.0 && w_cd[1] <= 0.0 {
618 *count = 1;
619 simplex[0] = vertex_c;
620 simplex[0].a = 1.0;
621 return true;
622 }
623
624 if w_ad[0] <= 0.0 && w_cd[0] <= 0.0 && w_db[1] <= 0.0 {
626 *count = 1;
627 simplex[0] = vertex_d;
628 simplex[0].a = 1.0;
629 return true;
630 }
631
632 let w_acb = barycentric_coords_tri(vertex_a.w, vertex_c.w, vertex_b.w);
633 let w_abd = barycentric_coords_tri(vertex_a.w, vertex_b.w, vertex_d.w);
634 let w_adc = barycentric_coords_tri(vertex_a.w, vertex_d.w, vertex_c.w);
635 let w_bcd = barycentric_coords_tri(vertex_b.w, vertex_c.w, vertex_d.w);
636
637 if w_abd[2] <= 0.0 && w_acb[1] <= 0.0 && w_ab[0] > 0.0 && w_ab[1] > 0.0 {
639 *count = 2;
640 simplex[0] = vertex_a;
641 simplex[1] = vertex_b;
642 let divisor = w_ab[2];
643 if divisor <= 0.0 {
644 return false;
645 }
646 simplex[0].a = w_ab[0] / divisor;
647 simplex[1].a = w_ab[1] / divisor;
648 return true;
649 }
650
651 if w_acb[2] <= 0.0 && w_adc[1] <= 0.0 && w_ac[0] > 0.0 && w_ac[1] > 0.0 {
653 *count = 2;
654 simplex[0] = vertex_a;
655 simplex[1] = vertex_c;
656 let divisor = w_ac[2];
657 if divisor <= 0.0 {
658 return false;
659 }
660 simplex[0].a = w_ac[0] / divisor;
661 simplex[1].a = w_ac[1] / divisor;
662 return true;
663 }
664
665 if w_adc[2] <= 0.0 && w_abd[1] <= 0.0 && w_ad[0] > 0.0 && w_ad[1] > 0.0 {
667 *count = 2;
668 simplex[0] = vertex_a;
669 simplex[1] = vertex_d;
670 let divisor = w_ad[2];
671 if divisor <= 0.0 {
672 return false;
673 }
674 simplex[0].a = w_ad[0] / divisor;
675 simplex[1].a = w_ad[1] / divisor;
676 return true;
677 }
678
679 if w_acb[0] <= 0.0 && w_bcd[2] <= 0.0 && w_bc[0] > 0.0 && w_bc[1] > 0.0 {
681 *count = 2;
682 simplex[0] = vertex_b;
683 simplex[1] = vertex_c;
684 let divisor = w_bc[2];
685 if divisor <= 0.0 {
686 return false;
687 }
688 simplex[0].a = w_bc[0] / divisor;
689 simplex[1].a = w_bc[1] / divisor;
690 return true;
691 }
692
693 if w_adc[0] <= 0.0 && w_bcd[0] <= 0.0 && w_cd[0] > 0.0 && w_cd[1] > 0.0 {
695 *count = 2;
696 simplex[0] = vertex_c;
697 simplex[1] = vertex_d;
698 let divisor = w_cd[2];
699 if divisor <= 0.0 {
700 return false;
701 }
702 simplex[0].a = w_cd[0] / divisor;
703 simplex[1].a = w_cd[1] / divisor;
704 return true;
705 }
706
707 if w_abd[0] <= 0.0 && w_bcd[1] <= 0.0 && w_db[0] > 0.0 && w_db[1] > 0.0 {
709 *count = 2;
710 simplex[0] = vertex_d;
711 simplex[1] = vertex_b;
712 let divisor = w_db[2];
713 if divisor <= 0.0 {
714 return false;
715 }
716 simplex[0].a = w_db[0] / divisor;
717 simplex[1].a = w_db[1] / divisor;
718 return true;
719 }
720
721 let w_abcd = barycentric_coords_tet(vertex_a.w, vertex_b.w, vertex_c.w, vertex_d.w);
722
723 if w_abcd[3] < 0.0 && w_acb[0] > 0.0 && w_acb[1] > 0.0 && w_acb[2] > 0.0 {
725 *count = 3;
726 simplex[0] = vertex_a;
727 simplex[1] = vertex_c;
728 simplex[2] = vertex_b;
729 let divisor = w_acb[3];
730 if divisor <= 0.0 {
731 return false;
732 }
733 simplex[0].a = w_acb[0] / divisor;
734 simplex[1].a = w_acb[1] / divisor;
735 simplex[2].a = w_acb[2] / divisor;
736 return true;
737 }
738
739 if w_abcd[2] < 0.0 && w_abd[0] > 0.0 && w_abd[1] > 0.0 && w_abd[2] > 0.0 {
741 *count = 3;
742 simplex[0] = vertex_a;
743 simplex[1] = vertex_b;
744 simplex[2] = vertex_d;
745 let divisor = w_abd[3];
746 if divisor <= 0.0 {
747 return false;
748 }
749 simplex[0].a = w_abd[0] / divisor;
750 simplex[1].a = w_abd[1] / divisor;
751 simplex[2].a = w_abd[2] / divisor;
752 return true;
753 }
754
755 if w_abcd[1] < 0.0 && w_adc[0] > 0.0 && w_adc[1] > 0.0 && w_adc[2] > 0.0 {
757 *count = 3;
758 simplex[0] = vertex_a;
759 simplex[1] = vertex_d;
760 simplex[2] = vertex_c;
761 let divisor = w_adc[3];
762 if divisor <= 0.0 {
763 return false;
764 }
765 simplex[0].a = w_adc[0] / divisor;
766 simplex[1].a = w_adc[1] / divisor;
767 simplex[2].a = w_adc[2] / divisor;
768 return true;
769 }
770
771 if w_abcd[0] < 0.0 && w_bcd[0] > 0.0 && w_bcd[1] > 0.0 && w_bcd[2] > 0.0 {
773 *count = 3;
774 simplex[0] = vertex_b;
775 simplex[1] = vertex_c;
776 simplex[2] = vertex_d;
777 let divisor = w_bcd[3];
778 if divisor <= 0.0 {
779 return false;
780 }
781 simplex[0].a = w_bcd[0] / divisor;
782 simplex[1].a = w_bcd[1] / divisor;
783 simplex[2].a = w_bcd[2] / divisor;
784 return true;
785 }
786
787 let divisor = w_abcd[4];
789 if divisor <= 0.0 {
790 return false;
791 }
792
793 simplex[0].a = w_abcd[0] / divisor;
795 simplex[1].a = w_abcd[1] / divisor;
796 simplex[2].a = w_abcd[2] / divisor;
797 simplex[3].a = w_abcd[3] / divisor;
798 true
799}
800
801#[cfg(feature = "dim3")]
807pub fn proxy_distance(
808 pos12: &Pose,
809 proxy_a: &ToiProxy,
810 proxy_b: &ToiProxy,
811 use_radii: bool,
812 cache: &mut SimplexCache,
813) -> ProxyDistanceOutput {
814 let points_a = proxy_a.points();
815 let points_b = proxy_b.points();
816 let point_b_in_a = |i: u32| pos12.transform_point(points_b[i as usize]);
817
818 let mut output = ProxyDistanceOutput::default();
819
820 let mut simplex = [SimplexVertex::default(); 4];
823 let mut count = if cache_is_valid(cache, proxy_a, proxy_b) {
824 cache.count as usize
825 } else {
826 0
827 };
828 for (i, v) in simplex.iter_mut().enumerate().take(count) {
829 v.index_a = cache.index_a[i];
830 v.index_b = cache.index_b[i];
831 v.wa = points_a[v.index_a as usize];
832 v.wb = point_b_in_a(v.index_b);
833 v.w = v.wb - v.wa;
834 v.a = 0.0;
835 }
836
837 if count > 0 {
840 let metric1 = cache.metric;
841 let metric2 = simplex_metric(&simplex, count);
842 if 2.0 * metric1 < metric2 || metric2 < 0.5 * metric1 || metric2 < Real::EPSILON {
843 count = 0;
844 }
845 }
846
847 if count == 0 {
849 let v = &mut simplex[0];
850 v.index_a = 0;
851 v.index_b = 0;
852 v.wa = points_a[0];
853 v.wb = point_b_in_a(0);
854 v.w = v.wb - v.wa;
855 v.a = 0.0;
856 count = 1;
857 }
858
859 let mut backup = simplex;
860 let mut backup_count = 0usize;
861
862 let mut distance_sq = Real::MAX;
864 let mut normal = Vector::ZERO;
865
866 let mut iteration = 0;
868 while iteration < MAX_GJK_ITERATIONS {
869 let solved = match count {
871 1 => {
872 simplex[0].a = 1.0;
873 true
874 }
875 2 => solve_simplex2_3d(&mut simplex, &mut count),
876 3 => solve_simplex3_3d(&mut simplex, &mut count),
877 4 => solve_simplex4_3d(&mut simplex, &mut count),
878 _ => unreachable!(),
879 };
880
881 if !solved {
882 if backup_count == 0 {
884 break;
885 }
886 simplex = backup;
887 count = backup_count;
888 break;
889 }
890
891 if count == 4 {
892 let (pa, pb) = witness_points3(&simplex, count);
894 output.point_a = pa;
895 output.point_b = pb;
896 output.iterations = iteration;
897 return output;
898 }
899
900 let old_distance_sq = distance_sq;
902
903 let closest_point = match count {
905 1 => simplex[0].w,
906 2 => simplex[0].a * simplex[0].w + simplex[1].a * simplex[1].w,
907 3 => {
908 simplex[0].a * simplex[0].w
909 + simplex[1].a * simplex[1].w
910 + simplex[2].a * simplex[2].w
911 }
912 _ => unreachable!(),
913 };
914
915 distance_sq = closest_point.dot(closest_point);
916
917 if distance_sq >= old_distance_sq {
918 if backup_count == 0 {
920 break;
921 }
922 simplex = backup;
923 count = backup_count;
924 break;
925 }
926
927 let search_direction = match count {
929 1 => -simplex[0].w,
930 2 => {
931 let a = simplex[0].w;
933 let b = simplex[1].w;
934 let ab = b - a;
935 ab.cross(-a).cross(ab)
936 }
937 3 => {
938 let a = simplex[0].w;
940 let b = simplex[1].w;
941 let c = simplex[2].w;
942 let n = (b - a).cross(c - a);
943 if n.dot(a) < 0.0 {
944 n
945 } else {
946 -n
947 }
948 }
949 _ => unreachable!(),
950 };
951
952 if search_direction.length_squared() < 1000.0 * Real::MIN_POSITIVE {
953 let (pa, pb) = witness_points3(&simplex, count);
956 output.point_a = pa;
957 output.point_b = pb;
958 output.iterations = iteration;
959 return output;
960 }
961
962 normal = -search_direction;
963
964 let index_a = proxy_a.support(-search_direction);
966 let support_a = points_a[index_a as usize];
967 let index_b = proxy_b.support(pos12.rotation.inverse() * search_direction);
968 let support_b = point_b_in_a(index_b);
969
970 backup = simplex;
972 backup_count = count;
973
974 let duplicate =
976 (0..count).any(|i| simplex[i].index_a == index_a && simplex[i].index_b == index_b);
977 if duplicate {
978 break;
979 }
980
981 simplex[count].index_a = index_a;
982 simplex[count].index_b = index_b;
983 simplex[count].wa = support_a;
984 simplex[count].wb = support_b;
985 simplex[count].w = support_b - support_a;
986 count += 1;
987
988 iteration += 1;
989 }
990
991 let normal = normal.normalize_or_zero();
992 if normal == Vector::ZERO {
993 output.iterations = iteration;
995 return output;
996 }
997
998 let (pa, pb) = witness_points3(&simplex, count);
1000 cache.metric = simplex_metric(&simplex, count);
1001 cache.count = count.min(3) as u8;
1002 for (i, v) in simplex.iter().enumerate().take(count.min(3)) {
1003 cache.index_a[i] = v.index_a;
1004 cache.index_b[i] = v.index_b;
1005 }
1006
1007 output.point_a = pa;
1009 output.point_b = pb;
1010 output.distance = pa.distance(pb);
1011 output.normal = normal;
1012 output.iterations = iteration;
1013
1014 if use_radii {
1016 let ra = proxy_a.radius;
1017 let rb = proxy_b.radius;
1018 output.distance = (output.distance - ra - rb).max(0.0);
1019
1020 output.point_a += ra * normal;
1023 output.point_b -= rb * normal;
1024 }
1025
1026 output
1027}