1use crate::b2_collision::*;
2use crate::b2_growable_stack::B2growableStack;
3use crate::b2_math::*;
4use crate::b2_common::*;
5use crate::private::collision::b2_dynamic_tree as private;
6
7pub const B2_NULL_NODE: i32 = -1;
8
9#[derive(Default, Clone, Debug)]
11pub struct B2treeNode<UserDataType> {
12 pub(crate) aabb: B2AABB,
14
15 pub(crate) user_data: Option<UserDataType>,
16
17 pub(crate) parent: i32,
24
25 pub(crate) child1: i32,
26 pub(crate) child2: i32,
27
28 pub(crate) height: i32,
30
31 pub(crate) moved: bool,
32}
33
34impl<UserDataType> B2treeNode<UserDataType> {
35 pub fn is_leaf(&self) -> bool {
36 return self.child1 == B2_NULL_NODE;
37 }
38}
39
40#[derive(Default, Clone, Debug)]
49pub struct B2dynamicTree<UserDataType> {
50 pub(crate) m_root: i32,
51
52 pub(crate) m_nodes: Vec<B2treeNode<UserDataType>>,
53 pub(crate) m_node_count: i32,
54 pub(crate) m_node_capacity: i32,
55
56 pub(crate) m_free_list: i32,
57
58 pub(crate) m_insertion_count: i32,
59}
60
61impl<UserDataType: Clone + Default> B2dynamicTree<UserDataType> {
62 pub fn new() -> Self {
64 return private::b2_dynamic_tree();
65 }
66
67 pub fn create_proxy(&mut self, aabb: B2AABB, user_data: &UserDataType) -> i32 {
72 return private::create_proxy(self, aabb, user_data);
73 }
74
75 pub fn destroy_proxy(&mut self, proxy_id: i32) {
77 private::destroy_proxy(self, proxy_id);
78 }
79
80 pub fn move_proxy(&mut self, proxy_id: i32, aabb1: B2AABB, displacement: B2vec2) -> bool {
86 return private::move_proxy(self, proxy_id, aabb1, displacement);
87 }
88
89 pub fn get_user_data(&self, proxy_id: i32) -> Option<UserDataType> {
93 return inline::get_user_data(self, proxy_id);
94 }
95
96 pub fn was_moved(&self, proxy_id: i32) -> bool {
97 return inline::was_moved(self, proxy_id);
98 }
99 pub fn clear_moved(&mut self, proxy_id: i32) {
100 inline::clear_moved(self, proxy_id);
101 }
102
103 pub fn get_fat_aabb(&self, proxy_id: i32) -> B2AABB {
105 return inline::get_fat_aabb(self, proxy_id);
106 }
107
108 pub fn query<F: QueryCallback>(&self, callback: F, aabb: B2AABB) {
111 inline::query(self, callback, aabb);
112 }
113
114 pub fn ray_cast<T: RayCastCallback>(&self, callback: T, input: &B2rayCastInput) {
122 inline::ray_cast(self, callback, input);
123 }
124
125 pub fn validate(&self) {
127 private::validate(self);
128 }
129
130 pub fn get_height(&self) -> i32 {
133 return private::get_height(self);
134 }
135
136 pub fn get_max_balance(&self) -> i32 {
139 return private::get_max_balance(self);
140 }
141
142 pub fn get_area_ration(&self) -> f32 {
144 return private::get_area_ratio(self);
145 }
146
147 pub fn rebuild_bottom_up(&mut self) {
149 private::rebuild_bottom_up(self);
150 }
151
152 pub fn shift_origin(&mut self, new_origin: B2vec2) {
156 private::shift_origin(self, new_origin);
157 }
158
159 pub(crate) fn allocate_node(&mut self) -> i32 {
160 return private::allocate_node(self);
161 }
162 pub(crate) fn free_node(&mut self, node: i32) {
163 private::free_node(self, node);
164 }
165
166 pub(crate) fn insert_leaf(&mut self, node: i32) {
167 private::insert_leaf(self, node);
168 }
169 pub(crate) fn remove_leaf(&mut self, node: i32) {
170 private::remove_leaf(self, node);
171 }
172
173 pub(crate) fn balance(&mut self, index: i32) -> i32 {
174 return private::balance(self, index);
175 }
176
177 pub(crate) fn compute_height(&self) -> i32 {
178 return private::compute_height(self);
179 }
180 pub(crate) fn compute_height_by_node(&self, node_id: i32) -> i32 {
181 return private::compute_height_by_node(self, node_id);
182 }
183
184 pub(crate) fn validate_structure(&self, index: i32) {
185 private::validate_structure(self, index);
186 }
187 pub(crate) fn validate_metrics(&self, index: i32) {
188 private::validate_metrics(self, index);
189 }
190}
191
192pub trait QueryCallback: FnMut(i32) -> bool {}
196impl <F> QueryCallback for F where F: FnMut(i32) -> bool {}
197
198pub trait RayCastCallback: FnMut(&B2rayCastInput, i32) -> f32 {}
202impl <F> RayCastCallback for F where F: FnMut(&B2rayCastInput, i32) -> f32 {}
203
204mod inline {
205 use super::*;
206
207 pub fn get_user_data<UserDataType: Clone + Default>(
208 self_: &B2dynamicTree<UserDataType>,
209 proxy_id: i32,
210 ) -> Option<UserDataType> {
211 return self_.m_nodes[proxy_id as usize].user_data.clone();
213 }
214
215 pub fn was_moved<UserDataType: Clone + Default>(
216 self_: &B2dynamicTree<UserDataType>,
217 proxy_id: i32,
218 ) -> bool {
219 return self_.m_nodes[proxy_id as usize].moved;
221 }
222
223 pub fn clear_moved<UserDataType: Clone + Default>(
224 self_: &mut B2dynamicTree<UserDataType>,
225 proxy_id: i32,
226 ) {
227 self_.m_nodes[proxy_id as usize].moved = false;
229 }
230
231 pub fn get_fat_aabb<UserDataType: Clone + Default>(
232 self_: &B2dynamicTree<UserDataType>,
233 proxy_id: i32,
234 ) -> B2AABB {
235 return self_.m_nodes[proxy_id as usize].aabb;
237 }
238
239 pub fn query<UserDataType, F: QueryCallback>(
240 self_: &B2dynamicTree<UserDataType>,
241 mut callback: F,
242 aabb: B2AABB,
243 ) {
244 let mut stack = B2growableStack::<i32, 256>::new();
245 stack.push(&self_.m_root);
246
247 while stack.get_count() > 0 {
248 let node_id: i32 = stack.pop();
249 if node_id == B2_NULL_NODE {
250 continue;
251 }
252
253 let node = &self_.m_nodes[node_id as usize];
254
255 if b2_test_overlap(node.aabb, aabb) {
256 if node.is_leaf() {
257 let proceed: bool = callback(node_id);
258 if proceed == false {
259 return;
260 }
261 } else {
262 stack.push(&node.child1);
263 stack.push(&node.child2);
264 }
265 }
266 }
267 }
268
269 pub fn ray_cast<T: RayCastCallback, UserDataType>(
270 self_: &B2dynamicTree<UserDataType>,
271 mut callback: T,
272 input: &B2rayCastInput,
273 ) {
274 let p1: B2vec2 = input.p1;
275 let p2: B2vec2 = input.p2;
276 let mut r: B2vec2 = p2 - p1;
277 b2_assert(r.length_squared() > 0.0);
278 r.normalize();
279
280 let v: B2vec2 = b2_cross_scalar_by_vec(1.0, r);
282 let abs_v: B2vec2 = b2_abs_vec2(v);
283
284 let mut max_fraction: f32 = input.max_fraction;
288
289 let mut segment_aabb = B2AABB::default();
291 {
292 let t: B2vec2 = p1 + max_fraction * (p2 - p1);
293 segment_aabb.lower_bound = b2_min_vec2(p1, t);
294 segment_aabb.upper_bound = b2_max_vec2(p1, t);
295 }
296
297 let mut stack = B2growableStack::<i32, 256>::new();
298 stack.push(&self_.m_root);
299
300 while stack.get_count() > 0 {
301 let node_id: i32 = stack.pop();
302 if node_id == B2_NULL_NODE {
303 continue;
304 }
305
306 let node = &self_.m_nodes[node_id as usize];
307
308 if b2_test_overlap(node.aabb, segment_aabb) == false {
309 continue;
310 }
311
312 let c: B2vec2 = node.aabb.get_center();
315 let h: B2vec2 = node.aabb.get_extents();
316 let separation: f32 = b2_abs(b2_dot(v, p1 - c)) - b2_dot(abs_v, h);
317 if separation > 0.0 {
318 continue;
319 }
320
321 if node.is_leaf() {
322 let sub_input = B2rayCastInput {
323 p1: input.p1,
324 p2: input.p2,
325 max_fraction: max_fraction,
326 };
327
328 let value: f32 = callback(&sub_input, node_id);
329
330 if value == 0.0 {
331 return;
333 }
334
335 if value > 0.0 {
336 max_fraction = value;
338 let t: B2vec2 = p1 + max_fraction * (p2 - p1);
339 segment_aabb.lower_bound = b2_min_vec2(p1, t);
340 segment_aabb.upper_bound = b2_max_vec2(p1, t);
341 }
342 } else {
343 stack.push(&node.child1);
344 stack.push(&node.child2);
345 }
346 }
347 }
348}