use crate::math::{RawRotation, RawVector}; use na::Unit; use rapier::dynamics::{ FixedJointBuilder, GenericJoint, JointAxesMask, JointAxis, MotorModel, PrismaticJointBuilder, RevoluteJointBuilder, RopeJointBuilder, SpringJointBuilder, }; #[cfg(feature = "dim3")] use rapier::dynamics::{GenericJointBuilder, SphericalJointBuilder}; use rapier::math::Isometry; use wasm_bindgen::prelude::*; #[wasm_bindgen] #[cfg(feature = "dim2")] pub enum RawJointType { Revolute, Fixed, Prismatic, Rope, Spring, Generic, } #[wasm_bindgen] #[cfg(feature = "dim3")] pub enum RawJointType { Revolute, Fixed, Prismatic, Rope, Spring, Spherical, Generic, } /// The type of this joint. #[cfg(feature = "dim2")] impl From for RawJointType { fn from(ty: JointAxesMask) -> RawJointType { let rev_axes = JointAxesMask::LIN_X | JointAxesMask::LIN_Y; let pri_axes = JointAxesMask::LIN_Y | JointAxesMask::ANG_X; let fix_axes = JointAxesMask::LIN_X | JointAxesMask::LIN_Y | JointAxesMask::ANG_X; if ty == rev_axes { RawJointType::Revolute } else if ty == pri_axes { RawJointType::Prismatic } else if ty == fix_axes { RawJointType::Fixed } else { RawJointType::Generic } } } /// The type of this joint. #[cfg(feature = "dim3")] impl From for RawJointType { fn from(ty: JointAxesMask) -> RawJointType { let rev_axes = JointAxesMask::LIN_X | JointAxesMask::LIN_Y | JointAxesMask::LIN_Z | JointAxesMask::ANG_Y | JointAxesMask::ANG_Z; let pri_axes = JointAxesMask::LIN_Y | JointAxesMask::LIN_Z | JointAxesMask::ANG_X | JointAxesMask::ANG_Y | JointAxesMask::ANG_Z; let sph_axes = JointAxesMask::ANG_X | JointAxesMask::ANG_Y | JointAxesMask::ANG_Z; let fix_axes = JointAxesMask::LIN_X | JointAxesMask::LIN_Y | JointAxesMask::LIN_Z | JointAxesMask::ANG_X | JointAxesMask::ANG_Y | JointAxesMask::ANG_Z; if ty == rev_axes { RawJointType::Revolute } else if ty == pri_axes { RawJointType::Prismatic } else if ty == sph_axes { RawJointType::Spherical } else if ty == fix_axes { RawJointType::Fixed } else { RawJointType::Generic } } } #[wasm_bindgen] pub enum RawMotorModel { AccelerationBased, ForceBased, } impl From for MotorModel { fn from(model: RawMotorModel) -> MotorModel { match model { RawMotorModel::AccelerationBased => MotorModel::AccelerationBased, RawMotorModel::ForceBased => MotorModel::ForceBased, } } } #[cfg(feature = "dim2")] #[wasm_bindgen] #[derive(Copy, Clone)] pub enum RawJointAxis { LinX, LinY, AngX, } #[cfg(feature = "dim3")] #[wasm_bindgen] #[derive(Copy, Clone)] pub enum RawJointAxis { LinX, LinY, LinZ, AngX, AngY, AngZ, } impl From for JointAxis { fn from(axis: RawJointAxis) -> JointAxis { match axis { RawJointAxis::LinX => JointAxis::LinX, RawJointAxis::LinY => JointAxis::LinY, #[cfg(feature = "dim3")] RawJointAxis::LinZ => JointAxis::LinZ, RawJointAxis::AngX => JointAxis::AngX, #[cfg(feature = "dim3")] RawJointAxis::AngY => JointAxis::AngY, #[cfg(feature = "dim3")] RawJointAxis::AngZ => JointAxis::AngZ, } } } #[wasm_bindgen] pub struct RawGenericJoint(pub(crate) GenericJoint); #[wasm_bindgen] impl RawGenericJoint { /// Creates a new joint descriptor that builds generic joints. /// /// Generic joints allow arbitrary axes of freedom to be selected /// for the joint from the available 6 degrees of freedom. #[cfg(feature = "dim3")] pub fn generic( anchor1: &RawVector, anchor2: &RawVector, axis: &RawVector, lockedAxes: u8, ) -> Option { let axesMask: JointAxesMask = JointAxesMask::from_bits(lockedAxes)?; let axis = Unit::try_new(axis.0, 0.0)?; let joint: GenericJoint = GenericJointBuilder::new(axesMask) .local_anchor1(anchor1.0.into()) .local_anchor2(anchor2.0.into()) .local_axis1(axis) .local_axis2(axis) .into(); Some(Self(joint)) } pub fn spring( rest_length: f32, stiffness: f32, damping: f32, anchor1: &RawVector, anchor2: &RawVector, ) -> Self { Self( SpringJointBuilder::new(rest_length, stiffness, damping) .local_anchor1(anchor1.0.into()) .local_anchor2(anchor2.0.into()) .into(), ) } pub fn rope(length: f32, anchor1: &RawVector, anchor2: &RawVector) -> Self { Self( RopeJointBuilder::new(length) .local_anchor1(anchor1.0.into()) .local_anchor2(anchor2.0.into()) .into(), ) } /// Create a new joint descriptor that builds spherical joints. /// /// A spherical joints allows three relative rotational degrees of freedom /// by preventing any relative translation between the anchors of the /// two attached rigid-bodies. #[cfg(feature = "dim3")] pub fn spherical(anchor1: &RawVector, anchor2: &RawVector) -> Self { Self( SphericalJointBuilder::new() .local_anchor1(anchor1.0.into()) .local_anchor2(anchor2.0.into()) .into(), ) } /// Creates a new joint descriptor that builds a Prismatic joint. /// /// A prismatic joint removes all the degrees of freedom between the /// affected bodies, except for the translation along one axis. /// /// Returns `None` if any of the provided axes cannot be normalized. #[cfg(feature = "dim2")] pub fn prismatic( anchor1: &RawVector, anchor2: &RawVector, axis: &RawVector, limitsEnabled: bool, limitsMin: f32, limitsMax: f32, ) -> Option { let axis = Unit::try_new(axis.0, 0.0)?; let mut joint = PrismaticJointBuilder::new(axis) .local_anchor1(anchor1.0.into()) .local_anchor2(anchor2.0.into()); if limitsEnabled { joint = joint.limits([limitsMin, limitsMax]); } Some(Self(joint.into())) } /// Creates a new joint descriptor that builds a Prismatic joint. /// /// A prismatic joint removes all the degrees of freedom between the /// affected bodies, except for the translation along one axis. /// /// Returns `None` if any of the provided axes cannot be normalized. #[cfg(feature = "dim3")] pub fn prismatic( anchor1: &RawVector, anchor2: &RawVector, axis: &RawVector, limitsEnabled: bool, limitsMin: f32, limitsMax: f32, ) -> Option { let axis = Unit::try_new(axis.0, 0.0)?; let mut joint = PrismaticJointBuilder::new(axis) .local_anchor1(anchor1.0.into()) .local_anchor2(anchor2.0.into()); if limitsEnabled { joint = joint.limits([limitsMin, limitsMax]); } Some(Self(joint.into())) } /// Creates a new joint descriptor that builds a Fixed joint. /// /// A fixed joint removes all the degrees of freedom between the affected bodies. pub fn fixed( anchor1: &RawVector, axes1: &RawRotation, anchor2: &RawVector, axes2: &RawRotation, ) -> RawGenericJoint { let pos1 = Isometry::from_parts(anchor1.0.into(), axes1.0); let pos2 = Isometry::from_parts(anchor2.0.into(), axes2.0); Self( FixedJointBuilder::new() .local_frame1(pos1) .local_frame2(pos2) .into(), ) } /// Create a new joint descriptor that builds Revolute joints. /// /// A revolute joint removes all degrees of freedom between the affected /// bodies except for the rotation. #[cfg(feature = "dim2")] pub fn revolute(anchor1: &RawVector, anchor2: &RawVector) -> Option { Some(Self( RevoluteJointBuilder::new() .local_anchor1(anchor1.0.into()) .local_anchor2(anchor2.0.into()) .into(), )) } /// Create a new joint descriptor that builds Revolute joints. /// /// A revolute joint removes all degrees of freedom between the affected /// bodies except for the rotation along one axis. #[cfg(feature = "dim3")] pub fn revolute( anchor1: &RawVector, anchor2: &RawVector, axis: &RawVector, ) -> Option { let axis = Unit::try_new(axis.0, 0.0)?; Some(Self( RevoluteJointBuilder::new(axis) .local_anchor1(anchor1.0.into()) .local_anchor2(anchor2.0.into()) .into(), )) } }