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 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 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 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 false
263 }
264
265 fn subshape_containing_feature(&self, _id: FeatureId) -> usize {
266 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}