diff options
| author | Crozet Sébastien <developer@crozet.re> | 2020-10-20 11:55:33 +0200 |
|---|---|---|
| committer | Crozet Sébastien <developer@crozet.re> | 2020-10-20 11:56:09 +0200 |
| commit | 865ce8a8e5301b23ca474adaaffe8b43e725803e (patch) | |
| tree | 67b57d0c63d11a6d5e4a23c6f1242f72efc721b9 /src/geometry/shape.rs | |
| parent | 947c4813c9666fd8215743de298fe17780fa3ef2 (diff) | |
| download | rapier-865ce8a8e5301b23ca474adaaffe8b43e725803e.tar.gz rapier-865ce8a8e5301b23ca474adaaffe8b43e725803e.tar.bz2 rapier-865ce8a8e5301b23ca474adaaffe8b43e725803e.zip | |
Collider shape: use a trait-object instead of an enum.
Diffstat (limited to 'src/geometry/shape.rs')
| -rw-r--r-- | src/geometry/shape.rs | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/src/geometry/shape.rs b/src/geometry/shape.rs new file mode 100644 index 0000000..c9e0a3a --- /dev/null +++ b/src/geometry/shape.rs @@ -0,0 +1,275 @@ +use crate::dynamics::{MassProperties, RigidBodyHandle, RigidBodySet}; +#[cfg(feature = "dim3")] +use crate::geometry::PolygonalFeatureMap; +use crate::geometry::{ + Ball, Capsule, ColliderGraphIndex, Contact, Cuboid, Cylinder, HeightField, InteractionGraph, + Polygon, Proximity, Ray, RayIntersection, Triangle, Trimesh, +}; +use crate::math::{AngVector, Isometry, Point, Rotation, Vector}; +use downcast_rs::{impl_downcast, DowncastSync}; +use erased_serde::Serialize; +use na::Point3; +use ncollide::bounding_volume::{HasBoundingVolume, AABB}; +use ncollide::query::{PointQuery, RayCast}; +use num::Zero; +use num_derive::FromPrimitive; +use std::any::Any; + +#[derive(Copy, Clone, Debug, FromPrimitive)] +/// Enum representing the type of a shape. +pub enum ShapeType { + /// A ball shape. + Ball = 1, + /// A convex polygon shape. + Polygon, + /// A cuboid shape. + Cuboid, + /// A capsule shape. + Capsule, + /// A triangle shape. + Triangle, + /// A triangle mesh shape. + Trimesh, + /// A heightfield shape. + HeightField, + #[cfg(feature = "dim3")] + /// A cylindrical shape. + Cylinder, + // /// A custom shape type. + // Custom(u8), +} + +/// Trait implemented by shapes usable by Rapier. +pub trait Shape: RayCast<f32> + PointQuery<f32> + DowncastSync { + /// Convert this shape as a serializable entity. + #[cfg(feature = "serde-serialize")] + fn as_serialize(&self) -> Option<&dyn Serialize> { + None + } + + /// Computes the AABB of this shape. + fn compute_aabb(&self, position: &Isometry<f32>) -> AABB<f32>; + + /// Compute the mass-properties of this shape given its uniform density. + fn mass_properties(&self, density: f32) -> MassProperties; + + /// Gets the type tag of this shape. + fn shape_type(&self) -> ShapeType; + + /// Converts this shape to a polygonal feature-map, if it is one. + #[cfg(feature = "dim3")] + fn as_polygonal_feature_map(&self) -> Option<&dyn PolygonalFeatureMap> { + None + } + + // fn as_rounded(&self) -> Option<&Rounded<Box<AnyShape>>> { + // None + // } +} + +impl_downcast!(sync Shape); + +impl dyn Shape { + /// Converts this abstract shape to a ball, if it is one. + pub fn as_ball(&self) -> Option<&Ball> { + self.downcast_ref() + } + + /// Converts this abstract shape to a cuboid, if it is one. + pub fn as_cuboid(&self) -> Option<&Cuboid> { + self.downcast_ref() + } + + /// Converts this abstract shape to a capsule, if it is one. + pub fn as_capsule(&self) -> Option<&Capsule> { + self.downcast_ref() + } + + /// Converts this abstract shape to a triangle, if it is one. + pub fn as_triangle(&self) -> Option<&Triangle> { + self.downcast_ref() + } + + /// Converts this abstract shape to a triangle mesh, if it is one. + pub fn as_trimesh(&self) -> Option<&Trimesh> { + self.downcast_ref() + } + + /// Converts this abstract shape to a heightfield, if it is one. + pub fn as_heightfield(&self) -> Option<&HeightField> { + self.downcast_ref() + } + + /// Converts this abstract shape to a cylinder, if it is one. + pub fn as_cylinder(&self) -> Option<&Cylinder> { + self.downcast_ref() + } +} + +impl Shape for Ball { + #[cfg(feature = "serde-serialize")] + fn as_serialize(&self) -> Option<&dyn Serialize> { + Some(self as &dyn Serialize) + } + + fn compute_aabb(&self, position: &Isometry<f32>) -> AABB<f32> { + self.bounding_volume(position) + } + + fn mass_properties(&self, density: f32) -> MassProperties { + MassProperties::from_ball(density, self.radius) + } + + fn shape_type(&self) -> ShapeType { + ShapeType::Ball + } +} + +// impl Shape for Polygon { +// #[cfg(feature = "serde-serialize")] +// fn as_serialize(&self) -> Option<&dyn Serialize> { +// Some(self as &dyn Serialize) +// } +// +// fn compute_aabb(&self, position: &Isometry<f32>) -> AABB<f32> { +// self.aabb(position) +// } +// +// fn mass_properties(&self, _density: f32) -> MassProperties { +// unimplemented!() +// } +// +// fn shape_type(&self) -> ShapeType { +// ShapeType::Polygon +// } +// } + +impl Shape for Cuboid { + #[cfg(feature = "serde-serialize")] + fn as_serialize(&self) -> Option<&dyn Serialize> { + Some(self as &dyn Serialize) + } + + fn compute_aabb(&self, position: &Isometry<f32>) -> AABB<f32> { + self.bounding_volume(position) + } + + fn mass_properties(&self, density: f32) -> MassProperties { + MassProperties::from_cuboid(density, self.half_extents) + } + + fn shape_type(&self) -> ShapeType { + ShapeType::Cuboid + } + + #[cfg(feature = "dim3")] + fn as_polygonal_feature_map(&self) -> Option<&dyn PolygonalFeatureMap> { + Some(self as &dyn PolygonalFeatureMap) + } +} + +impl Shape for Capsule { + #[cfg(feature = "serde-serialize")] + fn as_serialize(&self) -> Option<&dyn Serialize> { + Some(self as &dyn Serialize) + } + + fn compute_aabb(&self, position: &Isometry<f32>) -> AABB<f32> { + self.bounding_volume(position) + } + + fn mass_properties(&self, density: f32) -> MassProperties { + MassProperties::from_capsule(density, self.half_height, self.radius) + } + + fn shape_type(&self) -> ShapeType { + ShapeType::Capsule + } +} + +impl Shape for Triangle { + #[cfg(feature = "serde-serialize")] + fn as_serialize(&self) -> Option<&dyn Serialize> { + Some(self as &dyn Serialize) + } + + fn compute_aabb(&self, position: &Isometry<f32>) -> AABB<f32> { + self.bounding_volume(position) + } + + fn mass_properties(&self, density: f32) -> MassProperties { + MassProperties::zero() + } + + fn shape_type(&self) -> ShapeType { + ShapeType::Triangle + } + + #[cfg(feature = "dim3")] + fn as_polygonal_feature_map(&self) -> Option<&dyn PolygonalFeatureMap> { + Some(self as &dyn PolygonalFeatureMap) + } +} + +impl Shape for Trimesh { + #[cfg(feature = "serde-serialize")] + fn as_serialize(&self) -> Option<&dyn Serialize> { + Some(self as &dyn Serialize) + } + + fn compute_aabb(&self, position: &Isometry<f32>) -> AABB<f32> { + self.aabb(position) + } + + fn mass_properties(&self, _density: f32) -> MassProperties { + MassProperties::zero() + } + + fn shape_type(&self) -> ShapeType { + ShapeType::Trimesh + } +} + +impl Shape for HeightField { + #[cfg(feature = "serde-serialize")] + fn as_serialize(&self) -> Option<&dyn Serialize> { + Some(self as &dyn Serialize) + } + + fn compute_aabb(&self, position: &Isometry<f32>) -> AABB<f32> { + self.bounding_volume(position) + } + + fn mass_properties(&self, _density: f32) -> MassProperties { + MassProperties::zero() + } + + fn shape_type(&self) -> ShapeType { + ShapeType::HeightField + } +} + +#[cfg(feature = "dim3")] +impl Shape for Cylinder { + #[cfg(feature = "serde-serialize")] + fn as_serialize(&self) -> Option<&dyn Serialize> { + Some(self as &dyn Serialize) + } + + fn compute_aabb(&self, position: &Isometry<f32>) -> AABB<f32> { + self.bounding_volume(position) + } + + fn mass_properties(&self, density: f32) -> MassProperties { + MassProperties::from_cylinder(density, self.half_height, self.radius) + } + + fn shape_type(&self) -> ShapeType { + ShapeType::Cylinder + } + + #[cfg(feature = "dim3")] + fn as_polygonal_feature_map(&self) -> Option<&dyn PolygonalFeatureMap> { + Some(self as &dyn PolygonalFeatureMap) + } +} |
