box2d_rust/dynamic_tree/
mod.rs1mod insert;
24mod query;
25mod rebuild;
26mod validate;
27
28use crate::core::NULL_INDEX;
29use crate::math_functions::{Aabb, Vec2, VEC2_ZERO};
30
31pub const DEFAULT_CATEGORY_BITS: u64 = 1;
33pub const DEFAULT_MASK_BITS: u64 = u64::MAX;
35
36pub(crate) const TREE_STACK_SIZE: usize = 1024;
37
38pub(crate) const ALLOCATED_NODE: u16 = 0x0001;
40pub(crate) const ENLARGED_NODE: u16 = 0x0002;
41pub(crate) const LEAF_NODE: u16 = 0x0004;
42
43#[derive(Debug, Clone, Copy)]
45pub struct TreeNode {
46 pub aabb: Aabb,
48 pub category_bits: u64,
50 pub child1: i32,
52 pub child2: i32,
54 pub user_data: u64,
56 pub parent: i32,
58 pub next: i32,
60 pub height: u16,
61 pub flags: u16,
62}
63
64impl TreeNode {
65 pub(crate) fn default_node() -> TreeNode {
67 TreeNode {
68 aabb: Aabb {
69 lower_bound: VEC2_ZERO,
70 upper_bound: VEC2_ZERO,
71 },
72 category_bits: DEFAULT_CATEGORY_BITS,
73 child1: NULL_INDEX,
74 child2: NULL_INDEX,
75 user_data: u64::MAX,
77 parent: NULL_INDEX,
78 next: NULL_INDEX,
79 height: 0,
80 flags: ALLOCATED_NODE,
81 }
82 }
83
84 fn zeroed() -> TreeNode {
86 TreeNode {
87 aabb: Aabb {
88 lower_bound: VEC2_ZERO,
89 upper_bound: VEC2_ZERO,
90 },
91 category_bits: 0,
92 child1: 0,
93 child2: 0,
94 user_data: 0,
95 parent: 0,
96 next: 0,
97 height: 0,
98 flags: 0,
99 }
100 }
101
102 pub(crate) fn is_leaf(&self) -> bool {
104 self.flags & LEAF_NODE != 0
105 }
106
107 pub(crate) fn is_allocated(&self) -> bool {
109 self.flags & ALLOCATED_NODE != 0
110 }
111}
112
113#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
115pub struct TreeStats {
116 pub node_visits: i32,
118 pub leaf_visits: i32,
120}
121
122#[derive(Debug, Clone, Copy, PartialEq, Default)]
124pub struct BoxCastInput {
125 pub box_: Aabb,
127 pub translation: Vec2,
129 pub max_fraction: f32,
131}
132
133#[derive(Debug, Clone, Default)]
139pub struct DynamicTree {
140 pub(crate) nodes: Vec<TreeNode>,
142 pub(crate) root: i32,
144 pub(crate) node_count: i32,
146 pub(crate) free_list: i32,
148 pub(crate) proxy_count: i32,
150 pub(crate) leaf_indices: Vec<i32>,
152 pub(crate) leaf_centers: Vec<Vec2>,
154 pub(crate) rebuild_capacity: i32,
156}
157
158impl DynamicTree {
159 pub fn new(proxy_capacity: i32) -> DynamicTree {
161 let capacity = crate::math_functions::max_int(proxy_capacity, 16);
162
163 let node_capacity = (2 * capacity - 1) as usize;
165 let mut nodes = vec![TreeNode::zeroed(); node_capacity];
166
167 for (i, node) in nodes.iter_mut().enumerate().take(node_capacity - 1) {
169 node.next = i as i32 + 1;
170 }
171 nodes[node_capacity - 1].next = NULL_INDEX;
172
173 DynamicTree {
174 nodes,
175 root: NULL_INDEX,
176 node_count: 0,
177 free_list: 0,
178 proxy_count: 0,
179 leaf_indices: Vec::new(),
180 leaf_centers: Vec::new(),
181 rebuild_capacity: 0,
182 }
183 }
184
185 pub fn destroy(&mut self) {
191 *self = DynamicTree {
192 nodes: Vec::new(),
193 root: 0,
194 node_count: 0,
195 free_list: 0,
196 proxy_count: 0,
197 leaf_indices: Vec::new(),
198 leaf_centers: Vec::new(),
199 rebuild_capacity: 0,
200 };
201 }
202
203 pub(crate) fn node_capacity(&self) -> i32 {
204 self.nodes.len() as i32
205 }
206
207 pub fn node_count(&self) -> i32 {
209 self.node_count
210 }
211
212 pub(crate) fn allocate_node(&mut self) -> i32 {
215 if self.free_list == NULL_INDEX {
217 debug_assert!(self.node_count == self.node_capacity());
218
219 let old_capacity = self.nodes.len();
221 let new_capacity = old_capacity + (old_capacity >> 1);
222 self.nodes.resize(new_capacity, TreeNode::zeroed());
223
224 for i in self.node_count as usize..new_capacity - 1 {
227 self.nodes[i].next = i as i32 + 1;
228 }
229 self.nodes[new_capacity - 1].next = NULL_INDEX;
230 self.free_list = self.node_count;
231 }
232
233 let node_index = self.free_list;
235 self.free_list = self.nodes[node_index as usize].next;
236 self.nodes[node_index as usize] = TreeNode::default_node();
237 self.node_count += 1;
238 node_index
239 }
240
241 pub(crate) fn free_node(&mut self, node_id: i32) {
243 debug_assert!(0 <= node_id && node_id < self.node_capacity());
244 debug_assert!(0 < self.node_count);
245 self.nodes[node_id as usize].next = self.free_list;
246 self.nodes[node_id as usize].flags = 0;
247 self.free_list = node_id;
248 self.node_count -= 1;
249 }
250
251 pub fn proxy_count(&self) -> i32 {
253 self.proxy_count
254 }
255
256 pub fn category_bits(&self, proxy_id: i32) -> u64 {
258 debug_assert!(0 <= proxy_id && proxy_id < self.node_capacity());
259 self.nodes[proxy_id as usize].category_bits
260 }
261
262 pub fn height(&self) -> i32 {
264 if self.root == NULL_INDEX {
265 return 0;
266 }
267
268 self.nodes[self.root as usize].height as i32
269 }
270
271 pub fn area_ratio(&self) -> f32 {
274 use crate::aabb::perimeter;
275
276 if self.root == NULL_INDEX {
277 return 0.0;
278 }
279
280 let root = &self.nodes[self.root as usize];
281 let root_area = perimeter(root.aabb);
282
283 let mut total_area = 0.0;
284 for (i, node) in self.nodes.iter().enumerate() {
285 if !node.is_allocated() || node.is_leaf() || i as i32 == self.root {
286 continue;
287 }
288
289 total_area += perimeter(node.aabb);
290 }
291
292 total_area / root_area
293 }
294
295 pub fn root_bounds(&self) -> Aabb {
298 if self.root != NULL_INDEX {
299 return self.nodes[self.root as usize].aabb;
300 }
301
302 Aabb {
303 lower_bound: VEC2_ZERO,
304 upper_bound: VEC2_ZERO,
305 }
306 }
307
308 pub fn byte_count(&self) -> i32 {
310 let size = core::mem::size_of::<DynamicTree>()
311 + core::mem::size_of::<TreeNode>() * self.nodes.len()
312 + self.rebuild_capacity as usize
313 * (core::mem::size_of::<i32>()
314 + core::mem::size_of::<Aabb>()
315 + core::mem::size_of::<Vec2>()
316 + core::mem::size_of::<i32>());
317
318 size as i32
319 }
320
321 pub fn user_data(&self, proxy_id: i32) -> u64 {
323 debug_assert!(0 <= proxy_id && proxy_id < self.node_capacity());
324 self.nodes[proxy_id as usize].user_data
325 }
326
327 pub fn aabb(&self, proxy_id: i32) -> Aabb {
329 debug_assert!(0 <= proxy_id && proxy_id < self.node_capacity());
330 self.nodes[proxy_id as usize].aabb
331 }
332}