diff options
| author | Sébastien Crozet <developer@crozet.re> | 2022-01-02 14:47:40 +0100 |
|---|---|---|
| committer | Sébastien Crozet <developer@crozet.re> | 2022-01-02 16:58:36 +0100 |
| commit | f74b8401ad9ef50b8cdbf1f43a2b21f6c42b0ebc (patch) | |
| tree | 53ac492fea5942a7d466f58a0095f39505674ea4 /src/dynamics/joint | |
| parent | b45d4b5ac2b31856c15e802b31e288a58940cbf2 (diff) | |
| download | rapier-f74b8401ad9ef50b8cdbf1f43a2b21f6c42b0ebc.tar.gz rapier-f74b8401ad9ef50b8cdbf1f43a2b21f6c42b0ebc.tar.bz2 rapier-f74b8401ad9ef50b8cdbf1f43a2b21f6c42b0ebc.zip | |
Implement multibody joints and the new solver
Diffstat (limited to 'src/dynamics/joint')
20 files changed, 2919 insertions, 902 deletions
diff --git a/src/dynamics/joint/ball_joint.rs b/src/dynamics/joint/ball_joint.rs deleted file mode 100644 index 0b626c0..0000000 --- a/src/dynamics/joint/ball_joint.rs +++ /dev/null @@ -1,148 +0,0 @@ -use crate::dynamics::SpringModel; -use crate::math::{Point, Real, Rotation, UnitVector, Vector}; - -#[derive(Copy, Clone, PartialEq)] -#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] -/// A joint that removes all relative linear motion between a pair of points on two bodies. -pub struct BallJoint { - /// Where the ball joint is attached on the first body, expressed in the first body local frame. - pub local_anchor1: Point<Real>, - /// Where the ball joint is attached on the second body, expressed in the second body local frame. - pub local_anchor2: Point<Real>, - /// The impulse applied by this joint on the first body. - /// - /// The impulse applied to the second body is given by `-impulse`. - pub impulse: Vector<Real>, - - /// The target relative angular velocity the motor will attempt to reach. - #[cfg(feature = "dim2")] - pub motor_target_vel: Real, - /// The target relative angular velocity the motor will attempt to reach. - #[cfg(feature = "dim3")] - pub motor_target_vel: Vector<Real>, - /// The target angular position of this joint, expressed as an axis-angle. - pub motor_target_pos: Rotation<Real>, - /// The motor's stiffness. - /// See the documentation of `SpringModel` for more information on this parameter. - pub motor_stiffness: Real, - /// The motor's damping. - /// See the documentation of `SpringModel` for more information on this parameter. - pub motor_damping: Real, - /// The maximal impulse the motor is able to deliver. - pub motor_max_impulse: Real, - /// The angular impulse applied by the motor. - #[cfg(feature = "dim2")] - pub motor_impulse: Real, - /// The angular impulse applied by the motor. - #[cfg(feature = "dim3")] - pub motor_impulse: Vector<Real>, - /// The spring-like model used by the motor to reach the target velocity and . - pub motor_model: SpringModel, - - /// Are the limits enabled for this joint? - pub limits_enabled: bool, - /// The axis of the limit cone for this joint, if the local-space of the first body. - pub limits_local_axis1: UnitVector<Real>, - /// The axis of the limit cone for this joint, if the local-space of the first body. - pub limits_local_axis2: UnitVector<Real>, - /// The maximum angle allowed between the two limit axes in world-space. - pub limits_angle: Real, - /// The impulse applied to enforce joint limits. - pub limits_impulse: Real, -} - -impl BallJoint { - /// Creates a new Ball joint from two anchors given on the local spaces of the respective bodies. - pub fn new(local_anchor1: Point<Real>, local_anchor2: Point<Real>) -> Self { - Self::with_impulse(local_anchor1, local_anchor2, Vector::zeros()) - } - - pub(crate) fn with_impulse( - local_anchor1: Point<Real>, - local_anchor2: Point<Real>, - impulse: Vector<Real>, - ) -> Self { - Self { - local_anchor1, - local_anchor2, - impulse, - motor_target_vel: na::zero(), - motor_target_pos: Rotation::identity(), - motor_stiffness: 0.0, - motor_damping: 0.0, - motor_impulse: na::zero(), - motor_max_impulse: Real::MAX, - motor_model: SpringModel::default(), - limits_enabled: false, - limits_local_axis1: Vector::x_axis(), - limits_local_axis2: Vector::x_axis(), - limits_angle: Real::MAX, - limits_impulse: 0.0, - } - } - - /// Can a SIMD constraint be used for resolving this joint? - pub fn supports_simd_constraints(&self) -> bool { - // SIMD ball constraints don't support motors and limits right now. - !self.limits_enabled - && (self.motor_max_impulse == 0.0 - || (self.motor_stiffness == 0.0 && self.motor_damping == 0.0)) - } - - /// Set the spring-like model used by the motor to reach the desired target velocity and position. - pub fn configure_motor_model(&mut self, model: SpringModel) { - self.motor_model = model; - } - - /// Sets the target velocity and velocity correction factor this motor. - #[cfg(feature = "dim2")] - pub fn configure_motor_velocity(&mut self, target_vel: Real, factor: Real) { - self.configure_motor(self.motor_target_pos, target_vel, 0.0, factor) - } - - /// Sets the target velocity and velocity correction factor this motor. - #[cfg(feature = "dim3")] - pub fn configure_motor_velocity(&mut self, target_vel: Vector<Real>, factor: Real) { - self.configure_motor(self.motor_target_pos, target_vel, 0.0, factor) - } - - /// Sets the target orientation this motor needs to reach. - pub fn configure_motor_position( - &mut self, - target_pos: Rotation<Real>, - stiffness: Real, - damping: Real, - ) { - self.configure_motor(target_pos, na::zero(), stiffness, damping) - } - - /// Sets the target orientation this motor needs to reach. - #[cfg(feature = "dim2")] - pub fn configure_motor( - &mut self, - target_pos: Rotation<Real>, - target_vel: Real, - stiffness: Real, - damping: Real, - ) { - self.motor_target_vel = target_vel; - self.motor_target_pos = target_pos; - self.motor_stiffness = stiffness; - self.motor_damping = damping; - } - - /// Configure both the target orientation and target velocity of the motor. - #[cfg(feature = "dim3")] - pub fn configure_motor( - &mut self, - target_pos: Rotation<Real>, - target_vel: Vector<Real>, - stiffness: Real, - damping: Real, - ) { - self.motor_target_vel = target_vel; - self.motor_target_pos = target_pos; - self.motor_stiffness = stiffness; - self.motor_damping = damping; - } -} diff --git a/src/dynamics/joint/fixed_joint.rs b/src/dynamics/joint/fixed_joint.rs index 6424750..10c4d7e 100644 --- a/src/dynamics/joint/fixed_joint.rs +++ b/src/dynamics/joint/fixed_joint.rs @@ -1,38 +1,55 @@ -use crate::math::{Isometry, Real, SpacialVector}; +use crate::dynamics::{JointAxesMask, JointData}; +use crate::math::{Isometry, Point, Real}; -#[derive(Copy, Clone, PartialEq)] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] -/// A joint that prevents all relative movement between two bodies. -/// -/// Given two frames of references, this joint aims to ensure these frame always coincide in world-space. +#[derive(Copy, Clone, Debug, PartialEq)] pub struct FixedJoint { - /// The frame of reference for the first body affected by this joint, expressed in the local frame - /// of the first body. - pub local_frame1: Isometry<Real>, - /// The frame of reference for the second body affected by this joint, expressed in the local frame - /// of the first body. - pub local_frame2: Isometry<Real>, - /// The impulse applied to the first body affected by this joint. - /// - /// The impulse applied to the second body affected by this joint is given by `-impulse`. - /// This combines both linear and angular impulses: - /// - In 2D, `impulse.xy()` gives the linear impulse, and `impulse.z` the angular impulse. - /// - In 3D, `impulse.xyz()` gives the linear impulse, and `(impulse[3], impulse[4], impulse[5])` the angular impulse. - pub impulse: SpacialVector<Real>, + data: JointData, } impl FixedJoint { - /// Creates a new fixed joint from the frames of reference of both bodies. - pub fn new(local_frame1: Isometry<Real>, local_frame2: Isometry<Real>) -> Self { - Self { - local_frame1, - local_frame2, - impulse: SpacialVector::zeros(), - } + pub fn new() -> Self { + #[cfg(feature = "dim2")] + let mask = JointAxesMask::X | JointAxesMask::Y | JointAxesMask::ANG_X; + #[cfg(feature = "dim3")] + let mask = JointAxesMask::X + | JointAxesMask::Y + | JointAxesMask::Z + | JointAxesMask::ANG_X + | JointAxesMask::ANG_Y + | JointAxesMask::ANG_Z; + + let data = JointData::default().lock_axes(mask); + Self { data } + } + + #[must_use] + pub fn local_frame1(mut self, local_frame: Isometry<Real>) -> Self { + self.data = self.data.local_frame1(local_frame); + self + } + + #[must_use] + pub fn local_frame2(mut self, local_frame: Isometry<Real>) -> Self { + self.data = self.data.local_frame2(local_frame); + self } - /// Can a SIMD constraint be used for resolving this joint? - pub fn supports_simd_constraints(&self) -> bool { - true + #[must_use] + pub fn local_anchor1(mut self, anchor1: Point<Real>) -> Self { + self.data = self.data.local_anchor1(anchor1); + self + } + + #[must_use] + pub fn local_anchor2(mut self, anchor2: Point<Real>) -> Self { + self.data = self.data.local_anchor2(anchor2); + self + } +} + +impl Into<JointData> for FixedJoint { + fn into(self) -> JointData { + self.data } } diff --git a/src/dynamics/joint/generic_joint.rs b/src/dynamics/joint/generic_joint.rs deleted file mode 100644 index 78f1e84..0000000 --- a/src/dynamics/joint/generic_joint.rs +++ /dev/null @@ -1,144 +0,0 @@ -use crate::dynamics::{BallJoint, FixedJoint, PrismaticJoint, RevoluteJoint}; -use crate::math::{Isometry, Real, SpacialVector}; -use crate::na::{Rotation3, UnitQuaternion}; - -#[derive(Copy, Clone, Debug, PartialEq)] -#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] -/// A joint that prevents all relative movement between two bodies. -/// -/// Given two frames of references, this joint aims to ensure these frame always coincide in world-space. -pub struct GenericJoint { - /// The frame of reference for the first body affected by this joint, expressed in the local frame - /// of the first body. - pub local_anchor1: Isometry<Real>, - /// The frame of reference for the second body affected by this joint, expressed in the local frame - /// of the first body. - pub local_anchor2: Isometry<Real>, - /// The impulse applied to the first body affected by this joint. - /// - /// The impulse applied to the second body affected by this joint is given by `-impulse`. - /// This combines both linear and angular impulses: - /// - In 2D, `impulse.xy()` gives the linear impulse, and `impulse.z` the angular impulse. - /// - In 3D, `impulse.xyz()` gives the linear impulse, and `(impulse[3], impulse[4], impulse[5])` the angular impulse. - pub impulse: SpacialVector<Real>, - - pub min_position: SpacialVector<Real>, - pub max_position: SpacialVector<Real>, - pub min_velocity: SpacialVector<Real>, - pub max_velocity: SpacialVector<Real>, - /// The minimum negative impulse the joint can apply on each DoF. Must be <= 0.0 - pub min_impulse: SpacialVector<Real>, - /// The maximum positive impulse the joint can apply on each DoF. Must be >= 0.0 - pub max_impulse: SpacialVector<Real>, - /// The minimum negative position impulse the joint can apply on each DoF. Must be <= 0.0 - pub min_pos_impulse: SpacialVector<Real>, - /// The maximum positive position impulse the joint can apply on each DoF. Must be >= 0.0 - pub max_pos_impulse: SpacialVector<Real>, -} - -impl GenericJoint { - /// Creates a new fixed joint from the frames of reference of both bodies. - pub fn new(local_anchor1: Isometry<Real>, local_anchor2: Isometry<Real>) -> Self { - Self { - local_anchor1, - local_anchor2, - impulse: SpacialVector::zeros(), - min_position: SpacialVector::zeros(), - max_position: SpacialVector::zeros(), - min_velocity: SpacialVector::zeros(), - max_velocity: SpacialVector::zeros(), - min_impulse: SpacialVector::repeat(-Real::MAX), - max_impulse: SpacialVector::repeat(Real::MAX), - min_pos_impulse: SpacialVector::repeat(-Real::MAX), - max_pos_impulse: SpacialVector::repeat(Real::MAX), - } - } - - pub fn set_dof_vel(&mut self, dof: u8, target_vel: Real, max_force: Real) { - self.min_velocity[dof as usize] = target_vel; - self.max_velocity[dof as usize] = target_vel; - self.min_impulse[dof as usize] = -max_force; - self.max_impulse[dof as usize] = max_force; - } - - pub fn free_dof(&mut self, dof: u8) { - self.min_position[dof as usize] = -Real::MAX; - self.max_position[dof as usize] = Real::MAX; - self.min_velocity[dof as usize] = -Real::MAX; - self.max_velocity[dof as usize] = Real::MAX; - self.min_impulse[dof as usize] = 0.0; - self.max_impulse[dof as usize] = 0.0; - self.min_pos_impulse[dof as usize] = 0.0; - self.max_pos_impulse[dof as usize] = 0.0; - } - - pub fn set_dof_limits(&mut self, dof: u8, min: Real, max: Real) { - self.min_position[dof as usize] = min; - self.max_position[dof as usize] = max; - } -} - -impl From<RevoluteJoint> for GenericJoint { - fn from(joint: RevoluteJoint) -> Self { - let basis1 = [*joint.local_axis1, joint.basis1[0], joint.basis1[1]]; - let basis2 = [*joint.local_axis2, joint.basis2[0], joint.basis2[1]]; - let quat1 = UnitQuaternion::from_basis_unchecked(&basis1); - let quat2 = UnitQuaternion::from_basis_unchecked(&basis2); - let local_anchor1 = Isometry::from_parts(joint.local_anchor1.coords.into(), quat1); - let local_anchor2 = Isometry::from_parts(joint.local_anchor2.coords.into(), quat2); - - let mut result = Self::new(local_anchor1, local_anchor2); - result.free_dof(3); - - if joint.motor_damping != 0.0 { - result.set_dof_vel(3, joint.motor_target_vel, joint.motor_max_impulse); - } - - result.impulse[0] = joint.impulse[0]; - result.impulse[1] = joint.impulse[1]; - result.impulse[2] = joint.impulse[2]; - result.impulse[3] = joint.motor_impulse; - result.impulse[4] = joint.impulse[3]; - result.impulse[5] = joint.impulse[4]; - - result - } -} - -impl From<BallJoint> for GenericJoint { - fn from(joint: BallJoint) -> Self { - let local_anchor1 = Isometry::new(joint.local_anchor1.coords, na::zero()); - let local_anchor2 = Isometry::new(joint.local_anchor2.coords, na::zero()); - - let mut result = Self::new(local_anchor1, local_anchor2); - result.impulse[0] = joint.impulse[0]; - result.impulse[1] = joint.impulse[1]; - result.impulse[2] = joint.impulse[2]; - result.free_dof(3); - result.free_dof(4); - result.free_dof(5); - result - } -} - -impl From<PrismaticJoint> for GenericJoint { - fn from(joint: PrismaticJoint) -> Self { - let basis1 = [*joint.local_axis1, joint.basis1[0], joint.basis1[1]]; - let basis2 = [*joint.local_axis2, joint.basis2[0], joint.basis2[1]]; - let quat1 = UnitQuaternion::from_basis_unchecked(&basis1); - let quat2 = UnitQuaternion::from_basis_unchecked(&basis2); - let local_anchor1 = Isometry::from_parts(joint.local_anchor1.coords.into(), quat1); - let local_anchor2 = Isometry::from_parts(joint.local_anchor2.coords.into(), quat2); - - let mut result = Self::new(local_anchor1, local_anchor2); - result.free_dof(0); - result.set_dof_limits(0, joint.limits[0], joint.limits[1]); - result - } -} - -impl From<FixedJoint> for GenericJoint { - fn from(joint: FixedJoint) -> Self { - Self::new(joint.local_anchor1, joint.local_anchor2) - } -} diff --git a/src/dynamics/joint/impulse_joint/impulse_joint.rs b/src/dynamics/joint/impulse_joint/impulse_joint.rs new file mode 100644 index 0000000..a12c533 --- /dev/null +++ b/src/dynamics/joint/impulse_joint/impulse_joint.rs @@ -0,0 +1,20 @@ +use crate::dynamics::{JointData, JointHandle, RigidBodyHandle}; +use crate::math::{Real, SpacialVector}; + +#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] +#[derive(Clone, Debug, PartialEq)] +/// A joint attached to two bodies. +pub struct ImpulseJoint { + /// Handle to the first body attached to this joint. + pub body1: RigidBodyHandle, + /// Handle to the second body attached to this joint. + pub body2: RigidBodyHandle, + + pub data: JointData, + pub impulses: SpacialVector<Real>, + + // A joint needs to know its handle to simplify its removal. + pub(crate) handle: JointHandle, + #[cfg(feature = "parallel")] + pub(crate) constraint_index: usize, +} diff --git a/src/dynamics/joint/joint_set.rs b/src/dynamics/joint/impulse_joint/impulse_joint_set.rs index aba2aa8..183b668 100644 --- a/src/dynamics/joint/joint_set.rs +++ b/src/dynamics/joint/impulse_joint/impulse_joint_set.rs @@ -1,10 +1,10 @@ -use super::Joint; +use super::ImpulseJoint; use crate::geometry::{InteractionGraph, RigidBodyGraphIndex, TemporaryInteractionIndex}; use crate::data::arena::Arena; use crate::data::{BundleSet, Coarena, ComponentSet, ComponentSetMut}; use crate::dynamics::{IslandManager, RigidBodyActivation, RigidBodyIds, RigidBodyType}; -use crate::dynamics::{JointParams, RigidBodyHandle}; +use crate::dynamics::{JointData, RigidBodyHandle}; /// The unique identifier of a joint added to the joint set. /// The unique identifier of a collider added to a collider set. @@ -34,19 +34,19 @@ impl JointHandle { } pub(crate) type JointIndex = usize; -pub(crate) type JointGraphEdge = crate::data::graph::Edge<Joint>; +pub(crate) type JointGraphEdge = crate::data::graph::Edge<ImpulseJoint>; #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[derive(Clone, Default)] -/// A set of joints that can be handled by a physics `World`. -pub struct JointSet { +/// A set of impulse_joints that can be handled by a physics `World`. +pub struct ImpulseJointSet { rb_graph_ids: Coarena<RigidBodyGraphIndex>, joint_ids: Arena<TemporaryInteractionIndex>, // Map joint handles to edge ids on the graph. - joint_graph: InteractionGraph<RigidBodyHandle, Joint>, + joint_graph: InteractionGraph<RigidBodyHandle, ImpulseJoint>, } -impl JointSet { - /// Creates a new empty set of joints. +impl ImpulseJointSet { + /// Creates a new empty set of impulse_joints. pub fn new() -> Self { Self { rb_graph_ids: Coarena::new(), @@ -55,26 +55,26 @@ impl JointSet { } } - /// The number of joints on this set. + /// The number of impulse_joints on this set. pub fn len(&self) -> usize { self.joint_graph.graph.edges.len() } - /// `true` if there are no joints in this set. + /// `true` if there are no impulse_joints in this set. pub fn is_empty(&self) -> bool { self.joint_graph.graph.edges.is_empty() } - /// Retrieve the joint graph where edges are joints and nodes are rigid body handles. - pub fn joint_graph(&self) -> &InteractionGraph<RigidBodyHandle, Joint> { + /// Retrieve the joint graph where edges are impulse_joints and nodes are rigid body handles. + pub fn joint_graph(&self) -> &InteractionGraph<RigidBodyHandle, ImpulseJoint> { &self.joint_graph } - /// Iterates through all the joitns attached to the given rigid-body. + /// Iterates through all the impulse_joints attached to the given rigid-body. pub fn joints_with<'a>( &'a self, body: RigidBodyHandle, - ) -> impl Iterator<Item = (RigidBodyHandle, RigidBodyHandle, &'a Joint)> { + ) -> impl Iterator<Item = (RigidBodyHandle, RigidBodyHandle, &'a ImpulseJoint)> { self.rb_graph_ids .get(body.0) .into_iter() @@ -87,13 +87,13 @@ impl JointSet { } /// Gets the joint with the given handle. - pub fn get(&self, handle: JointHandle) -> Option<&Joint> { + pub fn get(&self, handle: JointHandle) -> Option<&ImpulseJoint> { let id = self.joint_ids.get(handle.0)?; self.joint_graph.graph.edge_weight(*id) } /// Gets a mutable reference to the joint with the given handle. - pub fn get_mut(&mut self, handle: JointHandle) -> Option<&mut Joint> { + pub fn get_mut(&mut self, handle: JointHandle) -> Option<&mut ImpulseJoint> { let id = self.joint_ids.get(handle.0)?; self.joint_graph.graph.edge_weight_mut(*id) } @@ -107,7 +107,7 @@ impl JointSet { /// /// Using this is discouraged in favor of `self.get(handle)` which does not /// suffer form the ABA problem. - pub fn get_unknown_gen(&self, i: u32) -> Option<(&Joint, JointHandle)> { + pub fn get_unknown_gen(&self, i: u32) -> Option<(&ImpulseJoint, JointHandle)> { let (id, handle) = self.joint_ids.get_unknown_gen(i)?; Some(( self.joint_graph.graph.edge_weight(*id)?, @@ -124,7 +124,7 @@ impl JointSet { /// /// Using this is discouraged in favor of `self.get_mut(handle)` which does not /// suffer form the ABA problem. - pub fn get_unknown_gen_mut(&mut self, i: u32) -> Option<(&mut Joint, JointHandle)> { + pub fn get_unknown_gen_mut(&mut self, i: u32) -> Option<(&mut ImpulseJoint, JointHandle)> { let (id, handle) = self.joint_ids.get_unknown_gen(i)?; Some(( self.joint_graph.graph.edge_weight_mut(*id)?, @@ -133,7 +133,7 @@ impl JointSet { } /// Iterates through all the joint on this set. - pub fn iter(&self) -> impl Iterator<Item = (JointHandle, &Joint)> { + pub fn iter(&self) -> impl Iterator<Item = (JointHandle, &ImpulseJoint)> { self.joint_graph .graph .edges @@ -142,7 +142,7 @@ impl JointSet { } /// Iterates mutably through all the joint on this set. - pub fn iter_mut(&mut self) -> impl Iterator<Item = (JointHandle, &mut Joint)> { + pub fn iter_mut(&mut self) -> impl Iterator<Item = (JointHandle, &mut ImpulseJoint)> { self.joint_graph .graph .edges @@ -150,8 +150,8 @@ impl JointSet { .map(|e| (e.weight.handle, &mut e.weight)) } - // /// The set of joints as an array. - // pub(crate) fn joints(&self) -> &[JointGraphEdge] { + // /// The set of impulse_joints as an array. + // pub(crate) fn impulse_joints(&self) -> &[JointGraphEdge] { // // self.joint_graph // // .graph // // .edges @@ -170,25 +170,22 @@ impl JointSet { } /// Inserts a new joint into this set and retrieve its handle. - pub fn insert<J>( + pub fn insert( &mut self, body1: RigidBodyHandle, body2: RigidBodyHandle, - joint_params: J, - ) -> JointHandle - where - J: Into<JointParams>, - { + data: impl Into<JointData>, + ) -> JointHandle { + let data = data.into(); let handle = self.joint_ids.insert(0.into()); - let joint = Joint { + let joint = ImpulseJoint { body1, body2, + data, + impulses: na::zero(), handle: JointHandle(handle), #[cfg(feature = "parallel")] constraint_index: 0, - #[cfg(feature = "parallel")] - position_constraint_index: 0, - params: joint_params.into(), }; let default_id = InteractionGraph::<(), ()>::invalid_graph_index(); @@ -201,12 +198,12 @@ impl JointSet { // NOTE: the body won't have a graph index if it does not // have any joint attached. - if !InteractionGraph::<RigidBodyHandle, Joint>::is_graph_index_valid(graph_index1) { + if !InteractionGraph::<RigidBodyHandle, ImpulseJoint>::is_graph_index_valid(graph_index1) { graph_index1 = self.joint_graph.graph.add_node(joint.body1); self.rb_graph_ids.insert(joint.body1.0, graph_index1); } - if !InteractionGraph::<RigidBodyHandle, Joint>::is_graph_index_valid(graph_index2) { + if !InteractionGraph::<RigidBodyHandle, ImpulseJoint>::is_graph_index_valid(graph_index2) { graph_index2 = self.joint_graph.graph.add_node(joint.body2); self.rb_graph_ids.insert(joint.body2.0, graph_index2); } @@ -215,7 +212,7 @@ impl JointSet { JointHandle(handle) } - /// Retrieve all the joints happening between two active bodies. + /// Retrieve all the impulse_joints happening between two active bodies. // NOTE: this is very similar to the code from NarrowPhase::select_active_interactions. pub(crate) fn select_active_interactions<Bodies>( &self, @@ -271,7 +268,7 @@ impl JointSet { islands: &mut IslandManager, bodies: &mut Bodies, wake_up: bool, - ) -> Option<Joint> + ) -> Option<ImpulseJoint> where Bodies: ComponentSetMut<RigidBodyActivation> + ComponentSet<RigidBodyType> @@ -299,11 +296,11 @@ impl JointSet { removed_joint } - /// Deletes all the joints attached to the given rigid-body. + /// Deletes all the impulse_joints attached to the given rigid-body. /// /// The provided rigid-body handle is not required to identify a rigid-body that /// is still contained by the `bodies` component set. - /// Returns the (now invalid) handles of the removed joints. + /// Returns the (now invalid) handles of the removed impulse_joints. pub fn remove_joints_attached_to_rigid_body<Bodies>( &mut self, handle: RigidBodyHandle, diff --git a/src/dynamics/joint/impulse_joint/mod.rs b/src/dynamics/joint/impulse_joint/mod.rs new file mode 100644 index 0000000..2afe078 --- /dev/null +++ b/src/dynamics/joint/impulse_joint/mod.rs @@ -0,0 +1,6 @@ +pub use self::impulse_joint::ImpulseJoint; +pub use self::impulse_joint_set::{ImpulseJointSet, JointHandle}; +pub(crate) use self::impulse_joint_set::{JointGraphEdge, JointIndex}; + +mod impulse_joint; +mod impulse_joint_set; diff --git a/src/dynamics/joint/joint.rs b/src/dynamics/joint/joint.rs deleted file mode 100644 index 0c2c864..0000000 --- a/src/dynamics/joint/joint.rs +++ /dev/null @@ -1,143 +0,0 @@ -#[cfg(feature = "dim3")] -use crate::dynamics::RevoluteJoint; -use crate::dynamics::{BallJoint, FixedJoint, JointHandle, PrismaticJoint, RigidBodyHandle}; - -#[derive(Copy, Clone, PartialEq)] -#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] -/// An enum grouping all possible types of joints. -pub enum JointParams { - /// A Ball joint that removes all relative linear degrees of freedom between the affected bodies. - BallJoint(BallJoint), - /// A fixed joint that removes all relative degrees of freedom between the affected bodies. - FixedJoint(FixedJoint), - /// A prismatic joint that removes all degrees of degrees of freedom between the affected - /// bodies except for the translation along one axis. - PrismaticJoint(PrismaticJoint), - #[cfg(feature = "dim3")] - /// A revolute joint that removes all degrees of degrees of freedom between the affected - /// bodies except for the translation along one axis. - RevoluteJoint(RevoluteJoint), - // GenericJoint(GenericJoint), -} - -impl JointParams { - /// An integer identifier for each type of joint. - pub fn type_id(&self) -> usize { - match self { - JointParams::BallJoint(_) => 0, - JointParams::FixedJoint(_) => 1, - JointParams::PrismaticJoint(_) => 2, - // JointParams::GenericJoint(_) => 3, - #[cfg(feature = "dim3")] - JointParams::RevoluteJoint(_) => 4, - } - } - - /// Gets a reference to the underlying ball joint, if `self` is one. - pub fn as_ball_joint(&self) -> Option<&BallJoint> { - if let JointParams::BallJoint(j) = self { - Some(j) - } else { - None - } - } - - /// Gets a reference to the underlying fixed joint, if `self` is one. - pub fn as_fixed_joint(&self) -> Option<&FixedJoint> { - if let JointParams::FixedJoint(j) = self { - Some(j) - } else { - None - } - } - - // /// Gets a reference to the underlying generic joint, if `self` is one. - // pub fn as_generic_joint(&self) -> Option<&GenericJoint> { - // if let JointParams::GenericJoint(j) = self { - // Some(j) - // } else { - // None - // } - // } - - /// Gets a reference to the underlying prismatic joint, if `self` is one. - pub fn as_prismatic_joint(&self) -> Option<&PrismaticJoint> { - if let JointParams::PrismaticJoint(j) = self { - Some(j) - } else { - None - } - } - - /// Gets a reference to the underlying revolute joint, if `self` is one. - #[cfg(feature = "dim3")] - pub fn as_revolute_joint(&self) -> Option<&RevoluteJoint> { - if let JointParams::RevoluteJoint(j) = self { - Some(j) - } else { - None - } - } -} - -impl From<BallJoint> for JointParams { - fn from(j: BallJoint) -> Self { - JointParams::BallJoint(j) - } -} - -impl From<FixedJoint> for JointParams { - fn from(j: FixedJoint) -> Self { - JointParams::FixedJoint(j) - } -} - -// impl From<GenericJoint> for JointParams { -// fn from(j: GenericJoint) -> Self { -// JointParams::GenericJoint(j) -// } -// } - -#[cfg(feature = "dim3")] -impl From<RevoluteJoint> for JointParams { - fn from(j: RevoluteJoint) -> Self { - JointParams::RevoluteJoint(j) - } -} - -impl From<PrismaticJoint> for JointParams { - fn from(j: PrismaticJoint) -> Self { - JointParams::PrismaticJoint(j) - } -} - -#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] -#[derive(Clone)] -/// A joint attached to two bodies. -pub struct Joint { - /// Handle to the first body attached to this joint. - pub body1: RigidBodyHandle, - /// Handle to the second body attached to this joint. |
