aboutsummaryrefslogtreecommitdiff
path: root/src/dynamics/joint
diff options
context:
space:
mode:
authorSébastien Crozet <developer@crozet.re>2022-01-02 18:05:50 +0100
committerGitHub <noreply@github.com>2022-01-02 18:05:50 +0100
commit1308db89948bc62fb865b32f832f19268f23dd23 (patch)
treeb3d8b0cbb6d2e75aa8fc7686e9cb8801527a31b8 /src/dynamics/joint
parent8e7da5ad45d180b0d3fa2bde37f8f3771b153b70 (diff)
parent9f9d3293605fa84555c08bec5efe68a71cd18432 (diff)
downloadrapier-1308db89948bc62fb865b32f832f19268f23dd23.tar.gz
rapier-1308db89948bc62fb865b32f832f19268f23dd23.tar.bz2
rapier-1308db89948bc62fb865b32f832f19268f23dd23.zip
Merge pull request #267 from dimforge/multibody
Implement multibody joints, and new velocity-based constraints solver
Diffstat (limited to 'src/dynamics/joint')
-rw-r--r--src/dynamics/joint/ball_joint.rs148
-rw-r--r--src/dynamics/joint/fixed_joint.rs73
-rw-r--r--src/dynamics/joint/generic_joint.rs144
-rw-r--r--src/dynamics/joint/impulse_joint/impulse_joint.rs20
-rw-r--r--src/dynamics/joint/impulse_joint/impulse_joint_set.rs (renamed from src/dynamics/joint/joint_set.rs)73
-rw-r--r--src/dynamics/joint/impulse_joint/mod.rs6
-rw-r--r--src/dynamics/joint/joint.rs143
-rw-r--r--src/dynamics/joint/joint_data.rs270
-rw-r--r--src/dynamics/joint/mod.rs27
-rw-r--r--src/dynamics/joint/motor_model.rs (renamed from src/dynamics/joint/spring_model.rs)36
-rw-r--r--src/dynamics/joint/multibody_joint/mod.rs15
-rw-r--r--src/dynamics/joint/multibody_joint/multibody.rs1021
-rw-r--r--src/dynamics/joint/multibody_joint/multibody_joint.rs571
-rw-r--r--src/dynamics/joint/multibody_joint/multibody_joint_set.rs352
-rw-r--r--src/dynamics/joint/multibody_joint/multibody_link.rs173
-rw-r--r--src/dynamics/joint/multibody_joint/multibody_workspace.rs27
-rw-r--r--src/dynamics/joint/multibody_joint/unit_multibody_joint.rs122
-rw-r--r--src/dynamics/joint/prismatic_joint.rs289
-rw-r--r--src/dynamics/joint/revolute_joint.rs220
-rw-r--r--src/dynamics/joint/spherical_joint.rs91
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(featu