ncollide3d/shape/
trimesh.rs

1//! 2d line strip, 3d triangle mesh, and nd subsimplex mesh.
2
3use 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)]
33/// Description of a face adjascent to an edge.
34pub struct FaceAdjacentToEdge {
35    /// Index of the face.
36    pub face_id: usize,
37    /// Index of the edge the edge is adjascent to.
38    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)]
49/// A face of a triangle mesh.
50pub struct TriMeshFace<N: RealField + Copy> {
51    /// Indices of the vertices of this face.
52    pub indices: Point3<usize>,
53    /// Indices of the edges of this face.
54    pub edges: Point3<usize>,
55    bvt_leaf: usize,
56    /// The normal of this face if it is not degenerate.
57    pub normal: Option<Unit<Vector<N>>>,
58    /// Outward edge normals on the face's plane.
59    pub side_normals: Option<[Unit<Vector<N>>; 3]>,
60}
61
62#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
63#[derive(Clone)]
64/// An edge of a triangle mesh.
65pub struct TriMeshEdge {
66    /// The indices of this edge.
67    pub indices: Point2<usize>,
68    /// The faces adjascent to this edge.
69    pub adj_faces: (FaceAdjacentToEdge, FaceAdjacentToEdge),
70}
71
72#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
73#[derive(Clone)]
74/// A vertex of a triangle mesh.
75pub struct TriMeshVertex {
76    /// Indirect indices of this vertex adjacent faces.
77    pub adj_faces: Range<usize>,
78    /// Indirect indices of this vertex adjacent vertices.
79    pub adj_vertices: Range<usize>,
80}
81
82/// A 3d triangle mesh.
83#[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    /// Builds a new mesh.
100    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(), // Will be set later.
137                    bvt_leaf: 0,             // Will be set later.
138                    normal,
139                    side_normals,
140                })
141            }
142        }
143
144        let bvt = BVT::new_balanced(leaves);
145
146        // Set face.bvt_leaf
147        for (i, leaf) in bvt.leaves().iter().enumerate() {
148            faces[*leaf.data()].bvt_leaf = i;
149        }
150
151        // Set face.edges
152        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), // FIXME: find a better way to define the margin.
179            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        // Build the adjacency list.
276        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        // Build the adjacency list.
317        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        // Set bvt leaves
348        for (i, leaf) in self.bvt.leaves().iter().enumerate() {
349            self.faces[*leaf.data()].bvt_leaf = i;
350        }
351    }
352
353    /// The triangle mesh's AABB.
354    #[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    /// The points of this mesh.
362    #[inline]
363    pub fn points(&self) -> &[Point<N>] {
364        &self.points
365    }
366
367    /// The faces of this mesh.
368    #[inline]
369    pub fn faces(&self) -> &[TriMeshFace<N>] {
370        &self.faces
371    }
372
373    /// The edges of this mesh.
374    #[inline]
375    pub fn edges(&self) -> &[TriMeshEdge] {
376        &self.edges
377    }
378
379    /// The vertices of this mesh.
380    #[inline]
381    pub fn vertices(&self) -> &[TriMeshVertex] {
382        &self.vertices
383    }
384
385    /// Applies in-place a transformation to this triangle mesh.
386    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    /// Applies a transformation to this triangle mesh.
394    pub fn transformed(mut self, transform: &Isometry<N>) -> Self {
395        self.transform_by(transform);
396        self
397    }
398
399    /// Applies in-place a non-uniform scale to this triangle mesh.
400    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    /// Applies a non-uniform scale to this triangle mesh.
408    pub fn scaled(mut self, scale: &Vector<N>) -> Self {
409        self.scale_by(scale);
410        self
411    }
412
413    /// Whether this trimesh is considered is oriented or not.
414    ///
415    /// By default a trimesh is not oriented.
416    #[inline]
417    pub fn oriented(&self) -> bool {
418        self.oriented
419    }
420
421    /// Whether this trimesh is considered as oriented or not.
422    ///
423    /// This is determined at the initialization of the trimesh.
424    #[inline]
425    pub fn set_oriented(&mut self, oriented: bool) {
426        self.oriented = oriented
427    }
428
429    /// Face containing feature.
430    #[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    /// The segment of the `i`-th edge on this triangle mesh.
441    #[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    /// The texture coordinates of this mesh.
448    #[inline]
449    pub fn uvs(&self) -> Option<&[Point2<N>]> {
450        self.uvs.as_ref().map(|uvs| &uvs[..])
451    }
452
453    /// The adjacent vertices list of this mesh.
454    ///
455    /// Use `TriMeshVertex.adj_vertices` to index this. Elements are indexes into the `vertices` list.
456    #[inline]
457    pub fn adj_vertex_list(&self) -> &[usize] {
458        &self.adj_vertex_list
459    }
460
461    /// The adjacent vertices list of this mesh.
462    ///
463    /// Use `TriMeshVertex.adj_faces` to index this. Elements are indexes into the `faces` list.
464    #[inline]
465    pub fn adj_face_list(&self) -> &[usize] {
466        &self.adj_face_list
467    }
468
469    /// Gets the i-th mesh element.
470    #[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    /// Returns `true` if the given feature is a FeatureId::Face and
478    /// identifies a backface of this trimesh.
479    #[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    /// The optimization structure used by this triangle mesh.
489    #[inline]
490    pub fn bvt(&self) -> &BVT<usize, AABB<N>> {
491        &self.bvt
492    }
493
494    /// Tests that the given `dir` is on the tangent cone of the `i`th vertex
495    /// of this mesh.
496    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    /// Tests that the given `dir` is on the polar of the tangent cone of the `i`th vertex
537    /// of this mesh.
538    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            // FIXME: don't compute the norm every time.
550            if edge_dir.dot(dir) < -sin_ang_tol * edge_dir.norm() {
551                return false;
552            }
553        }
554
555        true
556    }
557
558    /// Tests that the given `dir` is on the tangent cone of the `i`th edge
559    /// of this mesh.
560    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    /// Tests that the given `dir` is on the polar of the tangent cone of the `i`th edge
601    /// of this mesh.
602    ///
603    /// The `dir` is assumed to be orthogonal to the edge.
604    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    /// Tests that the given `dir` is on the polar of the tangent cone of the `i`th edge
636    /// of this mesh.
637    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    /// Tests that the given `dir` is on the tangent cone of the `i`th face
652    /// of this mesh.
653    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    /// Checks if the polar of the tangent cone of the `i`-th face of this triangle mesh contains
696    /// the specified direction within an angular tolerence.
697    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    /// Checks if the polar of the tangent cone of the specified feature of this triangle mesh contains
721    /// the specified direction within an angular tolerence.
722    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    /// Updates all the degrees of freedom of this shape.
801    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        // There is a bit of unsafe code in order to perform a memcopy for
811        // efficiency reasons when the mapping between degrees of freedom
812        // is trivial.
813        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                // We have to update the adjacent bounding volumes.
827                // Note that they can be duplicates on `tri_to_update`.
828                // Those duplicates will be filtered using timestamps in the next for loop.
829                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        // Update normals.
838        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        // Apply the bounding volumes changes.
857        for tri_id in self.deformations.tri_to_update.drain(..) {
858            if self.deformations.timestamps[tri_id] != self.deformations.curr_timestamp {
859                // Update the BV.
860                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        // FIXME: measure efficiency with a non-zero margin.
874        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        // Fix the feature ID.
977        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        // Test the validity of the LMD.
1004        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}