1use crate::bounding_volume::{self, BoundingVolume, AABB};
4use crate::math::{Isometry, Point, Vector, DIM};
5use crate::partitioning::{BVHImpl, BVT};
6use crate::procedural;
7use crate::query::{
8 Contact, ContactKinematic, ContactPrediction, ContactPreprocessor, LocalShapeApproximation,
9 NeighborhoodGeometry,
10};
11use crate::shape::{
12 CompositeShape, DeformableShape, DeformationsType, FeatureId, Segment, Shape, Triangle,
13};
14use crate::utils::DeterministicState;
15use na::{self, Point2, Point3, RealField, Unit};
16use std::collections::{hash_map::Entry, HashMap};
17use std::iter;
18use std::ops::Range;
19use std::slice;
20
21#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
22#[derive(Clone)]
23struct DeformationInfos<N: RealField + Copy> {
24 margin: N,
25 curr_timestamp: usize,
26 timestamps: Vec<usize>,
27 ref_vertices: Vec<Point<N>>,
28 tri_to_update: Vec<usize>,
29}
30
31#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
32#[derive(Clone)]
33pub struct FaceAdjacentToEdge {
35 pub face_id: usize,
37 pub edge_id: usize,
39}
40
41impl FaceAdjacentToEdge {
42 fn new(face_id: usize, edge_id: usize) -> Self {
43 FaceAdjacentToEdge { face_id, edge_id }
44 }
45}
46
47#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
48#[derive(Clone)]
49pub struct TriMeshFace<N: RealField + Copy> {
51 pub indices: Point3<usize>,
53 pub edges: Point3<usize>,
55 bvt_leaf: usize,
56 pub normal: Option<Unit<Vector<N>>>,
58 pub side_normals: Option<[Unit<Vector<N>>; 3]>,
60}
61
62#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
63#[derive(Clone)]
64pub struct TriMeshEdge {
66 pub indices: Point2<usize>,
68 pub adj_faces: (FaceAdjacentToEdge, FaceAdjacentToEdge),
70}
71
72#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
73#[derive(Clone)]
74pub struct TriMeshVertex {
76 pub adj_faces: Range<usize>,
78 pub adj_vertices: Range<usize>,
80}
81
82#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
84#[derive(Clone)]
85pub struct TriMesh<N: RealField + Copy> {
86 bvt: BVT<usize, AABB<N>>,
87 uvs: Option<Vec<Point2<N>>>,
88 points: Vec<Point<N>>,
89 vertices: Vec<TriMeshVertex>,
90 edges: Vec<TriMeshEdge>,
91 faces: Vec<TriMeshFace<N>>,
92 adj_face_list: Vec<usize>,
93 adj_vertex_list: Vec<usize>,
94 deformations: DeformationInfos<N>,
95 oriented: bool,
96}
97
98impl<N: RealField + Copy> TriMesh<N> {
99 pub fn new(
101 points: Vec<Point<N>>,
102 indices: Vec<Point3<usize>>,
103 uvs: Option<Vec<Point2<N>>>,
104 ) -> TriMesh<N> {
105 let mut leaves = Vec::with_capacity(indices.len());
106 let mut vertices: Vec<TriMeshVertex> = iter::repeat(TriMeshVertex {
107 adj_faces: 0..0,
108 adj_vertices: 0..0,
109 })
110 .take(points.len())
111 .collect();
112 let mut faces = Vec::with_capacity(indices.len());
113
114 let edges = Self::create_edges_list(&indices);
115 let adj_face_list = Self::create_adj_face_list(&indices, &mut vertices);
116 let adj_vertex_list = Self::create_adj_vertex_list(&edges, &mut vertices);
117
118 {
119 let is = &*indices;
120
121 for (i, is) in is.iter().enumerate() {
122 let triangle = Triangle::new(points[is.x], points[is.y], points[is.z]);
123 let normal = triangle.normal();
124 let side_normals = normal.map(|n| {
125 [
126 Unit::new_normalize((triangle.b - triangle.a).cross(&n)),
127 Unit::new_normalize((triangle.c - triangle.b).cross(&n)),
128 Unit::new_normalize((triangle.a - triangle.c).cross(&n)),
129 ]
130 });
131
132 let bv = triangle.local_aabb();
133 leaves.push((i, bv.clone()));
134 faces.push(TriMeshFace {
135 indices: *is,
136 edges: Point3::origin(), bvt_leaf: 0, normal,
139 side_normals,
140 })
141 }
142 }
143
144 let bvt = BVT::new_balanced(leaves);
145
146 for (i, leaf) in bvt.leaves().iter().enumerate() {
148 faces[*leaf.data()].bvt_leaf = i;
149 }
150
151 for (i, e) in edges.iter().enumerate() {
153 let fid1 = e.adj_faces.0.face_id;
154 let fid2 = e.adj_faces.1.face_id;
155
156 for k1 in 0..3 {
157 let k2 = (k1 + 1) % 3;
158
159 if (faces[fid1].indices[k1] == e.indices.x
160 && faces[fid1].indices[k2] == e.indices.y)
161 || (faces[fid1].indices[k1] == e.indices.y
162 && faces[fid1].indices[k2] == e.indices.x)
163 {
164 faces[fid1].edges[k1] = i;
165 }
166
167 if (faces[fid2].indices[k1] == e.indices.x
168 && faces[fid2].indices[k2] == e.indices.y)
169 || (faces[fid2].indices[k1] == e.indices.y
170 && faces[fid2].indices[k2] == e.indices.x)
171 {
172 faces[fid2].edges[k1] = i;
173 }
174 }
175 }
176
177 let deformations = DeformationInfos {
178 margin: na::convert(0.1), curr_timestamp: 0,
180 timestamps: Vec::new(),
181 ref_vertices: Vec::new(),
182 tri_to_update: Vec::new(),
183 };
184
185 TriMesh {
186 bvt,
187 points,
188 uvs,
189 deformations,
190 vertices,
191 edges,
192 faces,
193 adj_face_list,
194 adj_vertex_list,
195 oriented: false,
196 }
197 }
198
199 fn create_edges_list(indices: &[Point3<usize>]) -> Vec<TriMeshEdge> {
200 let mut edges = HashMap::with_hasher(DeterministicState::new());
201
202 fn key(a: usize, b: usize) -> (usize, usize) {
203 if a < b {
204 (a, b)
205 } else {
206 (b, a)
207 }
208 }
209
210 for (fid, idx) in indices.iter().enumerate() {
211 let e1 = key(idx.x, idx.y);
212 let e2 = key(idx.y, idx.z);
213 let e3 = key(idx.z, idx.x);
214
215 match edges.entry(e1) {
216 Entry::Vacant(e) => {
217 let _ = e.insert(TriMeshEdge {
218 indices: Point2::new(e1.0, e1.1),
219 adj_faces: (
220 FaceAdjacentToEdge::new(fid, 0),
221 FaceAdjacentToEdge::new(fid, 0),
222 ),
223 });
224 }
225 Entry::Occupied(mut e) => e.get_mut().adj_faces.1 = FaceAdjacentToEdge::new(fid, 0),
226 }
227
228 match edges.entry(e2) {
229 Entry::Vacant(e) => {
230 let _ = e.insert(TriMeshEdge {
231 indices: Point2::new(e2.0, e2.1),
232 adj_faces: (
233 FaceAdjacentToEdge::new(fid, 1),
234 FaceAdjacentToEdge::new(fid, 1),
235 ),
236 });
237 }
238 Entry::Occupied(e) => e.into_mut().adj_faces.1 = FaceAdjacentToEdge::new(fid, 1),
239 }
240
241 match edges.entry(e3) {
242 Entry::Vacant(e) => {
243 let _ = e.insert(TriMeshEdge {
244 indices: Point2::new(e3.0, e3.1),
245 adj_faces: (
246 FaceAdjacentToEdge::new(fid, 2),
247 FaceAdjacentToEdge::new(fid, 2),
248 ),
249 });
250 }
251 Entry::Occupied(e) => e.into_mut().adj_faces.1 = FaceAdjacentToEdge::new(fid, 2),
252 }
253 }
254
255 edges.values().cloned().collect()
256 }
257
258 fn create_adj_vertex_list(edges: &[TriMeshEdge], vertices: &mut [TriMeshVertex]) -> Vec<usize> {
259 let mut num_neighbors: Vec<usize> = iter::repeat(0).take(vertices.len()).collect();
260
261 for e in edges {
262 num_neighbors[e.indices.x] += 1;
263 num_neighbors[e.indices.y] += 1;
264 }
265
266 let mut total_num_nbh = 0;
267
268 for (num_nbh, vtx) in num_neighbors.iter().zip(vertices.iter_mut()) {
269 vtx.adj_vertices = total_num_nbh..total_num_nbh + num_nbh;
270 total_num_nbh += num_nbh;
271 }
272
273 let mut adj_vertex_list: Vec<usize> = iter::repeat(0).take(total_num_nbh).collect();
274
275 for n in &mut num_neighbors {
277 *n = 0;
278 }
279
280 for e in edges.iter() {
281 adj_vertex_list
282 [vertices[e.indices.x].adj_vertices.start + num_neighbors[e.indices.x]] =
283 e.indices.y;
284 adj_vertex_list
285 [vertices[e.indices.y].adj_vertices.start + num_neighbors[e.indices.y]] =
286 e.indices.x;
287
288 num_neighbors[e.indices.x] += 1;
289 num_neighbors[e.indices.y] += 1;
290 }
291
292 adj_vertex_list
293 }
294
295 fn create_adj_face_list(
296 indices: &[Point3<usize>],
297 vertices: &mut [TriMeshVertex],
298 ) -> Vec<usize> {
299 let mut num_neighbors: Vec<usize> = iter::repeat(0).take(vertices.len()).collect();
300
301 for idx in indices {
302 num_neighbors[idx.x] += 1;
303 num_neighbors[idx.y] += 1;
304 num_neighbors[idx.z] += 1;
305 }
306
307 let mut total_num_nbh = 0;
308
309 for (num_nbh, vtx) in num_neighbors.iter().zip(vertices.iter_mut()) {
310 vtx.adj_faces = total_num_nbh..total_num_nbh + num_nbh;
311 total_num_nbh += num_nbh;
312 }
313
314 let mut adj_face_list: Vec<usize> = iter::repeat(0).take(total_num_nbh).collect();
315
316 for n in &mut num_neighbors {
318 *n = 0;
319 }
320
321 for (i, idx) in indices.iter().enumerate() {
322 adj_face_list[vertices[idx.x].adj_faces.start + num_neighbors[idx.x]] = i;
323 adj_face_list[vertices[idx.y].adj_faces.start + num_neighbors[idx.y]] = i;
324 adj_face_list[vertices[idx.z].adj_faces.start + num_neighbors[idx.z]] = i;
325
326 num_neighbors[idx.x] += 1;
327 num_neighbors[idx.y] += 1;
328 num_neighbors[idx.z] += 1;
329 }
330
331 adj_face_list
332 }
333
334 fn refit_bvt(&mut self) {
335 let mut leaves = Vec::with_capacity(self.faces.len());
336 for (i, face) in self.faces.iter().enumerate() {
337 let triangle = Triangle::new(
338 self.points[face.indices[0]],
339 self.points[face.indices[1]],
340 self.points[face.indices[2]],
341 );
342 let bv = triangle.local_aabb();
343 leaves.push((i, bv));
344 }
345 self.bvt = BVT::new_balanced(leaves);
346
347 for (i, leaf) in self.bvt.leaves().iter().enumerate() {
349 self.faces[*leaf.data()].bvt_leaf = i;
350 }
351 }
352
353 #[inline]
355 pub fn aabb(&self) -> &AABB<N> {
356 self.bvt
357 .root_bounding_volume()
358 .expect("An empty TriMesh has no AABB.")
359 }
360
361 #[inline]
363 pub fn points(&self) -> &[Point<N>] {
364 &self.points
365 }
366
367 #[inline]
369 pub fn faces(&self) -> &[TriMeshFace<N>] {
370 &self.faces
371 }
372
373 #[inline]
375 pub fn edges(&self) -> &[TriMeshEdge] {
376 &self.edges
377 }
378
379 #[inline]
381 pub fn vertices(&self) -> &[TriMeshVertex] {
382 &self.vertices
383 }
384
385 pub fn transform_by(&mut self, transform: &Isometry<N>) {
387 for pt in &mut self.points {
388 *pt = transform * *pt
389 }
390 self.refit_bvt();
391 }
392
393 pub fn transformed(mut self, transform: &Isometry<N>) -> Self {
395 self.transform_by(transform);
396 self
397 }
398
399 pub fn scale_by(&mut self, scale: &Vector<N>) {
401 for pt in &mut self.points {
402 pt.coords.component_mul_assign(scale)
403 }
404 self.refit_bvt();
405 }
406
407 pub fn scaled(mut self, scale: &Vector<N>) -> Self {
409 self.scale_by(scale);
410 self
411 }
412
413 #[inline]
417 pub fn oriented(&self) -> bool {
418 self.oriented
419 }
420
421 #[inline]
425 pub fn set_oriented(&mut self, oriented: bool) {
426 self.oriented = oriented
427 }
428
429 #[inline]
431 pub fn face_containing_feature(&self, id: FeatureId) -> usize {
432 match id {
433 FeatureId::Vertex(i) => self.adj_face_list[self.vertices[i].adj_faces.start],
434 FeatureId::Edge(i) => self.edges[i].adj_faces.0.face_id,
435 FeatureId::Face(i) => i % self.faces.len(),
436 _ => panic!("Feature ID cannot be unknown."),
437 }
438 }
439
440 #[inline]
442 pub fn edge_segment(&self, i: usize) -> Segment<N> {
443 let edge = &self.edges[i];
444 Segment::new(self.points[edge.indices.x], self.points[edge.indices.y])
445 }
446
447 #[inline]
449 pub fn uvs(&self) -> Option<&[Point2<N>]> {
450 self.uvs.as_ref().map(|uvs| &uvs[..])
451 }
452
453 #[inline]
457 pub fn adj_vertex_list(&self) -> &[usize] {
458 &self.adj_vertex_list
459 }
460
461 #[inline]
465 pub fn adj_face_list(&self) -> &[usize] {
466 &self.adj_face_list
467 }
468
469 #[inline]
471 pub fn triangle_at(&self, i: usize) -> Triangle<N> {
472 let idx = self.faces[i].indices;
473
474 Triangle::new(self.points[idx.x], self.points[idx.y], self.points[idx.z])
475 }
476
477 #[inline]
480 pub fn is_backface(&self, feature: FeatureId) -> bool {
481 if let FeatureId::Face(i) = feature {
482 i >= self.faces.len()
483 } else {
484 false
485 }
486 }
487
488 #[inline]
490 pub fn bvt(&self) -> &BVT<usize, AABB<N>> {
491 &self.bvt
492 }
493
494 pub fn vertex_tangent_cone_contains_dir(
497 &self,
498 i: usize,
499 deformations: Option<&[N]>,
500 dir: &Unit<Vector<N>>,
501 ) -> bool {
502 if !self.oriented {
503 return false;
504 }
505
506 let v = &self.vertices[i];
507
508 if let Some(coords) = deformations {
509 for adj_face in &self.adj_face_list[v.adj_faces.clone()] {
510 let indices = self.faces[*adj_face].indices * DIM;
511 let tri = Triangle::new(
512 Point::from_slice(&coords[indices.x..indices.x + DIM]),
513 Point::from_slice(&coords[indices.y..indices.y + DIM]),
514 Point::from_slice(&coords[indices.z..indices.z + DIM]),
515 );
516
517 if tri.scaled_normal().dot(dir) > N::zero() {
518 return false;
519 }
520 }
521 } else {
522 for adj_face in &self.adj_face_list[v.adj_faces.clone()] {
523 let face = &self.faces[*adj_face];
524
525 if let Some(ref n) = face.normal {
526 if n.dot(dir) > N::zero() {
527 return false;
528 }
529 }
530 }
531 }
532
533 true
534 }
535
536 pub fn vertex_tangent_cone_polar_contains_dir(
539 &self,
540 i: usize,
541 dir: &Unit<Vector<N>>,
542 sin_ang_tol: N,
543 ) -> bool {
544 let v = &self.vertices[i];
545
546 for adj_vtx in &self.adj_vertex_list[v.adj_vertices.clone()] {
547 let edge_dir = self.points[i] - self.points[*adj_vtx];
548
549 if edge_dir.dot(dir) < -sin_ang_tol * edge_dir.norm() {
551 return false;
552 }
553 }
554
555 true
556 }
557
558 pub fn edge_tangent_cone_contains_dir(
561 &self,
562 i: usize,
563 deformations: Option<&[N]>,
564 dir: &Unit<Vector<N>>,
565 ) -> bool {
566 if !self.oriented {
567 return false;
568 }
569
570 let e = &self.edges[i];
571
572 if let Some(coords) = deformations {
573 for adj_face in [e.adj_faces.0.face_id, e.adj_faces.1.face_id].iter() {
574 let indices = self.faces[*adj_face].indices * DIM;
575 let tri = Triangle::new(
576 Point::from_slice(&coords[indices.x..indices.x + DIM]),
577 Point::from_slice(&coords[indices.y..indices.y + DIM]),
578 Point::from_slice(&coords[indices.z..indices.z + DIM]),
579 );
580
581 if tri.scaled_normal().dot(dir) > N::zero() {
582 return false;
583 }
584 }
585 } else {
586 for adj_face in [e.adj_faces.0.face_id, e.adj_faces.1.face_id].iter() {
587 let face = &self.faces[*adj_face];
588
589 if let Some(ref n) = face.normal {
590 if n.dot(dir) > N::zero() {
591 return false;
592 }
593 }
594 }
595 }
596
597 true
598 }
599
600 pub fn edge_tangent_cone_polar_contains_orthogonal_dir(
605 &self,
606 i: usize,
607 dir: &Unit<Vector<N>>,
608 sin_ang_tol: N,
609 ) -> bool {
610 let e = &self.edges[i];
611 let f1 = &self.faces[e.adj_faces.0.face_id];
612 let f2 = &self.faces[e.adj_faces.1.face_id];
613
614 if let Some(side_normal1) = f1.side_normals.as_ref() {
615 if side_normal1[e.adj_faces.0.edge_id].dot(dir) <= na::convert(-sin_ang_tol) {
616 return false;
617 }
618 }
619
620 if let Some(side_normal2) = f2.side_normals.as_ref() {
621 if side_normal2[e.adj_faces.1.edge_id].dot(dir) <= na::convert(-sin_ang_tol) {
622 return false;
623 }
624 }
625
626 if let (Some(n1), Some(n2)) = (f1.normal, f2.normal) {
627 if (n1.into_inner() + n2.into_inner()).dot(dir) < N::zero() {
628 return false;
629 }
630 }
631
632 true
633 }
634
635 pub fn edge_tangent_cone_polar_contains_dir(
638 &self,
639 i: usize,
640 dir: &Unit<Vector<N>>,
641 sin_ang_tol: N,
642 _cos_ang_tol: N,
643 ) -> bool {
644 let e = &self.edges[i];
645 let edge_dir = self.points[e.indices.y] - self.points[e.indices.x];
646
647 edge_dir.dot(dir).abs() <= sin_ang_tol * edge_dir.norm()
648 && self.edge_tangent_cone_polar_contains_orthogonal_dir(i, dir, sin_ang_tol)
649 }
650
651 pub fn face_tangent_cone_contains_dir(
654 &self,
655 i: usize,
656 deformations: Option<&[N]>,
657 dir: &Unit<Vector<N>>,
658 ) -> bool {
659 if !self.oriented {
660 return false;
661 }
662
663 let normal;
664
665 if let Some(coords) = deformations {
666 let indices = self.faces[i % self.faces.len()].indices * DIM;
667 let tri = Triangle::new(
668 Point::from_slice(&coords[indices.x..indices.x + DIM]),
669 Point::from_slice(&coords[indices.y..indices.y + DIM]),
670 Point::from_slice(&coords[indices.z..indices.z + DIM]),
671 );
672
673 if i >= self.faces.len() {
674 normal = -tri.scaled_normal();
675 } else {
676 normal = tri.scaled_normal();
677 }
678 } else {
679 if i >= self.faces.len() {
680 normal = -self.faces[i - self.faces.len()]
681 .normal
682 .map(|n| n.into_inner())
683 .unwrap_or(Vector::zeros());
684 } else {
685 normal = self.faces[i]
686 .normal
687 .map(|n| n.into_inner())
688 .unwrap_or(Vector::zeros());
689 }
690 }
691
692 normal.dot(dir) <= N::zero()
693 }
694
695 pub fn face_tangent_cone_polar_contains_dir(
698 &self,
699 i: usize,
700 dir: &Unit<Vector<N>>,
701 cos_ang_tol: N,
702 ) -> bool {
703 let normal;
704
705 if i >= self.faces.len() {
706 normal = -self.faces[i - self.faces.len()]
707 .normal
708 .map(|n| n.into_inner())
709 .unwrap_or(Vector::zeros());
710 } else {
711 normal = self.faces[i]
712 .normal
713 .map(|n| n.into_inner())
714 .unwrap_or(Vector::zeros());
715 }
716
717 normal.dot(dir) >= cos_ang_tol
718 }
719
720 pub fn tangent_cone_polar_contains_dir(
723 &self,
724 feature: FeatureId,
725 dir: &Unit<Vector<N>>,
726 sin_ang_tol: N,
727 cos_ang_tol: N,
728 ) -> bool {
729 match feature {
730 FeatureId::Face(i) => self.face_tangent_cone_polar_contains_dir(i, dir, cos_ang_tol),
731 FeatureId::Edge(i) => {
732 self.edge_tangent_cone_polar_contains_dir(i, dir, sin_ang_tol, cos_ang_tol)
733 }
734 FeatureId::Vertex(i) => {
735 self.vertex_tangent_cone_polar_contains_dir(i, dir, sin_ang_tol)
736 }
737 FeatureId::Unknown => false,
738 }
739 }
740
741 fn init_deformation_infos(&mut self) -> bool {
742 if self.deformations.ref_vertices.is_empty() {
743 self.deformations.timestamps = iter::repeat(0).take(self.faces.len()).collect();
744 self.deformations.ref_vertices = self.points.clone();
745 true
746 } else {
747 false
748 }
749 }
750}
751
752impl<N: RealField + Copy> CompositeShape<N> for TriMesh<N> {
753 #[inline]
754 fn nparts(&self) -> usize {
755 self.faces.len()
756 }
757
758 #[inline(always)]
759 fn map_part_at(
760 &self,
761 i: usize,
762 m: &Isometry<N>,
763 f: &mut dyn FnMut(&Isometry<N>, &dyn Shape<N>),
764 ) {
765 let element = self.triangle_at(i);
766 f(m, &element)
767 }
768
769 fn map_part_and_preprocessor_at(
770 &self,
771 i: usize,
772 m: &Isometry<N>,
773 prediction: &ContactPrediction<N>,
774 f: &mut dyn FnMut(&Isometry<N>, &dyn Shape<N>, &dyn ContactPreprocessor<N>),
775 ) {
776 let element = self.triangle_at(i);
777 let preprocessor = TriMeshContactProcessor::new(self, m, i, prediction);
778 f(m, &element, &preprocessor)
779 }
780
781 #[inline]
782 fn aabb_at(&self, i: usize) -> AABB<N> {
783 self.bvt
784 .leaf(self.faces[i].bvt_leaf)
785 .bounding_volume()
786 .clone()
787 }
788
789 #[inline]
790 fn bvh(&self) -> BVHImpl<N, usize, AABB<N>> {
791 BVHImpl::BVT(&self.bvt)
792 }
793}
794
795impl<N: RealField + Copy> DeformableShape<N> for TriMesh<N> {
796 fn deformations_type(&self) -> DeformationsType {
797 DeformationsType::Vectors
798 }
799
800 fn set_deformations(&mut self, coords: &[N]) {
802 assert!(
803 coords.len() >= self.points.len() * DIM,
804 "Set deformations error: dimension mismatch."
805 );
806
807 let is_first_init = self.init_deformation_infos();
808 self.deformations.curr_timestamp += 1;
809
810 unsafe {
814 let len = self.points.len();
815 let coords_ptr = coords.as_ptr() as *const Point<N>;
816 let coords_pt: &[Point<N>] = slice::from_raw_parts(coords_ptr, len);
817 self.points.copy_from_slice(coords_pt);
818 }
819
820 for (target, pt) in self.points.iter_mut().enumerate() {
821 let ref_pt = &mut self.deformations.ref_vertices[target];
822 let sq_dist_to_ref = na::distance_squared(pt, ref_pt);
823
824 if is_first_init || sq_dist_to_ref > self.deformations.margin * self.deformations.margin
825 {
826 let ids = self.vertices[target].adj_faces.clone();
830 self.deformations
831 .tri_to_update
832 .extend_from_slice(&self.adj_face_list[ids]);
833 *ref_pt = *pt;
834 }
835 }
836
837 for f in &mut self.faces {
839 let ab = self.points[f.indices.y] - self.points[f.indices.x];
840 let ac = self.points[f.indices.z] - self.points[f.indices.x];
841
842 if let Some(n) = Unit::try_new(ab.cross(&ac), N::default_epsilon()) {
843 let bc = self.points[f.indices.z] - self.points[f.indices.y];
844 f.normal = Some(n);
845 f.side_normals = Some([
846 Unit::new_normalize(ab.cross(&n)),
847 Unit::new_normalize(bc.cross(&n)),
848 Unit::new_normalize(-ac.cross(&n)),
849 ]);
850 } else {
851 f.normal = None;
852 f.side_normals = None;
853 }
854 }
855
856 for tri_id in self.deformations.tri_to_update.drain(..) {
858 if self.deformations.timestamps[tri_id] != self.deformations.curr_timestamp {
859 let idx = &self.faces[tri_id].indices;
861 let mut new_bv = bounding_volume::local_point_cloud_aabb(&[
862 self.points[idx.x],
863 self.points[idx.y],
864 self.points[idx.z],
865 ]);
866 new_bv.loosen(self.deformations.margin);
867 self.bvt
868 .set_leaf_bounding_volume(self.faces[tri_id].bvt_leaf, new_bv, false);
869 self.deformations.timestamps[tri_id] = self.deformations.curr_timestamp;
870 }
871 }
872
873 self.bvt.refit(N::zero())
875 }
876
877 fn update_local_approximation(&self, coords: &[N], approx: &mut LocalShapeApproximation<N>) {
878 match approx.feature {
879 FeatureId::Vertex(i) => {
880 approx.point = Point::from_slice(&coords[i * DIM..(i + 1) * DIM]);
881 approx.geometry = NeighborhoodGeometry::Point;
882 }
883 FeatureId::Edge(i) => {
884 let edge = &self.edges[i];
885 let pid1 = edge.indices.x * DIM;
886 let pid2 = edge.indices.y * DIM;
887 let seg = Segment::new(
888 Point::from_slice(&coords[pid1..pid1 + DIM]),
889 Point::from_slice(&coords[pid2..pid2 + DIM]),
890 );
891 approx.point = seg.a;
892
893 if let Some(dir) = seg.direction() {
894 approx.geometry = NeighborhoodGeometry::Line(dir);
895 } else {
896 approx.geometry = NeighborhoodGeometry::Point;
897 }
898 }
899 FeatureId::Face(mut i) => {
900 let is_backface = i >= self.faces.len();
901 if is_backface {
902 i -= self.faces.len();
903 }
904
905 let face = &self.faces[i];
906 let pid1 = face.indices.x * DIM;
907 let pid2 = face.indices.y * DIM;
908 let pid3 = face.indices.z * DIM;
909 let tri = Triangle::new(
910 Point::from_slice(&coords[pid1..pid1 + DIM]),
911 Point::from_slice(&coords[pid2..pid2 + DIM]),
912 Point::from_slice(&coords[pid3..pid3 + DIM]),
913 );
914
915 approx.point = tri.a;
916
917 if let Some(n) = tri.normal() {
918 if !is_backface {
919 approx.geometry = NeighborhoodGeometry::Plane(n);
920 } else {
921 approx.geometry = NeighborhoodGeometry::Plane(-n);
922 }
923 } else {
924 approx.geometry = NeighborhoodGeometry::Point;
925 }
926 }
927 _ => panic!(
928 "Encountered invalid triangle feature: {:?}.",
929 approx.feature
930 ),
931 }
932 }
933}
934
935impl<N: RealField + Copy> From<procedural::TriMesh<N>> for TriMesh<N> {
936 fn from(trimesh: procedural::TriMesh<N>) -> Self {
937 let indices = trimesh
938 .flat_indices()
939 .chunks(3)
940 .map(|idx| Point3::new(idx[0] as usize, idx[1] as usize, idx[2] as usize))
941 .collect();
942 TriMesh::new(trimesh.coords, indices, trimesh.uvs)
943 }
944}
945
946struct TriMeshContactProcessor<'a, N: RealField + Copy> {
947 mesh: &'a TriMesh<N>,
948 pos: &'a Isometry<N>,
949 face_id: usize,
950 prediction: &'a ContactPrediction<N>,
951}
952
953impl<'a, N: RealField + Copy> TriMeshContactProcessor<'a, N> {
954 pub fn new(
955 mesh: &'a TriMesh<N>,
956 pos: &'a Isometry<N>,
957 face_id: usize,
958 prediction: &'a ContactPrediction<N>,
959 ) -> Self {
960 TriMeshContactProcessor {
961 mesh,
962 pos,
963 face_id,
964 prediction,
965 }
966 }
967}
968
969impl<'a, N: RealField + Copy> ContactPreprocessor<N> for TriMeshContactProcessor<'a, N> {
970 fn process_contact(
971 &self,
972 c: &mut Contact<N>,
973 kinematic: &mut ContactKinematic<N>,
974 is_first: bool,
975 ) -> bool {
976 let feature = if is_first {
978 kinematic.feature1()
979 } else {
980 kinematic.feature2()
981 };
982
983 let face = &self.mesh.faces()[self.face_id];
984 let actual_feature = match feature {
985 FeatureId::Vertex(i) => FeatureId::Vertex(face.indices[i]),
986 FeatureId::Edge(i) => FeatureId::Edge(face.edges[i]),
987 FeatureId::Face(i) => {
988 if i == 0 {
989 FeatureId::Face(self.face_id)
990 } else {
991 FeatureId::Face(self.face_id + self.mesh.faces().len())
992 }
993 }
994 FeatureId::Unknown => FeatureId::Unknown,
995 };
996
997 if is_first {
998 kinematic.set_feature1(actual_feature);
999 } else {
1000 kinematic.set_feature2(actual_feature);
1001 }
1002
1003 if c.depth > N::zero() {
1005 true
1006 } else {
1007 let local_dir = self.pos.inverse_transform_unit_vector(&c.normal);
1008
1009 if is_first {
1010 self.mesh.tangent_cone_polar_contains_dir(
1011 actual_feature,
1012 &local_dir,
1013 self.prediction.sin_angular1(),
1014 self.prediction.cos_angular1(),
1015 )
1016 } else {
1017 self.mesh.tangent_cone_polar_contains_dir(
1018 actual_feature,
1019 &-local_dir,
1020 self.prediction.sin_angular2(),
1021 self.prediction.cos_angular2(),
1022 )
1023 }
1024 }
1025 }
1026}