use crate::math::{Pose, Real, Vector};
use crate::shape::SupportMap;
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
#[cfg_attr(feature = "encase", derive(encase::ShaderType))]
#[cfg_attr(
feature = "rkyv",
derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize)
)]
#[derive(PartialEq, Debug, Copy, Clone)]
#[repr(C)]
pub struct Ball {
pub radius: Real,
}
impl Ball {
#[inline]
pub fn new(radius: Real) -> Ball {
Ball { radius }
}
#[cfg(all(feature = "dim2", feature = "alloc"))]
#[inline]
pub fn scaled(
self,
scale: Vector,
nsubdivs: u32,
) -> Option<either::Either<Self, super::ConvexPolygon>> {
if scale.x != scale.y {
let mut vtx = self.to_polyline(nsubdivs);
vtx.iter_mut().for_each(|pt| *pt *= scale);
Some(either::Either::Right(
super::ConvexPolygon::from_convex_polyline(vtx)?,
))
} else {
let uniform_scale = scale.x;
Some(either::Either::Left(Self::new(
self.radius * uniform_scale.abs(),
)))
}
}
#[cfg(all(feature = "dim3", feature = "alloc"))]
#[inline]
pub fn scaled(
self,
scale: Vector,
nsubdivs: u32,
) -> Option<either::Either<Self, super::ConvexPolyhedron>> {
if scale.x != scale.y || scale.x != scale.z || scale.y != scale.z {
let (mut vtx, idx) = self.to_trimesh(nsubdivs, nsubdivs);
vtx.iter_mut().for_each(|pt| *pt *= scale);
Some(either::Either::Right(
super::ConvexPolyhedron::from_convex_mesh(vtx, &idx)?,
))
} else {
let uniform_scale = scale.x;
Some(either::Either::Left(Self::new(
self.radius * uniform_scale.abs(),
)))
}
}
}
impl SupportMap for Ball {
#[inline]
fn support_point(&self, m: &Pose, dir: Vector) -> Vector {
self.support_point_toward(m, dir.normalize())
}
#[inline]
fn support_point_toward(&self, m: &Pose, dir: Vector) -> Vector {
m.translation + dir * self.radius
}
#[inline]
fn local_support_point(&self, dir: Vector) -> Vector {
self.local_support_point_toward(dir.normalize())
}
#[inline]
fn local_support_point_toward(&self, dir: Vector) -> Vector {
dir * self.radius
}
}