Skip to main content

box2d_rust/types/
joint.rs

1// Joint definition types from include/box2d/types.h and their b2Default*
2// constructors from src/joint.c.
3//
4// SPDX-FileCopyrightText: 2023 Erin Catto
5// SPDX-License-Identifier: MIT
6
7use crate::constants::huge;
8use crate::core::{get_length_units_per_meter, SECRET_COOKIE};
9use crate::id::BodyId;
10use crate::math_functions::{Transform, Vec2, ROT_IDENTITY, TRANSFORM_IDENTITY, VEC2_ZERO};
11
12/// Base joint definition used by all joint types.
13/// The local frames are measured from the body's origin rather than the center
14/// of mass because:
15/// 1. you might not know where the center of mass will be
16/// 2. if you add/remove shapes from a body and recompute the mass, the joints
17///    will be broken
18///
19/// (b2JointDef)
20#[derive(Debug, Clone, Copy, PartialEq)]
21pub struct JointDef {
22    /// User data
23    pub user_data: u64,
24
25    /// The first attached body
26    pub body_id_a: BodyId,
27
28    /// The second attached body
29    pub body_id_b: BodyId,
30
31    /// The first local joint frame
32    pub local_frame_a: Transform,
33
34    /// The second local joint frame
35    pub local_frame_b: Transform,
36
37    /// Force threshold for joint events
38    pub force_threshold: f32,
39
40    /// Torque threshold for joint events
41    pub torque_threshold: f32,
42
43    /// Constraint hertz (advanced feature)
44    pub constraint_hertz: f32,
45
46    /// Constraint damping ratio (advanced feature)
47    pub constraint_damping_ratio: f32,
48
49    /// Debug draw scale
50    pub draw_scale: f32,
51
52    /// Set this flag to true if the attached bodies should collide
53    pub collide_connected: bool,
54}
55
56/// (static b2DefaultJointDef)
57pub(crate) fn default_joint_def() -> JointDef {
58    JointDef {
59        user_data: 0,
60        body_id_a: BodyId::default(),
61        body_id_b: BodyId::default(),
62        local_frame_a: Transform {
63            q: ROT_IDENTITY,
64            ..TRANSFORM_IDENTITY
65        },
66        local_frame_b: Transform {
67            q: ROT_IDENTITY,
68            ..TRANSFORM_IDENTITY
69        },
70        force_threshold: f32::MAX,
71        torque_threshold: f32::MAX,
72        constraint_hertz: 60.0,
73        constraint_damping_ratio: 2.0,
74        draw_scale: get_length_units_per_meter(),
75        collide_connected: false,
76    }
77}
78
79/// Distance joint definition.
80/// Connects a point on body A with a point on body B by a segment.
81/// Useful for ropes and springs. (b2DistanceJointDef)
82#[derive(Debug, Clone, Copy, PartialEq)]
83pub struct DistanceJointDef {
84    /// Base joint definition
85    pub base: JointDef,
86
87    /// The rest length of this joint. Clamped to a stable minimum value.
88    pub length: f32,
89
90    /// Enable the distance constraint to behave like a spring. If false then
91    /// the distance joint will be rigid, overriding the limit and motor.
92    pub enable_spring: bool,
93
94    /// The lower spring force controls how much tension it can sustain
95    pub lower_spring_force: f32,
96
97    /// The upper spring force controls how much compression it an sustain
98    pub upper_spring_force: f32,
99
100    /// The spring linear stiffness Hertz, cycles per second
101    pub hertz: f32,
102
103    /// The spring linear damping ratio, non-dimensional
104    pub damping_ratio: f32,
105
106    /// Enable/disable the joint limit
107    pub enable_limit: bool,
108
109    /// Minimum length for limit. Clamped to a stable minimum value.
110    pub min_length: f32,
111
112    /// Maximum length for limit. Must be greater than or equal to the minimum
113    /// length.
114    pub max_length: f32,
115
116    /// Enable/disable the joint motor
117    pub enable_motor: bool,
118
119    /// The maximum motor force, usually in newtons
120    pub max_motor_force: f32,
121
122    /// The desired motor speed, usually in meters per second
123    pub motor_speed: f32,
124
125    /// Used internally to detect a valid definition. DO NOT SET.
126    pub internal_value: i32,
127}
128
129/// (b2DefaultDistanceJointDef)
130pub fn default_distance_joint_def() -> DistanceJointDef {
131    DistanceJointDef {
132        base: default_joint_def(),
133        length: 1.0,
134        enable_spring: false,
135        lower_spring_force: -f32::MAX,
136        upper_spring_force: f32::MAX,
137        hertz: 0.0,
138        damping_ratio: 0.0,
139        enable_limit: false,
140        min_length: 0.0,
141        max_length: huge(),
142        enable_motor: false,
143        max_motor_force: 0.0,
144        motor_speed: 0.0,
145        internal_value: SECRET_COOKIE,
146    }
147}
148
149impl Default for DistanceJointDef {
150    fn default() -> Self {
151        default_distance_joint_def()
152    }
153}
154
155/// A motor joint is used to control the relative velocity and or transform
156/// between two bodies. With a velocity of zero this acts like top-down
157/// friction. (b2MotorJointDef)
158#[derive(Debug, Clone, Copy, PartialEq)]
159pub struct MotorJointDef {
160    /// Base joint definition
161    pub base: JointDef,
162
163    /// The desired linear velocity
164    pub linear_velocity: Vec2,
165
166    /// The maximum motor force in newtons
167    pub max_velocity_force: f32,
168
169    /// The desired angular velocity
170    pub angular_velocity: f32,
171
172    /// The maximum motor torque in newton-meters
173    pub max_velocity_torque: f32,
174
175    /// Linear spring hertz for position control
176    pub linear_hertz: f32,
177
178    /// Linear spring damping ratio
179    pub linear_damping_ratio: f32,
180
181    /// Maximum spring force in newtons
182    pub max_spring_force: f32,
183
184    /// Angular spring hertz for position control
185    pub angular_hertz: f32,
186
187    /// Angular spring damping ratio
188    pub angular_damping_ratio: f32,
189
190    /// Maximum spring torque in newton-meters
191    pub max_spring_torque: f32,
192
193    /// Used internally to detect a valid definition. DO NOT SET.
194    pub internal_value: i32,
195}
196
197/// (b2DefaultMotorJointDef)
198pub fn default_motor_joint_def() -> MotorJointDef {
199    MotorJointDef {
200        base: default_joint_def(),
201        linear_velocity: VEC2_ZERO,
202        max_velocity_force: 0.0,
203        angular_velocity: 0.0,
204        max_velocity_torque: 0.0,
205        linear_hertz: 0.0,
206        linear_damping_ratio: 0.0,
207        max_spring_force: 0.0,
208        angular_hertz: 0.0,
209        angular_damping_ratio: 0.0,
210        max_spring_torque: 0.0,
211        internal_value: SECRET_COOKIE,
212    }
213}
214
215impl Default for MotorJointDef {
216    fn default() -> Self {
217        default_motor_joint_def()
218    }
219}
220
221/// A filter joint is used to disable collision between two specific bodies.
222/// (b2FilterJointDef)
223#[derive(Debug, Clone, Copy, PartialEq)]
224pub struct FilterJointDef {
225    /// Base joint definition
226    pub base: JointDef,
227
228    /// Used internally to detect a valid definition. DO NOT SET.
229    pub internal_value: i32,
230}
231
232/// (b2DefaultFilterJointDef)
233pub fn default_filter_joint_def() -> FilterJointDef {
234    FilterJointDef {
235        base: default_joint_def(),
236        internal_value: SECRET_COOKIE,
237    }
238}
239
240impl Default for FilterJointDef {
241    fn default() -> Self {
242        default_filter_joint_def()
243    }
244}
245
246/// Prismatic joint definition.
247/// Body B may slide along the x-axis in local frame A. Body B cannot rotate
248/// relative to body A. The joint translation is zero when the local frame
249/// origins coincide in world space. (b2PrismaticJointDef)
250#[derive(Debug, Clone, Copy, PartialEq)]
251pub struct PrismaticJointDef {
252    /// Base joint definition
253    pub base: JointDef,
254
255    /// Enable a linear spring along the prismatic joint axis
256    pub enable_spring: bool,
257
258    /// The spring stiffness Hertz, cycles per second
259    pub hertz: f32,
260
261    /// The spring damping ratio, non-dimensional
262    pub damping_ratio: f32,
263
264    /// The target translation for the joint in meters. The spring-damper will
265    /// drive to this translation.
266    pub target_translation: f32,
267
268    /// Enable/disable the joint limit
269    pub enable_limit: bool,
270
271    /// The lower translation limit
272    pub lower_translation: f32,
273
274    /// The upper translation limit
275    pub upper_translation: f32,
276
277    /// Enable/disable the joint motor
278    pub enable_motor: bool,
279
280    /// The maximum motor force, typically in newtons
281    pub max_motor_force: f32,
282
283    /// The desired motor speed, typically in meters per second
284    pub motor_speed: f32,
285
286    /// Used internally to detect a valid definition. DO NOT SET.
287    pub internal_value: i32,
288}
289
290/// (b2DefaultPrismaticJointDef)
291pub fn default_prismatic_joint_def() -> PrismaticJointDef {
292    PrismaticJointDef {
293        base: default_joint_def(),
294        enable_spring: false,
295        hertz: 0.0,
296        damping_ratio: 0.0,
297        target_translation: 0.0,
298        enable_limit: false,
299        lower_translation: 0.0,
300        upper_translation: 0.0,
301        enable_motor: false,
302        max_motor_force: 0.0,
303        motor_speed: 0.0,
304        internal_value: SECRET_COOKIE,
305    }
306}
307
308impl Default for PrismaticJointDef {
309    fn default() -> Self {
310        default_prismatic_joint_def()
311    }
312}
313
314/// Revolute joint definition.
315/// A point on body B is fixed to a point on body A. Allows relative rotation.
316/// (b2RevoluteJointDef)
317#[derive(Debug, Clone, Copy, PartialEq)]
318pub struct RevoluteJointDef {
319    /// Base joint definition
320    pub base: JointDef,
321
322    /// The target angle for the joint in radians. The spring-damper will
323    /// drive to this angle.
324    pub target_angle: f32,
325
326    /// Enable a rotational spring on the revolute hinge axis
327    pub enable_spring: bool,
328
329    /// The spring stiffness Hertz, cycles per second
330    pub hertz: f32,
331
332    /// The spring damping ratio, non-dimensional
333    pub damping_ratio: f32,
334
335    /// A flag to enable joint limits
336    pub enable_limit: bool,
337
338    /// The lower angle for the joint limit in radians. Minimum of -0.99*pi
339    /// radians.
340    pub lower_angle: f32,
341
342    /// The upper angle for the joint limit in radians. Maximum of 0.99*pi
343    /// radians.
344    pub upper_angle: f32,
345
346    /// A flag to enable the joint motor
347    pub enable_motor: bool,
348
349    /// The maximum motor torque, typically in newton-meters
350    pub max_motor_torque: f32,
351
352    /// The desired motor speed in radians per second
353    pub motor_speed: f32,
354
355    /// Used internally to detect a valid definition. DO NOT SET.
356    pub internal_value: i32,
357}
358
359/// (b2DefaultRevoluteJointDef)
360pub fn default_revolute_joint_def() -> RevoluteJointDef {
361    RevoluteJointDef {
362        base: default_joint_def(),
363        target_angle: 0.0,
364        enable_spring: false,
365        hertz: 0.0,
366        damping_ratio: 0.0,
367        enable_limit: false,
368        lower_angle: 0.0,
369        upper_angle: 0.0,
370        enable_motor: false,
371        max_motor_torque: 0.0,
372        motor_speed: 0.0,
373        internal_value: SECRET_COOKIE,
374    }
375}
376
377impl Default for RevoluteJointDef {
378    fn default() -> Self {
379        default_revolute_joint_def()
380    }
381}
382
383/// Weld joint definition.
384/// Connects two bodies together rigidly. This constraint provides springs to
385/// mimic soft-body simulation.
386/// Note: The approximate solver in Box2D cannot hold many bodies together
387/// rigidly. (b2WeldJointDef)
388#[derive(Debug, Clone, Copy, PartialEq)]
389pub struct WeldJointDef {
390    /// Base joint definition
391    pub base: JointDef,
392
393    /// Linear stiffness expressed as Hertz (cycles per second). Use zero for
394    /// maximum stiffness.
395    pub linear_hertz: f32,
396
397    /// Angular stiffness as Hertz (cycles per second). Use zero for maximum
398    /// stiffness.
399    pub angular_hertz: f32,
400
401    /// Linear damping ratio, non-dimensional. Use 1 for critical damping.
402    pub linear_damping_ratio: f32,
403
404    /// Linear damping ratio, non-dimensional. Use 1 for critical damping.
405    pub angular_damping_ratio: f32,
406
407    /// Used internally to detect a valid definition. DO NOT SET.
408    pub internal_value: i32,
409}
410
411/// (b2DefaultWeldJointDef)
412pub fn default_weld_joint_def() -> WeldJointDef {
413    WeldJointDef {
414        base: default_joint_def(),
415        linear_hertz: 0.0,
416        angular_hertz: 0.0,
417        linear_damping_ratio: 0.0,
418        angular_damping_ratio: 0.0,
419        internal_value: SECRET_COOKIE,
420    }
421}
422
423impl Default for WeldJointDef {
424    fn default() -> Self {
425        default_weld_joint_def()
426    }
427}
428
429/// Wheel joint definition.
430/// Body B is a wheel that may rotate freely and slide along the local x-axis
431/// in frame A. The joint translation is zero when the local frame origins
432/// coincide in world space. (b2WheelJointDef)
433#[derive(Debug, Clone, Copy, PartialEq)]
434pub struct WheelJointDef {
435    /// Base joint definition
436    pub base: JointDef,
437
438    /// Enable a linear spring along the local axis
439    pub enable_spring: bool,
440
441    /// Spring stiffness in Hertz
442    pub hertz: f32,
443
444    /// Spring damping ratio, non-dimensional
445    pub damping_ratio: f32,
446
447    /// Enable/disable the joint linear limit
448    pub enable_limit: bool,
449
450    /// The lower translation limit
451    pub lower_translation: f32,
452
453    /// The upper translation limit
454    pub upper_translation: f32,
455
456    /// Enable/disable the joint rotational motor
457    pub enable_motor: bool,
458
459    /// The maximum motor torque, typically in newton-meters
460    pub max_motor_torque: f32,
461
462    /// The desired motor speed in radians per second
463    pub motor_speed: f32,
464
465    /// Used internally to detect a valid definition. DO NOT SET.
466    pub internal_value: i32,
467}
468
469/// (b2DefaultWheelJointDef)
470pub fn default_wheel_joint_def() -> WheelJointDef {
471    WheelJointDef {
472        base: default_joint_def(),
473        enable_spring: true,
474        hertz: 1.0,
475        damping_ratio: 0.7,
476        enable_limit: false,
477        lower_translation: 0.0,
478        upper_translation: 0.0,
479        enable_motor: false,
480        max_motor_torque: 0.0,
481        motor_speed: 0.0,
482        internal_value: SECRET_COOKIE,
483    }
484}
485
486impl Default for WheelJointDef {
487    fn default() -> Self {
488        default_wheel_joint_def()
489    }
490}