1use super::{category_bits_match, BoxCastInput, DynamicTree, TreeStats, TREE_STACK_SIZE};
10use crate::core::NULL_INDEX;
11use crate::geometry::RayCastInput;
12use crate::math_functions::{
13 aabb_center, aabb_extents, aabb_overlaps, add, clamp, distance_squared, dot, max, min, mul_add,
14 mul_sv, sub, test_bounds_ray_overlap, Aabb, Vec3,
15};
16
17fn distance_to_node_sqr(point: Vec3, node_aabb: Aabb) -> f32 {
19 let r = sub(
20 point,
21 clamp(point, node_aabb.lower_bound, node_aabb.upper_bound),
22 );
23 dot(r, r)
24}
25
26#[derive(Clone, Copy)]
27struct QueryClosestItem {
28 node_index: i32,
29 distance_to_node_sqr: f32,
30}
31
32impl DynamicTree {
33 pub fn query(
37 &self,
38 aabb: Aabb,
39 mask_bits: u64,
40 require_all_bits: bool,
41 mut callback: impl FnMut(i32, u64) -> bool,
42 ) -> TreeStats {
43 let mut result = TreeStats::default();
44
45 if self.node_count == 0 {
46 return result;
47 }
48
49 let mut stack = [0i32; TREE_STACK_SIZE];
50 let mut stack_count = 0usize;
51 stack[stack_count] = self.root;
52 stack_count += 1;
53
54 while stack_count > 0 {
55 stack_count -= 1;
56 let node_id = stack[stack_count];
57 if node_id == NULL_INDEX {
58 debug_assert!(false);
59 continue;
60 }
61
62 let node = &self.nodes[node_id as usize];
63 result.node_visits += 1;
64
65 if category_bits_match(node.category_bits, mask_bits, require_all_bits)
66 && aabb_overlaps(node.aabb, aabb)
67 {
68 if node.is_leaf() {
69 let proceed = callback(node_id, node.user_data);
71 result.leaf_visits += 1;
72
73 if !proceed {
74 return result;
75 }
76 } else {
77 debug_assert!(stack_count < TREE_STACK_SIZE - 1);
78 if stack_count < TREE_STACK_SIZE - 1 {
79 stack[stack_count] = node.child1;
80 stack_count += 1;
81 stack[stack_count] = node.child2;
82 stack_count += 1;
83 }
84 }
85 }
86 }
87
88 result
89 }
90
91 pub fn query_closest(
95 &self,
96 point: Vec3,
97 mask_bits: u64,
98 require_all_bits: bool,
99 mut callback: impl FnMut(f32, i32, u64) -> f32,
100 min_distance_sqr: &mut f32,
101 ) -> TreeStats {
102 let mut result = TreeStats::default();
103
104 if self.node_count == 0 {
105 return result;
106 }
107
108 let mut min_sqr = *min_distance_sqr;
109 let mut stack = [QueryClosestItem {
110 node_index: 0,
111 distance_to_node_sqr: 0.0,
112 }; TREE_STACK_SIZE];
113 let mut stack_count = 0usize;
114
115 let root_distance_sqr = distance_to_node_sqr(point, self.nodes[self.root as usize].aabb);
116 stack[stack_count] = QueryClosestItem {
117 node_index: self.root,
118 distance_to_node_sqr: root_distance_sqr,
119 };
120 stack_count += 1;
121
122 while stack_count > 0 {
123 stack_count -= 1;
124 let item = stack[stack_count];
125 let node = &self.nodes[item.node_index as usize];
126 result.node_visits += 1;
127
128 if category_bits_match(node.category_bits, mask_bits, require_all_bits)
129 && item.distance_to_node_sqr < min_sqr
130 {
131 if node.is_leaf() {
132 let dd = callback(min_sqr, item.node_index, node.user_data);
133
134 if dd < min_sqr {
135 min_sqr = dd;
136 }
137
138 result.leaf_visits += 1;
139 } else {
140 debug_assert!(stack_count < TREE_STACK_SIZE - 1);
141 if stack_count < TREE_STACK_SIZE - 1 {
142 let child1 = node.child1;
143 let child2 = node.child2;
144
145 let item1 = QueryClosestItem {
146 node_index: child1,
147 distance_to_node_sqr: distance_to_node_sqr(
148 point,
149 self.nodes[child1 as usize].aabb,
150 ),
151 };
152
153 let item2 = QueryClosestItem {
154 node_index: child2,
155 distance_to_node_sqr: distance_to_node_sqr(
156 point,
157 self.nodes[child2 as usize].aabb,
158 ),
159 };
160
161 if item2.distance_to_node_sqr < item1.distance_to_node_sqr {
163 stack[stack_count] = item1;
164 stack_count += 1;
165 stack[stack_count] = item2;
166 stack_count += 1;
167 } else {
168 stack[stack_count] = item2;
169 stack_count += 1;
170 stack[stack_count] = item1;
171 stack_count += 1;
172 }
173 }
174 }
175 }
176 }
177
178 *min_distance_sqr = min_sqr;
179
180 result
181 }
182
183 pub fn ray_cast(
192 &self,
193 input: &RayCastInput,
194 mask_bits: u64,
195 require_all_bits: bool,
196 mut callback: impl FnMut(&RayCastInput, i32, u64) -> f32,
197 ) -> TreeStats {
198 let mut result = TreeStats::default();
199
200 if self.node_count == 0 {
201 return result;
202 }
203
204 let p1 = input.origin;
205 let d = input.translation;
206
207 let mut max_fraction = input.max_fraction;
208
209 let mut p2 = mul_add(p1, max_fraction, d);
210
211 let mut segment_aabb = Aabb {
213 lower_bound: min(p1, p2),
214 upper_bound: max(p1, p2),
215 };
216
217 let mut stack = [0i32; TREE_STACK_SIZE];
218 let mut stack_count = 0usize;
219 stack[stack_count] = self.root;
220 stack_count += 1;
221
222 let mut sub_input = *input;
223
224 while stack_count > 0 {
225 stack_count -= 1;
226 let node_id = stack[stack_count];
227 if node_id == NULL_INDEX {
228 debug_assert!(false);
229 continue;
230 }
231
232 let node = &self.nodes[node_id as usize];
233 result.node_visits += 1;
234
235 let node_aabb = node.aabb;
236
237 if !category_bits_match(node.category_bits, mask_bits, require_all_bits)
238 || !aabb_overlaps(node_aabb, segment_aabb)
239 {
240 continue;
241 }
242
243 if !test_bounds_ray_overlap(node_aabb.lower_bound, node_aabb.upper_bound, p1, d) {
244 continue;
245 }
246
247 if node.is_leaf() {
248 sub_input.max_fraction = max_fraction;
249
250 let value = callback(&sub_input, node_id, node.user_data);
251 result.leaf_visits += 1;
252
253 if value == 0.0 {
256 return result;
258 }
259
260 if 0.0 < value && value <= max_fraction {
261 max_fraction = value;
263 p2 = mul_add(p1, max_fraction, d);
264 segment_aabb.lower_bound = min(p1, p2);
265 segment_aabb.upper_bound = max(p1, p2);
266 }
267 } else {
268 debug_assert!(stack_count < TREE_STACK_SIZE - 1);
269 if stack_count < TREE_STACK_SIZE - 1 {
270 let c1 = aabb_center(self.nodes[node.child1 as usize].aabb);
271 let c2 = aabb_center(self.nodes[node.child2 as usize].aabb);
272 if distance_squared(c1, p1) < distance_squared(c2, p1) {
273 stack[stack_count] = node.child2;
274 stack_count += 1;
275 stack[stack_count] = node.child1;
276 stack_count += 1;
277 } else {
278 stack[stack_count] = node.child1;
279 stack_count += 1;
280 stack[stack_count] = node.child2;
281 stack_count += 1;
282 }
283 }
284 }
285 }
286
287 result
288 }
289
290 pub fn box_cast(
294 &self,
295 input: &BoxCastInput,
296 mask_bits: u64,
297 require_all_bits: bool,
298 mut callback: impl FnMut(&BoxCastInput, i32, u64) -> f32,
299 ) -> TreeStats {
300 let mut stats = TreeStats::default();
301
302 if self.node_count == 0 {
303 return stats;
304 }
305
306 let origin_aabb = input.box_;
308
309 let p1 = aabb_center(origin_aabb);
310 let extension = aabb_extents(origin_aabb);
311
312 let d = input.translation;
313
314 let mut max_fraction = input.max_fraction;
315
316 let mut t = mul_sv(max_fraction, input.translation);
318 let mut total_aabb = Aabb {
319 lower_bound: min(origin_aabb.lower_bound, add(origin_aabb.lower_bound, t)),
320 upper_bound: max(origin_aabb.upper_bound, add(origin_aabb.upper_bound, t)),
321 };
322
323 let mut sub_input = *input;
324
325 let mut stack = [0i32; TREE_STACK_SIZE];
326 let mut stack_count = 0usize;
327 stack[stack_count] = self.root;
328 stack_count += 1;
329
330 while stack_count > 0 {
331 stack_count -= 1;
332 let node_id = stack[stack_count];
333 if node_id == NULL_INDEX {
334 debug_assert!(false);
335 continue;
336 }
337
338 let node = &self.nodes[node_id as usize];
339 stats.node_visits += 1;
340
341 if !category_bits_match(node.category_bits, mask_bits, require_all_bits)
342 || !aabb_overlaps(node.aabb, total_aabb)
343 {
344 continue;
345 }
346
347 let lower = sub(node.aabb.lower_bound, extension);
349 let upper = add(node.aabb.upper_bound, extension);
350 if !test_bounds_ray_overlap(lower, upper, p1, d) {
351 continue;
352 }
353
354 if node.is_leaf() {
355 sub_input.max_fraction = max_fraction;
356
357 let value = callback(&sub_input, node_id, node.user_data);
358 stats.leaf_visits += 1;
359
360 if value == 0.0 {
361 return stats;
363 }
364
365 if 0.0 < value && value < max_fraction {
366 max_fraction = value;
367 t = mul_sv(max_fraction, input.translation);
368 total_aabb.lower_bound =
369 min(origin_aabb.lower_bound, add(origin_aabb.lower_bound, t));
370 total_aabb.upper_bound =
371 max(origin_aabb.upper_bound, add(origin_aabb.upper_bound, t));
372 }
373 } else {
374 debug_assert!(stack_count < TREE_STACK_SIZE - 1);
375 if stack_count < TREE_STACK_SIZE - 1 {
376 let c1 = aabb_center(self.nodes[node.child1 as usize].aabb);
377 let c2 = aabb_center(self.nodes[node.child2 as usize].aabb);
378 if distance_squared(c1, p1) < distance_squared(c2, p1) {
379 stack[stack_count] = node.child2;
380 stack_count += 1;
381 stack[stack_count] = node.child1;
382 stack_count += 1;
383 } else {
384 stack[stack_count] = node.child1;
385 stack_count += 1;
386 stack[stack_count] = node.child2;
387 stack_count += 1;
388 }
389 }
390 }
391 }
392
393 stats
394 }
395}