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