use core::fmt::Debug;
use crate::bounding_volume::{Aabb, BoundingSphere, BoundingVolume};
use crate::mass_properties::MassProperties;
use crate::math::{Isometry, Point, Real, Vector};
#[cfg(not(feature = "std"))]
use crate::num::Float;
use crate::query::{PointQuery, RayCast};
#[cfg(feature = "serde-serialize")]
use crate::shape::SharedShape;
#[cfg(feature = "std")]
use crate::shape::{composite_shape::SimdCompositeShape, Compound, HeightField, Polyline, TriMesh};
use crate::shape::{
Ball, Capsule, Cuboid, FeatureId, HalfSpace, PolygonalFeatureMap, RoundCuboid, RoundShape,
RoundTriangle, Segment, SupportMap, Triangle,
};
#[cfg(feature = "dim3")]
use crate::shape::{Cone, Cylinder, RoundCone, RoundCylinder};
#[cfg(feature = "dim3")]
#[cfg(feature = "std")]
use crate::shape::{ConvexPolyhedron, RoundConvexPolyhedron};
#[cfg(feature = "dim2")]
#[cfg(feature = "std")]
use crate::shape::{ConvexPolygon, RoundConvexPolygon};
use downcast_rs::{impl_downcast, DowncastSync};
use na::{RealField, Unit};
use num::Zero;
use num_derive::FromPrimitive;
#[derive(Copy, Clone, Debug, FromPrimitive, PartialEq, Eq, Hash)]
pub enum ShapeType {
Ball = 0,
Cuboid,
Capsule,
Segment,
Triangle,
TriMesh,
Polyline,
HalfSpace,
HeightField,
Compound,
#[cfg(feature = "dim2")]
ConvexPolygon,
#[cfg(feature = "dim3")]
ConvexPolyhedron,
#[cfg(feature = "dim3")]
Cylinder,
#[cfg(feature = "dim3")]
Cone,
RoundCuboid,
RoundTriangle,
#[cfg(feature = "dim3")]
RoundCylinder,
#[cfg(feature = "dim3")]
RoundCone,
#[cfg(feature = "dim3")]
RoundConvexPolyhedron,
#[cfg(feature = "dim2")]
RoundConvexPolygon,
Custom,
}
#[derive(Copy, Clone)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize))]
pub enum TypedShape<'a> {
Ball(&'a Ball),
Cuboid(&'a Cuboid),
Capsule(&'a Capsule),
Segment(&'a Segment),
Triangle(&'a Triangle),
#[cfg(feature = "std")]
TriMesh(&'a TriMesh),
#[cfg(feature = "std")]
Polyline(&'a Polyline),
HalfSpace(&'a HalfSpace),
#[cfg(feature = "std")]
HeightField(&'a HeightField),
#[cfg(feature = "std")]
Compound(&'a Compound),
#[cfg(feature = "dim2")]
#[cfg(feature = "std")]
ConvexPolygon(&'a ConvexPolygon),
#[cfg(feature = "dim3")]
#[cfg(feature = "std")]
ConvexPolyhedron(&'a ConvexPolyhedron),
#[cfg(feature = "dim3")]
Cylinder(&'a Cylinder),
#[cfg(feature = "dim3")]
Cone(&'a Cone),
RoundCuboid(&'a RoundCuboid),
RoundTriangle(&'a RoundTriangle),
#[cfg(feature = "dim3")]
RoundCylinder(&'a RoundCylinder),
#[cfg(feature = "dim3")]
RoundCone(&'a RoundCone),
#[cfg(feature = "dim3")]
#[cfg(feature = "std")]
RoundConvexPolyhedron(&'a RoundConvexPolyhedron),
#[cfg(feature = "dim2")]
#[cfg(feature = "std")]
RoundConvexPolygon(&'a RoundConvexPolygon),
#[cfg_attr(feature = "serde-serialize", serde(skip))]
Custom(&'a dyn Shape),
}
impl Debug for TypedShape<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::Ball(arg0) => f.debug_tuple("Ball").field(arg0).finish(),
Self::Cuboid(arg0) => f.debug_tuple("Cuboid").field(arg0).finish(),
Self::Capsule(arg0) => f.debug_tuple("Capsule").field(arg0).finish(),
Self::Segment(arg0) => f.debug_tuple("Segment").field(arg0).finish(),
Self::Triangle(arg0) => f.debug_tuple("Triangle").field(arg0).finish(),
#[cfg(feature = "std")]
Self::TriMesh(arg0) => f.debug_tuple("TriMesh").field(arg0).finish(),
#[cfg(feature = "std")]
Self::Polyline(arg0) => f.debug_tuple("Polyline").field(arg0).finish(),
Self::HalfSpace(arg0) => f.debug_tuple("HalfSpace").field(arg0).finish(),
#[cfg(feature = "std")]
Self::HeightField(arg0) => f.debug_tuple("HeightField").field(arg0).finish(),
#[cfg(feature = "std")]
Self::Compound(arg0) => f.debug_tuple("Compound").field(arg0).finish(),
#[cfg(feature = "dim2")]
#[cfg(feature = "std")]
Self::ConvexPolygon(arg0) => f.debug_tuple("ConvexPolygon").field(arg0).finish(),
#[cfg(feature = "dim3")]
#[cfg(feature = "std")]
Self::ConvexPolyhedron(arg0) => f.debug_tuple("ConvexPolyhedron").field(arg0).finish(),
#[cfg(feature = "dim3")]
Self::Cylinder(arg0) => f.debug_tuple("Cylinder").field(arg0).finish(),
#[cfg(feature = "dim3")]
Self::Cone(arg0) => f.debug_tuple("Cone").field(arg0).finish(),
Self::RoundCuboid(arg0) => f.debug_tuple("RoundCuboid").field(arg0).finish(),
Self::RoundTriangle(arg0) => f.debug_tuple("RoundTriangle").field(arg0).finish(),
#[cfg(feature = "dim3")]
Self::RoundCylinder(arg0) => f.debug_tuple("RoundCylinder").field(arg0).finish(),
#[cfg(feature = "dim3")]
Self::RoundCone(arg0) => f.debug_tuple("RoundCone").field(arg0).finish(),
#[cfg(feature = "dim3")]
#[cfg(feature = "std")]
Self::RoundConvexPolyhedron(arg0) => {
f.debug_tuple("RoundConvexPolyhedron").field(arg0).finish()
}
#[cfg(feature = "dim2")]
#[cfg(feature = "std")]
Self::RoundConvexPolygon(arg0) => {
f.debug_tuple("RoundConvexPolygon").field(arg0).finish()
}
Self::Custom(_) => f.debug_tuple("Custom").finish(),
}
}
}
#[cfg(feature = "serde-serialize")]
#[derive(Deserialize)]
pub(crate) enum DeserializableTypedShape {
Ball(Ball),
Cuboid(Cuboid),
Capsule(Capsule),
Segment(Segment),
Triangle(Triangle),
#[cfg(feature = "std")]
TriMesh(TriMesh),
#[cfg(feature = "std")]
Polyline(Polyline),
HalfSpace(HalfSpace),
#[cfg(feature = "std")]
HeightField(HeightField),
#[cfg(feature = "std")]
Compound(Compound),
#[cfg(feature = "dim2")]
#[cfg(feature = "std")]
ConvexPolygon(ConvexPolygon),
#[cfg(feature = "dim3")]
#[cfg(feature = "std")]
ConvexPolyhedron(ConvexPolyhedron),
#[cfg(feature = "dim3")]
Cylinder(Cylinder),
#[cfg(feature = "dim3")]
Cone(Cone),
RoundCuboid(RoundCuboid),
RoundTriangle(RoundTriangle),
#[cfg(feature = "dim3")]
RoundCylinder(RoundCylinder),
#[cfg(feature = "dim3")]
RoundCone(RoundCone),
#[cfg(feature = "dim3")]
#[cfg(feature = "std")]
RoundConvexPolyhedron(RoundConvexPolyhedron),
#[cfg(feature = "dim2")]
#[cfg(feature = "std")]
RoundConvexPolygon(RoundConvexPolygon),
#[allow(dead_code)]
Custom,
}
#[cfg(feature = "serde-serialize")]
impl DeserializableTypedShape {
pub fn into_shared_shape(self) -> Option<SharedShape> {
match self {
DeserializableTypedShape::Ball(s) => Some(SharedShape::new(s)),
DeserializableTypedShape::Cuboid(s) => Some(SharedShape::new(s)),
DeserializableTypedShape::Capsule(s) => Some(SharedShape::new(s)),
DeserializableTypedShape::Segment(s) => Some(SharedShape::new(s)),
DeserializableTypedShape::Triangle(s) => Some(SharedShape::new(s)),
#[cfg(feature = "std")]
DeserializableTypedShape::TriMesh(s) => Some(SharedShape::new(s)),
#[cfg(feature = "std")]
DeserializableTypedShape::Polyline(s) => Some(SharedShape::new(s)),
DeserializableTypedShape::HalfSpace(s) => Some(SharedShape::new(s)),
#[cfg(feature = "std")]
DeserializableTypedShape::HeightField(s) => Some(SharedShape::new(s)),
#[cfg(feature = "std")]
DeserializableTypedShape::Compound(s) => Some(SharedShape::new(s)),
#[cfg(feature = "dim2")]
#[cfg(feature = "std")]
DeserializableTypedShape::ConvexPolygon(s) => Some(SharedShape::new(s)),
#[cfg(feature = "dim3")]
#[cfg(feature = "std")]
DeserializableTypedShape::ConvexPolyhedron(s) => Some(SharedShape::new(s)),
#[cfg(feature = "dim3")]
DeserializableTypedShape::Cylinder(s) => Some(SharedShape::new(s)),
#[cfg(feature = "dim3")]
DeserializableTypedShape::Cone(s) => Some(SharedShape::new(s)),
DeserializableTypedShape::RoundCuboid(s) => Some(SharedShape::new(s)),
DeserializableTypedShape::RoundTriangle(s) => Some(SharedShape::new(s)),
#[cfg(feature = "dim3")]
DeserializableTypedShape::RoundCylinder(s) => Some(SharedShape::new(s)),
#[cfg(feature = "dim3")]
DeserializableTypedShape::RoundCone(s) => Some(SharedShape::new(s)),
#[cfg(feature = "dim3")]
#[cfg(feature = "std")]
DeserializableTypedShape::RoundConvexPolyhedron(s) => Some(SharedShape::new(s)),
#[cfg(feature = "dim2")]
#[cfg(feature = "std")]
DeserializableTypedShape::RoundConvexPolygon(s) => Some(SharedShape::new(s)),
DeserializableTypedShape::Custom => None,
}
}
}
pub trait Shape: RayCast + PointQuery + DowncastSync {
fn compute_local_aabb(&self) -> Aabb;
fn compute_local_bounding_sphere(&self) -> BoundingSphere;
#[cfg(feature = "std")]
#[deprecated = "renamed to `clone_dyn`"]
fn clone_box(&self) -> Box<dyn Shape> {
self.clone_dyn()
}
#[cfg(feature = "std")]
fn clone_dyn(&self) -> Box<dyn Shape>;
#[cfg(feature = "std")]
fn scale_dyn(&self, scale: &Vector<Real>, num_subdivisions: u32) -> Option<Box<dyn Shape>>;
fn compute_aabb(&self, position: &Isometry<Real>) -> Aabb {
self.compute_local_aabb().transform_by(position)
}
fn compute_bounding_sphere(&self, position: &Isometry<Real>) -> BoundingSphere {
self.compute_local_bounding_sphere().transform_by(position)
}
fn mass_properties(&self, density: Real) -> MassProperties;
fn shape_type(&self) -> ShapeType;
fn as_typed_shape(&self) -> TypedShape;
fn ccd_thickness(&self) -> Real;
fn ccd_angular_thickness(&self) -> Real;
fn is_convex(&self) -> bool {
false
}
fn as_support_map(&self) -> Option<&dyn SupportMap> {
None
}
#[cfg(feature = "std")]
fn as_composite_shape(&self) -> Option<&dyn SimdCompositeShape> {
None
}
fn as_polygonal_feature_map(&self) -> Option<(&dyn PolygonalFeatureMap, Real)> {
None
}
fn feature_normal_at_point(
&self,
_feature: FeatureId,
_point: &Point<Real>,
) -> Option<Unit<Vector<Real>>> {
None
}
fn compute_swept_aabb(&self, start_pos: &Isometry<Real>, end_pos: &Isometry<Real>) -> Aabb {
let aabb1 = self.compute_aabb(start_pos);
let aabb2 = self.compute_aabb(end_pos);
aabb1.merged(&aabb2)
}
}
impl_downcast!(sync Shape);
impl dyn Shape {
pub fn as_shape<T: Shape>(&self) -> Option<&T> {
self.downcast_ref()
}
pub fn as_shape_mut<T: Shape>(&mut self) -> Option<&mut T> {
self.downcast_mut()
}
pub fn as_ball(&self) -> Option<&Ball> {
self.downcast_ref()
}
pub fn as_ball_mut(&mut self) -> Option<&mut Ball> {
self.downcast_mut()
}
pub fn as_cuboid(&self) -> Option<&Cuboid> {
self.downcast_ref()
}
pub fn as_cuboid_mut(&mut self) -> Option<&mut Cuboid> {
self.downcast_mut()
}
pub fn as_halfspace(&self) -> Option<&HalfSpace> {
self.downcast_ref()
}
pub fn as_halfspace_mut(&mut self) -> Option<&mut HalfSpace> {
self.downcast_mut()
}
pub fn as_segment(&self) -> Option<&Segment> {
self.downcast_ref()
}
pub fn as_segment_mut(&mut self) -> Option<&mut Segment> {
self.downcast_mut()
}
pub fn as_capsule(&self) -> Option<&Capsule> {
self.downcast_ref()
}
pub fn as_capsule_mut(&mut self) -> Option<&mut Capsule> {
self.downcast_mut()
}
pub fn as_triangle(&self) -> Option<&Triangle> {
self.downcast_ref()
}
pub fn as_triangle_mut(&mut self) -> Option<&mut Triangle> {
self.downcast_mut()
}
#[cfg(feature = "std")]
pub fn as_compound(&self) -> Option<&Compound> {
self.downcast_ref()
}
#[cfg(feature = "std")]
pub fn as_compound_mut(&mut self) -> Option<&mut Compound> {
self.downcast_mut()
}
#[cfg(feature = "std")]
pub fn as_trimesh(&self) -> Option<&TriMesh> {
self.downcast_ref()
}
#[cfg(feature = "std")]
pub fn as_trimesh_mut(&mut self) -> Option<&mut TriMesh> {
self.downcast_mut()
}
#[cfg(feature = "std")]
pub fn as_polyline(&self) -> Option<&Polyline> {
self.downcast_ref()
}
#[cfg(feature = "std")]
pub fn as_polyline_mut(&mut self) -> Option<&mut Polyline> {
self.downcast_mut()
}
#[cfg(feature = "std")]
pub fn as_heightfield(&self) -> Option<&HeightField> {
self.downcast_ref()
}
#[cfg(feature = "std")]
pub fn as_heightfield_mut(&mut self) -> Option<&mut HeightField> {
self.downcast_mut()
}
pub fn as_round_cuboid(&self) -> Option<&RoundCuboid> {
self.downcast_ref()
}
pub fn as_round_cuboid_mut(&mut self) -> Option<&mut RoundCuboid> {
self.downcast_mut()
}
pub fn as_round_triangle(&self) -> Option<&RoundTriangle> {
self.downcast_ref()
}
pub fn as_round_triangle_mut(&mut self) -> Option<&mut RoundTriangle> {
self.downcast_mut()
}
#[cfg(feature = "dim2")]
#[cfg(feature = "std")]
pub fn as_convex_polygon(&self) -> Option<&ConvexPolygon> {
self.downcast_ref()
}
#[cfg(feature = "dim2")]
#[cfg(feature = "std")]
pub fn as_convex_polygon_mut(&mut self) -> Option<&mut ConvexPolygon> {
self.downcast_mut()
}
#[cfg(feature = "dim2")]
#[cfg(feature = "std")]
pub fn as_round_convex_polygon(&self) -> Option<&RoundConvexPolygon> {
self.downcast_ref()
}
#[cfg(feature = "dim2")]
#[cfg(feature = "std")]
pub fn as_round_convex_polygon_mut(&mut self) -> Option<&mut RoundConvexPolygon> {
self.downcast_mut()
}
#[cfg(feature = "dim3")]
#[cfg(feature = "std")]
pub fn as_convex_polyhedron(&self) -> Option<&ConvexPolyhedron> {
self.downcast_ref()
}
#[cfg(feature = "dim3")]
#[cfg(feature = "std")]
pub fn as_convex_polyhedron_mut(&mut self) -> Option<&mut ConvexPolyhedron> {
self.downcast_mut()
}
#[cfg(feature = "dim3")]
pub fn as_cylinder(&self) -> Option<&Cylinder> {
self.downcast_ref()
}
#[cfg(feature = "dim3")]
pub fn as_cylinder_mut(&mut self) -> Option<&mut Cylinder> {
self.downcast_mut()
}
#[cfg(feature = "dim3")]
pub fn as_cone(&self) -> Option<&Cone> {
self.downcast_ref()
}
#[cfg(feature = "dim3")]
pub fn as_cone_mut(&mut self) -> Option<&mut Cone> {
self.downcast_mut()
}
#[cfg(feature = "dim3")]
pub fn as_round_cylinder(&self) -> Option<&RoundCylinder> {
self.downcast_ref()
}
#[cfg(feature = "dim3")]
pub fn as_round_cylinder_mut(&mut self) -> Option<&mut RoundCylinder> {
self.downcast_mut()
}
#[cfg(feature = "dim3")]
pub fn as_round_cone(&self) -> Option<&RoundCone> {
self.downcast_ref()
}
#[cfg(feature = "dim3")]
pub fn as_round_cone_mut(&mut self) -> Option<&mut RoundCone> {
self.downcast_mut()
}
#[cfg(feature = "dim3")]
#[cfg(feature = "std")]
pub fn as_round_convex_polyhedron(&self) -> Option<&RoundConvexPolyhedron> {
self.downcast_ref()
}
#[cfg(feature = "dim3")]
#[cfg(feature = "std")]
pub fn as_round_convex_polyhedron_mut(&mut self) -> Option<&mut RoundConvexPolyhedron> {
self.downcast_mut()
}
}
impl Shape for Ball {
#[cfg(feature = "std")]
fn clone_dyn(&self) -> Box<dyn Shape> {
Box::new(*self)
}
#[cfg(feature = "std")]
fn scale_dyn(&self, scale: &Vector<Real>, num_subdivisions: u32) -> Option<Box<dyn Shape>> {
let scaled = self.scaled(scale, num_subdivisions)?;
Some(scaled.either::<_, _, Box<dyn Shape>>(|x| Box::new(x), |x| Box::new(x)))
}
fn compute_local_aabb(&self) -> Aabb {
self.local_aabb()
}
fn compute_local_bounding_sphere(&self) -> BoundingSphere {
self.local_bounding_sphere()
}
fn compute_aabb(&self, position: &Isometry<Real>) -> Aabb {
self.aabb(position)
}
fn mass_properties(&self, density: Real) -> MassProperties {
MassProperties::from_ball(density, self.radius)
}
fn ccd_thickness(&self) -> Real {
self.radius
}
fn ccd_angular_thickness(&self) -> Real {
Real::pi()
}
fn is_convex(&self) -> bool {
true
}
fn shape_type(&self) -> ShapeType {
ShapeType::Ball
}
fn as_typed_shape(&self) -> TypedShape {
TypedShape::Ball(self)
}
fn as_support_map(&self) -> Option<&dyn SupportMap> {
Some(self as &dyn SupportMap)
}
#[inline]
fn feature_normal_at_point(
&self,
_: FeatureId,
point: &Point<Real>,
) -> Option<Unit<Vector<Real>>> {
Unit::try_new(point.coords, crate::math::DEFAULT_EPSILON)
}
}
impl Shape for Cuboid {
#[cfg(feature = "std")]
fn clone_dyn(&self) -> Box<dyn Shape> {
Box::new(*self)
}
#[cfg(feature = "std")]
fn scale_dyn(&self, scale: &Vector<Real>, _num_subdivisions: u32) -> Option<Box<dyn Shape>> {
Some(Box::new(self.scaled(scale)))
}
fn compute_local_aabb(&self) -> Aabb {
self.local_aabb()
}
fn compute_local_bounding_sphere(&self) -> BoundingSphere {
self.local_bounding_sphere()
}
fn compute_aabb(&self, position: &Isometry<Real>) -> Aabb {
self.aabb(position)
}
fn mass_properties(&self, density: Real) -> MassProperties {
MassProperties::from_cuboid(density, self.half_extents)
}
fn is_convex(&self) -> bool {
true
}
fn shape_type(&self) -> ShapeType {
ShapeType::Cuboid
}
fn as_typed_shape(&self) -> TypedShape {
TypedShape::Cuboid(self)
}
fn ccd_thickness(&self) -> Real {
self.half_extents.min()
}
fn ccd_angular_thickness(&self) -> Real {
Real::frac_pi_2()
}
fn as_support_map(&self) -> Option<&dyn SupportMap> {
Some(self as &dyn SupportMap)
}
fn as_polygonal_feature_map(&self) -> Option<(&dyn PolygonalFeatureMap, Real)> {
Some((self as &dyn PolygonalFeatureMap, 0.0))
}
fn feature_normal_at_point(
&self,
feature: FeatureId,
_point: &Point<Real>,
) -> Option<Unit<Vector<Real>>> {
self.feature_normal(feature)
}
}
impl Shape for Capsule {
#[cfg(feature = "std")]
fn clone_dyn(&self) -> Box<dyn Shape> {
Box::new(*self)
}
#[cfg(feature = "std")]
fn scale_dyn(&self, scale: &Vector<Real>, num_subdivisions: u32) -> Option<Box<dyn Shape>> {
let scaled = self.scaled(scale, num_subdivisions)?;
Some(scaled.either::<_, _, Box<dyn Shape>>(|x| Box::new(x), |x| Box::new(x)))
}
fn compute_local_aabb(&self) -> Aabb {
self.local_aabb()
}
fn compute_local_bounding_sphere(&self) -> BoundingSphere {
self.local_bounding_sphere()
}
fn compute_aabb(&self, position: &Isometry<Real>) -> Aabb {
self.aabb(position)
}
fn mass_properties(&self, density: Real) -> MassProperties {
MassProperties::from_capsule(density, self.segment.a, self.segment.b, self.radius)
}
fn is_convex(&self) -> bool {
true
}
fn shape_type(&self) -> ShapeType {
ShapeType::Capsule
}
fn as_typed_shape(&self) -> TypedShape {
TypedShape::Capsule(self)
}
fn ccd_thickness(&self) -> Real {
self.radius
}
fn ccd_angular_thickness(&self) -> Real {
Real::frac_pi_2()
}
fn as_support_map(&self) -> Option<&dyn SupportMap> {
Some(self as &dyn SupportMap)
}
fn as_polygonal_feature_map(&self) -> Option<(&dyn PolygonalFeatureMap, Real)> {
Some((&self.segment as &dyn PolygonalFeatureMap, self.radius))
}
}
impl Shape for Triangle {
#[cfg(feature = "std")]
fn clone_dyn(&self) -> Box<dyn Shape> {
Box::new(*self)
}
#[cfg(feature = "std")]
fn scale_dyn(&self, scale: &Vector<Real>, _num_subdivisions: u32) -> Option<Box<dyn Shape>> {
Some(Box::new(self.scaled(scale)))
}
fn compute_local_aabb(&self) -> Aabb {
self.local_aabb()
}
fn compute_local_bounding_sphere(&self) -> BoundingSphere {
self.local_bounding_sphere()
}
fn compute_aabb(&self, position: &Isometry<Real>) -> Aabb {
self.aabb(position)
}
fn mass_properties(&self, _density: Real) -> MassProperties {
#[cfg(feature = "dim2")]
return MassProperties::from_triangle(_density, &self.a, &self.b, &self.c);
#[cfg(feature = "dim3")]
return MassProperties::zero();
}
fn is_convex(&self) -> bool {
true
}
fn shape_type(&self) -> ShapeType {
ShapeType::Triangle
}
fn as_typed_shape(&self) -> TypedShape {
TypedShape::Triangle(self)
}
fn ccd_thickness(&self) -> Real {
0.0
}
fn ccd_angular_thickness(&self) -> Real {
Real::frac_pi_2()
}
fn as_support_map(&self) -> Option<&dyn SupportMap> {
Some(self as &dyn SupportMap)
}
fn as_polygonal_feature_map(&self) -> Option<(&dyn PolygonalFeatureMap, Real)> {
Some((self as &dyn PolygonalFeatureMap, 0.0))
}
fn feature_normal_at_point(
&self,
_feature: FeatureId,
_point: &Point<Real>,
) -> Option<Unit<Vector<Real>>> {
#[cfg(feature = "dim2")]
return None;
#[cfg(feature = "dim3")]
return self.feature_normal(_feature);
}
}
impl Shape for Segment {
#[cfg(feature = "std")]
fn clone_dyn(&self) -> Box<dyn Shape> {
Box::new(*self)
}
#[cfg(feature = "std")]
fn scale_dyn(&self, scale: &Vector<Real>, _num_subdivisions: u32) -> Option<Box<dyn Shape>> {
Some(Box::new(self.scaled(scale)))
}
fn compute_local_aabb(&self) -> Aabb {
self.local_aabb()
}
fn compute_local_bounding_sphere(&self) -> BoundingSphere {
self.local_bounding_sphere()
}
fn compute_aabb(&self, position: &Isometry<Real>) -> Aabb {
self.aabb(position)
}
fn mass_properties(&self, _density: Real) -> MassProperties {
MassProperties::zero()
}
fn is_convex(&self) -> bool {
true
}
fn ccd_thickness(&self) -> Real {
0.0
}
fn ccd_angular_thickness(&self) -> Real {
Real::frac_pi_2()
}
fn shape_type(&self) -> ShapeType {
ShapeType::Segment
}
fn as_typed_shape(&self) -> TypedShape {
TypedShape::Segment(self)
}
fn as_support_map(&self) -> Option<&dyn SupportMap> {
Some(self as &dyn SupportMap)
}
fn as_polygonal_feature_map(&self) -> Option<(&dyn PolygonalFeatureMap, Real)> {
Some((self as &dyn PolygonalFeatureMap, 0.0))
}
fn feature_normal_at_point(
&self,
feature: FeatureId,
_point: &Point<Real>,
) -> Option<Unit<Vector<Real>>> {
self.feature_normal(feature)
}
}
#[cfg(feature = "std")]
impl Shape for Compound {
fn clone_dyn(&self) -> Box<dyn Shape> {
Box::new(self.clone())
}
fn scale_dyn(&self, scale: &Vector<Real>, num_subdivisions: u32) -> Option<Box<dyn Shape>> {
use super::SharedShape;
let scaled: Vec<_> = self
.shapes()
.iter()
.map(|(pos, shape)| {
let scaled_shape = shape.scale_dyn(scale, num_subdivisions)?;
Some((
Isometry::from_parts(
(pos.translation.vector.component_mul(scale)).into(),
pos.rotation,
),
SharedShape(scaled_shape.into()),
))
})
.collect::<Option<Vec<_>>>()?;
Some(Box::new(Compound::new(scaled)))
}
fn compute_local_aabb(&self) -> Aabb {
*self.local_aabb()
}
fn compute_local_bounding_sphere(&self) -> BoundingSphere {
self.local_bounding_sphere()
}
fn compute_aabb(&self, position: &Isometry<Real>) -> Aabb {
self.local_aabb().transform_by(position)
}
fn mass_properties(&self, density: Real) -> MassProperties {
MassProperties::from_compound(density, self.shapes())
}
fn shape_type(&self) -> ShapeType {
ShapeType::Compound
}
fn as_typed_shape(&self) -> TypedShape {
TypedShape::Compound(self)
}
fn ccd_thickness(&self) -> Real {
self.shapes()
.iter()
.fold(Real::MAX, |curr, (_, s)| curr.min(s.ccd_thickness()))
}
fn ccd_angular_thickness(&self) -> Real {
self.shapes().iter().fold(Real::MAX, |curr, (_, s)| {
curr.max(s.ccd_angular_thickness())
})
}
#[cfg(feature = "std")]
fn as_composite_shape(&self) -> Option<&dyn SimdCompositeShape> {
Some(self as &dyn SimdCompositeShape)
}
}
#[cfg(feature = "std")]
impl Shape for Polyline {
fn clone_dyn(&self) -> Box<dyn Shape> {
Box::new(self.clone())
}
fn scale_dyn(&self, scale: &Vector<Real>, _num_subdivisions: u32) -> Option<Box<dyn Shape>> {
Some(Box::new(self.clone().scaled(scale)))
}
fn compute_local_aabb(&self) -> Aabb {
*self.local_aabb()
}
fn compute_local_bounding_sphere(&self) -> BoundingSphere {
self.local_bounding_sphere()
}
fn compute_aabb(&self, position: &Isometry<Real>) -> Aabb {
self.aabb(position)
}
fn mass_properties(&self, _density: Real) -> MassProperties {
MassProperties::zero()
}
fn shape_type(&self) -> ShapeType {
ShapeType::Polyline
}
fn as_typed_shape(&self) -> TypedShape {
TypedShape::Polyline(self)
}
fn ccd_thickness(&self) -> Real {
0.0
}
fn ccd_angular_thickness(&self) -> Real {
Real::frac_pi_4()
}
#[cfg(feature = "std")]
fn as_composite_shape(&self) -> Option<&dyn SimdCompositeShape> {
Some(self as &dyn SimdCompositeShape)
}
}
#[cfg(feature = "std")]
impl Shape for TriMesh {
fn clone_dyn(&self) -> Box<dyn Shape> {
Box::new(self.clone())
}
fn scale_dyn(&self, scale: &Vector<Real>, _num_subdivisions: u32) -> Option<Box<dyn Shape>> {
Some(Box::new(self.clone().scaled(scale)))
}
fn compute_local_aabb(&self) -> Aabb {
*self.local_aabb()
}
fn compute_local_bounding_sphere(&self) -> BoundingSphere {
self.local_bounding_sphere()
}
fn compute_aabb(&self, position: &Isometry<Real>) -> Aabb {
self.aabb(position)
}
fn mass_properties(&self, density: Real) -> MassProperties {
MassProperties::from_trimesh(density, self.vertices(), self.indices())
}
fn shape_type(&self) -> ShapeType {
ShapeType::TriMesh
}
fn as_typed_shape(&self) -> TypedShape {
TypedShape::TriMesh(self)
}
fn ccd_thickness(&self) -> Real {
0.0
}
fn ccd_angular_thickness(&self) -> Real {
Real::frac_pi_4()
}
fn feature_normal_at_point(
&self,
_feature: FeatureId,
_point: &Point<Real>,
) -> Option<Unit<Vector<Real>>> {
#[cfg(feature = "dim2")]
return None;
#[cfg(feature = "dim3")]
return self.feature_normal(_feature);
}
#[cfg(feature = "std")]
fn as_composite_shape(&self) -> Option<&dyn SimdCompositeShape> {
Some(self as &dyn SimdCompositeShape)
}
}
#[cfg(feature = "std")]
impl Shape for HeightField {
fn clone_dyn(&self) -> Box<dyn Shape> {
Box::new(self.clone())
}
fn scale_dyn(&self, scale: &Vector<Real>, _num_subdivisions: u32) -> Option<Box<dyn Shape>> {
Some(Box::new(self.clone().scaled(scale)))
}
fn compute_local_aabb(&self) -> Aabb {
self.local_aabb()
}
fn compute_local_bounding_sphere(&self) -> BoundingSphere {
self.local_bounding_sphere()
}
fn compute_aabb(&self, position: &Isometry<Real>) -> Aabb {
self.aabb(position)
}
fn mass_properties(&self, _density: Real) -> MassProperties {
MassProperties::zero()
}
fn shape_type(&self) -> ShapeType {
ShapeType::HeightField
}
fn as_typed_shape(&self) -> TypedShape {
TypedShape::HeightField(self)
}
fn ccd_thickness(&self) -> Real {
0.0
}
fn ccd_angular_thickness(&self) -> Real {
Real::frac_pi_4()
}
}
#[cfg(feature = "dim2")]
#[cfg(feature = "std")]
impl Shape for ConvexPolygon {
fn clone_dyn(&self) -> Box<dyn Shape> {
Box::new(self.clone())
}
fn scale_dyn(&self, scale: &Vector<Real>, _num_subdivisions: u32) -> Option<Box<dyn Shape>> {
Some(Box::new(self.clone().scaled(scale)?))
}
fn compute_local_aabb(&self) -> Aabb {
self.local_aabb()
}
fn compute_local_bounding_sphere(&self) -> BoundingSphere {
self.local_bounding_sphere()
}
fn compute_aabb(&self, position: &Isometry<Real>) -> Aabb {
self.aabb(position)
}
fn mass_properties(&self, density: Real) -> MassProperties {
MassProperties::from_convex_polygon(density, self.points())
}
fn is_convex(&self) -> bool {
true
}
fn shape_type(&self) -> ShapeType {
ShapeType::ConvexPolygon
}
fn as_typed_shape(&self) -> TypedShape {
TypedShape::ConvexPolygon(self)
}
fn ccd_thickness(&self) -> Real {
self.compute_local_aabb().half_extents().min()
}
fn ccd_angular_thickness(&self) -> Real {
Real::frac_pi_4()
}
fn as_support_map(&self) -> Option<&dyn SupportMap> {
Some(self as &dyn SupportMap)
}
fn as_polygonal_feature_map(&self) -> Option<(&dyn PolygonalFeatureMap, Real)> {
Some((self as &dyn PolygonalFeatureMap, 0.0))
}
fn feature_normal_at_point(
&self,
feature: FeatureId,
_point: &Point<Real>,
) -> Option<Unit<Vector<Real>>> {
self.feature_normal(feature)
}
}
#[cfg(feature = "dim3")]
#[cfg(feature = "std")]
impl Shape for ConvexPolyhedron {
fn clone_dyn(&self) -> Box<dyn Shape> {
Box::new(self.clone())
}
fn scale_dyn(&self, scale: &Vector<Real>, _num_subdivisions: u32) -> Option<Box<dyn Shape>> {
Some(Box::new(self.clone().scaled(scale)?))
}
fn compute_local_aabb(&self) -> Aabb {
self.local_aabb()
}
fn compute_local_bounding_sphere(&self) -> BoundingSphere {
self.local_bounding_sphere()
}
fn compute_aabb(&self, position: &Isometry<Real>) -> Aabb {
self.aabb(position)
}
fn mass_properties(&self, density: Real) -> MassProperties {
let (vertices, indices) = self.to_trimesh();
MassProperties::from_convex_polyhedron(density, &vertices, &indices)
}
fn is_convex(&self) -> bool {
true
}
fn shape_type(&self) -> ShapeType {
ShapeType::ConvexPolyhedron
}
fn as_typed_shape(&self) -> TypedShape {
TypedShape::ConvexPolyhedron(self)
}
fn ccd_thickness(&self) -> Real {
self.compute_local_aabb().half_extents().min()
}
fn ccd_angular_thickness(&self) -> Real {
Real::frac_pi_4()
}
fn as_support_map(&self) -> Option<&dyn SupportMap> {
Some(self as &dyn SupportMap)
}
fn as_polygonal_feature_map(&self) -> Option<(&dyn PolygonalFeatureMap, Real)> {
Some((self as &dyn PolygonalFeatureMap, 0.0))
}
fn feature_normal_at_point(
&self,
feature: FeatureId,
_point: &Point<Real>,
) -> Option<Unit<Vector<Real>>> {
self.feature_normal(feature)
}
}
#[cfg(feature = "dim3")]
impl Shape for Cylinder {
#[cfg(feature = "std")]
fn clone_dyn(&self) -> Box<dyn Shape> {
Box::new(*self)
}
#[cfg(feature = "std")]
fn scale_dyn(&self, scale: &Vector<Real>, num_subdivisions: u32) -> Option<Box<dyn Shape>> {
let scaled = self.scaled(scale, num_subdivisions)?;
Some(scaled.either::<_, _, Box<dyn Shape>>(|x| Box::new(x), |x| Box::new(x)))
}
fn compute_local_aabb(&self) -> Aabb {
self.local_aabb()
}
fn compute_local_bounding_sphere(&self) -> BoundingSphere {
self.local_bounding_sphere()
}
fn compute_aabb(&self, position: &Isometry<Real>) -> Aabb {
self.aabb(position)
}
fn mass_properties(&self, density: Real) -> MassProperties {
MassProperties::from_cylinder(density, self.half_height, self.radius)
}
fn is_convex(&self) -> bool {
true
}
fn shape_type(&self) -> ShapeType {
ShapeType::Cylinder
}
fn as_typed_shape(&self) -> TypedShape {
TypedShape::Cylinder(self)
}
fn ccd_thickness(&self) -> Real {
self.radius
}
fn ccd_angular_thickness(&self) -> Real {
Real::frac_pi_2()
}
fn as_support_map(&self) -> Option<&dyn SupportMap> {
Some(self as &dyn SupportMap)
}
fn as_polygonal_feature_map(&self) -> Option<(&dyn PolygonalFeatureMap, Real)> {
Some((self as &dyn PolygonalFeatureMap, 0.0))
}
}
#[cfg(feature = "dim3")]
impl Shape for Cone {
#[cfg(feature = "std")]
fn clone_dyn(&self) -> Box<dyn Shape> {
Box::new(*self)
}
#[cfg(feature = "std")]
fn scale_dyn(&self, scale: &Vector<Real>, num_subdivisions: u32) -> Option<Box<dyn Shape>> {
let scaled = self.scaled(scale, num_subdivisions)?;
Some(scaled.either::<_, _, Box<dyn Shape>>(|x| Box::new(x), |x| Box::new(x)))
}
fn compute_local_aabb(&self) -> Aabb {
self.local_aabb()
}
fn compute_local_bounding_sphere(&self) -> BoundingSphere {
self.local_bounding_sphere()
}
fn compute_aabb(&self, position: &Isometry<Real>) -> Aabb {
self.aabb(position)
}
fn mass_properties(&self, density: Real) -> MassProperties {
MassProperties::from_cone(density, self.half_height, self.radius)
}
fn is_convex(&self) -> bool {
true
}
fn shape_type(&self) -> ShapeType {
ShapeType::Cone
}
fn as_typed_shape(&self) -> TypedShape {
TypedShape::Cone(self)
}
fn ccd_thickness(&self) -> Real {
self.radius
}
fn ccd_angular_thickness(&self) -> Real {
let apex_half_angle = RealField::atan2(self.radius, self.half_height);
assert!(apex_half_angle >= 0.0);
let basis_angle = Real::frac_pi_2() - apex_half_angle;
basis_angle.min(apex_half_angle * 2.0)
}
fn as_support_map(&self) -> Option<&dyn SupportMap> {
Some(self as &dyn SupportMap)
}
fn as_polygonal_feature_map(&self) -> Option<(&dyn PolygonalFeatureMap, Real)> {
Some((self as &dyn PolygonalFeatureMap, 0.0))
}
}
impl Shape for HalfSpace {
#[cfg(feature = "std")]
fn clone_dyn(&self) -> Box<dyn Shape> {
Box::new(*self)
}
#[cfg(feature = "std")]
fn scale_dyn(&self, scale: &Vector<Real>, _num_subdivisions: u32) -> Option<Box<dyn Shape>> {
Some(Box::new(self.clone().scaled(scale)?))
}
fn compute_local_aabb(&self) -> Aabb {
self.local_aabb()
}
fn compute_local_bounding_sphere(&self) -> BoundingSphere {
self.local_bounding_sphere()
}
fn compute_aabb(&self, position: &Isometry<Real>) -> Aabb {
self.aabb(position)
}
fn is_convex(&self) -> bool {
true
}
fn ccd_thickness(&self) -> Real {
f32::MAX as Real
}
fn ccd_angular_thickness(&self) -> Real {
Real::pi()
}
fn mass_properties(&self, _: Real) -> MassProperties {
MassProperties::zero()
}
fn shape_type(&self) -> ShapeType {
ShapeType::HalfSpace
}
fn as_typed_shape(&self) -> TypedShape {
TypedShape::HalfSpace(self)
}
}
macro_rules! impl_shape_for_round_shape(
($S: ty, $Tag: ident, $t: tt) => {
impl Shape for RoundShape<$S> {
#[cfg(feature = "std")]
fn clone_dyn(&self) -> Box<dyn Shape> {
Box::new(self.clone())
}
#[cfg(feature = "std")]
fn scale_dyn(&self, scale: &Vector<Real>, num_subdivisions: u32) -> Option<Box<dyn Shape>> {
$t(self, scale, num_subdivisions)
}
fn compute_local_aabb(&self) -> Aabb {
self.inner_shape.local_aabb().loosened(self.border_radius)
}
fn compute_local_bounding_sphere(&self) -> BoundingSphere {
self.inner_shape.local_bounding_sphere().loosened(self.border_radius)
}
fn compute_aabb(&self, position: &Isometry<Real>) -> Aabb {
self.inner_shape.aabb(position).loosened(self.border_radius)
}
fn mass_properties(&self, density: Real) -> MassProperties {
self.inner_shape.mass_properties(density)
}
fn is_convex(&self) -> bool {
self.inner_shape.is_convex()
}
fn shape_type(&self) -> ShapeType {
ShapeType::$Tag
}
fn as_typed_shape(&self) -> TypedShape {
TypedShape::$Tag(self)
}
fn ccd_thickness(&self) -> Real {
self.inner_shape.ccd_thickness() + self.border_radius
}
fn ccd_angular_thickness(&self) -> Real {
self.inner_shape.ccd_angular_thickness()
}
fn as_support_map(&self) -> Option<&dyn SupportMap> {
Some(self as &dyn SupportMap)
}
fn as_polygonal_feature_map(&self) -> Option<(&dyn PolygonalFeatureMap, Real)> {
Some((&self.inner_shape as &dyn PolygonalFeatureMap, self.border_radius))
}
}
}
);
impl_shape_for_round_shape!(
Cuboid,
RoundCuboid,
(|this: &Self, scale: &Vector<Real>, _num_subdivisions: u32| {
let shape = RoundShape {
border_radius: this.border_radius,
inner_shape: this.inner_shape.scaled(scale),
};
Some(Box::new(shape) as Box<dyn Shape>)
})
);
impl_shape_for_round_shape!(
Triangle,
RoundTriangle,
(|this: &Self, scale: &Vector<Real>, _num_subdivisions: u32| {
let shape = RoundShape {
border_radius: this.border_radius,
inner_shape: this.inner_shape.scaled(scale),
};
Some(Box::new(shape) as Box<dyn Shape>)
})
);
#[cfg(feature = "dim2")]
#[cfg(feature = "std")]
impl_shape_for_round_shape!(
ConvexPolygon,
RoundConvexPolygon,
(|this: &Self, scale: &Vector<Real>, _num_subdivisions: u32| {
let shape = RoundShape {
border_radius: this.border_radius,
inner_shape: this.inner_shape.clone().scaled(scale)?,
};
Some(Box::new(shape) as Box<dyn Shape>)
})
);
#[cfg(feature = "dim3")]
impl_shape_for_round_shape!(
Cylinder,
RoundCylinder,
(|this: &Self, scale: &Vector<Real>, num_subdivisions: u32| {
Some(
this.inner_shape
.scaled(scale, num_subdivisions)?
.either::<_, _, Box<dyn Shape>>(
|inner_shape| {
Box::new(RoundShape {
border_radius: this.border_radius,
inner_shape,
})
},
|inner_shape| {
Box::new(RoundShape {
border_radius: this.border_radius,
inner_shape,
})
},
),
)
})
);
#[cfg(feature = "dim3")]
impl_shape_for_round_shape!(
Cone,
RoundCone,
(|this: &Self, scale: &Vector<Real>, num_subdivisions: u32| {
Some(
this.inner_shape
.scaled(scale, num_subdivisions)?
.either::<_, _, Box<dyn Shape>>(
|inner_shape| {
Box::new(RoundShape {
border_radius: this.border_radius,
inner_shape,
})
},
|inner_shape| {
Box::new(RoundShape {
border_radius: this.border_radius,
inner_shape,
})
},
),
)
})
);
#[cfg(feature = "dim3")]
#[cfg(feature = "std")]
impl_shape_for_round_shape!(
ConvexPolyhedron,
RoundConvexPolyhedron,
(|this: &Self, scale: &Vector<Real>, _num_subdivisions: u32| {
let shape = RoundShape {
border_radius: this.border_radius,
inner_shape: this.inner_shape.clone().scaled(scale)?,
};
Some(Box::new(shape) as Box<dyn Shape>)
})
);