1#[cfg(feature = "alloc")]
2use alloc::{boxed::Box, vec::Vec};
3use core::fmt::Debug;
4
5use crate::bounding_volume::{Aabb, BoundingSphere, BoundingVolume};
6use crate::mass_properties::MassProperties;
7use crate::math::{Isometry, Point, Real, Vector};
8#[cfg(not(feature = "alloc"))]
9use crate::num::Float;
10use crate::query::{PointQuery, RayCast};
11#[cfg(feature = "serde-serialize")]
12use crate::shape::SharedShape;
13#[cfg(feature = "alloc")]
14use crate::shape::{composite_shape::CompositeShape, Compound, HeightField, Polyline, TriMesh};
15use crate::shape::{
16 Ball, Capsule, Cuboid, FeatureId, HalfSpace, PolygonalFeatureMap, RoundCuboid, RoundShape,
17 RoundTriangle, Segment, SupportMap, Triangle,
18};
19#[cfg(feature = "dim3")]
20use crate::shape::{Cone, Cylinder, RoundCone, RoundCylinder};
21
22#[cfg(feature = "dim3")]
23#[cfg(feature = "alloc")]
24use crate::shape::{ConvexPolyhedron, RoundConvexPolyhedron, Voxels};
25
26#[cfg(feature = "dim2")]
27#[cfg(feature = "alloc")]
28use crate::shape::{ConvexPolygon, RoundConvexPolygon, Voxels};
29use downcast_rs::{impl_downcast, DowncastSync};
30use na::{RealField, Unit};
31use num::Zero;
32use num_derive::FromPrimitive;
33
34#[derive(Copy, Clone, Debug, FromPrimitive, PartialEq, Eq, Hash)]
35pub enum ShapeType {
37 Ball = 0,
39 Cuboid,
41 Capsule,
43 Segment,
45 Triangle,
47 Voxels,
49 TriMesh,
51 Polyline,
53 HalfSpace,
55 HeightField,
57 Compound,
59 #[cfg(feature = "dim2")]
60 ConvexPolygon,
61 #[cfg(feature = "dim3")]
62 ConvexPolyhedron,
64 #[cfg(feature = "dim3")]
65 Cylinder,
67 #[cfg(feature = "dim3")]
68 Cone,
70 RoundCuboid,
74 RoundTriangle,
76 #[cfg(feature = "dim3")]
82 RoundCylinder,
83 #[cfg(feature = "dim3")]
85 RoundCone,
86 #[cfg(feature = "dim3")]
88 RoundConvexPolyhedron,
89 #[cfg(feature = "dim2")]
91 RoundConvexPolygon,
92 Custom,
94}
95
96#[derive(Copy, Clone)]
97#[cfg_attr(feature = "serde-serialize", derive(Serialize))]
98pub enum TypedShape<'a> {
100 Ball(&'a Ball),
102 Cuboid(&'a Cuboid),
104 Capsule(&'a Capsule),
106 Segment(&'a Segment),
108 Triangle(&'a Triangle),
110 #[cfg(feature = "alloc")]
111 Voxels(&'a Voxels),
113 #[cfg(feature = "alloc")]
115 TriMesh(&'a TriMesh),
116 #[cfg(feature = "alloc")]
118 Polyline(&'a Polyline),
119 HalfSpace(&'a HalfSpace),
121 #[cfg(feature = "alloc")]
123 HeightField(&'a HeightField),
124 #[cfg(feature = "alloc")]
126 Compound(&'a Compound),
127 #[cfg(feature = "dim2")]
128 #[cfg(feature = "alloc")]
129 ConvexPolygon(&'a ConvexPolygon),
130 #[cfg(feature = "dim3")]
131 #[cfg(feature = "alloc")]
132 ConvexPolyhedron(&'a ConvexPolyhedron),
134 #[cfg(feature = "dim3")]
135 Cylinder(&'a Cylinder),
137 #[cfg(feature = "dim3")]
138 Cone(&'a Cone),
140 RoundCuboid(&'a RoundCuboid),
142 RoundTriangle(&'a RoundTriangle),
144 #[cfg(feature = "dim3")]
150 RoundCylinder(&'a RoundCylinder),
151 #[cfg(feature = "dim3")]
153 RoundCone(&'a RoundCone),
154 #[cfg(feature = "dim3")]
156 #[cfg(feature = "alloc")]
157 RoundConvexPolyhedron(&'a RoundConvexPolyhedron),
158 #[cfg(feature = "dim2")]
160 #[cfg(feature = "alloc")]
161 RoundConvexPolygon(&'a RoundConvexPolygon),
162 #[cfg_attr(feature = "serde-serialize", serde(skip))]
164 Custom(&'a dyn Shape),
165}
166impl Debug for TypedShape<'_> {
167 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
168 match self {
169 Self::Ball(arg0) => f.debug_tuple("Ball").field(arg0).finish(),
170 Self::Cuboid(arg0) => f.debug_tuple("Cuboid").field(arg0).finish(),
171 Self::Capsule(arg0) => f.debug_tuple("Capsule").field(arg0).finish(),
172 Self::Segment(arg0) => f.debug_tuple("Segment").field(arg0).finish(),
173 Self::Triangle(arg0) => f.debug_tuple("Triangle").field(arg0).finish(),
174 #[cfg(feature = "alloc")]
175 Self::Voxels(arg0) => f.debug_tuple("Voxels").field(arg0).finish(),
176 #[cfg(feature = "alloc")]
177 Self::TriMesh(arg0) => f.debug_tuple("TriMesh").field(arg0).finish(),
178 #[cfg(feature = "alloc")]
179 Self::Polyline(arg0) => f.debug_tuple("Polyline").field(arg0).finish(),
180 Self::HalfSpace(arg0) => f.debug_tuple("HalfSpace").field(arg0).finish(),
181 #[cfg(feature = "alloc")]
182 Self::HeightField(arg0) => f.debug_tuple("HeightField").field(arg0).finish(),
183 #[cfg(feature = "alloc")]
184 Self::Compound(arg0) => f.debug_tuple("Compound").field(arg0).finish(),
185 #[cfg(feature = "dim2")]
186 #[cfg(feature = "alloc")]
187 Self::ConvexPolygon(arg0) => f.debug_tuple("ConvexPolygon").field(arg0).finish(),
188 #[cfg(feature = "dim3")]
189 #[cfg(feature = "alloc")]
190 Self::ConvexPolyhedron(arg0) => f.debug_tuple("ConvexPolyhedron").field(arg0).finish(),
191 #[cfg(feature = "dim3")]
192 Self::Cylinder(arg0) => f.debug_tuple("Cylinder").field(arg0).finish(),
193 #[cfg(feature = "dim3")]
194 Self::Cone(arg0) => f.debug_tuple("Cone").field(arg0).finish(),
195 Self::RoundCuboid(arg0) => f.debug_tuple("RoundCuboid").field(arg0).finish(),
196 Self::RoundTriangle(arg0) => f.debug_tuple("RoundTriangle").field(arg0).finish(),
197 #[cfg(feature = "dim3")]
198 Self::RoundCylinder(arg0) => f.debug_tuple("RoundCylinder").field(arg0).finish(),
199 #[cfg(feature = "dim3")]
200 Self::RoundCone(arg0) => f.debug_tuple("RoundCone").field(arg0).finish(),
201 #[cfg(feature = "dim3")]
202 #[cfg(feature = "alloc")]
203 Self::RoundConvexPolyhedron(arg0) => {
204 f.debug_tuple("RoundConvexPolyhedron").field(arg0).finish()
205 }
206 #[cfg(feature = "dim2")]
207 #[cfg(feature = "alloc")]
208 Self::RoundConvexPolygon(arg0) => {
209 f.debug_tuple("RoundConvexPolygon").field(arg0).finish()
210 }
211 Self::Custom(_) => f.debug_tuple("Custom").finish(),
212 }
213 }
214}
215
216#[cfg(feature = "serde-serialize")]
217#[derive(Deserialize)]
218pub(crate) enum DeserializableTypedShape {
221 Ball(Ball),
223 Cuboid(Cuboid),
225 Capsule(Capsule),
227 Segment(Segment),
229 Triangle(Triangle),
231 #[cfg(feature = "alloc")]
233 Voxels(Voxels),
234 #[cfg(feature = "alloc")]
236 TriMesh(TriMesh),
237 #[cfg(feature = "alloc")]
239 Polyline(Polyline),
240 HalfSpace(HalfSpace),
242 #[cfg(feature = "alloc")]
244 HeightField(HeightField),
245 #[cfg(feature = "alloc")]
247 Compound(Compound),
248 #[cfg(feature = "dim2")]
249 #[cfg(feature = "alloc")]
250 ConvexPolygon(ConvexPolygon),
251 #[cfg(feature = "dim3")]
252 #[cfg(feature = "alloc")]
253 ConvexPolyhedron(ConvexPolyhedron),
255 #[cfg(feature = "dim3")]
256 Cylinder(Cylinder),
258 #[cfg(feature = "dim3")]
259 Cone(Cone),
261 RoundCuboid(RoundCuboid),
265 RoundTriangle(RoundTriangle),
267 #[cfg(feature = "dim3")]
273 RoundCylinder(RoundCylinder),
274 #[cfg(feature = "dim3")]
276 RoundCone(RoundCone),
277 #[cfg(feature = "dim3")]
279 #[cfg(feature = "alloc")]
280 RoundConvexPolyhedron(RoundConvexPolyhedron),
281 #[cfg(feature = "dim2")]
283 #[cfg(feature = "alloc")]
284 RoundConvexPolygon(RoundConvexPolygon),
285 #[allow(dead_code)]
287 Custom,
288}
289
290#[cfg(feature = "serde-serialize")]
291impl DeserializableTypedShape {
292 pub fn into_shared_shape(self) -> Option<SharedShape> {
294 match self {
295 DeserializableTypedShape::Ball(s) => Some(SharedShape::new(s)),
296 DeserializableTypedShape::Cuboid(s) => Some(SharedShape::new(s)),
297 DeserializableTypedShape::Capsule(s) => Some(SharedShape::new(s)),
298 DeserializableTypedShape::Segment(s) => Some(SharedShape::new(s)),
299 DeserializableTypedShape::Triangle(s) => Some(SharedShape::new(s)),
300 #[cfg(feature = "alloc")]
301 DeserializableTypedShape::Voxels(s) => Some(SharedShape::new(s)),
302 #[cfg(feature = "alloc")]
303 DeserializableTypedShape::TriMesh(s) => Some(SharedShape::new(s)),
304 #[cfg(feature = "alloc")]
305 DeserializableTypedShape::Polyline(s) => Some(SharedShape::new(s)),
306 DeserializableTypedShape::HalfSpace(s) => Some(SharedShape::new(s)),
307 #[cfg(feature = "alloc")]
308 DeserializableTypedShape::HeightField(s) => Some(SharedShape::new(s)),
309 #[cfg(feature = "alloc")]
310 DeserializableTypedShape::Compound(s) => Some(SharedShape::new(s)),
311 #[cfg(feature = "dim2")]
312 #[cfg(feature = "alloc")]
313 DeserializableTypedShape::ConvexPolygon(s) => Some(SharedShape::new(s)),
314 #[cfg(feature = "dim3")]
315 #[cfg(feature = "alloc")]
316 DeserializableTypedShape::ConvexPolyhedron(s) => Some(SharedShape::new(s)),
317 #[cfg(feature = "dim3")]
318 DeserializableTypedShape::Cylinder(s) => Some(SharedShape::new(s)),
319 #[cfg(feature = "dim3")]
320 DeserializableTypedShape::Cone(s) => Some(SharedShape::new(s)),
321 DeserializableTypedShape::RoundCuboid(s) => Some(SharedShape::new(s)),
322 DeserializableTypedShape::RoundTriangle(s) => Some(SharedShape::new(s)),
323 #[cfg(feature = "dim3")]
324 DeserializableTypedShape::RoundCylinder(s) => Some(SharedShape::new(s)),
325 #[cfg(feature = "dim3")]
326 DeserializableTypedShape::RoundCone(s) => Some(SharedShape::new(s)),
327 #[cfg(feature = "dim3")]
328 #[cfg(feature = "alloc")]
329 DeserializableTypedShape::RoundConvexPolyhedron(s) => Some(SharedShape::new(s)),
330 #[cfg(feature = "dim2")]
331 #[cfg(feature = "alloc")]
332 DeserializableTypedShape::RoundConvexPolygon(s) => Some(SharedShape::new(s)),
333 DeserializableTypedShape::Custom => None,
334 }
335 }
336}
337
338pub trait Shape: RayCast + PointQuery + DowncastSync {
340 fn compute_local_aabb(&self) -> Aabb;
342 fn compute_local_bounding_sphere(&self) -> BoundingSphere;
344
345 #[cfg(feature = "alloc")]
349 #[deprecated = "renamed to `clone_dyn`"]
350 fn clone_box(&self) -> Box<dyn Shape> {
351 self.clone_dyn()
352 }
353
354 #[cfg(feature = "alloc")]
358 fn clone_dyn(&self) -> Box<dyn Shape>;
359
360 #[cfg(feature = "alloc")]
366 fn scale_dyn(&self, scale: &Vector<Real>, num_subdivisions: u32) -> Option<Box<dyn Shape>>;
367
368 fn compute_aabb(&self, position: &Isometry<Real>) -> Aabb {
370 self.compute_local_aabb().transform_by(position)
371 }
372 fn compute_bounding_sphere(&self, position: &Isometry<Real>) -> BoundingSphere {
374 self.compute_local_bounding_sphere().transform_by(position)
375 }
376
377 fn mass_properties(&self, density: Real) -> MassProperties;
379
380 fn shape_type(&self) -> ShapeType;
382
383 fn as_typed_shape(&self) -> TypedShape<'_>;
385
386 fn ccd_thickness(&self) -> Real;
387
388 fn ccd_angular_thickness(&self) -> Real;
395
396 fn is_convex(&self) -> bool {
402 false
403 }
404
405 fn as_support_map(&self) -> Option<&dyn SupportMap> {
407 None
408 }
409
410 #[cfg(feature = "alloc")]
411 fn as_composite_shape(&self) -> Option<&dyn CompositeShape> {
412 None
413 }
414
415 fn as_polygonal_feature_map(&self) -> Option<(&dyn PolygonalFeatureMap, Real)> {
417 None
418 }
419
420 fn feature_normal_at_point(
426 &self,
427 _feature: FeatureId,
428 _point: &Point<Real>,
429 ) -> Option<Unit<Vector<Real>>> {
430 None
431 }
432
433 fn compute_swept_aabb(&self, start_pos: &Isometry<Real>, end_pos: &Isometry<Real>) -> Aabb {
436 let aabb1 = self.compute_aabb(start_pos);
437 let aabb2 = self.compute_aabb(end_pos);
438 aabb1.merged(&aabb2)
439 }
440}
441
442impl_downcast!(sync Shape);
443
444impl dyn Shape {
445 pub fn as_shape<T: Shape>(&self) -> Option<&T> {
447 self.downcast_ref()
448 }
449 pub fn as_shape_mut<T: Shape>(&mut self) -> Option<&mut T> {
451 self.downcast_mut()
452 }
453
454 pub fn as_ball(&self) -> Option<&Ball> {
456 self.downcast_ref()
457 }
458 pub fn as_ball_mut(&mut self) -> Option<&mut Ball> {
460 self.downcast_mut()
461 }
462
463 pub fn as_cuboid(&self) -> Option<&Cuboid> {
465 self.downcast_ref()
466 }
467 pub fn as_cuboid_mut(&mut self) -> Option<&mut Cuboid> {
469 self.downcast_mut()
470 }
471
472 pub fn as_halfspace(&self) -> Option<&HalfSpace> {
474 self.downcast_ref()
475 }
476 pub fn as_halfspace_mut(&mut self) -> Option<&mut HalfSpace> {
478 self.downcast_mut()
479 }
480
481 pub fn as_segment(&self) -> Option<&Segment> {
483 self.downcast_ref()
484 }
485 pub fn as_segment_mut(&mut self) -> Option<&mut Segment> {
487 self.downcast_mut()
488 }
489
490 pub fn as_capsule(&self) -> Option<&Capsule> {
492 self.downcast_ref()
493 }
494 pub fn as_capsule_mut(&mut self) -> Option<&mut Capsule> {
496 self.downcast_mut()
497 }
498
499 pub fn as_triangle(&self) -> Option<&Triangle> {
501 self.downcast_ref()
502 }
503 pub fn as_triangle_mut(&mut self) -> Option<&mut Triangle> {
505 self.downcast_mut()
506 }
507
508 #[cfg(feature = "alloc")]
510 pub fn as_voxels(&self) -> Option<&Voxels> {
511 self.downcast_ref()
512 }
513 #[cfg(feature = "alloc")]
515 pub fn as_voxels_mut(&mut self) -> Option<&mut Voxels> {
516 self.downcast_mut()
517 }
518
519 #[cfg(feature = "alloc")]
521 pub fn as_compound(&self) -> Option<&Compound> {
522 self.downcast_ref()
523 }
524 #[cfg(feature = "alloc")]
526 pub fn as_compound_mut(&mut self) -> Option<&mut Compound> {
527 self.downcast_mut()
528 }
529
530 #[cfg(feature = "alloc")]
532 pub fn as_trimesh(&self) -> Option<&TriMesh> {
533 self.downcast_ref()
534 }
535 #[cfg(feature = "alloc")]
537 pub fn as_trimesh_mut(&mut self) -> Option<&mut TriMesh> {
538 self.downcast_mut()
539 }
540
541 #[cfg(feature = "alloc")]
543 pub fn as_polyline(&self) -> Option<&Polyline> {
544 self.downcast_ref()
545 }
546 #[cfg(feature = "alloc")]
548 pub fn as_polyline_mut(&mut self) -> Option<&mut Polyline> {
549 self.downcast_mut()
550 }
551
552 #[cfg(feature = "alloc")]
554 pub fn as_heightfield(&self) -> Option<&HeightField> {
555 self.downcast_ref()
556 }
557 #[cfg(feature = "alloc")]
559 pub fn as_heightfield_mut(&mut self) -> Option<&mut HeightField> {
560 self.downcast_mut()
561 }
562
563 pub fn as_round_cuboid(&self) -> Option<&RoundCuboid> {
565 self.downcast_ref()
566 }
567 pub fn as_round_cuboid_mut(&mut self) -> Option<&mut RoundCuboid> {
569 self.downcast_mut()
570 }
571
572 pub fn as_round_triangle(&self) -> Option<&RoundTriangle> {
574 self.downcast_ref()
575 }
576 pub fn as_round_triangle_mut(&mut self) -> Option<&mut RoundTriangle> {
578 self.downcast_mut()
579 }
580
581 #[cfg(feature = "dim2")]
583 #[cfg(feature = "alloc")]
584 pub fn as_convex_polygon(&self) -> Option<&ConvexPolygon> {
585 self.downcast_ref()
586 }
587 #[cfg(feature = "dim2")]
589 #[cfg(feature = "alloc")]
590 pub fn as_convex_polygon_mut(&mut self) -> Option<&mut ConvexPolygon> {
591 self.downcast_mut()
592 }
593
594 #[cfg(feature = "dim2")]
596 #[cfg(feature = "alloc")]
597 pub fn as_round_convex_polygon(&self) -> Option<&RoundConvexPolygon> {
598 self.downcast_ref()
599 }
600 #[cfg(feature = "dim2")]
602 #[cfg(feature = "alloc")]
603 pub fn as_round_convex_polygon_mut(&mut self) -> Option<&mut RoundConvexPolygon> {
604 self.downcast_mut()
605 }
606
607 #[cfg(feature = "dim3")]
608 #[cfg(feature = "alloc")]
609 pub fn as_convex_polyhedron(&self) -> Option<&ConvexPolyhedron> {
610 self.downcast_ref()
611 }
612 #[cfg(feature = "dim3")]
613 #[cfg(feature = "alloc")]
614 pub fn as_convex_polyhedron_mut(&mut self) -> Option<&mut ConvexPolyhedron> {
615 self.downcast_mut()
616 }
617
618 #[cfg(feature = "dim3")]
620 pub fn as_cylinder(&self) -> Option<&Cylinder> {
621 self.downcast_ref()
622 }
623 #[cfg(feature = "dim3")]
625 pub fn as_cylinder_mut(&mut self) -> Option<&mut Cylinder> {
626 self.downcast_mut()
627 }
628
629 #[cfg(feature = "dim3")]
631 pub fn as_cone(&self) -> Option<&Cone> {
632 self.downcast_ref()
633 }
634 #[cfg(feature = "dim3")]
636 pub fn as_cone_mut(&mut self) -> Option<&mut Cone> {
637 self.downcast_mut()
638 }
639
640 #[cfg(feature = "dim3")]
642 pub fn as_round_cylinder(&self) -> Option<&RoundCylinder> {
643 self.downcast_ref()
644 }
645 #[cfg(feature = "dim3")]
647 pub fn as_round_cylinder_mut(&mut self) -> Option<&mut RoundCylinder> {
648 self.downcast_mut()
649 }
650
651 #[cfg(feature = "dim3")]
653 pub fn as_round_cone(&self) -> Option<&RoundCone> {
654 self.downcast_ref()
655 }
656 #[cfg(feature = "dim3")]
658 pub fn as_round_cone_mut(&mut self) -> Option<&mut RoundCone> {
659 self.downcast_mut()
660 }
661
662 #[cfg(feature = "dim3")]
664 #[cfg(feature = "alloc")]
665 pub fn as_round_convex_polyhedron(&self) -> Option<&RoundConvexPolyhedron> {
666 self.downcast_ref()
667 }
668 #[cfg(feature = "dim3")]
670 #[cfg(feature = "alloc")]
671 pub fn as_round_convex_polyhedron_mut(&mut self) -> Option<&mut RoundConvexPolyhedron> {
672 self.downcast_mut()
673 }
674}
675
676impl Shape for Ball {
677 #[cfg(feature = "alloc")]
678 fn clone_dyn(&self) -> Box<dyn Shape> {
679 Box::new(*self)
680 }
681
682 #[cfg(feature = "alloc")]
683 fn scale_dyn(&self, scale: &Vector<Real>, num_subdivisions: u32) -> Option<Box<dyn Shape>> {
684 let scaled = self.scaled(scale, num_subdivisions)?;
685 Some(scaled.either::<_, _, Box<dyn Shape>>(|x| Box::new(x), |x| Box::new(x)))
686 }
687
688 fn compute_local_aabb(&self) -> Aabb {
689 self.local_aabb()
690 }
691
692 fn compute_local_bounding_sphere(&self) -> BoundingSphere {
693 self.local_bounding_sphere()
694 }
695
696 fn compute_aabb(&self, position: &Isometry<Real>) -> Aabb {
697 self.aabb(position)
698 }
699
700 fn mass_properties(&self, density: Real) -> MassProperties {
701 MassProperties::from_ball(density, self.radius)
702 }
703
704 fn ccd_thickness(&self) -> Real {
705 self.radius
706 }
707
708 fn ccd_angular_thickness(&self) -> Real {
709 Real::pi()
710 }
711
712 fn is_convex(&self) -> bool {
713 true
714 }
715
716 fn shape_type(&self) -> ShapeType {
717 ShapeType::Ball
718 }
719
720 fn as_typed_shape(&self) -> TypedShape<'_> {
721 TypedShape::Ball(self)
722 }
723
724 fn as_support_map(&self) -> Option<&dyn SupportMap> {
725 Some(self as &dyn SupportMap)
726 }
727
728 #[inline]
730 fn feature_normal_at_point(
731 &self,
732 _: FeatureId,
733 point: &Point<Real>,
734 ) -> Option<Unit<Vector<Real>>> {
735 Unit::try_new(point.coords, crate::math::DEFAULT_EPSILON)
736 }
737}
738
739impl Shape for Cuboid {
740 #[cfg(feature = "alloc")]
741 fn clone_dyn(&self) -> Box<dyn Shape> {
742 Box::new(*self)
743 }
744
745 #[cfg(feature = "alloc")]
746 fn scale_dyn(&self, scale: &Vector<Real>, _num_subdivisions: u32) -> Option<Box<dyn Shape>> {
747 Some(Box::new(self.scaled(scale)))
748 }
749
750 fn compute_local_aabb(&self) -> Aabb {
751 self.local_aabb()
752 }
753
754 fn compute_local_bounding_sphere(&self) -> BoundingSphere {
755 self.local_bounding_sphere()
756 }
757
758 fn compute_aabb(&self, position: &Isometry<Real>) -> Aabb {
759 self.aabb(position)
760 }
761
762 fn mass_properties(&self, density: Real) -> MassProperties {
763 MassProperties::from_cuboid(density, self.half_extents)
764 }
765
766 fn is_convex(&self) -> bool {
767 true
768 }
769
770 fn shape_type(&self) -> ShapeType {
771 ShapeType::Cuboid
772 }
773
774 fn as_typed_shape(&self) -> TypedShape<'_> {
775 TypedShape::Cuboid(self)
776 }
777
778 fn ccd_thickness(&self) -> Real {
779 self.half_extents.min()
780 }
781
782 fn ccd_angular_thickness(&self) -> Real {
783 Real::frac_pi_2()
784 }
785
786 fn as_support_map(&self) -> Option<&dyn SupportMap> {
787 Some(self as &dyn SupportMap)
788 }
789
790 fn as_polygonal_feature_map(&self) -> Option<(&dyn PolygonalFeatureMap, Real)> {
791 Some((self as &dyn PolygonalFeatureMap, 0.0))
792 }
793
794 fn feature_normal_at_point(
795 &self,
796 feature: FeatureId,
797 _point: &Point<Real>,
798 ) -> Option<Unit<Vector<Real>>> {
799 self.feature_normal(feature)
800 }
801}
802
803impl Shape for Capsule {
804 #[cfg(feature = "alloc")]
805 fn clone_dyn(&self) -> Box<dyn Shape> {
806 Box::new(*self)
807 }
808
809 #[cfg(feature = "alloc")]
810 fn scale_dyn(&self, scale: &Vector<Real>, num_subdivisions: u32) -> Option<Box<dyn Shape>> {
811 let scaled = self.scaled(scale, num_subdivisions)?;
812 Some(scaled.either::<_, _, Box<dyn Shape>>(|x| Box::new(x), |x| Box::new(x)))
813 }
814
815 fn compute_local_aabb(&self) -> Aabb {
816 self.local_aabb()
817 }
818
819 fn compute_local_bounding_sphere(&self) -> BoundingSphere {
820 self.local_bounding_sphere()
821 }
822
823 fn compute_aabb(&self, position: &Isometry<Real>) -> Aabb {
824 self.aabb(position)
825 }
826
827 fn mass_properties(&self, density: Real) -> MassProperties {
828 MassProperties::from_capsule(density, self.segment.a, self.segment.b, self.radius)
829 }
830
831 fn is_convex(&self) -> bool {
832 true
833 }
834
835 fn shape_type(&self) -> ShapeType {
836 ShapeType::Capsule
837 }
838
839 fn as_typed_shape(&self) -> TypedShape<'_> {
840 TypedShape::Capsule(self)
841 }
842
843 fn ccd_thickness(&self) -> Real {
844 self.radius
845 }
846
847 fn ccd_angular_thickness(&self) -> Real {
848 Real::frac_pi_2()
849 }
850
851 fn as_support_map(&self) -> Option<&dyn SupportMap> {
852 Some(self as &dyn SupportMap)
853 }
854
855 fn as_polygonal_feature_map(&self) -> Option<(&dyn PolygonalFeatureMap, Real)> {
856 Some((&self.segment as &dyn PolygonalFeatureMap, self.radius))
857 }
858}
859
860impl Shape for Triangle {
861 #[cfg(feature = "alloc")]
862 fn clone_dyn(&self) -> Box<dyn Shape> {
863 Box::new(*self)
864 }
865
866 #[cfg(feature = "alloc")]
867 fn scale_dyn(&self, scale: &Vector<Real>, _num_subdivisions: u32) -> Option<Box<dyn Shape>> {
868 Some(Box::new(self.scaled(scale)))
869 }
870
871 fn compute_local_aabb(&self) -> Aabb {
872 self.local_aabb()
873 }
874
875 fn compute_local_bounding_sphere(&self) -> BoundingSphere {
876 self.local_bounding_sphere()
877 }
878
879 fn compute_aabb(&self, position: &Isometry<Real>) -> Aabb {
880 self.aabb(position)
881 }
882
883 fn mass_properties(&self, _density: Real) -> MassProperties {
884 #[cfg(feature = "dim2")]
885 return MassProperties::from_triangle(_density, &self.a, &self.b, &self.c);
886 #[cfg(feature = "dim3")]
887 return MassProperties::zero();
888 }
889
890 fn is_convex(&self) -> bool {
891 true
892 }
893
894 fn shape_type(&self) -> ShapeType {
895 ShapeType::Triangle
896 }
897
898 fn as_typed_shape(&self) -> TypedShape<'_> {
899 TypedShape::Triangle(self)
900 }
901
902 fn ccd_thickness(&self) -> Real {
903 0.0
905 }
906
907 fn ccd_angular_thickness(&self) -> Real {
908 Real::frac_pi_2()
909 }
910
911 fn as_support_map(&self) -> Option<&dyn SupportMap> {
912 Some(self as &dyn SupportMap)
913 }
914
915 fn as_polygonal_feature_map(&self) -> Option<(&dyn PolygonalFeatureMap, Real)> {
916 Some((self as &dyn PolygonalFeatureMap, 0.0))
917 }
918
919 fn feature_normal_at_point(
920 &self,
921 _feature: FeatureId,
922 _point: &Point<Real>,
923 ) -> Option<Unit<Vector<Real>>> {
924 #[cfg(feature = "dim2")]
925 return None;
926 #[cfg(feature = "dim3")]
927 return self.feature_normal(_feature);
928 }
929}
930
931impl Shape for Segment {
932 #[cfg(feature = "alloc")]
933 fn clone_dyn(&self) -> Box<dyn Shape> {
934 Box::new(*self)
935 }
936
937 #[cfg(feature = "alloc")]
938 fn scale_dyn(&self, scale: &Vector<Real>, _num_subdivisions: u32) -> Option<Box<dyn Shape>> {
939 Some(Box::new(self.scaled(scale)))
940 }
941
942 fn compute_local_aabb(&self) -> Aabb {
943 self.local_aabb()
944 }
945
946 fn compute_local_bounding_sphere(&self) -> BoundingSphere {
947 self.local_bounding_sphere()
948 }
949
950 fn compute_aabb(&self, position: &Isometry<Real>) -> Aabb {
951 self.aabb(position)
952 }
953
954 fn mass_properties(&self, _density: Real) -> MassProperties {
955 MassProperties::zero()
956 }
957
958 fn is_convex(&self) -> bool {
959 true
960 }
961
962 fn ccd_thickness(&self) -> Real {
963 0.0
964 }
965
966 fn ccd_angular_thickness(&self) -> Real {
967 Real::frac_pi_2()
968 }
969
970 fn shape_type(&self) -> ShapeType {
971 ShapeType::Segment
972 }
973
974 fn as_typed_shape(&self) -> TypedShape<'_> {
975 TypedShape::Segment(self)
976 }
977
978 fn as_support_map(&self) -> Option<&dyn SupportMap> {
979 Some(self as &dyn SupportMap)
980 }
981
982 fn as_polygonal_feature_map(&self) -> Option<(&dyn PolygonalFeatureMap, Real)> {
983 Some((self as &dyn PolygonalFeatureMap, 0.0))
984 }
985
986 fn feature_normal_at_point(
987 &self,
988 feature: FeatureId,
989 _point: &Point<Real>,
990 ) -> Option<Unit<Vector<Real>>> {
991 self.feature_normal(feature)
992 }
993}
994
995#[cfg(feature = "alloc")]
996impl Shape for Compound {
997 fn clone_dyn(&self) -> Box<dyn Shape> {
998 Box::new(self.clone())
999 }
1000
1001 fn scale_dyn(&self, scale: &Vector<Real>, num_subdivisions: u32) -> Option<Box<dyn Shape>> {
1002 use super::SharedShape;
1003
1004 let scaled: Vec<_> = self
1005 .shapes()
1006 .iter()
1007 .map(|(pos, shape)| {
1008 let scaled_shape = shape.scale_dyn(scale, num_subdivisions)?;
1009 Some((
1010 Isometry::from_parts(
1011 (pos.translation.vector.component_mul(scale)).into(),
1012 pos.rotation,
1013 ),
1014 SharedShape(scaled_shape.into()),
1015 ))
1016 })
1017 .collect::<Option<Vec<_>>>()?;
1018 Some(Box::new(Compound::new(scaled)))
1019 }
1020
1021 fn compute_local_aabb(&self) -> Aabb {
1022 *self.local_aabb()
1023 }
1024
1025 fn compute_local_bounding_sphere(&self) -> BoundingSphere {
1026 self.local_bounding_sphere()
1027 }
1028
1029 fn compute_aabb(&self, position: &Isometry<Real>) -> Aabb {
1030 self.local_aabb().transform_by(position)
1031 }
1032
1033 fn mass_properties(&self, density: Real) -> MassProperties {
1034 MassProperties::from_compound(density, self.shapes())
1035 }
1036
1037 fn shape_type(&self) -> ShapeType {
1038 ShapeType::Compound
1039 }
1040
1041 fn as_typed_shape(&self) -> TypedShape<'_> {
1042 TypedShape::Compound(self)
1043 }
1044
1045 fn ccd_thickness(&self) -> Real {
1046 self.shapes()
1047 .iter()
1048 .fold(Real::MAX, |curr, (_, s)| curr.min(s.ccd_thickness()))
1049 }
1050
1051 fn ccd_angular_thickness(&self) -> Real {
1052 self.shapes().iter().fold(Real::MAX, |curr, (_, s)| {
1053 curr.max(s.ccd_angular_thickness())
1054 })
1055 }
1056
1057 #[cfg(feature = "alloc")]
1058 fn as_composite_shape(&self) -> Option<&dyn CompositeShape> {
1059 Some(self as &dyn CompositeShape)
1060 }
1061}
1062
1063#[cfg(feature = "alloc")]
1064impl Shape for Polyline {
1065 fn clone_dyn(&self) -> Box<dyn Shape> {
1066 Box::new(self.clone())
1067 }
1068
1069 fn scale_dyn(&self, scale: &Vector<Real>, _num_subdivisions: u32) -> Option<Box<dyn Shape>> {
1070 Some(Box::new(self.clone().scaled(scale)))
1071 }
1072
1073 fn compute_local_aabb(&self) -> Aabb {
1074 self.local_aabb()
1075 }
1076
1077 fn compute_local_bounding_sphere(&self) -> BoundingSphere {
1078 self.local_bounding_sphere()
1079 }
1080
1081 fn compute_aabb(&self, position: &Isometry<Real>) -> Aabb {
1082 self.aabb(position)
1083 }
1084
1085 fn mass_properties(&self, _density: Real) -> MassProperties {
1086 MassProperties::zero()
1087 }
1088
1089 fn shape_type(&self) -> ShapeType {
1090 ShapeType::Polyline
1091 }
1092
1093 fn as_typed_shape(&self) -> TypedShape<'_> {
1094 TypedShape::Polyline(self)
1095 }
1096
1097 fn ccd_thickness(&self) -> Real {
1098 0.0
1099 }
1100
1101 fn ccd_angular_thickness(&self) -> Real {
1102 Real::frac_pi_4()
1105 }
1106
1107 #[cfg(feature = "alloc")]
1108 fn as_composite_shape(&self) -> Option<&dyn CompositeShape> {
1109 Some(self as &dyn CompositeShape)
1110 }
1111}
1112
1113#[cfg(feature = "alloc")]
1114impl Shape for TriMesh {
1115 fn clone_dyn(&self) -> Box<dyn Shape> {
1116 Box::new(self.clone())
1117 }
1118
1119 fn scale_dyn(&self, scale: &Vector<Real>, _num_subdivisions: u32) -> Option<Box<dyn Shape>> {
1120 Some(Box::new(self.clone().scaled(scale)))
1121 }
1122
1123 fn compute_local_aabb(&self) -> Aabb {
1124 self.local_aabb()
1125 }
1126
1127 fn compute_local_bounding_sphere(&self) -> BoundingSphere {
1128 self.local_bounding_sphere()
1129 }
1130
1131 fn compute_aabb(&self, position: &Isometry<Real>) -> Aabb {
1132 self.aabb(position)
1133 }
1134
1135 fn mass_properties(&self, density: Real) -> MassProperties {
1136 MassProperties::from_trimesh(density, self.vertices(), self.indices())
1137 }
1138
1139 fn shape_type(&self) -> ShapeType {
1140 ShapeType::TriMesh
1141 }
1142
1143 fn as_typed_shape(&self) -> TypedShape<'_> {
1144 TypedShape::TriMesh(self)
1145 }
1146
1147 fn ccd_thickness(&self) -> Real {
1148 0.0
1150 }
1151
1152 fn ccd_angular_thickness(&self) -> Real {
1153 Real::frac_pi_4()
1156 }
1157
1158 fn feature_normal_at_point(
1160 &self,
1161 _feature: FeatureId,
1162 _point: &Point<Real>,
1163 ) -> Option<Unit<Vector<Real>>> {
1164 #[cfg(feature = "dim2")]
1165 return None;
1166 #[cfg(feature = "dim3")]
1167 return self.feature_normal(_feature);
1168 }
1169
1170 #[cfg(feature = "alloc")]
1171 fn as_composite_shape(&self) -> Option<&dyn CompositeShape> {
1172 Some(self as &dyn CompositeShape)
1173 }
1174}
1175
1176#[cfg(feature = "alloc")]
1177impl Shape for HeightField {
1178 fn clone_dyn(&self) -> Box<dyn Shape> {
1179 Box::new(self.clone())
1180 }
1181
1182 fn scale_dyn(&self, scale: &Vector<Real>, _num_subdivisions: u32) -> Option<Box<dyn Shape>> {
1183 Some(Box::new(self.clone().scaled(scale)))
1184 }
1185
1186 fn compute_local_aabb(&self) -> Aabb {
1187 self.local_aabb()
1188 }
1189
1190 fn compute_local_bounding_sphere(&self) -> BoundingSphere {
1191 self.local_bounding_sphere()
1192 }
1193
1194 fn compute_aabb(&self, position: &Isometry<Real>) -> Aabb {
1195 self.aabb(position)
1196 }
1197
1198 fn mass_properties(&self, _density: Real) -> MassProperties {
1199 MassProperties::zero()
1200 }
1201
1202 fn shape_type(&self) -> ShapeType {
1203 ShapeType::HeightField
1204 }
1205
1206 fn as_typed_shape(&self) -> TypedShape<'_> {
1207 TypedShape::HeightField(self)
1208 }
1209
1210 fn ccd_thickness(&self) -> Real {
1211 0.0
1212 }
1213
1214 fn ccd_angular_thickness(&self) -> Real {
1215 Real::frac_pi_4()
1218 }
1219}
1220
1221#[cfg(feature = "dim2")]
1222#[cfg(feature = "alloc")]
1223impl Shape for ConvexPolygon {
1224 fn clone_dyn(&self) -> Box<dyn Shape> {
1225 Box::new(self.clone())
1226 }
1227
1228 fn scale_dyn(&self, scale: &Vector<Real>, _num_subdivisions: u32) -> Option<Box<dyn Shape>> {
1229 Some(Box::new(self.clone().scaled(scale)?))
1230 }
1231
1232 fn compute_local_aabb(&self) -> Aabb {
1233 self.local_aabb()
1234 }
1235
1236 fn compute_local_bounding_sphere(&self) -> BoundingSphere {
1237 self.local_bounding_sphere()
1238 }
1239
1240 fn compute_aabb(&self, position: &Isometry<Real>) -> Aabb {
1241 self.aabb(position)
1242 }
1243
1244 fn mass_properties(&self, density: Real) -> MassProperties {
1245 MassProperties::from_convex_polygon(density, self.points())
1246 }
1247
1248 fn is_convex(&self) -> bool {
1249 true
1250 }
1251
1252 fn shape_type(&self) -> ShapeType {
1253 ShapeType::ConvexPolygon
1254 }
1255
1256 fn as_typed_shape(&self) -> TypedShape {
1257 TypedShape::ConvexPolygon(self)
1258 }
1259
1260 fn ccd_thickness(&self) -> Real {
1261 self.compute_local_aabb().half_extents().min()
1263 }
1264
1265 fn ccd_angular_thickness(&self) -> Real {
1266 Real::frac_pi_4()
1269 }
1270
1271 fn as_support_map(&self) -> Option<&dyn SupportMap> {
1272 Some(self as &dyn SupportMap)
1273 }
1274
1275 fn as_polygonal_feature_map(&self) -> Option<(&dyn PolygonalFeatureMap, Real)> {
1276 Some((self as &dyn PolygonalFeatureMap, 0.0))
1277 }
1278
1279 fn feature_normal_at_point(
1280 &self,
1281 feature: FeatureId,
1282 _point: &Point<Real>,
1283 ) -> Option<Unit<Vector<Real>>> {
1284 self.feature_normal(feature)
1285 }
1286}
1287
1288#[cfg(feature = "dim3")]
1289#[cfg(feature = "alloc")]
1290impl Shape for ConvexPolyhedron {
1291 fn clone_dyn(&self) -> Box<dyn Shape> {
1292 Box::new(self.clone())
1293 }
1294
1295 fn scale_dyn(&self, scale: &Vector<Real>, _num_subdivisions: u32) -> Option<Box<dyn Shape>> {
1296 Some(Box::new(self.clone().scaled(scale)?))
1297 }
1298
1299 fn compute_local_aabb(&self) -> Aabb {
1300 self.local_aabb()
1301 }
1302
1303 fn compute_local_bounding_sphere(&self) -> BoundingSphere {
1304 self.local_bounding_sphere()
1305 }
1306
1307 fn compute_aabb(&self, position: &Isometry<Real>) -> Aabb {
1308 self.aabb(position)
1309 }
1310
1311 fn mass_properties(&self, density: Real) -> MassProperties {
1312 let (vertices, indices) = self.to_trimesh();
1313 MassProperties::from_convex_polyhedron(density, &vertices, &indices)
1314 }
1315
1316 fn is_convex(&self) -> bool {
1317 true
1318 }
1319
1320 fn shape_type(&self) -> ShapeType {
1321 ShapeType::ConvexPolyhedron
1322 }
1323
1324 fn as_typed_shape(&self) -> TypedShape<'_> {
1325 TypedShape::ConvexPolyhedron(self)
1326 }
1327
1328 fn ccd_thickness(&self) -> Real {
1329 self.compute_local_aabb().half_extents().min()
1331 }
1332
1333 fn ccd_angular_thickness(&self) -> Real {
1334 Real::frac_pi_4()
1337 }
1338
1339 fn as_support_map(&self) -> Option<&dyn SupportMap> {
1340 Some(self as &dyn SupportMap)
1341 }
1342
1343 fn as_polygonal_feature_map(&self) -> Option<(&dyn PolygonalFeatureMap, Real)> {
1344 Some((self as &dyn PolygonalFeatureMap, 0.0))
1345 }
1346
1347 fn feature_normal_at_point(
1348 &self,
1349 feature: FeatureId,
1350 _point: &Point<Real>,
1351 ) -> Option<Unit<Vector<Real>>> {
1352 self.feature_normal(feature)
1353 }
1354}
1355
1356#[cfg(feature = "dim3")]
1357impl Shape for Cylinder {
1358 #[cfg(feature = "alloc")]
1359 fn clone_dyn(&self) -> Box<dyn Shape> {
1360 Box::new(*self)
1361 }
1362
1363 #[cfg(feature = "alloc")]
1364 fn scale_dyn(&self, scale: &Vector<Real>, num_subdivisions: u32) -> Option<Box<dyn Shape>> {
1365 let scaled = self.scaled(scale, num_subdivisions)?;
1366 Some(scaled.either::<_, _, Box<dyn Shape>>(|x| Box::new(x), |x| Box::new(x)))
1367 }
1368
1369 fn compute_local_aabb(&self) -> Aabb {
1370 self.local_aabb()
1371 }
1372
1373 fn compute_local_bounding_sphere(&self) -> BoundingSphere {
1374 self.local_bounding_sphere()
1375 }
1376
1377 fn compute_aabb(&self, position: &Isometry<Real>) -> Aabb {
1378 self.aabb(position)
1379 }
1380
1381 fn mass_properties(&self, density: Real) -> MassProperties {
1382 MassProperties::from_cylinder(density, self.half_height, self.radius)
1383 }
1384
1385 fn is_convex(&self) -> bool {
1386 true
1387 }
1388
1389 fn shape_type(&self) -> ShapeType {
1390 ShapeType::Cylinder
1391 }
1392
1393 fn as_typed_shape(&self) -> TypedShape<'_> {
1394 TypedShape::Cylinder(self)
1395 }
1396
1397 fn ccd_thickness(&self) -> Real {
1398 self.radius
1399 }
1400
1401 fn ccd_angular_thickness(&self) -> Real {
1402 Real::frac_pi_2()
1403 }
1404
1405 fn as_support_map(&self) -> Option<&dyn SupportMap> {
1406 Some(self as &dyn SupportMap)
1407 }
1408
1409 fn as_polygonal_feature_map(&self) -> Option<(&dyn PolygonalFeatureMap, Real)> {
1410 Some((self as &dyn PolygonalFeatureMap, 0.0))
1411 }
1412}
1413
1414#[cfg(feature = "dim3")]
1415impl Shape for Cone {
1416 #[cfg(feature = "alloc")]
1417 fn clone_dyn(&self) -> Box<dyn Shape> {
1418 Box::new(*self)
1419 }
1420
1421 #[cfg(feature = "alloc")]
1422 fn scale_dyn(&self, scale: &Vector<Real>, num_subdivisions: u32) -> Option<Box<dyn Shape>> {
1423 let scaled = self.scaled(scale, num_subdivisions)?;
1424 Some(scaled.either::<_, _, Box<dyn Shape>>(|x| Box::new(x), |x| Box::new(x)))
1425 }
1426
1427 fn compute_local_aabb(&self) -> Aabb {
1428 self.local_aabb()
1429 }
1430
1431 fn compute_local_bounding_sphere(&self) -> BoundingSphere {
1432 self.local_bounding_sphere()
1433 }
1434
1435 fn compute_aabb(&self, position: &Isometry<Real>) -> Aabb {
1436 self.aabb(position)
1437 }
1438
1439 fn mass_properties(&self, density: Real) -> MassProperties {
1440 MassProperties::from_cone(density, self.half_height, self.radius)
1441 }
1442
1443 fn is_convex(&self) -> bool {
1444 true
1445 }
1446
1447 fn shape_type(&self) -> ShapeType {
1448 ShapeType::Cone
1449 }
1450
1451 fn as_typed_shape(&self) -> TypedShape<'_> {
1452 TypedShape::Cone(self)
1453 }
1454
1455 fn ccd_thickness(&self) -> Real {
1456 self.radius
1457 }
1458
1459 fn ccd_angular_thickness(&self) -> Real {
1460 let apex_half_angle = RealField::atan2(self.radius, self.half_height);
1461 assert!(apex_half_angle >= 0.0);
1462 let basis_angle = Real::frac_pi_2() - apex_half_angle;
1463 basis_angle.min(apex_half_angle * 2.0)
1464 }
1465
1466 fn as_support_map(&self) -> Option<&dyn SupportMap> {
1467 Some(self as &dyn SupportMap)
1468 }
1469
1470 fn as_polygonal_feature_map(&self) -> Option<(&dyn PolygonalFeatureMap, Real)> {
1471 Some((self as &dyn PolygonalFeatureMap, 0.0))
1472 }
1473}
1474
1475impl Shape for HalfSpace {
1476 #[cfg(feature = "alloc")]
1477 fn clone_dyn(&self) -> Box<dyn Shape> {
1478 Box::new(*self)
1479 }
1480
1481 #[cfg(feature = "alloc")]
1482 fn scale_dyn(&self, scale: &Vector<Real>, _num_subdivisions: u32) -> Option<Box<dyn Shape>> {
1483 Some(Box::new(self.scaled(scale)?))
1484 }
1485
1486 fn compute_local_aabb(&self) -> Aabb {
1487 self.local_aabb()
1488 }
1489
1490 fn compute_local_bounding_sphere(&self) -> BoundingSphere {
1491 self.local_bounding_sphere()
1492 }
1493
1494 fn compute_aabb(&self, position: &Isometry<Real>) -> Aabb {
1495 self.aabb(position)
1496 }
1497
1498 fn is_convex(&self) -> bool {
1499 true
1500 }
1501
1502 fn ccd_thickness(&self) -> Real {
1503 #[cfg_attr(feature = "f32", expect(clippy::unnecessary_cast))]
1504 let result = f32::MAX as Real;
1505 result
1506 }
1507
1508 fn ccd_angular_thickness(&self) -> Real {
1509 Real::pi()
1510 }
1511
1512 fn mass_properties(&self, _: Real) -> MassProperties {
1513 MassProperties::zero()
1514 }
1515
1516 fn shape_type(&self) -> ShapeType {
1517 ShapeType::HalfSpace
1518 }
1519
1520 fn as_typed_shape(&self) -> TypedShape<'_> {
1521 TypedShape::HalfSpace(self)
1522 }
1523}
1524
1525#[cfg(feature = "alloc")]
1526impl Shape for Voxels {
1527 fn compute_local_aabb(&self) -> Aabb {
1528 self.local_aabb()
1529 }
1530
1531 fn compute_local_bounding_sphere(&self) -> BoundingSphere {
1532 self.local_bounding_sphere()
1533 }
1534
1535 fn clone_dyn(&self) -> Box<dyn Shape> {
1536 Box::new(self.clone())
1537 }
1538
1539 fn scale_dyn(&self, scale: &Vector<Real>, _num_subdivisions: u32) -> Option<Box<dyn Shape>> {
1540 Some(Box::new(self.clone().scaled(scale)))
1541 }
1542
1543 fn mass_properties(&self, density: Real) -> MassProperties {
1544 MassProperties::from_voxels(density, self)
1545 }
1546
1547 fn shape_type(&self) -> ShapeType {
1548 ShapeType::Voxels
1549 }
1550
1551 fn as_typed_shape(&self) -> TypedShape<'_> {
1552 TypedShape::Voxels(self)
1553 }
1554
1555 fn ccd_thickness(&self) -> Real {
1556 self.voxel_size().min()
1557 }
1558
1559 fn ccd_angular_thickness(&self) -> Real {
1560 Real::frac_pi_2()
1561 }
1562}
1563
1564macro_rules! impl_shape_for_round_shape(
1565 ($S: ty, $Tag: ident, $t: tt) => {
1566 impl Shape for RoundShape<$S> {
1567 #[cfg(feature = "alloc")]
1568 fn clone_dyn(&self) -> Box<dyn Shape> {
1569 Box::new(self.clone())
1570 }
1571
1572 #[cfg(feature = "alloc")]
1573 fn scale_dyn(&self, scale: &Vector<Real>, num_subdivisions: u32) -> Option<Box<dyn Shape>> {
1574 $t(self, scale, num_subdivisions)
1575 }
1576
1577 fn compute_local_aabb(&self) -> Aabb {
1578 self.inner_shape.local_aabb().loosened(self.border_radius)
1579 }
1580
1581 fn compute_local_bounding_sphere(&self) -> BoundingSphere {
1582 self.inner_shape.local_bounding_sphere().loosened(self.border_radius)
1583 }
1584
1585 fn compute_aabb(&self, position: &Isometry<Real>) -> Aabb {
1586 self.inner_shape.aabb(position).loosened(self.border_radius)
1587 }
1588
1589 fn mass_properties(&self, density: Real) -> MassProperties {
1590 self.inner_shape.mass_properties(density)
1591 }
1592
1593 fn is_convex(&self) -> bool {
1594 self.inner_shape.is_convex()
1595 }
1596
1597 fn shape_type(&self) -> ShapeType {
1598 ShapeType::$Tag
1599 }
1600
1601 fn as_typed_shape(&self) -> TypedShape<'_> {
1602 TypedShape::$Tag(self)
1603 }
1604
1605 fn ccd_thickness(&self) -> Real {
1606 self.inner_shape.ccd_thickness() + self.border_radius
1607 }
1608
1609 fn ccd_angular_thickness(&self) -> Real {
1610 self.inner_shape.ccd_angular_thickness()
1613 }
1614
1615 fn as_support_map(&self) -> Option<&dyn SupportMap> {
1616 Some(self as &dyn SupportMap)
1617 }
1618
1619 fn as_polygonal_feature_map(&self) -> Option<(&dyn PolygonalFeatureMap, Real)> {
1620 Some((&self.inner_shape as &dyn PolygonalFeatureMap, self.border_radius))
1621 }
1622 }
1623 }
1624);
1625
1626impl_shape_for_round_shape!(
1627 Cuboid,
1628 RoundCuboid,
1629 (|this: &Self, scale: &Vector<Real>, _num_subdivisions: u32| {
1630 let shape = RoundShape {
1631 border_radius: this.border_radius,
1632 inner_shape: this.inner_shape.scaled(scale),
1633 };
1634 Some(Box::new(shape) as Box<dyn Shape>)
1635 })
1636);
1637
1638impl_shape_for_round_shape!(
1639 Triangle,
1640 RoundTriangle,
1641 (|this: &Self, scale: &Vector<Real>, _num_subdivisions: u32| {
1642 let shape = RoundShape {
1643 border_radius: this.border_radius,
1644 inner_shape: this.inner_shape.scaled(scale),
1645 };
1646 Some(Box::new(shape) as Box<dyn Shape>)
1647 })
1648);
1649
1650#[cfg(feature = "dim2")]
1651#[cfg(feature = "alloc")]
1652impl_shape_for_round_shape!(
1653 ConvexPolygon,
1654 RoundConvexPolygon,
1655 (|this: &Self, scale: &Vector<Real>, _num_subdivisions: u32| {
1656 let shape = RoundShape {
1657 border_radius: this.border_radius,
1658 inner_shape: this.inner_shape.clone().scaled(scale)?,
1659 };
1660 Some(Box::new(shape) as Box<dyn Shape>)
1661 })
1662);
1663
1664#[cfg(feature = "dim3")]
1665impl_shape_for_round_shape!(
1666 Cylinder,
1667 RoundCylinder,
1668 (|this: &Self, scale: &Vector<Real>, num_subdivisions: u32| {
1669 Some(
1670 this.inner_shape
1671 .scaled(scale, num_subdivisions)?
1672 .either::<_, _, Box<dyn Shape>>(
1673 |inner_shape| {
1674 Box::new(RoundShape {
1675 border_radius: this.border_radius,
1676 inner_shape,
1677 })
1678 },
1679 |inner_shape| {
1680 Box::new(RoundShape {
1681 border_radius: this.border_radius,
1682 inner_shape,
1683 })
1684 },
1685 ),
1686 )
1687 })
1688);
1689#[cfg(feature = "dim3")]
1690impl_shape_for_round_shape!(
1691 Cone,
1692 RoundCone,
1693 (|this: &Self, scale: &Vector<Real>, num_subdivisions: u32| {
1694 Some(
1695 this.inner_shape
1696 .scaled(scale, num_subdivisions)?
1697 .either::<_, _, Box<dyn Shape>>(
1698 |inner_shape| {
1699 Box::new(RoundShape {
1700 border_radius: this.border_radius,
1701 inner_shape,
1702 })
1703 },
1704 |inner_shape| {
1705 Box::new(RoundShape {
1706 border_radius: this.border_radius,
1707 inner_shape,
1708 })
1709 },
1710 ),
1711 )
1712 })
1713);
1714
1715#[cfg(feature = "dim3")]
1716#[cfg(feature = "alloc")]
1717impl_shape_for_round_shape!(
1718 ConvexPolyhedron,
1719 RoundConvexPolyhedron,
1720 (|this: &Self, scale: &Vector<Real>, _num_subdivisions: u32| {
1721 let shape = RoundShape {
1722 border_radius: this.border_radius,
1723 inner_shape: this.inner_shape.clone().scaled(scale)?,
1724 };
1725 Some(Box::new(shape) as Box<dyn Shape>)
1726 })
1727);