Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/avian2d/examples/distance_joint_2d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
2 changes: 1 addition & 1 deletion crates/avian3d/examples/distance_joint_3d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
);

Expand Down
34 changes: 8 additions & 26 deletions src/dynamics/solver/joints/distance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<DistanceLimit>,
pub length_limits: DistanceLimit,
/// Linear damping applied by the joint.
pub damping_linear: Scalar,
/// Angular damping applied by the joint.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
}
}

Expand Down
48 changes: 48 additions & 0 deletions src/dynamics/solver/joints/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,30 @@ pub struct DistanceLimit {
pub max: Scalar,
}

impl From<Scalar> 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 };
Expand Down Expand Up @@ -215,6 +239,30 @@ pub struct AngleLimit {
pub max: Scalar,
}

impl From<Scalar> 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 };
Expand Down
Loading