Replace the Rounded<S> type by a non-generic RoundCylinder type.

This commit is contained in:
Crozet Sébastien
2020-10-27 09:20:40 +01:00
parent dbdd797d59
commit 8c872dc0af
6 changed files with 54 additions and 58 deletions

View File

@@ -4,7 +4,7 @@ use crate::geometry::{
Segment, Shape, ShapeType, Triangle, Trimesh, Segment, Shape, ShapeType, Triangle, Trimesh,
}; };
#[cfg(feature = "dim3")] #[cfg(feature = "dim3")]
use crate::geometry::{Cone, Cylinder, Rounded}; use crate::geometry::{Cone, Cylinder, RoundCylinder};
use crate::math::{AngVector, Isometry, Point, Rotation, Vector}; use crate::math::{AngVector, Isometry, Point, Rotation, Vector};
use na::Point3; use na::Point3;
use ncollide::bounding_volume::AABB; use ncollide::bounding_volume::AABB;
@@ -39,10 +39,11 @@ impl ColliderShape {
/// (along along the y axis), its radius, and its roundedness (the /// (along along the y axis), its radius, and its roundedness (the
/// radius of the sphere used for dilating the cylinder). /// radius of the sphere used for dilating the cylinder).
#[cfg(feature = "dim3")] #[cfg(feature = "dim3")]
pub fn round_cylinder(half_height: f32, radius: f32, round_radius: f32) -> Self { pub fn round_cylinder(half_height: f32, radius: f32, border_radius: f32) -> Self {
ColliderShape(Arc::new(Rounded::new( ColliderShape(Arc::new(RoundCylinder::new(
Cylinder::new(half_height, radius), half_height,
round_radius, radius,
border_radius,
))) )))
} }
@@ -170,7 +171,7 @@ impl<'de> serde::Deserialize<'de> for ColliderShape {
#[cfg(feature = "dim3")] #[cfg(feature = "dim3")]
Some(ShapeType::Cone) => deser::<A, Cone>(&mut seq)?, Some(ShapeType::Cone) => deser::<A, Cone>(&mut seq)?,
#[cfg(feature = "dim3")] #[cfg(feature = "dim3")]
Some(ShapeType::RoundCylinder) => deser::<A, Rounded<Cylinder>>(&mut seq)?, Some(ShapeType::RoundCylinder) => deser::<A, RoundCylinder>(&mut seq)?,
None => { None => {
return Err(serde::de::Error::custom( return Err(serde::de::Error::custom(
"found invalid shape type to deserialize", "found invalid shape type to deserialize",
@@ -332,11 +333,11 @@ impl ColliderBuilder {
/// (along along the y axis), its radius, and its roundedness (the /// (along along the y axis), its radius, and its roundedness (the
/// radius of the sphere used for dilating the cylinder). /// radius of the sphere used for dilating the cylinder).
#[cfg(feature = "dim3")] #[cfg(feature = "dim3")]
pub fn round_cylinder(half_height: f32, radius: f32, round_radius: f32) -> Self { pub fn round_cylinder(half_height: f32, radius: f32, border_radius: f32) -> Self {
Self::new(ColliderShape::round_cylinder( Self::new(ColliderShape::round_cylinder(
half_height, half_height,
radius, radius,
round_radius, border_radius,
)) ))
} }

View File

@@ -24,11 +24,11 @@ impl Default for PfmPfmContactManifoldGeneratorWorkspace {
} }
pub fn generate_contacts_pfm_pfm(ctxt: &mut PrimitiveContactGenerationContext) { pub fn generate_contacts_pfm_pfm(ctxt: &mut PrimitiveContactGenerationContext) {
if let (Some((pfm1, round_radius1)), Some((pfm2, round_radius2))) = ( if let (Some((pfm1, border_radius1)), Some((pfm2, border_radius2))) = (
ctxt.shape1.as_polygonal_feature_map(), ctxt.shape1.as_polygonal_feature_map(),
ctxt.shape2.as_polygonal_feature_map(), ctxt.shape2.as_polygonal_feature_map(),
) { ) {
do_generate_contacts(pfm1, round_radius1, pfm2, round_radius2, ctxt); do_generate_contacts(pfm1, border_radius1, pfm2, border_radius2, ctxt);
ctxt.manifold.update_warmstart_multiplier(); ctxt.manifold.update_warmstart_multiplier();
ctxt.manifold.sort_contacts(ctxt.prediction_distance); ctxt.manifold.sort_contacts(ctxt.prediction_distance);
} }
@@ -36,9 +36,9 @@ pub fn generate_contacts_pfm_pfm(ctxt: &mut PrimitiveContactGenerationContext) {
fn do_generate_contacts( fn do_generate_contacts(
pfm1: &dyn PolygonalFeatureMap, pfm1: &dyn PolygonalFeatureMap,
round_radius1: f32, border_radius1: f32,
pfm2: &dyn PolygonalFeatureMap, pfm2: &dyn PolygonalFeatureMap,
round_radius2: f32, border_radius2: f32,
ctxt: &mut PrimitiveContactGenerationContext, ctxt: &mut PrimitiveContactGenerationContext,
) { ) {
let pos12 = ctxt.position1.inverse() * ctxt.position2; let pos12 = ctxt.position1.inverse() * ctxt.position2;
@@ -61,7 +61,7 @@ fn do_generate_contacts(
.downcast_mut() .downcast_mut()
.expect("Invalid workspace type, expected a PfmPfmContactManifoldGeneratorWorkspace."); .expect("Invalid workspace type, expected a PfmPfmContactManifoldGeneratorWorkspace.");
let total_prediction = ctxt.prediction_distance + round_radius1 + round_radius2; let total_prediction = ctxt.prediction_distance + border_radius1 + border_radius2;
let contact = query::contact_support_map_support_map_with_params( let contact = query::contact_support_map_support_map_with_params(
&Isometry::identity(), &Isometry::identity(),
pfm1, pfm1,
@@ -93,11 +93,11 @@ fn do_generate_contacts(
ctxt.manifold, ctxt.manifold,
); );
if round_radius1 != 0.0 || round_radius2 != 0.0 { if border_radius1 != 0.0 || border_radius2 != 0.0 {
for contact in &mut ctxt.manifold.points { for contact in &mut ctxt.manifold.points {
contact.local_p1 += *normal1 * round_radius1; contact.local_p1 += *normal1 * border_radius1;
contact.local_p2 += *normal2 * round_radius2; contact.local_p2 += *normal2 * border_radius2;
contact.dist -= round_radius1 + round_radius2; contact.dist -= border_radius1 + border_radius2;
} }
} }

View File

@@ -19,7 +19,7 @@ pub use self::narrow_phase::NarrowPhase;
pub use self::polygon::Polygon; pub use self::polygon::Polygon;
pub use self::proximity::ProximityPair; pub use self::proximity::ProximityPair;
pub use self::proximity_detector::{DefaultProximityDispatcher, ProximityDispatcher}; pub use self::proximity_detector::{DefaultProximityDispatcher, ProximityDispatcher};
pub use self::rounded::{Roundable, Rounded}; pub use self::round_cylinder::RoundCylinder;
pub use self::trimesh::Trimesh; pub use self::trimesh::Trimesh;
pub use ncollide::query::Proximity; pub use ncollide::query::Proximity;
@@ -98,5 +98,5 @@ mod wquadtree;
mod capsule; mod capsule;
#[cfg(feature = "dim3")] #[cfg(feature = "dim3")]
mod polygonal_feature_map; mod polygonal_feature_map;
mod rounded; mod round_cylinder;
mod shape; mod shape;

View File

@@ -1,6 +1,5 @@
#[cfg(feature = "dim3")] #[cfg(feature = "dim3")]
use crate::geometry::Cylinder; use crate::geometry::Cylinder;
use crate::geometry::ShapeType;
use crate::math::{Isometry, Point, Vector}; use crate::math::{Isometry, Point, Vector};
use na::Unit; use na::Unit;
use ncollide::query::{ use ncollide::query::{
@@ -8,44 +7,35 @@ use ncollide::query::{
}; };
use ncollide::shape::{FeatureId, SupportMap}; use ncollide::shape::{FeatureId, SupportMap};
/// A shape which corner can be rounded. /// A rounded cylinder.
pub trait Roundable {
/// The ShapeType fo this shape after rounding its corners.
fn rounded_shape_type() -> ShapeType;
}
#[cfg(feature = "dim3")]
impl Roundable for Cylinder {
fn rounded_shape_type() -> ShapeType {
ShapeType::RoundCylinder
}
}
/// A rounded shape.
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
pub struct Rounded<S: Roundable> { #[derive(Copy, Clone, Debug)]
/// The shape being rounded. pub struct RoundCylinder {
pub shape: S, /// The cylinder being rounded.
pub cylinder: Cylinder,
/// The rounding radius. /// The rounding radius.
pub radius: f32, pub border_radius: f32,
} }
impl<S: Roundable> Rounded<S> { impl RoundCylinder {
/// Create sa new shape where all its edges and vertices are rounded by a radius of `radius`. /// Create sa new cylinder where all its edges and vertices are rounded by a radius of `radius`.
/// ///
/// This is done by applying a dilation of the given radius to the shape. /// This is done by applying a dilation of the given radius to the cylinder.
pub fn new(shape: S, radius: f32) -> Self { pub fn new(half_height: f32, radius: f32, border_radius: f32) -> Self {
Self { shape, radius } Self {
cylinder: Cylinder::new(half_height, radius),
border_radius,
}
} }
} }
impl<S: Roundable + SupportMap<f32>> SupportMap<f32> for Rounded<S> { impl SupportMap<f32> for RoundCylinder {
fn local_support_point(&self, dir: &Vector<f32>) -> Point<f32> { fn local_support_point(&self, dir: &Vector<f32>) -> Point<f32> {
self.local_support_point_toward(&Unit::new_normalize(*dir)) self.local_support_point_toward(&Unit::new_normalize(*dir))
} }
fn local_support_point_toward(&self, dir: &Unit<Vector<f32>>) -> Point<f32> { fn local_support_point_toward(&self, dir: &Unit<Vector<f32>>) -> Point<f32> {
self.shape.local_support_point_toward(dir) + **dir * self.radius self.cylinder.local_support_point_toward(dir) + **dir * self.border_radius
} }
fn support_point(&self, transform: &Isometry<f32>, dir: &Vector<f32>) -> Point<f32> { fn support_point(&self, transform: &Isometry<f32>, dir: &Vector<f32>) -> Point<f32> {
@@ -63,7 +53,7 @@ impl<S: Roundable + SupportMap<f32>> SupportMap<f32> for Rounded<S> {
} }
} }
impl<S: Roundable + SupportMap<f32>> RayCast<f32> for Rounded<S> { impl RayCast<f32> for RoundCylinder {
fn toi_and_normal_with_ray( fn toi_and_normal_with_ray(
&self, &self,
m: &Isometry<f32>, m: &Isometry<f32>,
@@ -90,7 +80,7 @@ impl<S: Roundable + SupportMap<f32>> RayCast<f32> for Rounded<S> {
// TODO: if PointQuery had a `project_point_with_normal` method, we could just // TODO: if PointQuery had a `project_point_with_normal` method, we could just
// call this and adjust the projected point accordingly. // call this and adjust the projected point accordingly.
impl<S: Roundable + SupportMap<f32>> PointQuery<f32> for Rounded<S> { impl PointQuery<f32> for RoundCylinder {
#[inline] #[inline]
fn project_point( fn project_point(
&self, &self,

View File

@@ -1,6 +1,6 @@
use crate::dynamics::MassProperties; use crate::dynamics::MassProperties;
use crate::geometry::{ use crate::geometry::{
Ball, Capsule, Cuboid, HeightField, Roundable, Rounded, Segment, Triangle, Trimesh, Ball, Capsule, Cuboid, HeightField, RoundCylinder, Segment, Triangle, Trimesh,
}; };
use crate::math::Isometry; use crate::math::Isometry;
use downcast_rs::{impl_downcast, DowncastSync}; use downcast_rs::{impl_downcast, DowncastSync};
@@ -132,11 +132,8 @@ impl dyn Shape {
} }
/// Converts this abstract shape to a cone, if it is one. /// Converts this abstract shape to a cone, if it is one.
pub fn as_rounded<S>(&self) -> Option<&Rounded<S>> #[cfg(feature = "dim3")]
where pub fn as_round_cylinder(&self) -> Option<&RoundCylinder> {
S: Roundable,
Rounded<S>: Shape,
{
self.downcast_ref() self.downcast_ref()
} }
} }
@@ -364,19 +361,21 @@ impl Shape for Cone {
} }
#[cfg(feature = "dim3")] #[cfg(feature = "dim3")]
impl Shape for Rounded<Cylinder> { impl Shape for RoundCylinder {
#[cfg(feature = "serde-serialize")] #[cfg(feature = "serde-serialize")]
fn as_serialize(&self) -> Option<&dyn Serialize> { fn as_serialize(&self) -> Option<&dyn Serialize> {
Some(self as &dyn Serialize) Some(self as &dyn Serialize)
} }
fn compute_aabb(&self, position: &Isometry<f32>) -> AABB<f32> { fn compute_aabb(&self, position: &Isometry<f32>) -> AABB<f32> {
self.shape.compute_aabb(position).loosened(self.radius) self.cylinder
.compute_aabb(position)
.loosened(self.border_radius)
} }
fn mass_properties(&self, density: f32) -> MassProperties { fn mass_properties(&self, density: f32) -> MassProperties {
// We ignore the margin here. // We ignore the margin here.
self.shape.mass_properties(density) self.cylinder.mass_properties(density)
} }
fn shape_type(&self) -> ShapeType { fn shape_type(&self) -> ShapeType {
@@ -385,6 +384,9 @@ impl Shape for Rounded<Cylinder> {
#[cfg(feature = "dim3")] #[cfg(feature = "dim3")]
fn as_polygonal_feature_map(&self) -> Option<(&dyn PolygonalFeatureMap, f32)> { fn as_polygonal_feature_map(&self) -> Option<(&dyn PolygonalFeatureMap, f32)> {
Some((&self.shape as &dyn PolygonalFeatureMap, self.radius)) Some((
&self.cylinder as &dyn PolygonalFeatureMap,
self.border_radius,
))
} }
} }

View File

@@ -412,7 +412,10 @@ impl GraphicsManager {
} }
#[cfg(feature = "dim3")] #[cfg(feature = "dim3")]
if let Some(cylinder) = shape.as_cylinder().or(shape.as_rounded().map(|r| &r.shape)) { if let Some(cylinder) = shape
.as_cylinder()
.or(shape.as_round_cylinder().map(|r| &r.cylinder))
{
out.push(Node::Cylinder(Cylinder::new( out.push(Node::Cylinder(Cylinder::new(
handle, handle,
cylinder.half_height, cylinder.half_height,