1mod insert;
27mod query;
28mod rebuild;
29mod validate;
30
31use crate::core::NULL_INDEX;
32use crate::math_functions::{Aabb, Vec3, VEC3_ZERO};
33
34pub const DEFAULT_CATEGORY_BITS: u64 = u64::MAX;
36pub const DEFAULT_MASK_BITS: u64 = u64::MAX;
38
39pub const DYNAMIC_TREE_VERSION: u64 = 0x93EDAF889FD30B4A;
41
42pub(crate) const TREE_STACK_SIZE: usize = 1024;
43
44pub(crate) const ALLOCATED_NODE: u16 = 0x0001;
46pub(crate) const ENLARGED_NODE: u16 = 0x0002;
47pub(crate) const LEAF_NODE: u16 = 0x0004;
48
49#[derive(Debug, Clone, Copy)]
51pub struct TreeNode {
52 pub aabb: Aabb,
54 pub category_bits: u64,
56 pub child1: i32,
58 pub child2: i32,
60 pub user_data: u64,
62 pub parent: i32,
64 pub next: i32,
66 pub height: u16,
67 pub flags: u16,
68}
69
70impl TreeNode {
71 pub(crate) fn default_node() -> TreeNode {
73 TreeNode {
74 aabb: Aabb {
75 lower_bound: VEC3_ZERO,
76 upper_bound: VEC3_ZERO,
77 },
78 category_bits: DEFAULT_CATEGORY_BITS,
79 child1: NULL_INDEX,
80 child2: NULL_INDEX,
81 user_data: u64::MAX,
83 parent: NULL_INDEX,
84 next: NULL_INDEX,
85 height: 0,
86 flags: ALLOCATED_NODE,
87 }
88 }
89
90 fn zeroed() -> TreeNode {
92 TreeNode {
93 aabb: Aabb {
94 lower_bound: VEC3_ZERO,
95 upper_bound: VEC3_ZERO,
96 },
97 category_bits: 0,
98 child1: 0,
99 child2: 0,
100 user_data: 0,
101 parent: 0,
102 next: 0,
103 height: 0,
104 flags: 0,
105 }
106 }
107
108 pub(crate) fn is_leaf(&self) -> bool {
110 self.flags & LEAF_NODE != 0
111 }
112
113 pub(crate) fn is_allocated(&self) -> bool {
115 self.flags & ALLOCATED_NODE != 0
116 }
117}
118
119#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
121pub struct TreeStats {
122 pub node_visits: i32,
124 pub leaf_visits: i32,
126}
127
128#[derive(Debug, Clone, Copy, PartialEq, Default)]
130pub struct BoxCastInput {
131 pub box_: Aabb,
133 pub translation: Vec3,
135 pub max_fraction: f32,
137}
138
139#[derive(Debug, Clone)]
145pub struct DynamicTree {
146 pub(crate) version: u64,
148 pub(crate) nodes: Vec<TreeNode>,
150 pub(crate) root: i32,
152 pub(crate) node_count: i32,
154 pub(crate) free_list: i32,
156 pub(crate) proxy_count: i32,
158 pub(crate) leaf_indices: Vec<i32>,
160 pub(crate) leaf_centers: Vec<Vec3>,
162 pub(crate) rebuild_capacity: i32,
164}
165
166impl Default for DynamicTree {
167 fn default() -> Self {
168 Self::new(16)
169 }
170}
171
172impl DynamicTree {
173 pub fn new(proxy_capacity: i32) -> DynamicTree {
175 let capacity = crate::math_functions::max_int(proxy_capacity, 16);
176
177 let node_capacity = (2 * capacity - 1) as usize;
179 let mut nodes = vec![TreeNode::zeroed(); node_capacity];
180
181 for (i, node) in nodes.iter_mut().enumerate().take(node_capacity - 1) {
183 node.next = i as i32 + 1;
184 }
185 nodes[node_capacity - 1].next = NULL_INDEX;
186
187 DynamicTree {
188 version: DYNAMIC_TREE_VERSION,
189 nodes,
190 root: NULL_INDEX,
191 node_count: 0,
192 free_list: 0,
193 proxy_count: 0,
194 leaf_indices: Vec::new(),
195 leaf_centers: Vec::new(),
196 rebuild_capacity: 0,
197 }
198 }
199
200 pub fn destroy(&mut self) {
206 *self = DynamicTree {
207 version: 0,
208 nodes: Vec::new(),
209 root: 0,
210 node_count: 0,
211 free_list: 0,
212 proxy_count: 0,
213 leaf_indices: Vec::new(),
214 leaf_centers: Vec::new(),
215 rebuild_capacity: 0,
216 };
217 }
218
219 pub fn version(&self) -> u64 {
222 self.version
223 }
224
225 pub(crate) fn node_capacity(&self) -> i32 {
226 self.nodes.len() as i32
227 }
228
229 pub fn node_count(&self) -> i32 {
231 self.node_count
232 }
233
234 pub(crate) fn allocate_node(&mut self) -> i32 {
237 if self.free_list == NULL_INDEX {
239 debug_assert!(self.node_count == self.node_capacity());
240
241 let old_capacity = self.nodes.len();
243 let new_capacity = old_capacity + (old_capacity >> 1);
244 self.nodes.resize(new_capacity, TreeNode::zeroed());
245
246 for i in self.node_count as usize..new_capacity - 1 {
249 self.nodes[i].next = i as i32 + 1;
250 }
251 self.nodes[new_capacity - 1].next = NULL_INDEX;
252 self.free_list = self.node_count;
253 }
254
255 let node_index = self.free_list;
257 self.free_list = self.nodes[node_index as usize].next;
258 self.nodes[node_index as usize] = TreeNode::default_node();
259 self.node_count += 1;
260 node_index
261 }
262
263 pub(crate) fn free_node(&mut self, node_id: i32) {
265 debug_assert!(0 <= node_id && node_id < self.node_capacity());
266 debug_assert!(0 < self.node_count);
267 self.nodes[node_id as usize].next = self.free_list;
268 self.nodes[node_id as usize].flags = 0;
269 self.free_list = node_id;
270 self.node_count -= 1;
271 }
272
273 pub fn proxy_count(&self) -> i32 {
275 self.proxy_count
276 }
277
278 pub fn category_bits(&self, proxy_id: i32) -> u64 {
280 debug_assert!(0 <= proxy_id && proxy_id < self.node_capacity());
281 self.nodes[proxy_id as usize].category_bits
282 }
283
284 pub fn height(&self) -> i32 {
286 if self.root == NULL_INDEX {
287 return 0;
288 }
289
290 self.nodes[self.root as usize].height as i32
291 }
292
293 pub fn area_ratio(&self) -> f32 {
296 use crate::aabb::perimeter;
297
298 if self.root == NULL_INDEX {
299 return 0.0;
300 }
301
302 let root = &self.nodes[self.root as usize];
303 let root_area = perimeter(root.aabb);
304
305 let mut total_area = 0.0;
306 for (i, node) in self.nodes.iter().enumerate() {
307 if !node.is_allocated() || node.is_leaf() || i as i32 == self.root {
308 continue;
309 }
310
311 total_area += perimeter(node.aabb);
312 }
313
314 total_area / root_area
315 }
316
317 pub fn root_bounds(&self) -> Aabb {
320 if self.root != NULL_INDEX {
321 return self.nodes[self.root as usize].aabb;
322 }
323
324 Aabb {
325 lower_bound: VEC3_ZERO,
326 upper_bound: VEC3_ZERO,
327 }
328 }
329
330 pub fn byte_count(&self) -> i32 {
335 let size = core::mem::size_of::<DynamicTree>()
336 + core::mem::size_of::<TreeNode>() * self.nodes.len()
337 + self.rebuild_capacity as usize
338 * (core::mem::size_of::<i32>()
339 + core::mem::size_of::<Aabb>()
340 + core::mem::size_of::<Vec3>()
341 + core::mem::size_of::<i32>());
342
343 size as i32
344 }
345
346 pub fn user_data(&self, proxy_id: i32) -> u64 {
348 debug_assert!(0 <= proxy_id && proxy_id < self.node_capacity());
349 self.nodes[proxy_id as usize].user_data
350 }
351
352 pub fn aabb(&self, proxy_id: i32) -> Aabb {
354 debug_assert!(0 <= proxy_id && proxy_id < self.node_capacity());
355 self.nodes[proxy_id as usize].aabb
356 }
357}
358
359#[inline]
361pub(crate) fn category_bits_match(
362 category_bits: u64,
363 mask_bits: u64,
364 require_all_bits: bool,
365) -> bool {
366 if require_all_bits {
367 (category_bits & mask_bits) == mask_bits
368 } else {
369 (category_bits & mask_bits) != 0
370 }
371}