ncollide3d/shape/
shape_impl.rs

1use crate::bounding_volume::{self, BoundingSphere, AABB};
2use crate::math::{Isometry, Vector};
3use crate::query::{PointQuery, RayCast};
4#[cfg(feature = "dim2")]
5use crate::shape::ConvexPolygon;
6use crate::shape::{
7    Ball, Capsule, CompositeShape, Compound, ConvexPolyhedron, Cuboid, DeformableShape, FeatureId,
8    HeightField, Plane, Polyline, Segment, Shape, SupportMap,
9};
10#[cfg(feature = "dim3")]
11use crate::shape::{ConvexHull, TriMesh, Triangle};
12use na::{RealField, Unit};
13
14macro_rules! impl_as_convex_polyhedron (
15    () => {
16        #[inline]
17        fn as_convex_polyhedron(&self) -> Option<&dyn ConvexPolyhedron<N>> {
18            Some(self)
19        }
20
21        #[inline]
22        fn is_convex_polyhedron(&self) -> bool {
23            true
24        }
25
26        #[inline]
27        fn tangent_cone_contains_dir(&self, feature: FeatureId, m: &Isometry<N>, _: Option<&[N]>, dir: &Unit<Vector<N>>) -> bool {
28            self.tangent_cone_contains_dir(feature, m, dir)
29        }
30    }
31);
32
33macro_rules! impl_as_support_map (
34    () => {
35        #[inline]
36        fn as_support_map(&self) -> Option<&dyn SupportMap<N>> {
37            Some(self)
38        }
39
40        #[inline]
41        fn is_support_map(&self) -> bool {
42            true
43        }
44    }
45);
46
47macro_rules! impl_as_composite_shape (
48    () => {
49        #[inline]
50        fn as_composite_shape(&self) -> Option<&dyn CompositeShape<N>> {
51            Some(self)
52        }
53
54        #[inline]
55        fn is_composite_shape(&self) -> bool {
56            true
57        }
58    }
59);
60
61macro_rules! impl_as_deformable_shape (
62    () => {
63        #[inline]
64        fn as_deformable_shape(&self) -> Option<&dyn DeformableShape<N>> {
65            Some(self)
66        }
67
68        #[inline]
69        fn as_deformable_shape_mut(&mut self) -> Option<&mut dyn DeformableShape<N>> {
70            Some(self)
71        }
72
73        #[inline]
74        fn is_deformable_shape(&self) -> bool {
75            true
76        }
77    }
78);
79
80macro_rules! impl_shape_common (
81    () => {
82        #[inline]
83        fn aabb(&self, m: &Isometry<N>) -> AABB<N> {
84            bounding_volume::aabb(self, m)
85        }
86
87        #[inline]
88        fn local_aabb(&self) -> AABB<N> {
89            bounding_volume::local_aabb(self)
90        }
91
92        #[inline]
93        fn bounding_sphere(&self, m: &Isometry<N>) -> BoundingSphere<N> {
94            bounding_volume::bounding_sphere(self, m)
95        }
96
97        #[inline]
98        fn as_ray_cast(&self) -> Option<&dyn RayCast<N>> {
99            Some(self)
100        }
101
102        #[inline]
103        fn as_point_query(&self) -> Option<&dyn PointQuery<N>> {
104            Some(self)
105        }
106    }
107);
108
109#[cfg(feature = "dim3")]
110impl<N: RealField + Copy> Shape<N> for Triangle<N> {
111    impl_shape_common!();
112    impl_as_support_map!();
113    impl_as_convex_polyhedron!();
114}
115
116impl<N: RealField + Copy> Shape<N> for Segment<N> {
117    impl_shape_common!();
118    impl_as_support_map!();
119    impl_as_convex_polyhedron!();
120}
121
122impl<N: RealField + Copy> Shape<N> for Ball<N> {
123    impl_shape_common!();
124    impl_as_support_map!();
125
126    // FIXME: this is wrong in theory but keep it this
127    // way for now because of the way the ContactKinematic
128    // currently works.
129    fn tangent_cone_contains_dir(
130        &self,
131        _: FeatureId,
132        _: &Isometry<N>,
133        _: Option<&[N]>,
134        _: &Unit<Vector<N>>,
135    ) -> bool {
136        false
137    }
138}
139
140impl<N: RealField + Copy> Shape<N> for Cuboid<N> {
141    impl_shape_common!();
142    impl_as_support_map!();
143    impl_as_convex_polyhedron!();
144}
145
146impl<N: RealField + Copy> Shape<N> for Capsule<N> {
147    impl_shape_common!();
148    impl_as_support_map!();
149
150    // FIXME: this is wrong in theory but keep it this
151    // way for now because of the way the ContactKinematic
152    // currently works.
153    fn tangent_cone_contains_dir(
154        &self,
155        _: FeatureId,
156        _: &Isometry<N>,
157        _: Option<&[N]>,
158        _: &Unit<Vector<N>>,
159    ) -> bool {
160        false
161    }
162}
163
164#[cfg(feature = "dim3")]
165impl<N: RealField + Copy> Shape<N> for ConvexHull<N> {
166    impl_shape_common!();
167    impl_as_support_map!();
168    impl_as_convex_polyhedron!();
169}
170
171#[cfg(feature = "dim2")]
172impl<N: RealField + Copy> Shape<N> for ConvexPolygon<N> {
173    impl_shape_common!();
174    impl_as_support_map!();
175    impl_as_convex_polyhedron!();
176}
177
178impl<N: RealField + Copy> Shape<N> for Compound<N> {
179    impl_shape_common!();
180    impl_as_composite_shape!();
181
182    fn tangent_cone_contains_dir(
183        &self,
184        feature: FeatureId,
185        m: &Isometry<N>,
186        _: Option<&[N]>,
187        dir: &Unit<Vector<N>>,
188    ) -> bool {
189        let (i, fid) = self.subshape_feature_id(feature);
190        let shape = &self.shapes()[i];
191        let ls_dir = m.inverse_transform_unit_vector(dir);
192        shape
193            .1
194            .tangent_cone_contains_dir(fid, &shape.0, None, &ls_dir)
195    }
196
197    fn subshape_containing_feature(&self, feature: FeatureId) -> usize {
198        self.subshape_feature_id(feature).0
199    }
200}
201
202#[cfg(feature = "dim3")]
203impl<N: RealField + Copy> Shape<N> for TriMesh<N> {
204    impl_shape_common!();
205    impl_as_composite_shape!();
206    impl_as_deformable_shape!();
207
208    fn tangent_cone_contains_dir(
209        &self,
210        fid: FeatureId,
211        m: &Isometry<N>,
212        deformations: Option<&[N]>,
213        dir: &Unit<Vector<N>>,
214    ) -> bool {
215        let ls_dir = m.inverse_transform_unit_vector(dir);
216
217        match fid {
218            FeatureId::Face(i) => self.face_tangent_cone_contains_dir(i, deformations, &ls_dir),
219            FeatureId::Edge(i) => self.edge_tangent_cone_contains_dir(i, deformations, &ls_dir),
220            FeatureId::Vertex(i) => self.vertex_tangent_cone_contains_dir(i, deformations, &ls_dir),
221            FeatureId::Unknown => false,
222        }
223    }
224
225    fn subshape_containing_feature(&self, id: FeatureId) -> usize {
226        self.face_containing_feature(id)
227    }
228}
229
230impl<N: RealField + Copy> Shape<N> for Polyline<N> {
231    impl_shape_common!();
232    impl_as_composite_shape!();
233    impl_as_deformable_shape!();
234
235    fn tangent_cone_contains_dir(
236        &self,
237        _feature: FeatureId,
238        _m: &Isometry<N>,
239        _deformations: Option<&[N]>,
240        _dir: &Unit<Vector<N>>,
241    ) -> bool {
242        // FIXME
243        false
244    }
245
246    fn subshape_containing_feature(&self, id: FeatureId) -> usize {
247        self.edge_containing_feature(id)
248    }
249}
250
251impl<N: RealField + Copy> Shape<N> for HeightField<N> {
252    impl_shape_common!();
253
254    fn tangent_cone_contains_dir(
255        &self,
256        _fid: FeatureId,
257        _m: &Isometry<N>,
258        _deformations: Option<&[N]>,
259        _dir: &Unit<Vector<N>>,
260    ) -> bool {
261        // FIXME
262        false
263    }
264
265    fn subshape_containing_feature(&self, _id: FeatureId) -> usize {
266        // FIXME
267        0
268    }
269}
270
271impl<N: RealField + Copy> Shape<N> for Plane<N> {
272    impl_shape_common!();
273
274    fn tangent_cone_contains_dir(
275        &self,
276        _: FeatureId,
277        m: &Isometry<N>,
278        _: Option<&[N]>,
279        dir: &Unit<Vector<N>>,
280    ) -> bool {
281        let world_normal = m * self.normal;
282        dir.dot(&world_normal) <= N::zero()
283    }
284}