rapier3d/dynamics/joint/
rope_joint.rs

1use crate::dynamics::joint::{GenericJoint, GenericJointBuilder, JointAxesMask};
2use crate::dynamics::{JointAxis, MotorModel};
3use crate::math::{Point, Real};
4
5use super::JointMotor;
6
7#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
8#[derive(Copy, Clone, Debug, PartialEq)]
9#[repr(transparent)]
10/// A rope joint, limits the maximum distance between two bodies
11pub struct RopeJoint {
12    /// The underlying joint data.
13    pub data: GenericJoint,
14}
15
16impl RopeJoint {
17    /// Creates a new rope joint limiting the max distance between two bodies.
18    ///
19    /// The `max_dist` must be strictly greater than 0.0.
20    pub fn new(max_dist: Real) -> Self {
21        let data = GenericJointBuilder::new(JointAxesMask::empty())
22            .coupled_axes(JointAxesMask::LIN_AXES)
23            .build();
24        let mut result = Self { data };
25        result.set_max_distance(max_dist);
26        result
27    }
28
29    /// The underlying generic joint.
30    pub fn data(&self) -> &GenericJoint {
31        &self.data
32    }
33
34    /// Are contacts between the attached rigid-bodies enabled?
35    pub fn contacts_enabled(&self) -> bool {
36        self.data.contacts_enabled
37    }
38
39    /// Sets whether contacts between the attached rigid-bodies are enabled.
40    pub fn set_contacts_enabled(&mut self, enabled: bool) -> &mut Self {
41        self.data.set_contacts_enabled(enabled);
42        self
43    }
44
45    /// The joint’s anchor, expressed in the local-space of the first rigid-body.
46    #[must_use]
47    pub fn local_anchor1(&self) -> Point<Real> {
48        self.data.local_anchor1()
49    }
50
51    /// Sets the joint’s anchor, expressed in the local-space of the first rigid-body.
52    pub fn set_local_anchor1(&mut self, anchor1: Point<Real>) -> &mut Self {
53        self.data.set_local_anchor1(anchor1);
54        self
55    }
56
57    /// The joint’s anchor, expressed in the local-space of the second rigid-body.
58    #[must_use]
59    pub fn local_anchor2(&self) -> Point<Real> {
60        self.data.local_anchor2()
61    }
62
63    /// Sets the joint’s anchor, expressed in the local-space of the second rigid-body.
64    pub fn set_local_anchor2(&mut self, anchor2: Point<Real>) -> &mut Self {
65        self.data.set_local_anchor2(anchor2);
66        self
67    }
68
69    /// The motor affecting the joint’s translational degree of freedom.
70    #[must_use]
71    pub fn motor(&self, axis: JointAxis) -> Option<&JointMotor> {
72        self.data.motor(axis)
73    }
74
75    /// Set the spring-like model used by the motor to reach the desired target velocity and position.
76    pub fn set_motor_model(&mut self, model: MotorModel) -> &mut Self {
77        self.data.set_motor_model(JointAxis::LinX, model);
78        self
79    }
80
81    /// Sets the target velocity this motor needs to reach.
82    pub fn set_motor_velocity(&mut self, target_vel: Real, factor: Real) -> &mut Self {
83        self.data
84            .set_motor_velocity(JointAxis::LinX, target_vel, factor);
85        self
86    }
87
88    /// Sets the target angle this motor needs to reach.
89    pub fn set_motor_position(
90        &mut self,
91        target_pos: Real,
92        stiffness: Real,
93        damping: Real,
94    ) -> &mut Self {
95        self.data
96            .set_motor_position(JointAxis::LinX, target_pos, stiffness, damping);
97        self
98    }
99
100    /// Configure both the target angle and target velocity of the motor.
101    pub fn set_motor(
102        &mut self,
103        target_pos: Real,
104        target_vel: Real,
105        stiffness: Real,
106        damping: Real,
107    ) -> &mut Self {
108        self.data
109            .set_motor(JointAxis::LinX, target_pos, target_vel, stiffness, damping);
110        self
111    }
112
113    /// Sets the maximum force the motor can deliver.
114    pub fn set_motor_max_force(&mut self, max_force: Real) -> &mut Self {
115        self.data.set_motor_max_force(JointAxis::LinX, max_force);
116        self
117    }
118
119    /// The maximum distance allowed between the attached objects.
120    #[must_use]
121    pub fn max_distance(&self) -> Real {
122        self.data
123            .limits(JointAxis::LinX)
124            .map(|l| l.max)
125            .unwrap_or(Real::MAX)
126    }
127
128    /// Sets the maximum allowed distance between the attached objects.
129    ///
130    /// The `max_dist` must be strictly greater than 0.0.
131    pub fn set_max_distance(&mut self, max_dist: Real) -> &mut Self {
132        self.data.set_limits(JointAxis::LinX, [0.0, max_dist]);
133        self
134    }
135}
136
137impl From<RopeJoint> for GenericJoint {
138    fn from(val: RopeJoint) -> GenericJoint {
139        val.data
140    }
141}
142
143/// Create rope joints using the builder pattern.
144///
145/// A rope joint, limits the maximum distance between two bodies.
146#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
147#[derive(Copy, Clone, Debug, PartialEq)]
148pub struct RopeJointBuilder(pub RopeJoint);
149
150impl RopeJointBuilder {
151    /// Creates a new builder for rope joints.
152    pub fn new(max_dist: Real) -> Self {
153        Self(RopeJoint::new(max_dist))
154    }
155
156    /// Sets whether contacts between the attached rigid-bodies are enabled.
157    #[must_use]
158    pub fn contacts_enabled(mut self, enabled: bool) -> Self {
159        self.0.set_contacts_enabled(enabled);
160        self
161    }
162
163    /// Sets the joint’s anchor, expressed in the local-space of the first rigid-body.
164    #[must_use]
165    pub fn local_anchor1(mut self, anchor1: Point<Real>) -> Self {
166        self.0.set_local_anchor1(anchor1);
167        self
168    }
169
170    /// Sets the joint’s anchor, expressed in the local-space of the second rigid-body.
171    #[must_use]
172    pub fn local_anchor2(mut self, anchor2: Point<Real>) -> Self {
173        self.0.set_local_anchor2(anchor2);
174        self
175    }
176
177    /// Set the spring-like model used by the motor to reach the desired target velocity and position.
178    #[must_use]
179    pub fn motor_model(mut self, model: MotorModel) -> Self {
180        self.0.set_motor_model(model);
181        self
182    }
183
184    /// Sets the target velocity this motor needs to reach.
185    #[must_use]
186    pub fn motor_velocity(mut self, target_vel: Real, factor: Real) -> Self {
187        self.0.set_motor_velocity(target_vel, factor);
188        self
189    }
190
191    /// Sets the target angle this motor needs to reach.
192    #[must_use]
193    pub fn motor_position(mut self, target_pos: Real, stiffness: Real, damping: Real) -> Self {
194        self.0.set_motor_position(target_pos, stiffness, damping);
195        self
196    }
197
198    /// Configure both the target angle and target velocity of the motor.
199    #[must_use]
200    pub fn set_motor(
201        mut self,
202        target_pos: Real,
203        target_vel: Real,
204        stiffness: Real,
205        damping: Real,
206    ) -> Self {
207        self.0.set_motor(target_pos, target_vel, stiffness, damping);
208        self
209    }
210
211    /// Sets the maximum force the motor can deliver.
212    #[must_use]
213    pub fn motor_max_force(mut self, max_force: Real) -> Self {
214        self.0.set_motor_max_force(max_force);
215        self
216    }
217
218    /// Sets the maximum allowed distance between the attached bodies.
219    ///
220    /// The `max_dist` must be strictly greater than 0.0.
221    #[must_use]
222    pub fn max_distance(mut self, max_dist: Real) -> Self {
223        self.0.set_max_distance(max_dist);
224        self
225    }
226
227    /// Builds the rope joint.
228    #[must_use]
229    pub fn build(self) -> RopeJoint {
230        self.0
231    }
232}
233
234impl From<RopeJointBuilder> for GenericJoint {
235    fn from(val: RopeJointBuilder) -> GenericJoint {
236        val.0.into()
237    }
238}