1use num_traits::AsPrimitive;
2
3fn expand_bits2(x: u32) -> u32 {
4 let x = (x | (x << 8)) & 0x00ff00ff;
5 let x = (x | (x << 4)) & 0x0f0f0f0f;
6 let x = (x | (x << 2)) & 0x33333333;
7 (x | (x << 1)) & 0x55555555
8}
9
10#[test]
11fn test_expand_bits2() {
12 assert_eq!(expand_bits2(0b11111111), 0b0101010101010101);
13 assert_eq!(expand_bits2(0b10001001), 0b0100000001000001);
14}
15
16pub fn morton_code2(x: f32, y: f32) -> u32 {
21 let ix = (x * 65536_f32).clamp(0_f32, 65535_f32) as u32;
23 let iy = (y * 65536_f32).clamp(0_f32, 65535_f32) as u32;
24 let ix = expand_bits2(ix);
25 let iy = expand_bits2(iy);
26 ix * 2 + iy
27}
28
29#[test]
30fn test_morton_code2() {
31 assert_eq!(morton_code2(0., 0.), 0u32); assert_eq!(morton_code2(0., 1.), 0b01010101010101010101010101010101);
33}
34
35pub fn sorted_morten_code2<Index>(
36 idx2vtx: &mut [Index],
37 idx2morton: &mut [u32],
38 vtx2morton: &mut [u32],
39 vtx2xy: &[f32],
40 transform_xy2uni: &[f32; 9],
41) where
42 Index: num_traits::PrimInt + 'static + AsPrimitive<usize>,
43 usize: AsPrimitive<Index>,
44{
45 assert_eq!(idx2vtx.len(), idx2morton.len());
46 assert_eq!(idx2vtx.len(), vtx2morton.len());
47 assert_eq!(idx2vtx.len(), vtx2xy.len() / 2);
48 vtx2xy
49 .chunks(2)
50 .zip(vtx2morton.iter_mut())
51 .for_each(|(xy, m)| {
52 let xy = del_geo_core::mat3_col_major::transform_homogeneous(
53 transform_xy2uni,
54 &[xy[0], xy[1]],
55 )
56 .unwrap();
57 *m = morton_code2(xy[0], xy[1]);
58 });
59 idx2vtx
60 .iter_mut()
61 .enumerate()
62 .for_each(|(iv, idx)| *idx = iv.as_());
63 idx2vtx.sort_by_key(|iv| vtx2morton[(*iv).as_()]);
64 for idx in 0..idx2vtx.len() {
65 idx2morton[idx] = vtx2morton[idx2vtx[idx].as_()];
66 }
67}
68
69fn expand_bits3(x: u32) -> u32 {
77 let x = (x | (x << 16)) & 0x030000FF;
78 let x = (x | (x << 8)) & 0x0300F00F;
79 let x = (x | (x << 4)) & 0x030C30C3;
80 (x | (x << 2)) & 0x09249249
81}
82
83#[test]
84fn test_expand_bits3() {
85 assert_eq!(expand_bits3(0b11111111), 0b001001001001001001001001);
86 assert_eq!(expand_bits3(0b10001001), 0b001000000000001000000001);
87}
88
89pub fn morton_code3(x: f32, y: f32, z: f32) -> u32 {
95 let ix = (x * 1024_f32).clamp(0_f32, 1023_f32) as u32;
96 let iy = (y * 1024_f32).clamp(0_f32, 1023_f32) as u32;
97 let iz = (z * 1024_f32).clamp(0_f32, 1023_f32) as u32;
98 let ix = expand_bits3(ix);
99 let iy = expand_bits3(iy);
100 let iz = expand_bits3(iz);
101 ix * 4 + iy * 2 + iz
102}
103
104#[test]
105fn test_morton_code3() {
106 assert_eq!(morton_code3(0., 0., 0.), 0u32); assert_eq!(morton_code3(0., 0., 1.), 0b001001001001001001001001001001);
108 assert_eq!(morton_code3(1., 0., 1.), 0b101101101101101101101101101101);
109 assert_eq!(morton_code3(1., 1., 1.), 0xFFFFFFFF >> 2);
110}
111
112pub fn sorted_morten_code3<Index>(
116 idx2vtx: &mut [Index],
117 idx2morton: &mut [u32],
118 vtx2morton: &mut [u32],
119 vtx2xyz: &[f32],
120 transform_xy2uni: &[f32; 16],
121) where
122 Index: num_traits::PrimInt + 'static + AsPrimitive<usize>,
123 usize: AsPrimitive<Index>,
124{
125 assert_eq!(idx2vtx.len(), idx2morton.len());
126 assert_eq!(idx2vtx.len(), vtx2morton.len());
127 assert_eq!(idx2vtx.len(), vtx2xyz.len() / 3);
128 vtx2xyz
129 .chunks(3)
130 .zip(vtx2morton.iter_mut())
131 .for_each(|(xyz, m)| {
132 let xyz = del_geo_core::mat4_col_major::transform_homogeneous(
133 transform_xy2uni,
134 &[xyz[0], xyz[1], xyz[2]],
135 )
136 .unwrap();
137 *m = morton_code3(xyz[0], xyz[1], xyz[2])
138 });
139 idx2vtx
140 .iter_mut()
141 .enumerate()
142 .for_each(|(iv, idx)| *idx = iv.as_());
143 idx2vtx.sort_by_key(|iv| vtx2morton[(*iv).as_()]);
144 for idx in 0..idx2vtx.len() {
145 idx2morton[idx] = vtx2morton[idx2vtx[idx].as_()];
146 }
147}
148
149#[test]
150fn test_sorted_morten_code() {
151 let vtx2xyz = vec![1., 1., 1., 0., 0., 0., 0., 0., 1., 1., 0., 1., 0., 0., 1.];
152 let num_vtx = vtx2xyz.len() / 3;
153 let mut vtx2morton = vec![0u32; num_vtx];
154 let mut idx2morton = vec![0u32; num_vtx];
155 let mut idx2vtx = vec![0usize; num_vtx];
156 sorted_morten_code3(
157 &mut idx2vtx,
158 &mut idx2morton,
159 &mut vtx2morton,
160 &vtx2xyz,
161 &del_geo_core::mat4_col_major::from_identity(),
162 );
163 for idx in 0..num_vtx - 1 {
164 let jdx = idx + 1;
165 assert!(idx2morton[idx] <= idx2morton[jdx]);
166 }
167}
168
169pub fn vtx2morton_from_vtx2co(
172 num_dim: usize,
173 vtx2co: &[f32],
174 transform_co2unit: &[f32],
175 vtx2morton: &mut [u32],
176) {
177 match num_dim {
178 2 => {
179 assert_eq!(transform_co2unit.len(), 9);
180 let transform_co2unit: &[f32; 9] = arrayref::array_ref![transform_co2unit, 0, 9];
181 vtx2co
182 .chunks(2)
183 .zip(vtx2morton.iter_mut())
184 .for_each(|(xy, m)| {
185 let xy = del_geo_core::mat3_col_major::transform_homogeneous(
186 transform_co2unit,
187 &[xy[0], xy[1]],
188 )
189 .unwrap();
190 *m = morton_code2(xy[0], xy[1]);
191 });
192 }
193 3 => {
194 assert_eq!(transform_co2unit.len(), 16);
195 let transform_co2unit: &[f32; 16] = arrayref::array_ref![transform_co2unit, 0, 16];
196 vtx2co
197 .chunks(3)
198 .zip(vtx2morton.iter_mut())
199 .for_each(|(xyz, m)| {
200 let xyz = del_geo_core::mat4_col_major::transform_homogeneous(
201 transform_co2unit,
202 &[xyz[0], xyz[1], xyz[2]],
203 )
204 .unwrap();
205 *m = morton_code3(xyz[0], xyz[1], xyz[2])
206 });
207 }
208 _ => {
209 panic!()
210 }
211 }
212}
213
214fn delta(idx0: usize, idx1: usize, idx2morton: &[u32]) -> i64 {
217 (idx2morton[idx0] ^ idx2morton[idx1]).leading_zeros().into()
218}
219
220pub fn range_of_binary_radix_tree_node(idx2morton: &[u32], idx1: usize) -> (usize, usize) {
222 let num_mc = idx2morton.len();
223 assert!(!idx2morton.is_empty());
224 if idx1 == 0 {
225 return (0, num_mc - 1);
226 }
227 if idx1 == num_mc - 1 {
228 return (num_mc - 1, num_mc - 1);
230 }
231 let mc0: u32 = idx2morton[idx1 - 1];
233 let mc1: u32 = idx2morton[idx1];
234 let mc2: u32 = idx2morton[idx1 + 1];
235 if mc0 == mc1 && mc1 == mc2 {
236 let mut jdx = idx1 + 1;
238 while jdx < num_mc - 1 {
239 jdx += 1;
240 if idx2morton[jdx] != mc1 {
241 return (idx1, jdx - 1);
242 }
243 }
244 return (idx1, jdx);
245 }
246 let d = delta(idx1, idx1 + 1, idx2morton) - delta(idx1, idx1 - 1, idx2morton);
250 let d: i64 = if d > 0 { 1 } else { -1 };
251
252 let delta_min = delta(idx1, (idx1 as i64 - d) as usize, idx2morton);
254 let mut lmax: i64 = 2;
255 loop {
256 let jdx = idx1 as i64 + lmax * d;
257 if jdx < 0 || jdx >= idx2morton.len() as i64 {
258 break;
259 }
260 if delta(idx1, jdx.try_into().unwrap(), idx2morton) <= delta_min {
261 break;
262 }
263 lmax *= 2;
264 }
265
266 let l = {
268 let mut l = 0;
269 let mut t = lmax / 2;
270 while t >= 1 {
271 let jdx = idx1 as i64 + (l + t) * d;
272 if jdx >= 0
273 && jdx < idx2morton.len() as i64
274 && delta(idx1, jdx as usize, idx2morton) > delta_min
275 {
276 l += t;
277 }
278 t /= 2;
279 }
280 l
281 };
282 let jdx = (idx1 as i64 + l * d) as usize;
283 if idx1 <= jdx {
284 (idx1, jdx)
285 } else {
286 (jdx, idx1)
287 }
288}
289
290pub fn split_of_binary_radix_tree_node(
291 idx2morton: &[u32],
292 i_mc_start: usize,
293 i_mc_end: usize,
294) -> usize {
295 if i_mc_start == i_mc_end {
296 return usize::MAX;
297 }
298
299 let mc_start: u32 = idx2morton[i_mc_start];
300 let nbitcommon0: u32 = (mc_start ^ idx2morton[i_mc_end]).leading_zeros();
301
302 if nbitcommon0 == 32 {
304 return i_mc_start;
305 } let mut i_mc_split: usize = i_mc_start; assert!(i_mc_start <= i_mc_end);
312 let mut step: usize = i_mc_end - i_mc_start;
313 while step > 1 {
314 step = step.div_ceil(2); let i_mc_new: usize = i_mc_split + step; if i_mc_new >= i_mc_end {
317 continue;
318 }
319 let nbitcommon1: u32 = (mc_start ^ idx2morton[i_mc_new]).leading_zeros();
320 if nbitcommon1 > nbitcommon0 {
321 i_mc_split = i_mc_new; }
323 }
324 i_mc_split
325}
326
327#[allow(dead_code)]
330pub fn check_morton_code_range_split(idx2morton: &[u32]) {
331 let num_vtx = idx2morton.len();
332 assert!(!idx2morton.is_empty());
333 for idx in 0..num_vtx - 1 {
334 let jdx = idx + 1;
335 assert!(idx2morton[idx] <= idx2morton[jdx]);
336 }
337 for ini in 0..idx2morton.len() - 1 {
338 let range = range_of_binary_radix_tree_node(idx2morton, ini);
339 let isplit = split_of_binary_radix_tree_node(idx2morton, range.0, range.1);
340 let range_a = range_of_binary_radix_tree_node(idx2morton, isplit);
341 let range_b = range_of_binary_radix_tree_node(idx2morton, isplit + 1);
342 assert_eq!(range.0, range_a.0);
343 assert_eq!(range.1, range_b.1);
344 let last1 = if isplit == range.0 { isplit } else { range_a.1 };
345 let first1 = if isplit + 1 == range.1 {
346 isplit + 1
347 } else {
348 range_b.0
349 };
350 assert_eq!(last1 + 1, first1);
351 }
352}
353
354pub fn update_sorted_morton_code<Index>(
355 idx2tri: &mut [Index],
356 idx2morton: &mut [u32],
357 tri2morton: &mut [u32],
358 vtx2xyz: &[f32],
359 num_dim: usize,
360) where
361 Index: num_traits::PrimInt + num_traits::AsPrimitive<usize>,
362 usize: AsPrimitive<Index>,
363{
364 match num_dim {
365 2 => {
366 let aabb = crate::vtx2xy::aabb2(vtx2xyz);
367 let transform_xy2uni =
368 del_geo_core::aabb2::to_transformation_world2unit_ortho_preserve_asp(&aabb);
369 sorted_morten_code2(idx2tri, idx2morton, tri2morton, vtx2xyz, &transform_xy2uni);
370 }
371 3 => {
372 let aabb = crate::vtx2xyz::aabb3(vtx2xyz, 0f32);
373 let transform_xy2uni =
374 del_geo_core::mat4_col_major::from_aabb3_fit_into_unit_preserve_asp(&aabb);
375 sorted_morten_code3(idx2tri, idx2morton, tri2morton, vtx2xyz, &transform_xy2uni);
377 }
378 _ => {
379 panic!();
380 }
381 }
382}
383
384pub fn check_binary_radix_tree(bnodes: &[u32], idx2morton: &[u32]) {
385 let num_vtx = idx2morton.len();
386 assert_eq!(bnodes.len(), (num_vtx - 1) * 3);
387 pub fn increment_leaf_binary_radix_tree<INDEX>(
388 bvhnodes: &[INDEX],
389 i_node: usize,
390 idx2flag: &mut [usize],
391 ) where
392 INDEX: num_traits::PrimInt + num_traits::AsPrimitive<usize>,
393 {
394 let num_idx = idx2flag.len();
395 assert_eq!(bvhnodes.len(), (num_idx - 1) * 3);
396 assert!(i_node < num_idx - 1);
397 let i0_node = bvhnodes[i_node * 3 + 1].as_();
398 if i0_node >= num_idx - 1 {
399 let idx = i0_node - (num_idx - 1);
400 idx2flag[idx] += 1;
401 } else {
402 increment_leaf_binary_radix_tree(bvhnodes, i0_node, idx2flag);
403 }
404 let i1_node = bvhnodes[i_node * 3 + 2].as_();
405 if i1_node >= num_idx - 1 {
406 let idx = i1_node - (num_idx - 1);
407 idx2flag[idx] += 1;
408 } else {
409 increment_leaf_binary_radix_tree(bvhnodes, i1_node, idx2flag);
410 }
411 }
412
413 let mut idx2flag = vec![0usize; num_vtx];
415 increment_leaf_binary_radix_tree(bnodes, 0, &mut idx2flag);
416 assert_eq!(idx2flag, vec!(1; num_vtx));
417 for i_branch in 0..num_vtx - 1 {
418 let i_left = bnodes[i_branch * 3 + 1] as usize;
419 let i_split = if i_left >= num_vtx - 1 {
420 i_left - (num_vtx - 1)
421 } else {
422 i_left
423 };
424 let range = range_of_binary_radix_tree_node(idx2morton, i_branch);
425 let i_split0 = split_of_binary_radix_tree_node(idx2morton, range.0, range.1);
426 assert_eq!(i_split0, i_split);
427 }
428 }