parry3d/shape/
cylinder.rs1use crate::math::{Point, Real, Vector};
4use crate::shape::SupportMap;
5use na;
6use num::Zero;
7
8#[cfg(feature = "alloc")]
9use either::Either;
10
11#[cfg(feature = "rkyv")]
12use rkyv::{bytecheck, CheckBytes};
13
14#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
16#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
17#[cfg_attr(
18 feature = "rkyv",
19 derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize, CheckBytes),
20 archive(as = "Self")
21)]
22#[derive(PartialEq, Debug, Copy, Clone)]
23#[repr(C)]
24pub struct Cylinder {
25 pub half_height: Real,
27 pub radius: Real,
29}
30
31impl Cylinder {
32 pub fn new(half_height: Real, radius: Real) -> Cylinder {
38 assert!(half_height.is_sign_positive() && radius.is_sign_positive());
39
40 Cylinder {
41 half_height,
42 radius,
43 }
44 }
45
46 #[cfg(feature = "alloc")]
53 #[inline]
54 pub fn scaled(
55 self,
56 scale: &Vector<Real>,
57 nsubdivs: u32,
58 ) -> Option<Either<Self, super::ConvexPolyhedron>> {
59 if scale.x != scale.z {
60 let (mut vtx, idx) = self.to_trimesh(nsubdivs);
62 vtx.iter_mut()
63 .for_each(|pt| pt.coords = pt.coords.component_mul(scale));
64 Some(Either::Right(super::ConvexPolyhedron::from_convex_mesh(
65 vtx, &idx,
66 )?))
67 } else {
68 Some(Either::Left(Self::new(
69 self.half_height * scale.y,
70 self.radius * scale.x,
71 )))
72 }
73 }
74}
75
76impl SupportMap for Cylinder {
77 fn local_support_point(&self, dir: &Vector<Real>) -> Point<Real> {
78 let mut vres = *dir;
79
80 vres[1] = 0.0;
81
82 if vres.normalize_mut().is_zero() {
83 vres = na::zero()
84 } else {
85 vres *= self.radius;
86 }
87
88 vres[1] = self.half_height.copysign(dir[1]);
89
90 Point::from(vres)
91 }
92}