1mod api;
24mod draw;
25mod dump;
26mod query;
27mod step;
28mod validate;
29
30pub use api::*;
31pub use draw::*;
32pub use dump::*;
33pub use query::*;
34
35use crate::bitset::BitSet;
36use crate::body::Body;
37use crate::broad_phase::BroadPhase;
38use crate::constants::CONTACT_MANIFOLD_COUNT_BUCKETS;
39use crate::constraint_graph::ConstraintGraph;
40use crate::contact::Contact;
41use crate::debug_draw::{
42 CreateDebugShapeCallback, DebugLine, DebugPoint, DestroyDebugShapeCallback,
43 DEBUG_LINE_CAPACITY, DEBUG_POINT_CAPACITY,
44};
45use crate::events::{
46 BodyMoveEvent, ContactBeginTouchEvent, ContactEndTouchEvent, ContactHitEvent, JointEvent,
47 SensorBeginTouchEvent, SensorEndTouchEvent,
48};
49use crate::hull::HullDatabase;
50use crate::id::ShapeId;
51use crate::id_pool::IdPool;
52use crate::island::Island;
53use crate::joint::Joint;
54use crate::math_functions::Vec3;
55use crate::name_cache::NameCache;
56use crate::sensor::{Sensor, SensorHit, SensorTaskContext};
57use crate::shape::Shape;
58use crate::solver_set::SolverSet;
59use crate::types::{Capacity, FrictionCallback, RestitutionCallback};
60
61pub type CustomFilterFcn = fn(ShapeId, ShapeId, u64) -> bool;
63
64pub type PreSolveFcn =
66 fn(ShapeId, ShapeId, crate::math_functions::Pos, crate::math_functions::Vec3, u64) -> bool;
67
68#[derive(Debug, Clone, Copy, PartialEq, Default)]
70pub struct Profile {
71 pub step: f32,
72 pub pairs: f32,
73 pub collide: f32,
74 pub solve: f32,
75 pub solver_setup: f32,
76 pub constraints: f32,
77 pub prepare_constraints: f32,
78 pub integrate_velocities: f32,
79 pub warm_start: f32,
80 pub solve_impulses: f32,
81 pub integrate_positions: f32,
82 pub relax_impulses: f32,
83 pub apply_restitution: f32,
84 pub store_impulses: f32,
85 pub split_islands: f32,
86 pub transforms: f32,
87 pub sensor_hits: f32,
88 pub joint_events: f32,
89 pub hit_events: f32,
90 pub refit: f32,
91 pub bullets: f32,
92 pub sleep_islands: f32,
93 pub sensors: f32,
94}
95
96#[derive(Debug, Clone)]
101pub struct TaskContext {
102 pub sensor_hits: Vec<SensorHit>,
104
105 pub contact_state_bit_set: BitSet,
107
108 pub joint_state_bit_set: BitSet,
110
111 pub hit_event_bit_set: BitSet,
113
114 pub has_hit_events: bool,
117
118 pub enlarged_sim_bit_set: BitSet,
120
121 pub awake_island_bit_set: BitSet,
123
124 pub split_sleep_time: f32,
126 pub split_island_id: i32,
127
128 pub sat_call_count: i32,
130 pub sat_cache_hit_count: i32,
131 pub distance_iterations: i32,
132 pub push_back_iterations: i32,
133 pub root_iterations: i32,
134
135 pub recycled_contact_count: i32,
137
138 pub manifold_counts: [i32; CONTACT_MANIFOLD_COUNT_BUCKETS],
139
140 pub points: [DebugPoint; DEBUG_POINT_CAPACITY],
142 pub point_count: usize,
143
144 pub lines: [DebugLine; DEBUG_LINE_CAPACITY],
146 pub line_count: usize,
147}
148
149impl Default for TaskContext {
150 fn default() -> Self {
151 TaskContext {
152 sensor_hits: Vec::new(),
153 contact_state_bit_set: BitSet::default(),
154 joint_state_bit_set: BitSet::default(),
155 hit_event_bit_set: BitSet::default(),
156 has_hit_events: false,
157 enlarged_sim_bit_set: BitSet::default(),
158 awake_island_bit_set: BitSet::default(),
159 split_sleep_time: 0.0,
160 split_island_id: 0,
161 sat_call_count: 0,
162 sat_cache_hit_count: 0,
163 distance_iterations: 0,
164 push_back_iterations: 0,
165 root_iterations: 0,
166 recycled_contact_count: 0,
167 manifold_counts: [0; CONTACT_MANIFOLD_COUNT_BUCKETS],
168 points: [DebugPoint::default(); DEBUG_POINT_CAPACITY],
169 point_count: 0,
170 lines: [DebugLine::default(); DEBUG_LINE_CAPACITY],
171 line_count: 0,
172 }
173 }
174}
175
176#[derive(Debug)]
179pub struct World {
180 pub broad_phase: BroadPhase,
181 pub constraint_graph: ConstraintGraph,
182
183 pub body_id_pool: IdPool,
185
186 pub bodies: Vec<Body>,
188
189 pub solver_set_id_pool: IdPool,
191
192 pub solver_sets: Vec<SolverSet>,
195
196 pub joint_id_pool: IdPool,
198
199 pub joints: Vec<Joint>,
202
203 pub contact_id_pool: IdPool,
205
206 pub contacts: Vec<Contact>,
208
209 pub island_id_pool: IdPool,
211
212 pub islands: Vec<Island>,
214
215 pub shape_id_pool: IdPool,
216
217 pub shapes: Vec<Shape>,
219
220 pub hull_database: HullDatabase,
222
223 pub names: NameCache,
225
226 pub sensors: Vec<Sensor>,
228
229 pub task_contexts: Vec<TaskContext>,
231 pub sensor_task_contexts: Vec<SensorTaskContext>,
232
233 pub body_move_events: Vec<BodyMoveEvent>,
234 pub sensor_begin_events: Vec<SensorBeginTouchEvent>,
235 pub contact_begin_events: Vec<ContactBeginTouchEvent>,
236
237 pub sensor_end_events: [Vec<SensorEndTouchEvent>; 2],
239 pub contact_end_events: [Vec<ContactEndTouchEvent>; 2],
240 pub end_event_array_index: i32,
241
242 pub contact_hit_events: Vec<ContactHitEvent>,
243 pub joint_events: Vec<JointEvent>,
244
245 pub debug_body_set: BitSet,
247 pub debug_joint_set: BitSet,
248 pub debug_contact_set: BitSet,
249 pub debug_island_set: BitSet,
250
251 pub step_index: u64,
253
254 pub split_island_id: i32,
256
257 pub gravity: Vec3,
258 pub hit_event_threshold: f32,
259 pub restitution_threshold: f32,
260 pub max_linear_speed: f32,
261 pub contact_speed: f32,
262 pub contact_hertz: f32,
263 pub contact_damping_ratio: f32,
264 pub contact_recycle_distance: f32,
265
266 pub friction_callback: Option<FrictionCallback>,
267 pub restitution_callback: Option<RestitutionCallback>,
268
269 pub generation: u16,
270
271 pub profile: Profile,
272 pub sat_call_count: i32,
273 pub sat_cache_hit_count: i32,
274 pub manifold_counts: [i32; CONTACT_MANIFOLD_COUNT_BUCKETS],
275
276 pub max_capacity: Capacity,
277
278 pub pre_solve_fcn: Option<PreSolveFcn>,
279 pub pre_solve_context: u64,
280
281 pub custom_filter_fcn: Option<CustomFilterFcn>,
282 pub custom_filter_context: u64,
283
284 pub create_debug_shape: Option<CreateDebugShapeCallback>,
286 pub destroy_debug_shape: Option<DestroyDebugShapeCallback>,
288 pub user_debug_shape_context: u64,
290
291 pub worker_count: i32,
292
293 pub user_data: u64,
294
295 pub inv_h: f32,
297
298 pub inv_dt: f32,
300
301 pub world_id: u16,
302
303 pub enable_sleep: bool,
304 pub locked: bool,
305 pub enable_warm_starting: bool,
306 pub enable_continuous: bool,
307 pub enable_speculative: bool,
308 pub in_use: bool,
309
310 pub recording: Option<*mut crate::recording::Recording>,
314}
315
316pub fn default_friction_callback(
319 friction_a: f32,
320 _material_a: u64,
321 friction_b: f32,
322 _material_b: u64,
323) -> f32 {
324 (friction_a * friction_b).sqrt()
325}
326
327pub fn default_restitution_callback(
329 restitution_a: f32,
330 _material_a: u64,
331 restitution_b: f32,
332 _material_b: u64,
333) -> f32 {
334 crate::math_functions::max_float(restitution_a, restitution_b)
335}
336
337impl World {
338 pub fn new(def: &crate::types::WorldDef) -> World {
347 use crate::constants::{
348 contact_recycle_distance, linear_slop, mesh_rest_offset, speculative_distance,
349 };
350 use crate::core::{NULL_INDEX, SECRET_COOKIE};
351 use crate::math_functions::max_int;
352 use crate::solver_set::{AWAKE_SET, DISABLED_SET, STATIC_SET};
353
354 debug_assert!(def.internal_value == SECRET_COOKIE);
355 debug_assert!(linear_slop() <= mesh_rest_offset());
356 debug_assert!(mesh_rest_offset() < speculative_distance());
357
358 use crate::contact::initialize_contact_registers;
359 initialize_contact_registers();
360
361 let body_capacity = max_int(
362 16,
363 def.capacity.static_body_count + def.capacity.dynamic_body_count,
364 ) as usize;
365 let shape_capacity = max_int(
366 16,
367 def.capacity.static_shape_count + def.capacity.dynamic_shape_count,
368 ) as usize;
369 let contact_capacity = max_int(16, def.capacity.contact_count) as usize;
370
371 let mut solver_set_id_pool = IdPool::new();
372 let mut solver_sets: Vec<SolverSet> = Vec::with_capacity(8);
373
374 let mut set = SolverSet {
377 set_index: solver_set_id_pool.alloc_id(),
378 ..Default::default()
379 };
380 set.body_sims
381 .reserve(max_int(16, def.capacity.static_body_count) as usize);
382 solver_sets.push(set);
383 debug_assert!(solver_sets[STATIC_SET as usize].set_index == STATIC_SET);
384
385 solver_sets.push(SolverSet {
387 set_index: solver_set_id_pool.alloc_id(),
388 ..Default::default()
389 });
390 debug_assert!(solver_sets[DISABLED_SET as usize].set_index == DISABLED_SET);
391
392 let mut awake = SolverSet {
394 set_index: solver_set_id_pool.alloc_id(),
395 ..Default::default()
396 };
397 awake
398 .body_sims
399 .reserve(max_int(16, def.capacity.dynamic_body_count) as usize);
400 awake
401 .body_states
402 .reserve(max_int(16, def.capacity.dynamic_body_count) as usize);
403 awake.contact_indices.reserve(contact_capacity);
404 solver_sets.push(awake);
405 debug_assert!(solver_sets[AWAKE_SET as usize].set_index == AWAKE_SET);
406
407 World {
408 broad_phase: BroadPhase::new(&def.capacity),
409 constraint_graph: ConstraintGraph::new(16),
410 body_id_pool: IdPool::new(),
411 bodies: Vec::with_capacity(body_capacity),
412 solver_set_id_pool,
413 solver_sets,
414 joint_id_pool: IdPool::new(),
415 joints: Vec::with_capacity(16),
416 contact_id_pool: IdPool::new(),
417 contacts: Vec::with_capacity(contact_capacity),
418 island_id_pool: IdPool::new(),
419 islands: Vec::with_capacity(max_int(16, def.capacity.dynamic_body_count) as usize),
420 shape_id_pool: IdPool::new(),
421 shapes: Vec::with_capacity(shape_capacity),
422 hull_database: HullDatabase::new(),
423 names: NameCache::new(),
424 sensors: Vec::with_capacity(4),
425 task_contexts: vec![TaskContext::default()],
427 sensor_task_contexts: vec![SensorTaskContext::default()],
428 body_move_events: Vec::with_capacity(4),
429 sensor_begin_events: Vec::with_capacity(4),
430 contact_begin_events: Vec::with_capacity(4),
431 sensor_end_events: [Vec::with_capacity(4), Vec::with_capacity(4)],
432 contact_end_events: [Vec::with_capacity(4), Vec::with_capacity(4)],
433 end_event_array_index: 0,
434 contact_hit_events: Vec::with_capacity(4),
435 joint_events: Vec::with_capacity(4),
436 debug_body_set: BitSet::new(256),
437 debug_joint_set: BitSet::new(256),
438 debug_contact_set: BitSet::new(256),
439 debug_island_set: BitSet::new(256),
440 step_index: 0,
441 split_island_id: NULL_INDEX,
442 gravity: def.gravity,
443 hit_event_threshold: def.hit_event_threshold,
444 restitution_threshold: def.restitution_threshold,
445 max_linear_speed: def.maximum_linear_speed,
446 contact_speed: def.contact_speed,
447 contact_hertz: def.contact_hertz,
448 contact_damping_ratio: def.contact_damping_ratio,
449 contact_recycle_distance: contact_recycle_distance(),
450 friction_callback: Some(def.friction_callback.unwrap_or(default_friction_callback)),
451 restitution_callback: Some(
452 def.restitution_callback
453 .unwrap_or(default_restitution_callback),
454 ),
455 generation: 0,
456 profile: Profile::default(),
457 sat_call_count: 0,
458 sat_cache_hit_count: 0,
459 manifold_counts: [0; CONTACT_MANIFOLD_COUNT_BUCKETS],
460 max_capacity: def.capacity,
461 pre_solve_fcn: None,
462 pre_solve_context: 0,
463 custom_filter_fcn: None,
464 custom_filter_context: 0,
465 create_debug_shape: def.create_debug_shape,
466 destroy_debug_shape: def.destroy_debug_shape,
467 user_debug_shape_context: def.user_debug_shape_context,
468 worker_count: 1,
469 user_data: def.user_data,
470 inv_h: 0.0,
471 inv_dt: 0.0,
472 world_id: 0,
473 enable_sleep: def.enable_sleep,
474 locked: false,
475 enable_warm_starting: true,
476 enable_continuous: def.enable_continuous,
477 enable_speculative: true,
478 in_use: true,
479 recording: None,
480 }
481 }
482
483 pub fn enable_continuous(&mut self, flag: bool) {
485 debug_assert!(!self.locked);
486 if self.locked {
487 return;
488 }
489 self.enable_continuous = flag;
490 }
491
492 pub fn is_continuous_enabled(&self) -> bool {
494 self.enable_continuous
495 }
496
497 pub fn get_sensor_events(&self) -> crate::events::SensorEvents<'_> {
500 let end_event_array_index = 1 - self.end_event_array_index;
501 crate::events::SensorEvents {
502 begin_events: &self.sensor_begin_events,
503 end_events: &self.sensor_end_events[end_event_array_index as usize],
504 }
505 }
506}