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}