box3d_rust/world/
validate.rs1use crate::world::World;
8
9impl World {
10 pub fn validate_solver_sets(&self) {
15 use crate::body::body_flags;
16 use crate::broad_phase::proxy_type;
17 use crate::constants::GRAPH_COLOR_COUNT;
18 use crate::constraint_graph::OVERFLOW_INDEX;
19 use crate::contact::contact_flags;
20 use crate::core::NULL_INDEX;
21 use crate::solver_set::{AWAKE_SET, DISABLED_SET, FIRST_SLEEPING_SET, STATIC_SET};
22 use crate::types::BodyType;
23
24 debug_assert!(self.body_id_pool.id_capacity() == self.bodies.len() as i32);
25 debug_assert!(self.contact_id_pool.id_capacity() == self.contacts.len() as i32);
26 debug_assert!(self.joint_id_pool.id_capacity() == self.joints.len() as i32);
27 debug_assert!(self.island_id_pool.id_capacity() == self.islands.len() as i32);
28 debug_assert!(self.solver_set_id_pool.id_capacity() == self.solver_sets.len() as i32);
29
30 let mut active_set_count = 0;
31 let mut total_body_count = 0;
32 let mut total_joint_count = 0;
33 let mut total_contact_count = 0;
34 let mut total_island_count = 0;
35
36 for (set_index, set) in self.solver_sets.iter().enumerate() {
38 if set.set_index != NULL_INDEX {
39 active_set_count += 1;
40
41 if set_index == STATIC_SET as usize {
42 debug_assert!(set.contact_indices.is_empty());
43 debug_assert!(set.island_sims.is_empty());
44 debug_assert!(set.body_states.is_empty());
45 } else if set_index == DISABLED_SET as usize {
46 debug_assert!(set.island_sims.is_empty());
47 debug_assert!(set.body_states.is_empty());
48 } else if set_index == AWAKE_SET as usize {
49 debug_assert!(set.body_sims.len() == set.body_states.len());
50 debug_assert!(set.joint_sims.is_empty());
51 } else {
52 debug_assert!(set.body_states.is_empty());
53 }
54
55 {
57 total_body_count += set.body_sims.len() as i32;
58 for (local_index, body_sim) in set.body_sims.iter().enumerate() {
59 let body_id = body_sim.body_id;
60 debug_assert!(0 <= body_id && (body_id as usize) < self.bodies.len());
61 let body = &self.bodies[body_id as usize];
62 debug_assert!(body.set_index == set_index as i32);
63 debug_assert!(body.local_index == local_index as i32);
64 debug_assert!(body.id == body_id);
65
66 let synced_flags = body.flags & !body_flags::BODY_TRANSIENT_FLAGS;
67 debug_assert!((body_sim.flags & synced_flags) == synced_flags);
68
69 if set_index == AWAKE_SET as usize {
70 let body_state = &set.body_states[local_index];
71 debug_assert!((body_state.flags & synced_flags) == synced_flags);
72 let _ = body_state;
73 }
74
75 if body.type_ == BodyType::Dynamic {
76 debug_assert!((body.flags & body_flags::DYNAMIC_FLAG) != 0);
77 }
78
79 if set_index == DISABLED_SET as usize {
80 debug_assert!(body.head_contact_key == NULL_INDEX);
81 }
82
83 let mut prev_shape_id = NULL_INDEX;
85 let mut shape_id = body.head_shape_id;
86 while shape_id != NULL_INDEX {
87 let shape = &self.shapes[shape_id as usize];
88 debug_assert!(shape.id == shape_id);
89 debug_assert!(shape.prev_shape_id == prev_shape_id);
90
91 if set_index == DISABLED_SET as usize {
92 debug_assert!(shape.proxy_key == NULL_INDEX);
93 } else if set_index == STATIC_SET as usize {
94 debug_assert!(proxy_type(shape.proxy_key) == BodyType::Static);
95 } else {
96 let proxy_type_ = proxy_type(shape.proxy_key);
97 debug_assert!(
98 proxy_type_ == BodyType::Kinematic
99 || proxy_type_ == BodyType::Dynamic
100 );
101 let _ = proxy_type_;
102 }
103
104 prev_shape_id = shape_id;
105 shape_id = shape.next_shape_id;
106 }
107
108 let mut contact_key = body.head_contact_key;
110 while contact_key != NULL_INDEX {
111 let contact_id = contact_key >> 1;
112 let edge_index = (contact_key & 1) as usize;
113
114 let contact = &self.contacts[contact_id as usize];
115 debug_assert!(contact.set_index != STATIC_SET);
116 debug_assert!(
117 contact.edges[0].body_id == body_id
118 || contact.edges[1].body_id == body_id
119 );
120 contact_key = contact.edges[edge_index].next_key;
121 }
122
123 let mut joint_key = body.head_joint_key;
125 while joint_key != NULL_INDEX {
126 let joint_id = joint_key >> 1;
127 let edge_index = (joint_key & 1) as usize;
128
129 let joint = &self.joints[joint_id as usize];
130
131 let other_edge_index = edge_index ^ 1;
132 let other_body =
133 &self.bodies[joint.edges[other_edge_index].body_id as usize];
134
135 if set_index == DISABLED_SET as usize
136 || other_body.set_index == DISABLED_SET
137 {
138 debug_assert!(joint.set_index == DISABLED_SET);
139 } else if set_index == STATIC_SET as usize
140 && other_body.set_index == STATIC_SET
141 {
142 debug_assert!(joint.set_index == STATIC_SET);
143 } else if body.type_ != BodyType::Dynamic
144 && other_body.type_ != BodyType::Dynamic
145 {
146 debug_assert!(joint.set_index == STATIC_SET);
147 } else if set_index == AWAKE_SET as usize {
148 debug_assert!(joint.set_index == AWAKE_SET);
149 } else if set_index >= FIRST_SLEEPING_SET as usize {
150 debug_assert!(joint.set_index == set_index as i32);
151 }
152
153 let joint_sim = if joint.set_index == AWAKE_SET {
155 debug_assert!(
156 0 <= joint.color_index && joint.color_index < GRAPH_COLOR_COUNT
157 );
158 &self.constraint_graph.colors[joint.color_index as usize].joint_sims
159 [joint.local_index as usize]
160 } else {
161 debug_assert!(joint.color_index == NULL_INDEX);
162 &self.solver_sets[joint.set_index as usize].joint_sims
163 [joint.local_index as usize]
164 };
165 debug_assert!(joint_sim.joint_id == joint_id);
166 debug_assert!(joint_sim.body_id_a == joint.edges[0].body_id);
167 debug_assert!(joint_sim.body_id_b == joint.edges[1].body_id);
168 let _ = joint_sim;
169
170 joint_key = joint.edges[edge_index].next_key;
171 }
172
173 let _ = (body, local_index);
174 }
175 }
176
177 {
179 total_contact_count += set.contact_indices.len() as i32;
180 for (local_index, &contact_index) in set.contact_indices.iter().enumerate() {
181 let contact = &self.contacts[contact_index as usize];
182 if set_index == AWAKE_SET as usize {
183 debug_assert!(
186 contact.manifold_count() == 0
187 || (contact.flags & contact_flags::SIM_STARTED_TOUCHING) != 0
188 );
189 }
190 debug_assert!(contact.set_index == set_index as i32);
191 debug_assert!(contact.color_index == NULL_INDEX);
192 debug_assert!(contact.local_index == local_index as i32);
193 let _ = (contact, local_index);
194 }
195 }
196
197 {
199 total_joint_count += set.joint_sims.len() as i32;
200 for (local_index, joint_sim) in set.joint_sims.iter().enumerate() {
201 let joint = &self.joints[joint_sim.joint_id as usize];
202 debug_assert!(joint.set_index == set_index as i32);
203 debug_assert!(joint.color_index == NULL_INDEX);
204 debug_assert!(joint.local_index == local_index as i32);
205 let _ = (joint, local_index);
206 }
207 }
208
209 {
211 total_island_count += set.island_sims.len() as i32;
212 for (local_index, island_sim) in set.island_sims.iter().enumerate() {
213 let island = &self.islands[island_sim.island_id as usize];
214 debug_assert!(island.set_index == set_index as i32);
215 debug_assert!(island.local_index == local_index as i32);
216 let _ = (island, local_index);
217 }
218 }
219 } else {
220 debug_assert!(set.body_sims.is_empty());
221 debug_assert!(set.contact_indices.is_empty());
222 debug_assert!(set.joint_sims.is_empty());
223 debug_assert!(set.island_sims.is_empty());
224 debug_assert!(set.body_states.is_empty());
225 }
226 }
227
228 debug_assert!(active_set_count == self.solver_set_id_pool.id_count());
229 debug_assert!(total_body_count == self.body_id_pool.id_count());
230 debug_assert!(total_island_count == self.island_id_pool.id_count());
231
232 for color_index in 0..GRAPH_COLOR_COUNT {
234 let color = &self.constraint_graph.colors[color_index as usize];
235 let mut bit_count = 0;
236
237 total_contact_count += color.convex_contacts.len() as i32;
238 for (local_index, &contact_id) in color.convex_contacts.iter().enumerate() {
239 let contact = &self.contacts[contact_id as usize];
240 debug_assert!(
242 contact.manifold_count() > 0
243 || (contact.flags
244 & (contact_flags::SIM_STOPPED_TOUCHING | contact_flags::SIM_DISJOINT))
245 != 0
246 );
247 debug_assert!(contact.set_index == AWAKE_SET);
248 debug_assert!(contact.color_index == color_index);
249 debug_assert!(contact.local_index == local_index as i32);
250
251 if color_index < OVERFLOW_INDEX {
252 let body_a = &self.bodies[contact.edges[0].body_id as usize];
253 let body_b = &self.bodies[contact.edges[1].body_id as usize];
254 debug_assert!(
255 color.body_set.get_bit(contact.edges[0].body_id as u32)
256 == (body_a.type_ == BodyType::Dynamic)
257 );
258 debug_assert!(
259 color.body_set.get_bit(contact.edges[1].body_id as u32)
260 == (body_b.type_ == BodyType::Dynamic)
261 );
262
263 bit_count += if body_a.type_ == BodyType::Dynamic {
264 1
265 } else {
266 0
267 };
268 bit_count += if body_b.type_ == BodyType::Dynamic {
269 1
270 } else {
271 0
272 };
273 }
274 let _ = (contact, local_index);
275 }
276
277 total_contact_count += color.contacts.len() as i32;
278 for (local_index, spec) in color.contacts.iter().enumerate() {
279 let contact = &self.contacts[spec.contact_id as usize];
280 debug_assert!(
282 contact.manifold_count() > 0
283 || (contact.flags
284 & (contact_flags::SIM_STOPPED_TOUCHING | contact_flags::SIM_DISJOINT))
285 != 0
286 );
287 debug_assert!(contact.set_index == AWAKE_SET);
288 debug_assert!(contact.color_index == color_index);
289 debug_assert!(contact.local_index == local_index as i32);
290
291 if color_index < OVERFLOW_INDEX {
292 let body_a = &self.bodies[contact.edges[0].body_id as usize];
293 let body_b = &self.bodies[contact.edges[1].body_id as usize];
294 debug_assert!(
295 color.body_set.get_bit(contact.edges[0].body_id as u32)
296 == (body_a.type_ == BodyType::Dynamic)
297 );
298 debug_assert!(
299 color.body_set.get_bit(contact.edges[1].body_id as u32)
300 == (body_b.type_ == BodyType::Dynamic)
301 );
302
303 bit_count += if body_a.type_ == BodyType::Dynamic {
304 1
305 } else {
306 0
307 };
308 bit_count += if body_b.type_ == BodyType::Dynamic {
309 1
310 } else {
311 0
312 };
313 }
314 let _ = (contact, local_index);
315 }
316
317 total_joint_count += color.joint_sims.len() as i32;
318 for (local_index, joint_sim) in color.joint_sims.iter().enumerate() {
319 let joint = &self.joints[joint_sim.joint_id as usize];
320 debug_assert!(joint.set_index == AWAKE_SET);
321 debug_assert!(joint.color_index == color_index);
322 debug_assert!(joint.local_index == local_index as i32);
323
324 if color_index < OVERFLOW_INDEX {
325 let body_a = &self.bodies[joint.edges[0].body_id as usize];
326 let body_b = &self.bodies[joint.edges[1].body_id as usize];
327 debug_assert!(
328 color.body_set.get_bit(joint.edges[0].body_id as u32)
329 == (body_a.type_ == BodyType::Dynamic)
330 );
331 debug_assert!(
332 color.body_set.get_bit(joint.edges[1].body_id as u32)
333 == (body_b.type_ == BodyType::Dynamic)
334 );
335
336 bit_count += if body_a.type_ == BodyType::Dynamic {
337 1
338 } else {
339 0
340 };
341 bit_count += if body_b.type_ == BodyType::Dynamic {
342 1
343 } else {
344 0
345 };
346 }
347 let _ = (joint, local_index);
348 }
349
350 debug_assert!(bit_count == color.body_set.count_set_bits());
352 let _ = bit_count;
353 }
354
355 debug_assert!(total_contact_count == self.contact_id_pool.id_count());
356 debug_assert!(total_contact_count == self.broad_phase.pair_set.count());
357
358 debug_assert!(total_joint_count == self.joint_id_pool.id_count());
359
360 let _ = (
361 active_set_count,
362 total_body_count,
363 total_joint_count,
364 total_contact_count,
365 total_island_count,
366 );
367 }
368}