1use crate::world::{Profile, World};
8
9impl World {
10 pub fn step(&mut self, time_step: f32, sub_step_count: i32) {
12 use crate::broad_phase::update_broad_phase_pairs;
13 use crate::math_functions::{is_valid_float, max_int, min_float};
14 use crate::solver::{make_soft, solve, StepContext};
15
16 debug_assert!(is_valid_float(time_step) && time_step >= 0.0);
17 debug_assert!(!self.locked);
18 if self.locked {
19 return;
20 }
21
22 crate::recording::capture::rec(self, |rec, wid| {
23 rec.write_step(wid, time_step, sub_step_count);
24 });
25
26 self.locked = true;
27
28 self.body_move_events.clear();
29 self.sensor_begin_events.clear();
30 self.contact_begin_events.clear();
31 self.contact_hit_events.clear();
32 self.joint_events.clear();
33 self.profile = Profile::default();
34
35 {
36 let c = &mut self.max_capacity;
37 c.static_shape_count = max_int(
38 c.static_shape_count,
39 self.broad_phase.trees[crate::types::BodyType::Static as usize].proxy_count(),
40 );
41 c.dynamic_shape_count = max_int(
42 c.dynamic_shape_count,
43 self.broad_phase.trees[crate::types::BodyType::Dynamic as usize].proxy_count(),
44 );
45 let static_body_count = self.solver_sets[crate::solver_set::STATIC_SET as usize]
46 .body_sims
47 .len() as i32;
48 c.static_body_count = max_int(c.static_body_count, static_body_count);
49 let total_body_count = self.body_id_pool.id_count();
50 c.dynamic_body_count =
51 max_int(c.dynamic_body_count, total_body_count - static_body_count);
52 c.contact_count = max_int(c.contact_count, self.contact_id_pool.id_count());
53 }
54
55 update_broad_phase_pairs(self);
56
57 let sub_steps = max_int(1, sub_step_count);
58 let mut context = StepContext {
59 dt: time_step,
60 sub_step_count: sub_steps,
61 ..StepContext::default()
62 };
63
64 if time_step > 0.0 {
65 context.inv_dt = 1.0 / time_step;
66 context.h = time_step / sub_steps as f32;
67 context.inv_h = sub_steps as f32 * context.inv_dt;
68 } else {
69 context.inv_dt = 0.0;
70 context.h = 0.0;
71 context.inv_h = 0.0;
72 }
73
74 self.inv_dt = context.inv_dt;
75 self.inv_h = context.inv_h;
76
77 let contact_hertz = min_float(self.contact_hertz, 0.125 * context.inv_h);
79 context.contact_softness = make_soft(contact_hertz, self.contact_damping_ratio, context.h);
80 context.static_softness = make_soft(
81 2.0 * contact_hertz,
82 0.5 * self.contact_damping_ratio,
83 context.h,
84 );
85 context.restitution_threshold = self.restitution_threshold;
86 context.max_linear_velocity = self.max_linear_speed;
87 context.contact_speed = self.contact_speed;
88 context.enable_warm_starting = self.enable_warm_starting;
89
90 crate::contact::collide(self, time_step);
91
92 if time_step > 0.0 {
93 solve(self, &context);
94 }
95
96 crate::sensor::overlap_sensors(self);
98
99 self.step_index = self.step_index.wrapping_add(1);
100 self.validate_solver_sets();
101
102 self.end_event_array_index = 1 - self.end_event_array_index;
104 self.sensor_end_events[self.end_event_array_index as usize].clear();
105 self.contact_end_events[self.end_event_array_index as usize].clear();
106 self.locked = false;
107
108 if self.recording.is_some() {
109 use crate::math_functions::aabb_union;
110 use crate::recording::hash::hash_world_state;
111 use crate::recording::session::world_public_id;
112 use crate::types::BODY_TYPE_COUNT;
113
114 let hash = hash_world_state(self);
115 let wid = world_public_id(self);
116 crate::recording::with_recording(self, |rec| {
117 rec.write_state_hash(wid, hash);
118 });
119
120 let mut world_bounds = crate::math_functions::Aabb::default();
121 let mut have_bounds = false;
122 for i in 0..BODY_TYPE_COUNT {
123 let tree = &self.broad_phase.trees[i];
124 if tree.proxy_count() == 0 {
125 continue;
126 }
127 let bounds = tree.root_bounds();
128 world_bounds = if have_bounds {
129 aabb_union(world_bounds, bounds)
130 } else {
131 bounds
132 };
133 have_bounds = true;
134 }
135 if have_bounds {
136 crate::recording::with_recording(self, |rec| {
137 rec.accumulate_bounds(world_bounds);
138 });
139 }
140 }
141 }
142}