parry3d/partitioning/bvh/
bvh_insert.rs1use super::bvh_tree::{BvhNodeIndex, BvhNodeWide};
2use super::BvhNode;
3use crate::bounding_volume::{Aabb, BoundingVolume};
4use crate::math::{Real, Vector};
5use crate::partitioning::Bvh;
6use alloc::vec;
7
8impl Bvh {
9 pub fn insert(&mut self, aabb: Aabb, leaf_index: u32) {
11 self.insert_with_change_detection(aabb, leaf_index, 0.0)
12 }
13
14 pub fn insert_with_change_detection(
20 &mut self,
21 aabb: Aabb,
22 leaf_index: u32,
23 change_detection_margin: Real,
24 ) {
25 if let Some(leaf) = self.leaf_node_indices.get(leaf_index as usize) {
26 let node = &mut self.nodes[*leaf];
27
28 if change_detection_margin > 0.0 {
29 if !node.contains_aabb(&aabb) {
30 node.mins = aabb.mins - Vector::repeat(change_detection_margin);
31 node.maxs = aabb.maxs + Vector::repeat(change_detection_margin);
32 node.data.set_change_pending();
33 } else {
34 return;
36 }
37 } else {
38 node.mins = aabb.mins;
39 node.maxs = aabb.maxs;
40 }
41
42 let wide_node_id = leaf.decompose().0;
55 if wide_node_id == 0 {
56 return;
58 }
59
60 let mut parent = self.parents[wide_node_id];
61 loop {
62 let node = &mut self.nodes[parent];
63 if node.contains_aabb(&aabb) {
64 break;
66 }
67
68 node.mins = node.mins.inf(&aabb.mins);
69 node.maxs = node.maxs.sup(&aabb.maxs);
70
71 let wide_node_id = parent.decompose().0;
72 if wide_node_id == 0 {
73 break;
74 }
75
76 parent = self.parents[wide_node_id];
77 }
78 } else {
79 self.insert_new_unchecked(aabb, leaf_index);
80 }
81 }
82
83 pub fn insert_or_update_partially(
94 &mut self,
95 aabb: Aabb,
96 leaf_index: u32,
97 change_detection_margin: Real,
98 ) {
99 if let Some(leaf) = self.leaf_node_indices.get(leaf_index as usize) {
100 let node = &mut self.nodes[*leaf];
101
102 if change_detection_margin > 0.0 {
103 if !node.contains_aabb(&aabb) {
104 node.mins = aabb.mins - Vector::repeat(change_detection_margin);
105 node.maxs = aabb.maxs + Vector::repeat(change_detection_margin);
106 node.data.set_change_pending();
107 }
108 } else {
109 node.mins = aabb.mins;
110 node.maxs = aabb.maxs;
111 }
112 } else {
113 self.insert_new_unchecked(aabb, leaf_index);
114 }
115 }
116
117 fn insert_new_unchecked(&mut self, aabb: Aabb, leaf_index: u32) {
119 let _ = self
120 .leaf_node_indices
121 .insert(leaf_index as usize, BvhNodeIndex::default());
122 let leaf_index_mut = &mut self.leaf_node_indices[leaf_index as usize];
123
124 if self.nodes.is_empty() {
126 self.nodes.push(BvhNodeWide {
127 left: BvhNode::leaf(aabb, leaf_index),
128 right: BvhNode::zeros(),
129 });
130 self.parents.push(BvhNodeIndex::default());
131 *leaf_index_mut = BvhNodeIndex::left(0);
132 return;
133 }
134
135 if self.nodes[0].right.leaf_count() == 0 {
137 self.nodes[0].right = BvhNode::leaf(aabb, leaf_index);
138 *leaf_index_mut = BvhNodeIndex::right(0);
139 return;
140 }
141
142 let mut curr_id = 0u32;
144 let mut path_taken = vec![];
145
146 const APPLY_ROTATIONS_DOWN: bool = true;
147 const APPLY_ROTATIONS_UP: bool = false;
148
149 loop {
150 if APPLY_ROTATIONS_UP {
151 path_taken.push(curr_id);
152 }
153
154 if APPLY_ROTATIONS_DOWN {
155 self.maybe_apply_rotation(curr_id);
156 }
157
158 let curr_node = &self.nodes[curr_id as usize];
159
160 let left = &curr_node.left;
162 let right = &curr_node.right;
163
164 let left_merged_aabb = left.aabb().merged(&aabb);
165 let right_merged_aabb = right.aabb().merged(&aabb);
166
167 let left_merged_vol = left_merged_aabb.volume();
168 let right_merged_vol = right_merged_aabb.volume();
169 let left_vol = left.aabb().volume();
170 let right_vol = right.aabb().volume();
171 let left_count = left.leaf_count();
172 let right_count = right.leaf_count();
173
174 let left_cost =
178 left_merged_vol * (left_count + 1) as Real + right_vol * right_count as Real;
179 let right_cost =
180 right_merged_vol * (right_count + 1) as Real + left_vol * left_count as Real;
181
182 if left_cost < right_cost || (left_cost == right_cost && left_count < right_count) {
185 if left.is_leaf() {
189 let new_leaf_id = self.nodes.len();
190 let wide_node = BvhNodeWide {
191 left: *left,
192 right: BvhNode::leaf(aabb, leaf_index),
193 };
194 self.nodes.push(wide_node);
195 self.parents.push(BvhNodeIndex::left(curr_id));
196
197 let left = &mut self.nodes[curr_id as usize].left;
198 self.leaf_node_indices[left.children as usize] =
199 BvhNodeIndex::left(new_leaf_id as u32);
200 self.leaf_node_indices[leaf_index as usize] =
201 BvhNodeIndex::right(new_leaf_id as u32);
202
203 left.children = new_leaf_id as u32;
204 left.data.add_leaf_count(1);
205 left.mins = left.mins.inf(&aabb.mins);
206 left.maxs = left.maxs.sup(&aabb.maxs);
207 break;
208 } else {
209 let left = &mut self.nodes[curr_id as usize].left;
210 curr_id = left.children;
211 left.data.add_leaf_count(1);
212 left.mins = left.mins.inf(&aabb.mins);
213 left.maxs = left.maxs.sup(&aabb.maxs);
214 }
215 } else {
216 if right.is_leaf() {
220 let new_leaf_id = self.nodes.len();
221 let new_node = BvhNodeWide {
222 left: BvhNode::leaf(aabb, leaf_index),
223 right: *right,
224 };
225 self.nodes.push(new_node);
226 self.parents.push(BvhNodeIndex::right(curr_id));
227
228 let right = &mut self.nodes[curr_id as usize].right;
229 self.leaf_node_indices[leaf_index as usize] =
230 BvhNodeIndex::left(new_leaf_id as u32);
231 self.leaf_node_indices[right.children as usize] =
232 BvhNodeIndex::right(new_leaf_id as u32);
233
234 right.children = new_leaf_id as u32;
235 right.data.add_leaf_count(1);
236 right.mins = right.mins.inf(&aabb.mins);
237 right.maxs = right.maxs.sup(&aabb.maxs);
238 break;
239 } else {
240 let right = &mut self.nodes[curr_id as usize].right;
241 curr_id = right.children;
242 right.data.add_leaf_count(1);
243 right.mins = right.mins.inf(&aabb.mins);
244 right.maxs = right.maxs.sup(&aabb.maxs);
245 }
246 }
247 }
248
249 if APPLY_ROTATIONS_UP {
250 while let Some(node) = path_taken.pop() {
251 self.maybe_apply_rotation(node);
252 }
253 }
254 }
255
256 fn maybe_apply_rotation(&mut self, node_id: u32) {
258 let node = self.nodes[node_id as usize];
259 let left = &node.left;
260 let right = &node.right;
261
262 let curr_score =
263 left.volume() * left.leaf_count() as Real + right.volume() * right.leaf_count() as Real;
264
265 macro_rules! eval_costs {
266 ($left: ident, $right: ident) => {
267 if !$left.is_leaf() {
268 let children = self.nodes[$left.children as usize];
269 let left_child = &children.left;
270 let right_child = &children.right;
271
272 let new_score1 = left_child.volume() * left_child.leaf_count() as Real
275 + right_child.merged_volume($right)
276 * (right_child.leaf_count() + $right.leaf_count()) as Real;
277
278 let new_score2 = right_child.volume() * right_child.leaf_count() as Real
281 + left_child.merged_volume($right)
282 * (left_child.leaf_count() + $right.leaf_count()) as Real;
283
284 if new_score1 < new_score2 {
285 (new_score1 - curr_score, true)
286 } else {
287 (new_score2 - curr_score, false)
288 }
289 } else {
290 (Real::MAX, false)
291 }
292 };
293 }
294
295 macro_rules! set_leaf_data {
298 ($leaf_data_id: ident, $node_id: ident, $left_or_right: expr) => {
299 self.leaf_node_indices[$leaf_data_id as usize] =
300 BvhNodeIndex::new($node_id, $left_or_right);
301 };
302 }
303
304 let (rotation_score0, left_child_moves_up0) = eval_costs!(left, right);
306 let (rotation_score1, left_child_moves_up1) = eval_costs!(right, left);
308
309 if rotation_score0 < 0.0 || rotation_score1 < 0.0 {
310 if rotation_score0 < rotation_score1 {
313 let children_id = left.children;
315 let children = self.nodes[children_id as usize];
316 let left_child = &children.left;
317 let right_child = &children.right;
318
319 let right_is_leaf = right.is_leaf();
320 let left_child_is_leaf = left_child.is_leaf();
321 let right_child_is_leaf = right_child.is_leaf();
322
323 let right_leaf_data = right.children;
324 let left_child_leaf_data = left_child.children;
325 let right_child_leaf_data = right_child.children;
326
327 self.parents[children_id as usize] = BvhNodeIndex::right(node_id);
328
329 if left_child_moves_up0 {
330 self.nodes[node_id as usize].left = *left_child;
332 self.nodes[children_id as usize].left = *right;
333 self.nodes[node_id as usize].right =
334 self.nodes[children_id as usize].merged(children_id);
335
336 if left_child_is_leaf {
337 self.leaf_node_indices[left_child_leaf_data as usize] =
338 BvhNodeIndex::left(node_id);
339 } else {
340 self.parents[left_child_leaf_data as usize] = BvhNodeIndex::left(node_id);
341 }
342 if right_is_leaf {
343 self.leaf_node_indices[right_leaf_data as usize] =
344 BvhNodeIndex::left(children_id);
345 } else {
346 self.parents[right_leaf_data as usize] = BvhNodeIndex::left(children_id);
347 }
348 } else {
349 self.nodes[node_id as usize].left = *right_child;
351 self.nodes[children_id as usize].right = *right;
352 self.nodes[node_id as usize].right =
353 self.nodes[children_id as usize].merged(children_id);
354 if right_child_is_leaf {
355 self.leaf_node_indices[right_child_leaf_data as usize] =
356 BvhNodeIndex::left(node_id);
357 } else {
358 self.parents[right_child_leaf_data as usize] = BvhNodeIndex::left(node_id);
359 }
360 if right_is_leaf {
361 self.leaf_node_indices[right_leaf_data as usize] =
362 BvhNodeIndex::right(children_id);
363 } else {
364 self.parents[right_leaf_data as usize] = BvhNodeIndex::right(children_id);
365 }
366 }
367 } else {
368 let children_id = right.children;
370 let children = self.nodes[children_id as usize];
371 let left_child = &children.left;
372 let right_child = &children.right;
373
374 let left_is_leaf = left.is_leaf();
375 let left_child_is_leaf = left_child.is_leaf();
376 let right_child_is_leaf = right_child.is_leaf();
377
378 let left_leaf_data = left.children;
379 let left_child_leaf_data = left_child.children;
380 let right_child_leaf_data = right_child.children;
381
382 self.parents[children_id as usize] = BvhNodeIndex::left(node_id);
383
384 if left_child_moves_up1 {
385 self.nodes[node_id as usize].right = *left_child;
387 self.nodes[children_id as usize].left = *left;
388 self.nodes[node_id as usize].left =
389 self.nodes[children_id as usize].merged(children_id);
390 if left_child_is_leaf {
391 self.leaf_node_indices[left_child_leaf_data as usize] =
392 BvhNodeIndex::right(node_id);
393 } else {
394 self.parents[left_child_leaf_data as usize] = BvhNodeIndex::right(node_id);
395 }
396 if left_is_leaf {
397 self.leaf_node_indices[left_leaf_data as usize] =
398 BvhNodeIndex::left(children_id);
399 } else {
400 self.parents[left_leaf_data as usize] = BvhNodeIndex::left(children_id);
401 }
402 } else {
403 self.nodes[node_id as usize].right = *right_child;
405 self.nodes[children_id as usize].right = *left;
406 self.nodes[node_id as usize].left =
407 self.nodes[children_id as usize].merged(children_id);
408 if right_child_is_leaf {
409 set_leaf_data!(right_child_leaf_data, node_id, BvhNodeIndex::RIGHT);
410 } else {
411 self.parents[right_child_leaf_data as usize] = BvhNodeIndex::right(node_id);
412 }
413 if left_is_leaf {
414 set_leaf_data!(left_leaf_data, children_id, BvhNodeIndex::RIGHT);
415 } else {
416 self.parents[left_leaf_data as usize] = BvhNodeIndex::right(children_id);
417 }
418 }
419 }
420 }
421 }
422}