use crate::material::ContactMaterial;
use phyz_math::{SpatialInertia, SpatialTransform};
#[derive(Debug, Clone)]
pub struct Body {
pub name: String,
pub inertia: SpatialInertia,
pub parent: i32,
pub joint_idx: usize,
pub geometry: Option<Geometry>,
pub collisions: Vec<GeomInstance>,
pub visuals: Vec<GeomInstance>,
pub material: Option<ContactMaterial>,
}
impl Body {
pub fn new(name: &str, inertia: SpatialInertia, parent: i32, joint_idx: usize) -> Self {
Self {
name: name.to_string(),
inertia,
parent,
joint_idx,
geometry: None,
collisions: Vec::new(),
visuals: Vec::new(),
material: None,
}
}
pub fn with_material(mut self, material: ContactMaterial) -> Self {
self.material = Some(material);
self
}
}
#[derive(Debug, Clone)]
pub struct GeomInstance {
pub name: Option<String>,
pub origin: SpatialTransform,
pub geometry: Geometry,
}
impl GeomInstance {
pub fn new(geometry: Geometry, origin: SpatialTransform) -> Self {
Self {
name: None,
origin,
geometry,
}
}
pub fn centered(geometry: Geometry) -> Self {
Self::new(geometry, SpatialTransform::identity())
}
pub fn is_centered(&self) -> bool {
const EPS: f64 = 1e-12;
self.origin.pos.norm_sq() < EPS
&& (self.origin.rot - phyz_math::Mat3::identity()).norm_sq() < EPS
}
}
#[derive(Debug, Clone)]
pub enum Geometry {
Sphere {
radius: f64,
},
Capsule {
radius: f64,
length: f64,
},
Box {
half_extents: phyz_math::Vec3,
},
Cylinder {
radius: f64,
height: f64,
},
Mesh {
vertices: Vec<phyz_math::Vec3>,
faces: Vec<[usize; 3]>,
},
Plane {
normal: phyz_math::Vec3,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Attachment {
Body(usize),
World,
}
impl Attachment {
#[inline]
pub fn body(self) -> Option<usize> {
match self {
Attachment::Body(i) => Some(i),
Attachment::World => None,
}
}
#[inline]
pub fn is_world(self) -> bool {
matches!(self, Attachment::World)
}
}