parry3d/partitioning/bvh/
bvh_validation.rs1use crate::partitioning::bvh::bvh_tree::BvhNodeIndex;
2use crate::partitioning::Bvh;
3use crate::utils::hashset::HashSet;
4
5impl Bvh {
6 pub fn reachable_leaf_count(&self, id: u32) -> u32 {
10 if self.nodes.is_empty() {
11 0
12 } else if self.nodes[0].right.leaf_count() == 0 {
13 (id == 0) as u32
14 } else {
15 let node = &self.nodes[id as usize];
16 let left_count = if node.left.is_leaf() {
17 1
18 } else {
19 self.reachable_leaf_count(node.left.children)
20 };
21 let right_count = if node.right.is_leaf() {
22 1
23 } else {
24 self.reachable_leaf_count(node.right.children)
25 };
26 left_count + right_count
27 }
28 }
29
30 pub fn changed_leaf_count(&self, id: u32) -> u32 {
35 if self.nodes.is_empty() {
36 0
37 } else if self.nodes[0].right.leaf_count() == 0 {
38 (id == 0 && self.nodes[0].left.data.is_changed()) as u32
39 } else {
40 let node = &self.nodes[id as usize];
41 let left_count = if node.left.is_leaf() {
42 node.left.is_changed() as u32
43 } else {
44 self.changed_leaf_count(node.left.children)
45 };
46 let right_count = if node.right.is_leaf() {
47 node.right.is_changed() as u32
48 } else {
49 self.changed_leaf_count(node.right.children)
50 };
51 left_count + right_count
52 }
53 }
54
55 pub fn assert_well_formed(&self) {
62 if self.is_empty() {
63 return;
64 } else if self.nodes[0].right.leaf_count() == 0 {
65 assert_eq!(self.nodes[0].leaf_count(), 1);
66 assert!(self.nodes[0].left.is_leaf());
67 return;
68 }
69
70 let mut loop_detection = HashSet::default();
71 let _ = self.assert_well_formed_recurse(0, &mut loop_detection);
72 }
73
74 fn assert_well_formed_recurse(&self, node_id: u32, loop_detection: &mut HashSet<u32>) -> u32 {
75 let node = &self.nodes[node_id as usize];
76
77 if !loop_detection.insert(node_id) {
78 panic!("Detected loop. Node {} visited twice.", node_id);
79 }
80
81 let left_count = if node.left.is_leaf() {
82 let leaf_data = self.leaf_node_indices[node.left.children as usize];
83 assert_eq!(leaf_data, BvhNodeIndex::left(node_id));
84 1
85 } else {
86 let calculated_leaf_count =
87 self.assert_well_formed_recurse(node.left.children, loop_detection);
88 let child = &self.nodes[node.left.children as usize];
89 assert_eq!(
90 self.parents[node.left.children as usize],
91 BvhNodeIndex::left(node_id)
92 );
93 assert_eq!(
94 child.right.is_changed() || child.left.is_changed(),
95 node.left.is_changed()
96 );
97 assert!(node.left.contains(&child.left));
98 assert!(node.left.contains(&child.right));
99 assert_eq!(
100 node.left.leaf_count(),
101 child.left.leaf_count() + child.right.leaf_count()
102 );
103 assert_eq!(node.left.leaf_count(), calculated_leaf_count);
104 calculated_leaf_count
105 };
106
107 let right_count = if node.right.is_leaf() {
108 let leaf_data = self.leaf_node_indices[node.right.children as usize];
109 assert_eq!(leaf_data, BvhNodeIndex::right(node_id));
110 1
111 } else {
112 let calculated_leaf_count =
113 self.assert_well_formed_recurse(node.right.children, loop_detection);
114 let child = &self.nodes[node.right.children as usize];
115 assert_eq!(
116 self.parents[node.right.children as usize],
117 BvhNodeIndex::right(node_id)
118 );
119 assert_eq!(
120 child.right.is_changed() || child.left.is_changed(),
121 node.right.is_changed()
122 );
123 assert!(node.right.contains(&child.left));
124 assert!(node.right.contains(&child.right));
125 assert_eq!(
126 node.right.leaf_count(),
127 child.left.leaf_count() + child.right.leaf_count()
128 );
129 assert_eq!(calculated_leaf_count, node.right.leaf_count());
130 calculated_leaf_count
131 };
132
133 left_count + right_count
134 }
135
136 pub fn assert_well_formed_topology_only(&self) {
142 let _ = self.assert_well_formed_topology_only_recurse(0);
143 }
144
145 fn assert_well_formed_topology_only_recurse(&self, node_id: u32) -> u32 {
146 let node = &self.nodes[node_id as usize];
147
148 let left_count = if node.left.is_leaf() {
149 assert!(self
150 .leaf_node_indices
151 .contains_key(node.left.children as usize));
152 1
153 } else {
154 let calculated_leaf_count =
155 self.assert_well_formed_topology_only_recurse(node.left.children);
156 let child = &self.nodes[node.left.children as usize];
157 assert_eq!(
158 self.parents[node.left.children as usize],
159 BvhNodeIndex::left(node_id)
160 );
161 assert_eq!(
162 node.left.leaf_count(),
163 child.left.leaf_count() + child.right.leaf_count()
164 );
165 assert_eq!(node.left.leaf_count(), calculated_leaf_count);
166 calculated_leaf_count
167 };
168
169 let right_count = if node.right.is_leaf() {
170 assert!(self
171 .leaf_node_indices
172 .contains_key(node.right.children as usize));
173 1
174 } else {
175 let calculated_leaf_count =
176 self.assert_well_formed_topology_only_recurse(node.right.children);
177 let child = &self.nodes[node.right.children as usize];
178 assert_eq!(
179 self.parents[node.right.children as usize],
180 BvhNodeIndex::right(node_id)
181 );
182 assert_eq!(
183 node.right.leaf_count(),
184 child.left.leaf_count() + child.right.leaf_count()
185 );
186 assert_eq!(calculated_leaf_count, node.right.leaf_count());
187 calculated_leaf_count
188 };
189
190 left_count + right_count
191 }
192
193 pub fn assert_is_depth_first(&self) {
197 if self.is_empty() || self.nodes[0].right.leaf_count() == 0 {
198 return;
200 }
201
202 let mut stack = alloc::vec![0];
203 let mut loop_id = 0;
204 while let Some(id) = stack.pop() {
205 assert_eq!(loop_id, id);
206 loop_id += 1;
207 let node = &self.nodes[id as usize];
208
209 if !node.right.is_leaf() {
210 stack.push(node.right.children);
211 }
212
213 if !node.left.is_leaf() {
214 stack.push(node.left.children);
215 }
216 }
217 }
218}