1use crate::impl_mesh::ManifoldImpl;
20use crate::linalg::{cross, distance2, dot, Mat3x4, Vec3};
21use crate::sort::{get_face_box_morton, morton_code};
22use crate::types::Box as BBox;
23
24const K_ROOT: i32 = 1;
29
30fn leaf_to_node(leaf: i32) -> i32 {
31 leaf * 2
32}
33fn node_to_leaf(node: i32) -> i32 {
34 node / 2
35}
36fn internal_to_node(internal: i32) -> i32 {
37 internal * 2 + 1
38}
39fn node_to_internal(node: i32) -> i32 {
40 node / 2
41}
42fn is_leaf(node: i32) -> bool {
43 node % 2 == 0
44}
45fn is_internal(node: i32) -> bool {
46 node % 2 == 1
47}
48
49#[derive(Clone, Debug, Default)]
56pub struct Collider {
57 node_bbox: Vec<BBox>, node_parent: Vec<i32>, internal_children: Vec<[i32; 2]>, }
61
62impl Collider {
63 pub fn new(leaf_bbox: Vec<BBox>, leaf_morton: Vec<u32>) -> Self {
68 debug_assert_eq!(leaf_bbox.len(), leaf_morton.len());
69 debug_assert!(
70 leaf_morton.windows(2).all(|w| w[0] <= w[1]),
71 "Collider leaves must be pre-sorted by morton code"
72 );
73 let n = leaf_bbox.len();
74 if n == 0 {
75 return Self::default();
76 }
77 let num_nodes = 2 * n - 1;
78 let mut collider = Self {
79 node_bbox: vec![BBox::default(); num_nodes],
80 node_parent: vec![-1; num_nodes],
81 internal_children: vec![[-1, -1]; n.saturating_sub(1)],
82 };
83 collider.create_radix_tree(&leaf_morton);
84 collider.update_boxes(leaf_bbox);
85 collider
86 }
87
88 fn num_leaves(&self) -> usize {
89 if self.node_bbox.is_empty() {
90 0
91 } else {
92 self.internal_children.len() + 1
93 }
94 }
95
96
97 fn create_radix_tree(&mut self, leaf_morton: &[u32]) {
101 let num_leaves = leaf_morton.len();
102 if num_leaves <= 1 {
103 return;
104 }
105 let num_internal = num_leaves - 1;
106
107 const K_INITIAL_LENGTH: i32 = 128;
108 const K_LENGTH_MULTIPLE: i32 = 4;
109
110 let prefix_length = |i: i32, j: i32| -> i32 {
112 if j < 0 || j >= num_leaves as i32 {
113 return -1;
114 }
115 let mi = leaf_morton[i as usize];
116 let mj = leaf_morton[j as usize];
117 let xor = mi ^ mj;
118 if xor == 0 {
119 32 + ((i as u32 ^ j as u32).leading_zeros() as i32)
121 } else {
122 xor.leading_zeros() as i32
123 }
124 };
125
126 let range_end = |i: i32| -> i32 {
128 let dir_val = prefix_length(i, i + 1) - prefix_length(i, i - 1);
129 let dir = if dir_val > 0 { 1i32 } else if dir_val < 0 { -1i32 } else { -1i32 };
130 let common_prefix = prefix_length(i, i - dir);
131 let mut max_length = K_INITIAL_LENGTH;
132 while prefix_length(i, i + dir * max_length) > common_prefix {
133 max_length *= K_LENGTH_MULTIPLE;
134 }
135 let mut length = 0i32;
136 let mut step = max_length / 2;
137 while step > 0 {
138 if prefix_length(i, i + dir * (length + step)) > common_prefix {
139 length += step;
140 }
141 step /= 2;
142 }
143 i + dir * length
144 };
145
146 let find_split = |first: i32, last: i32| -> i32 {
148 let common_prefix = prefix_length(first, last);
149 let mut split = first;
150 let mut step = last - first;
151 loop {
152 step = (step + 1) >> 1; let new_split = split + step;
154 if new_split < last {
155 let split_prefix = prefix_length(first, new_split);
156 if split_prefix > common_prefix {
157 split = new_split;
158 }
159 }
160 if step <= 1 { break; }
161 }
162 split
163 };
164
165 for internal in 0..num_internal {
167 let i = internal as i32;
168 let mut first = i;
169 let mut last = range_end(i);
170 if first > last {
171 std::mem::swap(&mut first, &mut last);
172 }
173
174 let split = find_split(first, last);
175
176 let child1 = if split == first {
178 leaf_to_node(split)
179 } else {
180 internal_to_node(split)
181 };
182 let split2 = split + 1;
184 let child2 = if split2 == last {
185 leaf_to_node(split2)
186 } else if (split2 as usize) < num_internal {
187 internal_to_node(split2)
188 } else {
189 child1
193 };
194
195 self.internal_children[internal] = [child1, child2];
196 let node = internal_to_node(i);
197 self.node_parent[child1 as usize] = node;
198 self.node_parent[child2 as usize] = node;
199 }
200 }
201
202 fn build_internal_boxes(&mut self) {
205 let num_leaves = self.num_leaves();
206 let num_internal = self.internal_children.len();
207 if num_internal == 0 {
208 return;
209 }
210 let mut counter = vec![0u32; num_internal];
211
212 for leaf in 0..num_leaves {
213 let mut node = leaf_to_node(leaf as i32);
214 loop {
215 let parent = self.node_parent[node as usize];
216 if parent < 0 {
217 break; }
219 let internal = node_to_internal(parent);
220 if internal < 0 || internal >= num_internal as i32 {
221 break;
222 }
223 let idx = internal as usize;
224 counter[idx] += 1;
225 if counter[idx] < 2 {
226 break; }
228 let [c1, c2] = self.internal_children[idx];
230 let b1 = self.node_bbox[c1 as usize];
231 let b2 = self.node_bbox[c2 as usize];
232 self.node_bbox[parent as usize] = b1.union_box(&b2);
233 node = parent;
234 }
235 }
236 }
237
238 pub fn collisions_one<R: FnMut(usize, usize)>(
243 &self,
244 query: &BBox,
245 query_idx: usize,
246 mut record: R,
247 ) {
248 if query.is_empty() {
249 return;
250 }
251 if self.internal_children.is_empty() {
254 return;
255 }
256 self.traverse_bvh(query, query_idx, false, &mut record);
257 }
258
259 pub fn collisions_fn<F, R>(
263 &self,
264 query_box_fn: F,
265 n: usize,
266 mut record: R,
267 ) where
268 F: Fn(usize) -> BBox,
269 R: FnMut(usize, usize),
270 {
271 if self.internal_children.is_empty() {
272 return;
273 }
274
275 for query_idx in 0..n {
276 let query = query_box_fn(query_idx);
277 if query.is_empty() {
278 continue;
279 }
280 self.traverse_bvh(&query, query_idx, false, &mut record);
281 }
282 }
283
284 pub fn collisions_with_boxes<F: FnMut(usize, usize)>(
286 &self,
287 queries: &[BBox],
288 self_collision: bool,
289 mut record: F,
290 ) {
291 if self.internal_children.is_empty() {
292 return;
293 }
294
295 for (query_idx, query) in queries.iter().enumerate() {
296 if query.is_empty() {
297 continue;
298 }
299 self.traverse_bvh(query, query_idx, self_collision, &mut record);
300 }
301 }
302
303 pub fn collisions_point<F, R>(
305 &self,
306 point_fn: F,
307 n: usize,
308 mut record: R,
309 ) where
310 F: Fn(usize) -> Vec3,
311 R: FnMut(usize, usize),
312 {
313 if self.internal_children.is_empty() {
314 return;
315 }
316
317 for query_idx in 0..n {
318 let pt = point_fn(query_idx);
319 let query = BBox::from_point(pt);
320 self.traverse_bvh(&query, query_idx, false, &mut record);
321 }
322 }
323
324 fn traverse_bvh<F: FnMut(usize, usize)>(
326 &self,
327 query: &BBox,
328 query_idx: usize,
329 self_collision: bool,
330 record: &mut F,
331 ) {
332 let mut stack = [0i32; 64];
333 let mut top: i32 = -1;
334 let mut node = K_ROOT;
335
336 loop {
337 let internal = node_to_internal(node);
338 if internal < 0 || internal as usize >= self.internal_children.len() {
339 if top < 0 { break; }
340 node = stack[top as usize];
341 top -= 1;
342 continue;
343 }
344 let [child1, child2] = self.internal_children[internal as usize];
345
346 let traverse1 = self.check_node(query, child1, query_idx, self_collision, record);
347 let traverse2 = self.check_node(query, child2, query_idx, self_collision, record);
348
349 if !traverse1 && !traverse2 {
350 if top < 0 {
351 break;
352 }
353 node = stack[top as usize];
354 top -= 1;
355 } else {
356 node = if traverse1 { child1 } else { child2 };
357 if traverse1 && traverse2 {
358 top += 1;
359 debug_assert!((top as usize) < 64, "BVH stack overflow");
360 stack[top as usize] = child2;
361 }
362 }
363 }
364 }
365
366 #[inline]
369 fn check_node<F: FnMut(usize, usize)>(
370 &self,
371 query: &BBox,
372 node: i32,
373 query_idx: usize,
374 self_collision: bool,
375 record: &mut F,
376 ) -> bool {
377 if node < 0 || node as usize >= self.node_bbox.len() {
378 return false;
379 }
380 let node_box = &self.node_bbox[node as usize];
381 let overlaps = query.does_overlap_box(node_box);
382 if overlaps && is_leaf(node) {
383 let leaf_idx = node_to_leaf(node) as usize;
386 if !self_collision || leaf_idx != query_idx {
387 record(query_idx, leaf_idx);
388 }
389 }
390 overlaps && is_internal(node)
391 }
392
393 pub fn update_boxes(&mut self, leaf_bbox: Vec<BBox>) {
397 debug_assert_eq!(leaf_bbox.len(), self.num_leaves());
398 for (i, bbox) in leaf_bbox.into_iter().enumerate() {
399 self.node_bbox[leaf_to_node(i as i32) as usize] = bbox;
400 }
401 self.build_internal_boxes();
402 }
403
404 pub fn transform(&mut self, transform: &Mat3x4) {
408 debug_assert!(Self::is_axis_aligned(transform));
409 for bbox in &mut self.node_bbox {
410 *bbox = bbox.transform(transform);
411 }
412 }
413
414 pub fn morton_code(position: Vec3, bbox: &BBox) -> u32 {
415 morton_code(position, bbox)
416 }
417
418 pub fn is_axis_aligned(transform: &Mat3x4) -> bool {
419 for row in 0..3 {
420 let mut zero_count = 0;
421 for col in 0..3 {
422 if transform[col][row] == 0.0 {
423 zero_count += 1;
424 }
425 }
426 if zero_count != 2 {
427 return false;
428 }
429 }
430 true
431 }
432
433}
434
435pub fn edge_edge_dist(p: Vec3, a: Vec3, q: Vec3, b: Vec3) -> (Vec3, Vec3) {
436 let t_vec = q - p;
437 let a_dot_a = dot(a, a);
438 let b_dot_b = dot(b, b);
439 let a_dot_b = dot(a, b);
440 let a_dot_t = dot(a, t_vec);
441 let b_dot_t = dot(b, t_vec);
442
443 let denom = a_dot_a * b_dot_b - a_dot_b * a_dot_b;
444 let mut t = if denom != 0.0 {
445 ((a_dot_t * b_dot_b - b_dot_t * a_dot_b) / denom).clamp(0.0, 1.0)
446 } else {
447 0.0
448 };
449
450 let u = if b_dot_b != 0.0 {
451 let u = (t * a_dot_b - b_dot_t) / b_dot_b;
452 if u < 0.0 {
453 t = if a_dot_a != 0.0 { (a_dot_t / a_dot_a).clamp(0.0, 1.0) } else { 0.0 };
454 0.0
455 } else if u > 1.0 {
456 t = if a_dot_a != 0.0 {
457 ((a_dot_b + a_dot_t) / a_dot_a).clamp(0.0, 1.0)
458 } else {
459 0.0
460 };
461 1.0
462 } else {
463 u
464 }
465 } else {
466 t = if a_dot_a != 0.0 { (a_dot_t / a_dot_a).clamp(0.0, 1.0) } else { 0.0 };
467 0.0
468 };
469
470 (p + a * t, q + b * u)
471}
472
473pub fn distance_triangle_triangle_squared(p: [Vec3; 3], q: [Vec3; 3]) -> f64 {
474 let sv = [p[1] - p[0], p[2] - p[1], p[0] - p[2]];
475 let tv = [q[1] - q[0], q[2] - q[1], q[0] - q[2]];
476
477 let mut shown_disjoint = false;
478 let mut mindd = f64::MAX;
479
480 for i in 0..3 {
481 for j in 0..3 {
482 let (cp, cq) = edge_edge_dist(p[i], sv[i], q[j], tv[j]);
483 let v = cq - cp;
484 let dd = dot(v, v);
485
486 if dd <= mindd {
487 mindd = dd;
488
489 let mut id = i + 2;
490 if id >= 3 { id -= 3; }
491 let z = p[id] - cp;
492 let mut a = dot(z, v);
493
494 id = j + 2;
495 if id >= 3 { id -= 3; }
496 let z = q[id] - cq;
497 let mut b = dot(z, v);
498
499 if a <= 0.0 && b >= 0.0 {
500 return dot(v, v);
501 }
502
503 if a <= 0.0 { a = 0.0; } else if b > 0.0 { b = 0.0; }
504
505 if mindd - a + b > 0.0 {
506 shown_disjoint = true;
507 }
508 }
509 }
510 }
511
512 let sn = cross(sv[0], sv[1]);
513 let snl = dot(sn, sn);
514 if snl > 1e-15 {
515 let tp = Vec3::new(dot(p[0] - q[0], sn), dot(p[0] - q[1], sn), dot(p[0] - q[2], sn));
516 let mut index = None;
517 if tp.x > 0.0 && tp.y > 0.0 && tp.z > 0.0 {
518 let mut idx = if tp.x < tp.y { 0 } else { 1 };
519 if tp.z < tp[idx] { idx = 2; }
520 index = Some(idx);
521 } else if tp.x < 0.0 && tp.y < 0.0 && tp.z < 0.0 {
522 let mut idx = if tp.x > tp.y { 0 } else { 1 };
523 if tp.z > tp[idx] { idx = 2; }
524 index = Some(idx);
525 }
526
527 if let Some(index) = index {
528 shown_disjoint = true;
529 let q_index = q[index];
530 let v = q_index - p[0];
531 let z = cross(sn, sv[0]);
532 if dot(v, z) > 0.0 {
533 let v = q_index - p[1];
534 let z = cross(sn, sv[1]);
535 if dot(v, z) > 0.0 {
536 let v = q_index - p[2];
537 let z = cross(sn, sv[2]);
538 if dot(v, z) > 0.0 {
539 let cp = q_index + sn * (tp[index] / snl);
540 let cq = q_index;
541 return dot(cp - cq, cp - cq);
542 }
543 }
544 }
545 }
546 }
547
548 let tn = cross(tv[0], tv[1]);
549 let tnl = dot(tn, tn);
550 if tnl > 1e-15 {
551 let sp = Vec3::new(dot(q[0] - p[0], tn), dot(q[0] - p[1], tn), dot(q[0] - p[2], tn));
552 let mut index = None;
553 if sp.x > 0.0 && sp.y > 0.0 && sp.z > 0.0 {
554 let mut idx = if sp.x < sp.y { 0 } else { 1 };
555 if sp.z < sp[idx] { idx = 2; }
556 index = Some(idx);
557 } else if sp.x < 0.0 && sp.y < 0.0 && sp.z < 0.0 {
558 let mut idx = if sp.x > sp.y { 0 } else { 1 };
559 if sp.z > sp[idx] { idx = 2; }
560 index = Some(idx);
561 }
562
563 if let Some(index) = index {
564 shown_disjoint = true;
565 let p_index = p[index];
566 let v = p_index - q[0];
567 let z = cross(tn, tv[0]);
568 if dot(v, z) > 0.0 {
569 let v = p_index - q[1];
570 let z = cross(tn, tv[1]);
571 if dot(v, z) > 0.0 {
572 let v = p_index - q[2];
573 let z = cross(tn, tv[2]);
574 if dot(v, z) > 0.0 {
575 let cp = p_index;
576 let cq = p_index + tn * (sp[index] / tnl);
577 return dot(cp - cq, cp - cq);
578 }
579 }
580 }
581 }
582 }
583
584 if shown_disjoint { mindd } else { 0.0 }
585}
586
587pub fn ray_triangle_intersection(
588 origin: Vec3,
589 direction: Vec3,
590 tri: [Vec3; 3],
591) -> Option<f64> {
592 let eps = 1e-9;
593 let edge1 = tri[1] - tri[0];
594 let edge2 = tri[2] - tri[0];
595 let h = cross(direction, edge2);
596 let a = dot(edge1, h);
597 if a.abs() < eps {
598 return None;
599 }
600 let f = 1.0 / a;
601 let s = origin - tri[0];
602 let u = f * dot(s, h);
603 if !(0.0..=1.0).contains(&u) {
604 return None;
605 }
606 let q = cross(s, edge1);
607 let v = f * dot(direction, q);
608 if v < 0.0 || u + v > 1.0 {
609 return None;
610 }
611 let t = f * dot(edge2, q);
612 if t > eps { Some(t) } else { None }
613}
614
615impl ManifoldImpl {
616 pub fn is_self_intersecting(&self) -> bool {
617 let ep = 2.0 * self.epsilon;
618 let epsilon_sq = ep * ep;
619 let (face_box, _face_morton) = get_face_box_morton(self);
622 let collider = &self.collider;
623 let mut intersecting = false;
624
625 collider.collisions_with_boxes(&face_box, true, |tri0, tri1| {
626 if intersecting {
627 return;
628 }
629 let tri_verts0 = self.face_triangle_vertices(tri0);
630 let tri_verts1 = self.face_triangle_vertices(tri1);
631
632 for a in &tri_verts0 {
633 for b in &tri_verts1 {
634 if distance2(*a, *b) <= epsilon_sq {
635 return;
636 }
637 }
638 }
639
640 if distance_triangle_triangle_squared(tri_verts0, tri_verts1) == 0.0 {
641 let mut tmp0 = tri_verts0;
642 let mut tmp1 = tri_verts1;
643 for i in 0..3 {
644 tmp0[i] = tri_verts0[i] + self.face_normal[tri1] * ep;
645 }
646 if distance_triangle_triangle_squared(tmp0, tri_verts1) > 0.0 {
647 return;
648 }
649 for i in 0..3 {
650 tmp0[i] = tri_verts0[i] - self.face_normal[tri1] * ep;
651 }
652 if distance_triangle_triangle_squared(tmp0, tri_verts1) > 0.0 {
653 return;
654 }
655 for i in 0..3 {
656 tmp1[i] = tri_verts1[i] + self.face_normal[tri0] * ep;
657 }
658 if distance_triangle_triangle_squared(tri_verts0, tmp1) > 0.0 {
659 return;
660 }
661 for i in 0..3 {
662 tmp1[i] = tri_verts1[i] - self.face_normal[tri0] * ep;
663 }
664 if distance_triangle_triangle_squared(tri_verts0, tmp1) > 0.0 {
665 return;
666 }
667 intersecting = true;
668 }
669 });
670
671 intersecting
672 }
673
674 pub fn min_gap(&self, other: &ManifoldImpl, search_length: f64) -> f64 {
675 let (mut other_box, _) = get_face_box_morton(other);
676 for bbox in &mut other_box {
677 bbox.min = bbox.min - Vec3::splat(search_length);
678 bbox.max = bbox.max + Vec3::splat(search_length);
679 }
680
681 let collider = &self.collider;
683 let mut min_distance = f64::INFINITY;
684 collider.collisions_with_boxes(&other_box, false, |tri_other, tri| {
685 let p = self.face_triangle_vertices(tri);
686 let q = other.face_triangle_vertices(tri_other);
687 min_distance = min_distance.min(distance_triangle_triangle_squared(p, q));
688 });
689
690 min_distance.min(search_length * search_length).sqrt()
691 }
692
693 fn face_triangle_vertices(&self, tri: usize) -> [Vec3; 3] {
694 [
695 self.vert_pos[self.halfedge[3 * tri].start_vert as usize],
696 self.vert_pos[self.halfedge[3 * tri + 1].start_vert as usize],
697 self.vert_pos[self.halfedge[3 * tri + 2].start_vert as usize],
698 ]
699 }
700}
701
702#[cfg(test)]
703mod tests {
704 use super::*;
705 use crate::linalg::{mat4_to_mat3x4, translation_matrix};
706
707 #[test]
708 fn test_collider_box_overlap() {
709 let boxes = vec![
710 BBox::from_points(Vec3::new(0.0, 0.0, 0.0), Vec3::new(1.0, 1.0, 1.0)),
711 BBox::from_points(Vec3::new(2.0, 2.0, 2.0), Vec3::new(3.0, 3.0, 3.0)),
712 ];
713 let collider = Collider::new(boxes.clone(), vec![0, 1]);
714 let mut hits = Vec::new();
715 collider.collisions_with_boxes(&boxes, true, |a, b| hits.push((a, b)));
716 assert!(hits.is_empty());
717
718 let queries = vec![BBox::from_points(Vec3::new(0.5, 0.5, 0.5), Vec3::new(2.5, 2.5, 2.5))];
719 collider.collisions_with_boxes(&queries, false, |a, b| hits.push((a, b)));
720 assert_eq!(hits, vec![(0, 0), (0, 1)]);
721 }
722
723 #[test]
724 fn test_ray_triangle_intersection() {
725 let tri = [
726 Vec3::new(0.0, 0.0, 0.0),
727 Vec3::new(1.0, 0.0, 0.0),
728 Vec3::new(0.0, 1.0, 0.0),
729 ];
730 let hit = ray_triangle_intersection(Vec3::new(0.25, 0.25, -1.0), Vec3::new(0.0, 0.0, 1.0), tri);
731 assert!(hit.is_some());
732 }
733
734 #[test]
735 fn test_triangle_triangle_distance_zero_for_intersection() {
736 let a = [
737 Vec3::new(0.0, 0.0, 0.0),
738 Vec3::new(1.0, 0.0, 0.0),
739 Vec3::new(0.0, 1.0, 0.0),
740 ];
741 let b = [
742 Vec3::new(0.25, 0.25, -1.0),
743 Vec3::new(0.25, 0.25, 1.0),
744 Vec3::new(0.75, 0.25, 0.0),
745 ];
746 assert_eq!(distance_triangle_triangle_squared(a, b), 0.0);
747 }
748
749 #[test]
750 fn test_cube_not_self_intersecting() {
751 let m = ManifoldImpl::cube(&Mat3x4::identity());
752 assert!(!m.is_self_intersecting());
753 }
754
755 #[test]
756 fn test_min_gap_between_cubes() {
757 let a = ManifoldImpl::cube(&Mat3x4::identity());
758 let b = ManifoldImpl::cube(&mat4_to_mat3x4(translation_matrix(Vec3::new(2.0, 0.0, 0.0))));
759 let gap = a.min_gap(&b, 5.0);
760 assert!((gap - 1.0).abs() < 1e-8, "gap = {}", gap);
761 }
762
763 #[test]
764 fn test_bvh_many_boxes() {
765 let n = 100;
767 let mut boxes = Vec::new();
768 let mut mortons = Vec::new();
769 for i in 0..n {
770 let x = i as f64 * 3.0;
771 boxes.push(BBox::from_points(
772 Vec3::new(x, 0.0, 0.0),
773 Vec3::new(x + 1.0, 1.0, 1.0),
774 ));
775 mortons.push(i as u32);
776 }
777 let collider = Collider::new(boxes.clone(), mortons);
778
779 let query = vec![BBox::from_points(
781 Vec3::new(150.5, 0.5, 0.5),
782 Vec3::new(150.6, 0.6, 0.6),
783 )];
784 let mut hits = Vec::new();
785 collider.collisions_with_boxes(&query, false, |a, b| hits.push((a, b)));
786 assert_eq!(hits, vec![(0, 50)]);
787 }
788}