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(&World, ShapeId, ShapeId, u64) -> bool;
84
85pub type PreSolveFcn =
87 fn(ShapeId, ShapeId, crate::math_functions::Pos, crate::math_functions::Vec3, u64) -> bool;
88
89#[derive(Debug, Clone, Copy, PartialEq, Default)]
91pub struct Profile {
92 pub step: f32,
93 pub pairs: f32,
94 pub collide: f32,
95 pub solve: f32,
96 pub solver_setup: f32,
97 pub constraints: f32,
98 pub prepare_constraints: f32,
99 pub integrate_velocities: f32,
100 pub warm_start: f32,
101 pub solve_impulses: f32,
102 pub integrate_positions: f32,
103 pub relax_impulses: f32,
104 pub apply_restitution: f32,
105 pub store_impulses: f32,
106 pub split_islands: f32,
107 pub transforms: f32,
108 pub sensor_hits: f32,
109 pub joint_events: f32,
110 pub hit_events: f32,
111 pub refit: f32,
112 pub bullets: f32,
113 pub sleep_islands: f32,
114 pub sensors: f32,
115}
116
117#[derive(Debug, Clone)]
122pub struct TaskContext {
123 pub sensor_hits: Vec<SensorHit>,
125
126 pub contact_state_bit_set: BitSet,
128
129 pub joint_state_bit_set: BitSet,
131
132 pub hit_event_bit_set: BitSet,
134
135 pub has_hit_events: bool,
138
139 pub enlarged_sim_bit_set: BitSet,
141
142 pub awake_island_bit_set: BitSet,
144
145 pub split_sleep_time: f32,
147 pub split_island_id: i32,
148
149 pub sat_call_count: i32,
151 pub sat_cache_hit_count: i32,
152 pub distance_iterations: i32,
153 pub push_back_iterations: i32,
154 pub root_iterations: i32,
155
156 pub recycled_contact_count: i32,
158
159 pub manifold_counts: [i32; CONTACT_MANIFOLD_COUNT_BUCKETS],
160
161 pub points: [DebugPoint; DEBUG_POINT_CAPACITY],
163 pub point_count: usize,
164
165 pub lines: [DebugLine; DEBUG_LINE_CAPACITY],
167 pub line_count: usize,
168}
169
170impl Default for TaskContext {
171 fn default() -> Self {
172 TaskContext {
173 sensor_hits: Vec::new(),
174 contact_state_bit_set: BitSet::default(),
175 joint_state_bit_set: BitSet::default(),
176 hit_event_bit_set: BitSet::default(),
177 has_hit_events: false,
178 enlarged_sim_bit_set: BitSet::default(),
179 awake_island_bit_set: BitSet::default(),
180 split_sleep_time: 0.0,
181 split_island_id: 0,
182 sat_call_count: 0,
183 sat_cache_hit_count: 0,
184 distance_iterations: 0,
185 push_back_iterations: 0,
186 root_iterations: 0,
187 recycled_contact_count: 0,
188 manifold_counts: [0; CONTACT_MANIFOLD_COUNT_BUCKETS],
189 points: [DebugPoint::default(); DEBUG_POINT_CAPACITY],
190 point_count: 0,
191 lines: [DebugLine::default(); DEBUG_LINE_CAPACITY],
192 line_count: 0,
193 }
194 }
195}
196
197#[derive(Debug)]
200pub struct World {
201 pub broad_phase: BroadPhase,
202 pub constraint_graph: ConstraintGraph,
203
204 pub body_id_pool: IdPool,
206
207 pub bodies: Vec<Body>,
209
210 pub solver_set_id_pool: IdPool,
212
213 pub solver_sets: Vec<SolverSet>,
216
217 pub joint_id_pool: IdPool,
219
220 pub joints: Vec<Joint>,
223
224 pub contact_id_pool: IdPool,
226
227 pub contacts: Vec<Contact>,
229
230 pub island_id_pool: IdPool,
232
233 pub islands: Vec<Island>,
235
236 pub shape_id_pool: IdPool,
237
238 pub shapes: Vec<Shape>,
240
241 pub hull_database: HullDatabase,
243
244 pub names: NameCache,
246
247 pub sensors: Vec<Sensor>,
249
250 pub task_contexts: Vec<TaskContext>,
252 pub sensor_task_contexts: Vec<SensorTaskContext>,
253
254 pub body_move_events: Vec<BodyMoveEvent>,
255 pub sensor_begin_events: Vec<SensorBeginTouchEvent>,
256 pub contact_begin_events: Vec<ContactBeginTouchEvent>,
257
258 pub sensor_end_events: [Vec<SensorEndTouchEvent>; 2],
260 pub contact_end_events: [Vec<ContactEndTouchEvent>; 2],
261 pub end_event_array_index: i32,
262
263 pub contact_hit_events: Vec<ContactHitEvent>,
264 pub joint_events: Vec<JointEvent>,
265
266 pub debug_body_set: BitSet,
268 pub debug_joint_set: BitSet,
269 pub debug_contact_set: BitSet,
270 pub debug_island_set: BitSet,
271
272 pub step_index: u64,
274
275 pub split_island_id: i32,
277
278 pub gravity: Vec3,
279 pub hit_event_threshold: f32,
280 pub restitution_threshold: f32,
281 pub max_linear_speed: f32,
282 pub contact_speed: f32,
283 pub contact_hertz: f32,
284 pub contact_damping_ratio: f32,
285 pub contact_recycle_distance: f32,
286
287 pub friction_callback: Option<FrictionCallback>,
288 pub restitution_callback: Option<RestitutionCallback>,
289
290 pub generation: u16,
291
292 pub profile: Profile,
293 pub sat_call_count: i32,
294 pub sat_cache_hit_count: i32,
295 pub manifold_counts: [i32; CONTACT_MANIFOLD_COUNT_BUCKETS],
296
297 pub max_capacity: Capacity,
298
299 pub pre_solve_fcn: Option<PreSolveFcn>,
300 pub pre_solve_context: u64,
301
302 pub custom_filter_fcn: Option<CustomFilterFcn>,
303 pub custom_filter_context: u64,
304
305 pub create_debug_shape: Option<CreateDebugShapeCallback>,
307 pub destroy_debug_shape: Option<DestroyDebugShapeCallback>,
309 pub user_debug_shape_context: u64,
311
312 pub worker_count: i32,
313
314 pub user_data: u64,
315
316 pub inv_h: f32,
318
319 pub inv_dt: f32,
321
322 pub world_id: u16,
323
324 pub enable_sleep: bool,
325 pub locked: bool,
326 pub enable_warm_starting: bool,
327 pub enable_continuous: bool,
328 pub enable_speculative: bool,
329 pub in_use: bool,
330
331 pub recording: Option<*mut crate::recording::Recording>,
335}
336
337pub fn default_friction_callback(
340 friction_a: f32,
341 _material_a: u64,
342 friction_b: f32,
343 _material_b: u64,
344) -> f32 {
345 (friction_a * friction_b).sqrt()
346}
347
348pub fn default_restitution_callback(
350 restitution_a: f32,
351 _material_a: u64,
352 restitution_b: f32,
353 _material_b: u64,
354) -> f32 {
355 crate::math_functions::max_float(restitution_a, restitution_b)
356}
357
358impl World {
359 pub fn new(def: &crate::types::WorldDef) -> World {
368 use crate::constants::{
369 contact_recycle_distance, linear_slop, mesh_rest_offset, speculative_distance,
370 };
371 use crate::core::{NULL_INDEX, SECRET_COOKIE};
372 use crate::math_functions::max_int;
373 use crate::solver_set::{AWAKE_SET, DISABLED_SET, STATIC_SET};
374
375 debug_assert!(def.internal_value == SECRET_COOKIE);
376 debug_assert!(linear_slop() <= mesh_rest_offset());
377 debug_assert!(mesh_rest_offset() < speculative_distance());
378
379 use crate::contact::initialize_contact_registers;
380 initialize_contact_registers();
381
382 let body_capacity = max_int(
383 16,
384 def.capacity.static_body_count + def.capacity.dynamic_body_count,
385 ) as usize;
386 let shape_capacity = max_int(
387 16,
388 def.capacity.static_shape_count + def.capacity.dynamic_shape_count,
389 ) as usize;
390 let contact_capacity = max_int(16, def.capacity.contact_count) as usize;
391
392 let mut solver_set_id_pool = IdPool::new();
393 let mut solver_sets: Vec<SolverSet> = Vec::with_capacity(8);
394
395 let mut set = SolverSet {
398 set_index: solver_set_id_pool.alloc_id(),
399 ..Default::default()
400 };
401 set.body_sims
402 .reserve(max_int(16, def.capacity.static_body_count) as usize);
403 solver_sets.push(set);
404 debug_assert!(solver_sets[STATIC_SET as usize].set_index == STATIC_SET);
405
406 solver_sets.push(SolverSet {
408 set_index: solver_set_id_pool.alloc_id(),
409 ..Default::default()
410 });
411 debug_assert!(solver_sets[DISABLED_SET as usize].set_index == DISABLED_SET);
412
413 let mut awake = SolverSet {
415 set_index: solver_set_id_pool.alloc_id(),
416 ..Default::default()
417 };
418 awake
419 .body_sims
420 .reserve(max_int(16, def.capacity.dynamic_body_count) as usize);
421 awake
422 .body_states
423 .reserve(max_int(16, def.capacity.dynamic_body_count) as usize);
424 awake.contact_indices.reserve(contact_capacity);
425 solver_sets.push(awake);
426 debug_assert!(solver_sets[AWAKE_SET as usize].set_index == AWAKE_SET);
427
428 World {
429 broad_phase: BroadPhase::new(&def.capacity),
430 constraint_graph: ConstraintGraph::new(16),
431 body_id_pool: IdPool::new(),
432 bodies: Vec::with_capacity(body_capacity),
433 solver_set_id_pool,
434 solver_sets,
435 joint_id_pool: IdPool::new(),
436 joints: Vec::with_capacity(16),
437 contact_id_pool: IdPool::new(),
438 contacts: Vec::with_capacity(contact_capacity),
439 island_id_pool: IdPool::new(),
440 islands: Vec::with_capacity(max_int(16, def.capacity.dynamic_body_count) as usize),
441 shape_id_pool: IdPool::new(),
442 shapes: Vec::with_capacity(shape_capacity),
443 hull_database: HullDatabase::new(),
444 names: NameCache::new(),
445 sensors: Vec::with_capacity(4),
446 task_contexts: vec![TaskContext::default()],
448 sensor_task_contexts: vec![SensorTaskContext::default()],
449 body_move_events: Vec::with_capacity(4),
450 sensor_begin_events: Vec::with_capacity(4),
451 contact_begin_events: Vec::with_capacity(4),
452 sensor_end_events: [Vec::with_capacity(4), Vec::with_capacity(4)],
453 contact_end_events: [Vec::with_capacity(4), Vec::with_capacity(4)],
454 end_event_array_index: 0,
455 contact_hit_events: Vec::with_capacity(4),
456 joint_events: Vec::with_capacity(4),
457 debug_body_set: BitSet::new(256),
458 debug_joint_set: BitSet::new(256),
459 debug_contact_set: BitSet::new(256),
460 debug_island_set: BitSet::new(256),
461 step_index: 0,
462 split_island_id: NULL_INDEX,
463 gravity: def.gravity,
464 hit_event_threshold: def.hit_event_threshold,
465 restitution_threshold: def.restitution_threshold,
466 max_linear_speed: def.maximum_linear_speed,
467 contact_speed: def.contact_speed,
468 contact_hertz: def.contact_hertz,
469 contact_damping_ratio: def.contact_damping_ratio,
470 contact_recycle_distance: contact_recycle_distance(),
471 friction_callback: Some(def.friction_callback.unwrap_or(default_friction_callback)),
472 restitution_callback: Some(
473 def.restitution_callback
474 .unwrap_or(default_restitution_callback),
475 ),
476 generation: 0,
477 profile: Profile::default(),
478 sat_call_count: 0,
479 sat_cache_hit_count: 0,
480 manifold_counts: [0; CONTACT_MANIFOLD_COUNT_BUCKETS],
481 max_capacity: def.capacity,
482 pre_solve_fcn: None,
483 pre_solve_context: 0,
484 custom_filter_fcn: None,
485 custom_filter_context: 0,
486 create_debug_shape: def.create_debug_shape,
487 destroy_debug_shape: def.destroy_debug_shape,
488 user_debug_shape_context: def.user_debug_shape_context,
489 worker_count: 1,
490 user_data: def.user_data,
491 inv_h: 0.0,
492 inv_dt: 0.0,
493 world_id: 0,
494 enable_sleep: def.enable_sleep,
495 locked: false,
496 enable_warm_starting: true,
497 enable_continuous: def.enable_continuous,
498 enable_speculative: true,
499 in_use: true,
500 recording: None,
501 }
502 }
503
504 pub fn enable_continuous(&mut self, flag: bool) {
506 debug_assert!(!self.locked);
507 if self.locked {
508 return;
509 }
510 self.enable_continuous = flag;
511 }
512
513 pub fn is_continuous_enabled(&self) -> bool {
515 self.enable_continuous
516 }
517
518 pub fn get_sensor_events(&self) -> crate::events::SensorEvents<'_> {
521 let end_event_array_index = 1 - self.end_event_array_index;
522 crate::events::SensorEvents {
523 begin_events: &self.sensor_begin_events,
524 end_events: &self.sensor_end_events[end_event_array_index as usize],
525 }
526 }
527}