bevy_rapier3d/dynamics/
spherical_joint.rs

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