Skip to main content

bevy_rapier3d/dynamics/
spherical_joint.rs

1use crate::dynamics::{GenericJoint, GenericJointBuilder};
2use crate::math::{Real, Rot, Vect};
3use rapier::dynamics::{JointAxesMask, JointAxis, JointLimits, JointMotor, MotorModel};
4use rapier::math::Pose;
5
6use super::{SpringCoefficients, TypedJoint};
7
8#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
9#[derive(Copy, Clone, Debug, PartialEq)]
10#[repr(transparent)]
11/// A spherical joint, locks all relative translations between two bodies.
12pub struct SphericalJoint {
13    /// The underlying joint data.
14    pub data: GenericJoint,
15}
16
17impl Default for SphericalJoint {
18    fn default() -> Self {
19        SphericalJoint::new()
20    }
21}
22
23impl SphericalJoint {
24    /// Creates a new spherical joint locking all relative translations between two bodies.
25    pub fn new() -> Self {
26        let data = GenericJointBuilder::new(JointAxesMask::LOCKED_SPHERICAL_AXES).build();
27        Self { data }
28    }
29
30    /// Are contacts between the attached rigid-bodies enabled?
31    pub fn contacts_enabled(&self) -> bool {
32        self.data.contacts_enabled()
33    }
34
35    /// Sets whether contacts between the attached rigid-bodies are enabled.
36    pub fn set_contacts_enabled(&mut self, enabled: bool) -> &mut Self {
37        self.data.set_contacts_enabled(enabled);
38        self
39    }
40
41    /// The spring coefficients controlling the softness of this joint’s locked degrees of freedom.
42    #[must_use]
43    pub fn softness(&self) -> SpringCoefficients<Real> {
44        self.data.softness()
45    }
46
47    /// Sets the spring coefficients controlling the softness of this joint’s locked degrees of freedom.
48    pub fn set_softness(&mut self, softness: SpringCoefficients<Real>) -> &mut Self {
49        self.data.set_softness(softness);
50        self
51    }
52
53    /// The joint’s anchor, expressed in the local-space of the first rigid-body.
54    #[must_use]
55    pub fn local_anchor1(&self) -> Vect {
56        self.data.local_anchor1()
57    }
58
59    /// Sets the joint’s anchor, expressed in the local-space of the first rigid-body.
60    pub fn set_local_anchor1(&mut self, anchor1: Vect) -> &mut Self {
61        self.data.set_local_anchor1(anchor1);
62        self
63    }
64
65    /// The joint’s anchor, expressed in the local-space of the second rigid-body.
66    #[must_use]
67    pub fn local_anchor2(&self) -> Vect {
68        self.data.local_anchor2()
69    }
70
71    /// Sets the joint’s anchor, expressed in the local-space of the second rigid-body.
72    pub fn set_local_anchor2(&mut self, anchor2: Vect) -> &mut Self {
73        self.data.set_local_anchor2(anchor2);
74        self
75    }
76
77    /// The joint’s basis, expressed in the first rigid-body’s local-space.
78    #[must_use]
79    pub fn local_basis1(&self) -> Rot {
80        self.data.local_basis1()
81    }
82
83    /// Sets the joint’s basis, expressed in the first rigid-body’s local-space.
84    pub fn set_local_basis1(&mut self, local_basis: Rot) -> &mut Self {
85        self.data.set_local_basis1(local_basis);
86        self
87    }
88
89    /// The joint’s basis, expressed in the second rigid-body’s local-space.
90    #[must_use]
91    pub fn local_basis2(&self) -> Rot {
92        self.data.local_basis2()
93    }
94
95    /// Sets the joint’s basis, expressed in the second rigid-body’s local-space.
96    pub fn set_local_basis2(&mut self, local_basis: Rot) -> &mut Self {
97        self.data.set_local_basis2(local_basis);
98        self
99    }
100
101    /// The joint’s frame (anchor and basis), expressed in the first rigid-body’s local-space.
102    #[must_use]
103    pub fn local_frame1(&self) -> Pose {
104        self.data.local_frame1()
105    }
106
107    /// Sets the joint’s frame (anchor and basis), expressed in the first rigid-body’s local-space.
108    pub fn set_local_frame1(&mut self, local_frame: Pose) -> &mut Self {
109        self.data.set_local_frame1(local_frame);
110        self
111    }
112
113    /// The joint’s frame (anchor and basis), expressed in the second rigid-body’s local-space.
114    #[must_use]
115    pub fn local_frame2(&self) -> Pose {
116        self.data.local_frame2()
117    }
118
119    /// Sets the joint’s frame (anchor and basis), expressed in the second rigid-body’s local-space.
120    pub fn set_local_frame2(&mut self, local_frame: Pose) -> &mut Self {
121        self.data.set_local_frame2(local_frame);
122        self
123    }
124
125    /// The motor affecting the joint’s rotational degree of freedom along the specified axis.
126    #[must_use]
127    pub fn motor(&self, axis: JointAxis) -> Option<&JointMotor> {
128        self.data.motor(axis)
129    }
130
131    /// Set the spring-like model used by the motor to reach the desired target velocity and position.
132    pub fn set_motor_model(&mut self, axis: JointAxis, model: MotorModel) -> &mut Self {
133        self.data.set_motor_model(axis, model);
134        self
135    }
136
137    /// Sets the target velocity this motor needs to reach.
138    pub fn set_motor_velocity(
139        &mut self,
140        axis: JointAxis,
141        target_vel: Real,
142        factor: Real,
143    ) -> &mut Self {
144        self.data.set_motor_velocity(axis, target_vel, factor);
145        self
146    }
147
148    /// Sets the target angle this motor needs to reach.
149    pub fn set_motor_position(
150        &mut self,
151        axis: JointAxis,
152        target_pos: Real,
153        stiffness: Real,
154        damping: Real,
155    ) -> &mut Self {
156        self.data
157            .set_motor_position(axis, target_pos, stiffness, damping);
158        self
159    }
160
161    /// Configure both the target angle and target velocity of the motor.
162    pub fn set_motor(
163        &mut self,
164        axis: JointAxis,
165        target_pos: Real,
166        target_vel: Real,
167        stiffness: Real,
168        damping: Real,
169    ) -> &mut Self {
170        self.data
171            .set_motor(axis, target_pos, target_vel, stiffness, damping);
172        self
173    }
174
175    /// Sets the maximum force the motor can deliver along the specified axis.
176    pub fn set_motor_max_force(&mut self, axis: JointAxis, max_force: Real) -> &mut Self {
177        self.data.set_motor_max_force(axis, max_force);
178        self
179    }
180
181    /// The limit distance attached bodies can translate along the specified axis.
182    #[must_use]
183    pub fn limits(&self, axis: JointAxis) -> Option<&JointLimits<Real>> {
184        self.data.limits(axis)
185    }
186
187    /// Sets the `[min,max]` limit angles attached bodies can translate along the joint’s principal axis.
188    pub fn set_limits(&mut self, axis: JointAxis, limits: [Real; 2]) -> &mut Self {
189        self.data.set_limits(axis, limits);
190        self
191    }
192}
193
194impl From<SphericalJoint> for GenericJoint {
195    fn from(joint: SphericalJoint) -> GenericJoint {
196        joint.data
197    }
198}
199
200/// Create spherical joints using the builder pattern.
201#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
202#[derive(Copy, Default, Clone, Debug, PartialEq)]
203pub struct SphericalJointBuilder(SphericalJoint);
204
205impl SphericalJointBuilder {
206    /// Creates a new builder for spherical joints.
207    pub fn new() -> Self {
208        Self(SphericalJoint::new())
209    }
210
211    /// Sets the joint’s anchor, expressed in the local-space of the first rigid-body.
212    #[must_use]
213    pub fn local_anchor1(mut self, anchor1: Vect) -> Self {
214        self.0.set_local_anchor1(anchor1);
215        self
216    }
217
218    /// Sets the joint’s anchor, expressed in the local-space of the second rigid-body.
219    #[must_use]
220    pub fn local_anchor2(mut self, anchor2: Vect) -> Self {
221        self.0.set_local_anchor2(anchor2);
222        self
223    }
224
225    /// Sets the joint’s basis, expressed in the first rigid-body’s local-space.
226    #[must_use]
227    pub fn local_basis1(mut self, local_basis: Rot) -> Self {
228        self.0.set_local_basis1(local_basis);
229        self
230    }
231
232    /// Sets the joint’s basis, expressed in the second rigid-body’s local-space.
233    #[must_use]
234    pub fn local_basis2(mut self, local_basis: Rot) -> Self {
235        self.0.set_local_basis2(local_basis);
236        self
237    }
238
239    /// Sets the joint’s frame (anchor and basis), expressed in the first rigid-body’s local-space.
240    #[must_use]
241    pub fn local_frame1(mut self, local_frame: Pose) -> Self {
242        self.0.set_local_frame1(local_frame);
243        self
244    }
245
246    /// Sets the joint’s frame (anchor and basis), expressed in the second rigid-body’s local-space.
247    #[must_use]
248    pub fn local_frame2(mut self, local_frame: Pose) -> Self {
249        self.0.set_local_frame2(local_frame);
250        self
251    }
252
253    /// Set the spring-like model used by the motor to reach the desired target velocity and position.
254    #[must_use]
255    pub fn motor_model(mut self, axis: JointAxis, model: MotorModel) -> Self {
256        self.0.set_motor_model(axis, model);
257        self
258    }
259
260    /// Sets the target velocity this motor needs to reach.
261    #[must_use]
262    pub fn motor_velocity(mut self, axis: JointAxis, target_vel: Real, factor: Real) -> Self {
263        self.0.set_motor_velocity(axis, target_vel, factor);
264        self
265    }
266
267    /// Sets the target angle this motor needs to reach.
268    #[must_use]
269    pub fn motor_position(
270        mut self,
271        axis: JointAxis,
272        target_pos: Real,
273        stiffness: Real,
274        damping: Real,
275    ) -> Self {
276        self.0
277            .set_motor_position(axis, target_pos, stiffness, damping);
278        self
279    }
280
281    /// Configure both the target angle and target velocity of the motor.
282    #[must_use]
283    pub fn motor(
284        mut self,
285        axis: JointAxis,
286        target_pos: Real,
287        target_vel: Real,
288        stiffness: Real,
289        damping: Real,
290    ) -> Self {
291        self.0
292            .set_motor(axis, target_pos, target_vel, stiffness, damping);
293        self
294    }
295
296    /// Sets the maximum force the motor can deliver along the specified axis.
297    #[must_use]
298    pub fn motor_max_force(mut self, axis: JointAxis, max_force: Real) -> Self {
299        self.0.set_motor_max_force(axis, max_force);
300        self
301    }
302
303    /// Sets the `[min,max]` limit distances attached bodies can rotate along the specified axis.
304    #[must_use]
305    pub fn limits(mut self, axis: JointAxis, limits: [Real; 2]) -> Self {
306        self.0.set_limits(axis, limits);
307        self
308    }
309
310    /// Sets whether contacts between the attached rigid-bodies are enabled.
311    #[must_use]
312    pub fn contacts_enabled(mut self, enabled: bool) -> Self {
313        self.0.set_contacts_enabled(enabled);
314        self
315    }
316
317    /// Sets the spring coefficients controlling the softness of this joint’s locked degrees of freedom.
318    #[must_use]
319    pub fn softness(mut self, softness: SpringCoefficients<Real>) -> Self {
320        self.0.set_softness(softness);
321        self
322    }
323
324    /// Builds the spherical joint.
325    #[must_use]
326    pub fn build(self) -> SphericalJoint {
327        self.0
328    }
329}
330
331impl From<SphericalJointBuilder> for TypedJoint {
332    fn from(joint: SphericalJointBuilder) -> TypedJoint {
333        joint.0.into()
334    }
335}
336
337impl From<SphericalJoint> for TypedJoint {
338    fn from(joint: SphericalJoint) -> TypedJoint {
339        TypedJoint::SphericalJoint(joint)
340    }
341}