mesh_graph/ops/
query.rs

1use itertools::Itertools;
2use parry3d::{
3    math::{Isometry, Point, Vector},
4    partitioning::Qbvh,
5    query::{
6        PointProjection, PointQuery, PointQueryWithLocation, Ray, RayCast, RayIntersection,
7        details::{
8            NormalConstraints, RayCompositeShapeToiAndNormalBestFirstVisitor,
9            RayCompositeShapeToiBestFirstVisitor,
10        },
11        point::PointCompositeShapeProjWithLocationBestFirstVisitor,
12    },
13    shape::{FeatureId, Shape, Triangle, TypedSimdCompositeShape},
14};
15
16use crate::{Face, MeshGraph};
17
18impl PointQuery for MeshGraph {
19    #[inline]
20    fn project_local_point(&self, point: &Point<f32>, solid: bool) -> PointProjection {
21        self.project_local_point_and_get_location(point, solid).0
22    }
23
24    fn project_local_point_and_get_feature(
25        &self,
26        _point: &Point<f32>,
27    ) -> (PointProjection, FeatureId) {
28        unimplemented!("Not available")
29    }
30}
31
32impl PointQueryWithLocation for MeshGraph {
33    type Location = (Face, ());
34
35    #[inline]
36    fn project_local_point_and_get_location(
37        &self,
38        point: &Point<f32>,
39        solid: bool,
40    ) -> (PointProjection, Self::Location) {
41        self.project_local_point_and_get_location_with_max_dist(point, solid, f32::MAX)
42            .unwrap()
43    }
44
45    /// Projects a point on `self`, with a maximum projection distance.
46    fn project_local_point_and_get_location_with_max_dist(
47        &self,
48        point: &Point<f32>,
49        solid: bool,
50        max_dist: f32,
51    ) -> Option<(PointProjection, Self::Location)> {
52        let mut visitor =
53            PointCompositeShapeProjWithLocationBestFirstVisitor::new(self, point, solid);
54
55        if let Some((_, (mut proj, (face, _)))) =
56            self.qbvh
57                .traverse_best_first_node(&mut visitor, 0, max_dist)
58        {
59            if let Some(vertex_normals) = &self.vertex_normals {
60                let pseudo_normal = vertex_normals[self.halfedges[face.halfedge].end_vertex];
61
62                let dpt = point - proj.point;
63                proj.is_inside = dpt.dot(&Vector::new(
64                    pseudo_normal.x,
65                    pseudo_normal.y,
66                    pseudo_normal.z,
67                )) <= 0.0;
68            }
69
70            Some((proj, (face, ())))
71        } else {
72            None
73        }
74    }
75}
76
77impl RayCast for MeshGraph {
78    #[inline]
79    fn cast_local_ray(&self, ray: &Ray, max_time_of_impact: f32, solid: bool) -> Option<f32> {
80        let mut visitor =
81            RayCompositeShapeToiBestFirstVisitor::new(self, ray, max_time_of_impact, solid);
82
83        self.qbvh
84            .traverse_best_first(&mut visitor)
85            .map(|(_, (_, toi))| toi)
86    }
87
88    #[inline]
89    fn cast_local_ray_and_get_normal(
90        &self,
91        ray: &Ray,
92        max_time_of_impact: f32,
93        solid: bool,
94    ) -> Option<RayIntersection> {
95        let mut visitor = RayCompositeShapeToiAndNormalBestFirstVisitor::new(
96            self,
97            ray,
98            max_time_of_impact,
99            solid,
100        );
101
102        self.qbvh
103            .traverse_best_first(&mut visitor)
104            .map(|(_, (_, res))| res)
105    }
106}
107
108impl TypedSimdCompositeShape for MeshGraph {
109    type PartShape = Triangle;
110    type PartNormalConstraints = (); // TODO : do we need TrianglePseudoNormals?
111    type PartId = Face;
112
113    #[inline(always)]
114    fn map_typed_part_at(
115        &self,
116        face: Face,
117        mut f: impl FnMut(
118            Option<&Isometry<f32>>,
119            &Self::PartShape,
120            Option<&Self::PartNormalConstraints>,
121        ),
122    ) {
123        let tri = self.triangle(face);
124        let pseudo_normals = None; // self.triangle_normal_constraints(face_id);
125        f(None, &tri, pseudo_normals.as_ref())
126    }
127
128    #[inline(always)]
129    fn map_untyped_part_at(
130        &self,
131        face: Face,
132        mut f: impl FnMut(Option<&Isometry<f32>>, &dyn Shape, Option<&dyn NormalConstraints>),
133    ) {
134        let tri = self.triangle(face);
135        let pseudo_normals = Some(()); // self.triangle_normal_constraints(face_id);
136        f(
137            None,
138            &tri,
139            pseudo_normals.as_ref().map(|n| n as &dyn NormalConstraints),
140        )
141    }
142
143    fn typed_qbvh(&self) -> &Qbvh<Face> {
144        &self.qbvh
145    }
146}
147
148impl MeshGraph {
149    pub fn triangle(&self, face: Face) -> Triangle {
150        let pos = face
151            .vertices(self)
152            .into_iter()
153            .map(|v_id| self.positions[v_id])
154            .collect_vec();
155
156        Triangle::new(
157            Point::new(pos[0].x, pos[0].y, pos[0].z),
158            Point::new(pos[1].x, pos[1].y, pos[1].z),
159            Point::new(pos[2].x, pos[2].y, pos[2].z),
160        )
161    }
162
163    // TODO : is this necessary?
164    // pub fn triangle_normal_constraints(&self, face_id: FaceId) -> Option<TrianglePseudoNormals> {
165    //     if let Some(vertex_normals) = &self.vertex_normals {
166    //         let triangle = self.triangle(face_id);
167    //         let pseudo_normals = self.pseudo_normals.as_ref()?;
168    //         let edges_pseudo_normals = pseudo_normals.edges_pseudo_normal[i as usize];
169
170    //         // TODO: could the pseudo-normal be pre-normalized instead of having to renormalize
171    //         //       every time we need them?
172    //         Some(TrianglePseudoNormals {
173    //             face: triangle.normal()?,
174    //             edges: [
175    //                 Unit::try_new(edges_pseudo_normals[0], 1.0e-6)?,
176    //                 Unit::try_new(edges_pseudo_normals[1], 1.0e-6)?,
177    //                 Unit::try_new(edges_pseudo_normals[2], 1.0e-6)?,
178    //             ],
179    //         })
180    //     } else {
181    //         None
182    //     }
183    // }
184}