box2d_rust/types/world.rs
1// World creation types and default from types.h / types.c.
2// SPDX-FileCopyrightText: 2023 Erin Catto
3// SPDX-License-Identifier: MIT
4
5use crate::core::{get_length_units_per_meter, SECRET_COOKIE};
6use crate::id::ShapeId;
7use crate::math_functions::{Pos, Vec2, POS_ZERO, VEC2_ZERO};
8
9/// Optional friction mixing callback. The default uses `sqrt(frictionA * frictionB)`.
10/// (b2FrictionCallback)
11///
12/// Args: `(friction_a, user_material_id_a, friction_b, user_material_id_b)`.
13pub type FrictionCallback = fn(f32, u64, f32, u64) -> f32;
14
15/// Optional restitution mixing callback. The default uses
16/// `max(restitutionA, restitutionB)`. (b2RestitutionCallback)
17pub type RestitutionCallback = fn(f32, u64, f32, u64) -> f32;
18
19/// Result from `b2World_RayCastClosest`. (b2RayResult)
20#[derive(Debug, Clone, Copy, PartialEq)]
21pub struct RayResult {
22 pub shape_id: ShapeId,
23 pub point: Pos,
24 pub normal: Vec2,
25 pub fraction: f32,
26 pub node_visits: i32,
27 pub leaf_visits: i32,
28 pub hit: bool,
29}
30
31impl Default for RayResult {
32 fn default() -> Self {
33 RayResult {
34 shape_id: ShapeId::default(),
35 point: POS_ZERO,
36 normal: VEC2_ZERO,
37 fraction: 0.0,
38 node_visits: 0,
39 leaf_visits: 0,
40 hit: false,
41 }
42 }
43}
44
45/// Optional world capacities that can be used to avoid run-time allocations.
46/// (b2Capacity)
47#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
48pub struct Capacity {
49 /// Number of expected static shapes.
50 pub static_shape_count: i32,
51 /// Number of expected dynamic and kinematic shapes.
52 pub dynamic_shape_count: i32,
53 /// Number of expected static bodies.
54 pub static_body_count: i32,
55 /// Number of expected dynamic and kinematic bodies.
56 pub dynamic_body_count: i32,
57 /// Number of expected contacts.
58 pub contact_count: i32,
59}
60
61/// World definition used to create a simulation world. Must be initialized
62/// using [`default_world_def`]. (b2WorldDef)
63///
64/// `PartialEq` is intentionally not derived: it holds optional function-pointer
65/// callbacks, and function-pointer equality is not meaningful.
66#[derive(Debug, Clone, Copy)]
67pub struct WorldDef {
68 /// Gravity vector. Box2D has no up-vector defined.
69 pub gravity: Vec2,
70 /// Restitution speed threshold, usually in m/s. Collisions above this speed
71 /// have restitution applied (will bounce).
72 pub restitution_threshold: f32,
73 /// Threshold speed for hit events. Usually meters per second.
74 pub hit_event_threshold: f32,
75 /// Contact stiffness. Cycles per second.
76 pub contact_hertz: f32,
77 /// Contact bounciness. Non-dimensional.
78 pub contact_damping_ratio: f32,
79 /// Speed cap on overlap resolution, usually meters per second.
80 pub contact_speed: f32,
81 /// Maximum linear speed. Usually meters per second.
82 pub maximum_linear_speed: f32,
83 /// Optional mixing callback for friction.
84 pub friction_callback: Option<FrictionCallback>,
85 /// Optional mixing callback for restitution.
86 pub restitution_callback: Option<RestitutionCallback>,
87 /// Can bodies go to sleep to improve performance.
88 pub enable_sleep: bool,
89 /// Enable continuous collision.
90 pub enable_continuous: bool,
91 /// Contact softening when mass ratios are large. Experimental.
92 pub enable_contact_softening: bool,
93 /// Number of workers for multithreading, clamped to `[1, MAX_WORKERS]`.
94 pub worker_count: i32,
95 /// User data.
96 pub user_data: u64,
97 /// Optional initial capacities.
98 pub capacity: Capacity,
99 /// Used internally to detect a valid definition. DO NOT SET.
100 pub internal_value: i32,
101}
102
103/// Initialize a world definition with the default values. (b2DefaultWorldDef)
104pub fn default_world_def() -> WorldDef {
105 let length_units = get_length_units_per_meter();
106 WorldDef {
107 gravity: Vec2 { x: 0.0, y: -10.0 },
108 hit_event_threshold: 1.0 * length_units,
109 restitution_threshold: 1.0 * length_units,
110 contact_speed: 3.0 * length_units,
111 contact_hertz: 30.0,
112 contact_damping_ratio: 10.0,
113 // 400 meters per second, faster than the speed of sound
114 maximum_linear_speed: 400.0 * length_units,
115 friction_callback: None,
116 restitution_callback: None,
117 enable_sleep: true,
118 enable_continuous: true,
119 enable_contact_softening: false,
120 worker_count: 0,
121 user_data: 0,
122 capacity: Capacity::default(),
123 internal_value: SECRET_COOKIE,
124 }
125}
126
127impl Default for WorldDef {
128 fn default() -> Self {
129 default_world_def()
130 }
131}