diff --git a/crates/avian2d/examples/distance_joint_2d.rs b/crates/avian2d/examples/distance_joint_2d.rs index 633e9b504..f03c27f98 100644 --- a/crates/avian2d/examples/distance_joint_2d.rs +++ b/crates/avian2d/examples/distance_joint_2d.rs @@ -42,7 +42,7 @@ fn setup(mut commands: Commands) { DistanceJoint::new(anchor, object) .with_local_anchor_1(Vector::ZERO) .with_local_anchor_2(Vector::ZERO) - .with_rest_length(100.0) + .with_limits(100.0, 100.0) .with_linear_velocity_damping(0.1) .with_angular_velocity_damping(1.0) .with_compliance(0.00000001), diff --git a/crates/avian3d/examples/distance_joint_3d.rs b/crates/avian3d/examples/distance_joint_3d.rs index 9e90f2b50..27281626a 100644 --- a/crates/avian3d/examples/distance_joint_3d.rs +++ b/crates/avian3d/examples/distance_joint_3d.rs @@ -45,7 +45,7 @@ fn setup( commands.spawn( DistanceJoint::new(static_cube, dynamic_cube) .with_local_anchor_2(0.5 * Vector::ONE) - .with_rest_length(1.5) + .with_limits(1.5, 1.5) .with_compliance(1.0 / 400.0), ); diff --git a/src/dynamics/solver/joints/distance.rs b/src/dynamics/solver/joints/distance.rs index c8e3aa4cc..db2009450 100644 --- a/src/dynamics/solver/joints/distance.rs +++ b/src/dynamics/solver/joints/distance.rs @@ -31,10 +31,8 @@ pub struct DistanceJoint { pub local_anchor1: Vector, /// Attachment point on the second body. pub local_anchor2: Vector, - /// The distance the attached bodies will be kept relative to each other. - pub rest_length: Scalar, /// The extents of the allowed relative translation between the attached bodies. - pub length_limits: Option, + pub length_limits: DistanceLimit, /// Linear damping applied by the joint. pub damping_linear: Scalar, /// Angular damping applied by the joint. @@ -110,15 +108,9 @@ impl XpbdConstraint<2> for DistanceJoint { + (world_r2 - world_r1) + self.pre_step.center_difference; - // If min and max limits aren't specified, use rest length - // TODO: Remove rest length, just use min/max limits. - let limits = self - .length_limits - .unwrap_or(DistanceLimit::new(self.rest_length, self.rest_length)); - // Compute the direction and magnitude of the positional correction required // to keep the bodies within a certain distance from each other. - let (dir, distance) = limits.compute_correction(separation); + let (dir, distance) = self.length_limits.compute_correction(separation); if distance <= Scalar::EPSILON { // No separation, no need to apply a correction. @@ -172,8 +164,7 @@ impl Joint for DistanceJoint { entity2, local_anchor1: Vector::ZERO, local_anchor2: Vector::ZERO, - rest_length: 0.0, - length_limits: None, + length_limits: DistanceLimit::ZERO, damping_linear: 0.0, damping_angular: 0.0, relative_dominance: 0, @@ -262,20 +253,11 @@ impl DistanceJoint { self.force } - /// Sets the minimum and maximum distances between the attached bodies. - pub fn with_limits(self, min: Scalar, max: Scalar) -> Self { - Self { - length_limits: Some(DistanceLimit::new(min, max)), - ..self - } - } - - /// Sets the joint's rest length, or distance the bodies will be kept at. - pub fn with_rest_length(self, rest_length: Scalar) -> Self { - Self { - rest_length, - ..self - } + /// Sets the minimum and maximum distance between the anchor points of the bodies. + #[inline] + pub const fn with_limits(mut self, min: Scalar, max: Scalar) -> Self { + self.length_limits = DistanceLimit { min, max }; + self } } diff --git a/src/dynamics/solver/joints/mod.rs b/src/dynamics/solver/joints/mod.rs index 0c4d4e3d1..817c72094 100644 --- a/src/dynamics/solver/joints/mod.rs +++ b/src/dynamics/solver/joints/mod.rs @@ -153,6 +153,30 @@ pub struct DistanceLimit { pub max: Scalar, } +impl From for DistanceLimit { + /// Converts the given `limit` into a [`DistanceLimit`] where `min == max`. + fn from(limit: Scalar) -> DistanceLimit { + DistanceLimit { + min: limit, + max: limit, + } + } +} + +impl From<[Scalar; 2]> for DistanceLimit { + /// Converts the given `[min, max]` array into a [`DistanceLimit`]. + fn from([min, max]: [Scalar; 2]) -> DistanceLimit { + DistanceLimit { min, max } + } +} + +impl From<(Scalar, Scalar)> for DistanceLimit { + /// Converts the given `(min, max)` pair into a [`DistanceLimit`]. + fn from((min, max): (Scalar, Scalar)) -> DistanceLimit { + DistanceLimit { min, max } + } +} + impl DistanceLimit { /// A `DistanceLimit` with `min` and `max` set to zero. pub const ZERO: Self = Self { min: 0.0, max: 0.0 }; @@ -215,6 +239,30 @@ pub struct AngleLimit { pub max: Scalar, } +impl From for AngleLimit { + /// Converts the given `limit` into a [`AngleLimit`] where `min == max`. + fn from(limit: Scalar) -> AngleLimit { + AngleLimit { + min: limit, + max: limit, + } + } +} + +impl From<[Scalar; 2]> for AngleLimit { + /// Converts the given `[min, max]` array into a [`AngleLimit`]. + fn from([min, max]: [Scalar; 2]) -> AngleLimit { + AngleLimit { min, max } + } +} + +impl From<(Scalar, Scalar)> for AngleLimit { + /// Converts the given `(min, max)` pair into a [`AngleLimit`]. + fn from((min, max): (Scalar, Scalar)) -> AngleLimit { + AngleLimit { min, max } + } +} + impl AngleLimit { /// An `AngleLimit` with `alpha` and `beta` set to zero. pub const ZERO: Self = Self { min: 0.0, max: 0.0 };