Blender V4.3
BLI_kdopbvh.c
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2006 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
26#include "MEM_guardedalloc.h"
27
28#include "BLI_alloca.h"
29#include "BLI_heap_simple.h"
30#include "BLI_kdopbvh.h"
31#include "BLI_math_geom.h"
32#include "BLI_stack.h"
33#include "BLI_task.h"
34#include "BLI_utildefines.h"
35
36#include "BLI_strict_flags.h" /* Keep last. */
37
38/* used for iterative_raycast */
39// #define USE_SKIP_LINKS
40
41/* Use to print balanced output. */
42// #define USE_PRINT_TREE
43
44/* Check tree is valid. */
45// #define USE_VERIFY_TREE
46
47#define MAX_TREETYPE 32
48
49/* Setting zero so we can catch bugs in BLI_task/KDOPBVH.
50 * TODO(sergey): Deduplicate the limits with #blender::bke::pbvh::Tree from BKE.
51 */
52#ifndef NDEBUG
53# define KDOPBVH_THREAD_LEAF_THRESHOLD 0
54#else
55# define KDOPBVH_THREAD_LEAF_THRESHOLD 1024
56#endif
57
58/* -------------------------------------------------------------------- */
62typedef uchar axis_t;
63
64typedef struct BVHNode {
65 struct BVHNode **children;
66 struct BVHNode *parent; /* some user defined traversed need that */
67#ifdef USE_SKIP_LINKS
68 struct BVHNode *skip[2];
69#endif
70 float *bv; /* Bounding volume of all nodes, max 13 axis */
71 int index; /* face, edge, vertex index */
72 char node_num; /* how many nodes are used, used for speedup */
73 char main_axis; /* Axis used to split this node */
75
76/* keep under 26 bytes for speed purposes */
77struct BVHTree {
79 BVHNode *nodearray; /* pre-alloc branch nodes */
80 BVHNode **nodechild; /* pre-alloc children for nodes */
81 float *nodebv; /* pre-alloc bounding-volumes for nodes */
82 float epsilon; /* Epsilon is used for inflation of the K-DOP. */
83 int leaf_num; /* leafs */
85 axis_t start_axis, stop_axis; /* bvhtree_kdop_axes array indices according to axis */
86 axis_t axis; /* KDOP type (6 => OBB, 7 => AABB, ...) */
87 char tree_type; /* type of tree (4 => quad-tree). */
88};
89
90/* optimization, ensure we stay small */
91BLI_STATIC_ASSERT((sizeof(void *) == 8 && sizeof(BVHTree) <= 48) ||
92 (sizeof(void *) == 4 && sizeof(BVHTree) <= 32),
93 "over sized")
94
95/* avoid duplicating vars in BVHOverlapData_Thread */
96typedef struct BVHOverlapData_Shared {
97 const BVHTree *tree1, *tree2;
98 axis_t start_axis, stop_axis;
99 bool use_self;
100
101 /* use for callbacks */
103 void *userdata;
105
106typedef struct BVHOverlapData_Thread {
108 BLI_Stack *overlap; /* store BVHTreeOverlap */
110 /* use for callbacks */
113
114typedef struct BVHNearestData {
115 const BVHTree *tree;
116 const float *co;
118 void *userdata;
119 float proj[13]; /* coordinates projection over axis */
121
123
124typedef struct BVHRayCastData {
125 const BVHTree *tree;
126
128 void *userdata;
129
131
132#ifdef USE_KDOPBVH_WATERTIGHT
133 struct IsectRayPrecalc isect_precalc;
134#endif
135
136 /* initialized by bvhtree_ray_cast_data_precalc */
137 float ray_dot_axis[13];
138 float idot_axis[13];
139 int index[6];
140
143
154
155typedef struct BVHIntersectPlaneData {
156 const BVHTree *tree;
157 float plane[4];
158 BLI_Stack *intersect; /* Store indexes. */
160
171const float bvhtree_kdop_axes[13][3] = {
172 {1.0, 0, 0},
173 {0, 1.0, 0},
174 {0, 0, 1.0},
175 {1.0, 1.0, 1.0},
176 {1.0, -1.0, 1.0},
177 {1.0, 1.0, -1.0},
178 {1.0, -1.0, -1.0},
179 {1.0, 1.0, 0},
180 {1.0, 0, 1.0},
181 {0, 1.0, 1.0},
182 {1.0, -1.0, 0},
183 {1.0, 0, -1.0},
184 {0, 1.0, -1.0},
185};
186
187/* Used to correct the epsilon and thus match the overlap distance. */
188static const float bvhtree_kdop_axes_length[13] = {
189 1.0f,
190 1.0f,
191 1.0f,
192 1.7320508075688772f,
193 1.7320508075688772f,
194 1.7320508075688772f,
195 1.7320508075688772f,
196 1.4142135623730951f,
197 1.4142135623730951f,
198 1.4142135623730951f,
199 1.4142135623730951f,
200 1.4142135623730951f,
201 1.4142135623730951f,
202};
203
204/* -------------------------------------------------------------------- */
209{
210 return (a < b) ? a : b;
211}
212#if 0
213MINLINE axis_t max_axis(axis_t a, axis_t b)
214{
215 return (b < a) ? a : b;
216}
217#endif
218
226static void node_minmax_init(const BVHTree *tree, BVHNode *node)
227{
228 axis_t axis_iter;
229 float(*bv)[2] = (float(*)[2])node->bv;
230
231 for (axis_iter = tree->start_axis; axis_iter != tree->stop_axis; axis_iter++) {
232 bv[axis_iter][0] = FLT_MAX;
233 bv[axis_iter][1] = -FLT_MAX;
234 }
235}
236
239/* -------------------------------------------------------------------- */
246static void bvh_insertionsort(BVHNode **a, int lo, int hi, int axis)
247{
248 int i, j;
249 BVHNode *t;
250 for (i = lo; i < hi; i++) {
251 j = i;
252 t = a[i];
253 while ((j != lo) && (t->bv[axis] < (a[j - 1])->bv[axis])) {
254 a[j] = a[j - 1];
255 j--;
256 }
257 a[j] = t;
258 }
259}
260
261static int bvh_partition(BVHNode **a, int lo, int hi, const BVHNode *x, int axis)
262{
263 int i = lo, j = hi;
264 while (1) {
265 while (a[i]->bv[axis] < x->bv[axis]) {
266 i++;
267 }
268 j--;
269 while (x->bv[axis] < a[j]->bv[axis]) {
270 j--;
271 }
272 if (!(i < j)) {
273 return i;
274 }
275 SWAP(BVHNode *, a[i], a[j]);
276 i++;
277 }
278}
279
280/* returns Sortable */
281static BVHNode *bvh_medianof3(BVHNode **a, int lo, int mid, int hi, int axis)
282{
283 if ((a[mid])->bv[axis] < (a[lo])->bv[axis]) {
284 if ((a[hi])->bv[axis] < (a[mid])->bv[axis]) {
285 return a[mid];
286 }
287 if ((a[hi])->bv[axis] < (a[lo])->bv[axis]) {
288 return a[hi];
289 }
290 return a[lo];
291 }
292
293 if ((a[hi])->bv[axis] < (a[mid])->bv[axis]) {
294 if ((a[hi])->bv[axis] < (a[lo])->bv[axis]) {
295 return a[lo];
296 }
297 return a[hi];
298 }
299 return a[mid];
300}
301
307static void partition_nth_element(BVHNode **a, int begin, int end, const int n, const int axis)
308{
309 while (end - begin > 3) {
310 const int cut = bvh_partition(
311 a, begin, end, bvh_medianof3(a, begin, (begin + end) / 2, end - 1, axis), axis);
312 if (cut <= n) {
313 begin = cut;
314 }
315 else {
316 end = cut;
317 }
318 }
319 bvh_insertionsort(a, begin, end, axis);
320}
321
322#ifdef USE_SKIP_LINKS
323static void build_skip_links(BVHTree *tree, BVHNode *node, BVHNode *left, BVHNode *right)
324{
325 int i;
326
327 node->skip[0] = left;
328 node->skip[1] = right;
329
330 for (i = 0; i < node->node_num; i++) {
331 if (i + 1 < node->node_num) {
332 build_skip_links(tree, node->children[i], left, node->children[i + 1]);
333 }
334 else {
335 build_skip_links(tree, node->children[i], left, right);
336 }
337
338 left = node->children[i];
339 }
340}
341#endif
342
343/*
344 * BVHTree bounding volumes functions
345 */
347 const BVHTree *tree, BVHNode *node, const float *co, int numpoints, int moving)
348{
349 float newminmax;
350 float *bv = node->bv;
351 int k;
352 axis_t axis_iter;
353
354 /* Don't initialize bounds for the moving case */
355 if (!moving) {
356 node_minmax_init(tree, node);
357 }
358
359 for (k = 0; k < numpoints; k++) {
360 /* for all Axes. */
361 for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) {
362 newminmax = dot_v3v3(&co[k * 3], bvhtree_kdop_axes[axis_iter]);
363 if (newminmax < bv[2 * axis_iter]) {
364 bv[2 * axis_iter] = newminmax;
365 }
366 if (newminmax > bv[(2 * axis_iter) + 1]) {
367 bv[(2 * axis_iter) + 1] = newminmax;
368 }
369 }
370 }
371}
372
376static void refit_kdop_hull(const BVHTree *tree, BVHNode *node, int start, int end)
377{
378 float newmin, newmax;
379 float *__restrict bv = node->bv;
380 int j;
381 axis_t axis_iter;
382
383 node_minmax_init(tree, node);
384
385 for (j = start; j < end; j++) {
386 const float *__restrict node_bv = tree->nodes[j]->bv;
387
388 /* for all Axes. */
389 for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) {
390 newmin = node_bv[(2 * axis_iter)];
391 if (newmin < bv[(2 * axis_iter)]) {
392 bv[(2 * axis_iter)] = newmin;
393 }
394
395 newmax = node_bv[(2 * axis_iter) + 1];
396 if (newmax > bv[(2 * axis_iter) + 1]) {
397 bv[(2 * axis_iter) + 1] = newmax;
398 }
399 }
400 }
401}
402
407static char get_largest_axis(const float *bv)
408{
409 float middle_point[3];
410
411 middle_point[0] = (bv[1]) - (bv[0]); /* x axis */
412 middle_point[1] = (bv[3]) - (bv[2]); /* y axis */
413 middle_point[2] = (bv[5]) - (bv[4]); /* z axis */
414 if (middle_point[0] > middle_point[1]) {
415 if (middle_point[0] > middle_point[2]) {
416 return 1; /* max x axis */
417 }
418 return 5; /* max z axis */
419 }
420 if (middle_point[1] > middle_point[2]) {
421 return 3; /* max y axis */
422 }
423 return 5; /* max z axis */
424}
425
430static void node_join(BVHTree *tree, BVHNode *node)
431{
432 int i;
433 axis_t axis_iter;
434
435 node_minmax_init(tree, node);
436
437 for (i = 0; i < tree->tree_type; i++) {
438 if (node->children[i]) {
439 for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) {
440 /* update minimum */
441 if (node->children[i]->bv[(2 * axis_iter)] < node->bv[(2 * axis_iter)]) {
442 node->bv[(2 * axis_iter)] = node->children[i]->bv[(2 * axis_iter)];
443 }
444
445 /* update maximum */
446 if (node->children[i]->bv[(2 * axis_iter) + 1] > node->bv[(2 * axis_iter) + 1]) {
447 node->bv[(2 * axis_iter) + 1] = node->children[i]->bv[(2 * axis_iter) + 1];
448 }
449 }
450 }
451 else {
452 break;
453 }
454 }
455}
456
457#ifdef USE_PRINT_TREE
458
459/* -------------------------------------------------------------------- */
463static void bvhtree_print_tree(BVHTree *tree, BVHNode *node, int depth)
464{
465 int i;
466 axis_t axis_iter;
467
468 for (i = 0; i < depth; i++) {
469 printf(" ");
470 }
471 printf(" - %d (%ld): ", node->index, (long int)(node - tree->nodearray));
472 for (axis_iter = (axis_t)(2 * tree->start_axis); axis_iter < (axis_t)(2 * tree->stop_axis);
473 axis_iter++)
474 {
475 printf("%.3f ", node->bv[axis_iter]);
476 }
477 printf("\n");
478
479 for (i = 0; i < tree->tree_type; i++) {
480 if (node->children[i]) {
481 bvhtree_print_tree(tree, node->children[i], depth + 1);
482 }
483 }
484}
485
486static void bvhtree_info(BVHTree *tree)
487{
488 printf("BVHTree Info: tree_type = %d, axis = %d, epsilon = %f\n",
489 tree->tree_type,
490 tree->axis,
491 tree->epsilon);
492 printf("nodes = %d, branches = %d, leafs = %d\n",
493 tree->branch_num + tree->leaf_num,
494 tree->branch_num,
495 tree->leaf_num);
496 printf(
497 "Memory per node = %ubytes\n",
498 (uint)(sizeof(BVHNode) + sizeof(BVHNode *) * tree->tree_type + sizeof(float) * tree->axis));
499 printf("BV memory = %ubytes\n", (uint)MEM_allocN_len(tree->nodebv));
500
501 printf("Total memory = %ubytes\n",
502 (uint)(sizeof(BVHTree) + MEM_allocN_len(tree->nodes) + MEM_allocN_len(tree->nodearray) +
503 MEM_allocN_len(tree->nodechild) + MEM_allocN_len(tree->nodebv)));
504
505 bvhtree_print_tree(tree, tree->nodes[tree->leaf_num], 0);
506}
507
510#endif /* USE_PRINT_TREE */
511
512#ifdef USE_VERIFY_TREE
513
514static void bvhtree_verify(BVHTree *tree)
515{
516 int i, j, check = 0;
517
518 /* check the pointer list */
519 for (i = 0; i < tree->leaf_num; i++) {
520 if (tree->nodes[i]->parent == NULL) {
521 printf("Leaf has no parent: %d\n", i);
522 }
523 else {
524 for (j = 0; j < tree->tree_type; j++) {
525 if (tree->nodes[i]->parent->children[j] == tree->nodes[i]) {
526 check = 1;
527 }
528 }
529 if (!check) {
530 printf("Parent child relationship doesn't match: %d\n", i);
531 }
532 check = 0;
533 }
534 }
535
536 /* check the leaf list */
537 for (i = 0; i < tree->leaf_num; i++) {
538 if (tree->nodearray[i].parent == NULL) {
539 printf("Leaf has no parent: %d\n", i);
540 }
541 else {
542 for (j = 0; j < tree->tree_type; j++) {
543 if (tree->nodearray[i].parent->children[j] == &tree->nodearray[i]) {
544 check = 1;
545 }
546 }
547 if (!check) {
548 printf("Parent child relationship doesn't match: %d\n", i);
549 }
550 check = 0;
551 }
552 }
553
554 printf("branches: %d, leafs: %d, total: %d\n",
555 tree->branch_num,
556 tree->leaf_num,
557 tree->branch_num + tree->leaf_num);
558}
559#endif /* USE_VERIFY_TREE */
560
561/* Helper data and structures to build a min-leaf generalized implicit tree
562 * This code can be easily reduced
563 * (basically this is only method to calculate pow(k, n) in O(1).. and stuff like that) */
577
579{
580 int depth = 0;
581 int remain;
582 int nnodes;
583
584 data->leafs_num = tree->leaf_num;
585 data->tree_type = tree->tree_type;
586
587 /* Calculate the smallest tree_type^n such that tree_type^n >= leafs_num */
588 for (data->leafs_per_child[0] = 1; data->leafs_per_child[0] < data->leafs_num;
589 data->leafs_per_child[0] *= data->tree_type)
590 {
591 /* pass */
592 }
593
594 data->branches_on_level[0] = 1;
595
596 for (depth = 1; (depth < 32) && data->leafs_per_child[depth - 1]; depth++) {
597 data->branches_on_level[depth] = data->branches_on_level[depth - 1] * data->tree_type;
598 data->leafs_per_child[depth] = data->leafs_per_child[depth - 1] / data->tree_type;
599 }
600
601 remain = data->leafs_num - data->leafs_per_child[1];
602 nnodes = (remain + data->tree_type - 2) / (data->tree_type - 1);
603 data->remain_leafs = remain + nnodes;
604}
605
609static int implicit_leafs_index(const BVHBuildHelper *data, const int depth, const int child_index)
610{
611 int min_leaf_index = child_index * data->leafs_per_child[depth - 1];
612 if (min_leaf_index <= data->remain_leafs) {
613 return min_leaf_index;
614 }
615 if (data->leafs_per_child[depth]) {
616 return data->leafs_num -
617 (data->branches_on_level[depth - 1] - child_index) * data->leafs_per_child[depth];
618 }
619 return data->remain_leafs;
620}
621
651/* This functions returns the number of branches needed to have the requested number of leafs. */
652static int implicit_needed_branches(int tree_type, int leafs)
653{
654 return max_ii(1, (leafs + tree_type - 3) / (tree_type - 1));
655}
656
669static void split_leafs(BVHNode **leafs_array,
670 const int nth[],
671 const int partitions,
672 const int split_axis)
673{
674 int i;
675 for (i = 0; i < partitions - 1; i++) {
676 if (nth[i] >= nth[partitions]) {
677 break;
678 }
679
680 partition_nth_element(leafs_array, nth[i], nth[partitions], nth[i + 1], split_axis);
681 }
682}
683
698
699static void non_recursive_bvh_div_nodes_task_cb(void *__restrict userdata,
700 const int j,
701 const TaskParallelTLS *__restrict UNUSED(tls))
702{
703 BVHDivNodesData *data = userdata;
704
705 int k;
706 const int parent_level_index = j - data->i;
707 BVHNode *parent = &data->branches_array[j];
708 int nth_positions[MAX_TREETYPE + 1];
709 char split_axis;
710
711 int parent_leafs_begin = implicit_leafs_index(data->data, data->depth, parent_level_index);
712 int parent_leafs_end = implicit_leafs_index(data->data, data->depth, parent_level_index + 1);
713
714 /* This calculates the bounding box of this branch
715 * and chooses the largest axis as the axis to divide leafs */
716 refit_kdop_hull(data->tree, parent, parent_leafs_begin, parent_leafs_end);
717 split_axis = get_largest_axis(parent->bv);
718
719 /* Save split axis (this can be used on ray-tracing to speedup the query time) */
720 parent->main_axis = split_axis / 2;
721
722 /* Split the children along the split_axis, NOTE: its not needed to sort the whole leafs array
723 * Only to assure that the elements are partitioned on a way that each child takes the elements
724 * it would take in case the whole array was sorted.
725 * Split_leafs takes care of that "sort" problem. */
726 nth_positions[0] = parent_leafs_begin;
727 nth_positions[data->tree_type] = parent_leafs_end;
728 for (k = 1; k < data->tree_type; k++) {
729 const int child_index = j * data->tree_type + data->tree_offset + k;
730 /* child level index */
731 const int child_level_index = child_index - data->first_of_next_level;
732 nth_positions[k] = implicit_leafs_index(data->data, data->depth + 1, child_level_index);
733 }
734
735 split_leafs(data->leafs_array, nth_positions, data->tree_type, split_axis);
736
737 /* Setup `children` and `node_num` counters
738 * Not really needed but currently most of BVH code
739 * relies on having an explicit children structure */
740 for (k = 0; k < data->tree_type; k++) {
741 const int child_index = j * data->tree_type + data->tree_offset + k;
742 /* child level index */
743 const int child_level_index = child_index - data->first_of_next_level;
744
745 const int child_leafs_begin = implicit_leafs_index(
746 data->data, data->depth + 1, child_level_index);
747 const int child_leafs_end = implicit_leafs_index(
748 data->data, data->depth + 1, child_level_index + 1);
749
750 if (child_leafs_end - child_leafs_begin > 1) {
751 parent->children[k] = &data->branches_array[child_index];
752 parent->children[k]->parent = parent;
753 }
754 else if (child_leafs_end - child_leafs_begin == 1) {
755 parent->children[k] = data->leafs_array[child_leafs_begin];
756 parent->children[k]->parent = parent;
757 }
758 else {
759 break;
760 }
761 }
762 parent->node_num = (char)k;
763}
764
784 BVHNode *branches_array,
785 BVHNode **leafs_array,
786 int leafs_num)
787{
788 int i;
789
790 const int tree_type = tree->tree_type;
791 /* this value is 0 (on binary trees) and negative on the others */
792 const int tree_offset = 2 - tree->tree_type;
793
794 const int branches_num = implicit_needed_branches(tree_type, leafs_num);
795
797 int depth;
798
799 {
800 /* set parent from root node to NULL */
801 BVHNode *root = &branches_array[1];
802 root->parent = NULL;
803
804 /* Most of bvhtree code relies on 1-leaf trees having at least one branch
805 * We handle that special case here */
806 if (leafs_num == 1) {
807 refit_kdop_hull(tree, root, 0, leafs_num);
808 root->main_axis = get_largest_axis(root->bv) / 2;
809 root->node_num = 1;
810 root->children[0] = leafs_array[0];
811 root->children[0]->parent = root;
812 return;
813 }
814 }
815
817
818 BVHDivNodesData cb_data = {
819 .tree = tree,
820 .branches_array = branches_array,
821 .leafs_array = leafs_array,
822 .tree_type = tree_type,
823 .tree_offset = tree_offset,
824 .data = &data,
825 .first_of_next_level = 0,
826 .depth = 0,
827 .i = 0,
828 };
829
830 /* Loop tree levels (log N) loops */
831 for (i = 1, depth = 1; i <= branches_num; i = i * tree_type + tree_offset, depth++) {
832 const int first_of_next_level = i * tree_type + tree_offset;
833 /* index of last branch on this level */
834 const int i_stop = min_ii(first_of_next_level, branches_num + 1);
835
836 /* Loop all branches on this level */
837 cb_data.first_of_next_level = first_of_next_level;
838 cb_data.i = i;
839 cb_data.depth = depth;
840
841 if (true) {
842 TaskParallelSettings settings;
844 settings.use_threading = (leafs_num > KDOPBVH_THREAD_LEAF_THRESHOLD);
845 BLI_task_parallel_range(i, i_stop, &cb_data, non_recursive_bvh_div_nodes_task_cb, &settings);
846 }
847 else {
848 /* Less hassle for debugging. */
849 TaskParallelTLS tls = {0};
850 for (int i_task = i; i_task < i_stop; i_task++) {
851 non_recursive_bvh_div_nodes_task_cb(&cb_data, i_task, &tls);
852 }
853 }
854 }
855}
856
859/* -------------------------------------------------------------------- */
863BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis)
864{
865 BVHTree *tree;
866 int numnodes, i;
867
868 BLI_assert(tree_type >= 2 && tree_type <= MAX_TREETYPE);
869
870 tree = MEM_callocN(sizeof(BVHTree), "BVHTree");
871
872 /* tree epsilon must be >= FLT_EPSILON
873 * so that tangent rays can still hit a bounding volume..
874 * this bug would show up when casting a ray aligned with a KDOP-axis
875 * and with an edge of 2 faces */
876 epsilon = max_ff(FLT_EPSILON, epsilon);
877
878 if (tree) {
879 tree->epsilon = epsilon;
880 tree->tree_type = tree_type;
881 tree->axis = axis;
882
883 if (axis == 26) {
884 tree->start_axis = 0;
885 tree->stop_axis = 13;
886 }
887 else if (axis == 18) {
888 tree->start_axis = 7;
889 tree->stop_axis = 13;
890 }
891 else if (axis == 14) {
892 tree->start_axis = 0;
893 tree->stop_axis = 7;
894 }
895 else if (axis == 8) { /* AABB */
896 tree->start_axis = 0;
897 tree->stop_axis = 4;
898 }
899 else if (axis == 6) { /* OBB */
900 tree->start_axis = 0;
901 tree->stop_axis = 3;
902 }
903 else {
904 /* should never happen! */
906
907 goto fail;
908 }
909
910 /* Allocate arrays */
911 numnodes = maxsize + implicit_needed_branches(tree_type, maxsize) + tree_type;
912
913 tree->nodes = MEM_callocN(sizeof(BVHNode *) * (size_t)numnodes, "BVHNodes");
914 tree->nodebv = MEM_callocN(sizeof(float) * (size_t)(axis * numnodes), "BVHNodeBV");
915 tree->nodechild = MEM_callocN(sizeof(BVHNode *) * (size_t)(tree_type * numnodes), "BVHNodeBV");
916 tree->nodearray = MEM_callocN(sizeof(BVHNode) * (size_t)numnodes, "BVHNodeArray");
917
918 if (UNLIKELY((!tree->nodes) || (!tree->nodebv) || (!tree->nodechild) || (!tree->nodearray))) {
919 goto fail;
920 }
921
922 /* link the dynamic bv and child links */
923 for (i = 0; i < numnodes; i++) {
924 tree->nodearray[i].bv = &tree->nodebv[i * axis];
925 tree->nodearray[i].children = &tree->nodechild[i * tree_type];
926 }
927 }
928 return tree;
929
930fail:
932 return NULL;
933}
934
936{
937 if (tree) {
938 MEM_SAFE_FREE(tree->nodes);
939 MEM_SAFE_FREE(tree->nodearray);
940 MEM_SAFE_FREE(tree->nodebv);
941 MEM_SAFE_FREE(tree->nodechild);
943 }
944}
945
947{
948 BVHNode **leafs_array = tree->nodes;
949
950 /* This function should only be called once
951 * (some big bug goes here if its being called more than once per tree) */
952 BLI_assert(tree->branch_num == 0);
953
954 /* Build the implicit tree */
956 tree, tree->nodearray + (tree->leaf_num - 1), leafs_array, tree->leaf_num);
957
958 /* current code expects the branches to be linked to the nodes array
959 * we perform that linkage here */
960 tree->branch_num = implicit_needed_branches(tree->tree_type, tree->leaf_num);
961 for (int i = 0; i < tree->branch_num; i++) {
962 tree->nodes[tree->leaf_num + i] = &tree->nodearray[tree->leaf_num + i];
963 }
964
965#ifdef USE_SKIP_LINKS
966 build_skip_links(tree, tree->nodes[tree->leaf_num], NULL, NULL);
967#endif
968
969#ifdef USE_VERIFY_TREE
970 bvhtree_verify(tree);
971#endif
972
973#ifdef USE_PRINT_TREE
974 bvhtree_info(tree);
975#endif
976}
977
978static void bvhtree_node_inflate(const BVHTree *tree, BVHNode *node, const float dist)
979{
980 axis_t axis_iter;
981 for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) {
982 float dist_corrected = dist * bvhtree_kdop_axes_length[axis_iter];
983 node->bv[(2 * axis_iter)] -= dist_corrected; /* minimum */
984 node->bv[(2 * axis_iter) + 1] += dist_corrected; /* maximum */
985 }
986}
987
988void BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints)
989{
990 BVHNode *node = NULL;
991
992 /* insert should only possible as long as tree->branch_num is 0 */
993 BLI_assert(tree->branch_num <= 0);
994 BLI_assert((size_t)tree->leaf_num < MEM_allocN_len(tree->nodes) / sizeof(*(tree->nodes)));
995
996 node = tree->nodes[tree->leaf_num] = &(tree->nodearray[tree->leaf_num]);
997 tree->leaf_num++;
998
999 create_kdop_hull(tree, node, co, numpoints, 0);
1000 node->index = index;
1001
1002 /* inflate the bv with some epsilon */
1003 bvhtree_node_inflate(tree, node, tree->epsilon);
1004}
1005
1007 BVHTree *tree, int index, const float co[3], const float co_moving[3], int numpoints)
1008{
1009 BVHNode *node = NULL;
1010
1011 /* check if index exists */
1012 if (index > tree->leaf_num) {
1013 return false;
1014 }
1015
1016 node = tree->nodearray + index;
1017
1018 create_kdop_hull(tree, node, co, numpoints, 0);
1019
1020 if (co_moving) {
1021 create_kdop_hull(tree, node, co_moving, numpoints, 1);
1022 }
1023
1024 /* inflate the bv with some epsilon */
1025 bvhtree_node_inflate(tree, node, tree->epsilon);
1026
1027 return true;
1028}
1029
1031{
1032 /* Update bottom=>top
1033 * TRICKY: the way we build the tree all the children have an index greater than the parent
1034 * This allows us todo a bottom up update by starting on the bigger numbered branch. */
1035
1036 BVHNode **root = tree->nodes + tree->leaf_num;
1037 BVHNode **index = tree->nodes + tree->leaf_num + tree->branch_num - 1;
1038
1039 for (; index >= root; index--) {
1040 node_join(tree, *index);
1041 }
1042}
1044{
1045 return tree->leaf_num;
1046}
1047
1049{
1050 return tree->tree_type;
1051}
1052
1054{
1055 return tree->epsilon;
1056}
1057
1058void BLI_bvhtree_get_bounding_box(const BVHTree *tree, float r_bb_min[3], float r_bb_max[3])
1059{
1060 const BVHNode *root = tree->nodes[tree->leaf_num];
1061 if (root != NULL) {
1062 const float bb_min[3] = {root->bv[0], root->bv[2], root->bv[4]};
1063 const float bb_max[3] = {root->bv[1], root->bv[3], root->bv[5]};
1064 copy_v3_v3(r_bb_min, bb_min);
1065 copy_v3_v3(r_bb_max, bb_max);
1066 }
1067 else {
1068 BLI_assert(false);
1069 zero_v3(r_bb_min);
1070 zero_v3(r_bb_max);
1071 }
1072}
1073
1076/* -------------------------------------------------------------------- */
1083static bool tree_overlap_test(const BVHNode *node1,
1084 const BVHNode *node2,
1085 axis_t start_axis,
1086 axis_t stop_axis)
1087{
1088 const float *bv1 = node1->bv + (start_axis << 1);
1089 const float *bv2 = node2->bv + (start_axis << 1);
1090 const float *bv1_end = node1->bv + (stop_axis << 1);
1091
1092 /* test all axis if min + max overlap */
1093 for (; bv1 != bv1_end; bv1 += 2, bv2 += 2) {
1094 if ((bv1[0] > bv2[1]) || (bv2[0] > bv1[1])) {
1095 return 0;
1096 }
1097 }
1098
1099 return 1;
1100}
1101
1103 const BVHNode *node1,
1104 const BVHNode *node2)
1105{
1106 const BVHOverlapData_Shared *data = data_thread->shared;
1107 int j;
1108
1109 if (tree_overlap_test(node1, node2, data->start_axis, data->stop_axis)) {
1110 /* check if node1 is a leaf */
1111 if (!node1->node_num) {
1112 /* check if node2 is a leaf */
1113 if (!node2->node_num) {
1114 BVHTreeOverlap *overlap;
1115
1116 if (UNLIKELY(node1 == node2)) {
1117 return;
1118 }
1119
1120 /* both leafs, insert overlap! */
1121 overlap = BLI_stack_push_r(data_thread->overlap);
1122 overlap->indexA = node1->index;
1123 overlap->indexB = node2->index;
1124 }
1125 else {
1126 for (j = 0; j < data->tree2->tree_type; j++) {
1127 if (node2->children[j]) {
1128 tree_overlap_traverse(data_thread, node1, node2->children[j]);
1129 }
1130 }
1131 }
1132 }
1133 else {
1134 for (j = 0; j < data->tree1->tree_type; j++) {
1135 if (node1->children[j]) {
1136 tree_overlap_traverse(data_thread, node1->children[j], node2);
1137 }
1138 }
1139 }
1140 }
1141}
1142
1147 const BVHNode *node1,
1148 const BVHNode *node2)
1149{
1150 BVHOverlapData_Shared *data = data_thread->shared;
1151 int j;
1152
1153 if (tree_overlap_test(node1, node2, data->start_axis, data->stop_axis)) {
1154 /* check if node1 is a leaf */
1155 if (!node1->node_num) {
1156 /* check if node2 is a leaf */
1157 if (!node2->node_num) {
1158 BVHTreeOverlap *overlap;
1159
1160 if (UNLIKELY(node1 == node2)) {
1161 return;
1162 }
1163
1164 /* only difference to tree_overlap_traverse! */
1165 if (data->callback(data->userdata, node1->index, node2->index, data_thread->thread)) {
1166 /* both leafs, insert overlap! */
1167 overlap = BLI_stack_push_r(data_thread->overlap);
1168 overlap->indexA = node1->index;
1169 overlap->indexB = node2->index;
1170 }
1171 }
1172 else {
1173 for (j = 0; j < data->tree2->tree_type; j++) {
1174 if (node2->children[j]) {
1175 tree_overlap_traverse_cb(data_thread, node1, node2->children[j]);
1176 }
1177 }
1178 }
1179 }
1180 else {
1181 for (j = 0; j < data->tree1->tree_type; j++) {
1182 if (node1->children[j]) {
1183 tree_overlap_traverse_cb(data_thread, node1->children[j], node2);
1184 }
1185 }
1186 }
1187 }
1188}
1189
1194 const BVHNode *node1,
1195 const BVHNode *node2)
1196{
1197 BVHOverlapData_Shared *data = data_thread->shared;
1198 int j;
1199
1200 if (tree_overlap_test(node1, node2, data->start_axis, data->stop_axis)) {
1201 /* check if node1 is a leaf */
1202 if (!node1->node_num) {
1203 /* check if node2 is a leaf */
1204 if (!node2->node_num) {
1205 BVHTreeOverlap *overlap;
1206
1207 if (UNLIKELY(node1 == node2)) {
1208 return false;
1209 }
1210
1211 /* only difference to tree_overlap_traverse! */
1212 if (!data->callback ||
1213 data->callback(data->userdata, node1->index, node2->index, data_thread->thread))
1214 {
1215 /* both leafs, insert overlap! */
1216 if (data_thread->overlap) {
1217 overlap = BLI_stack_push_r(data_thread->overlap);
1218 overlap->indexA = node1->index;
1219 overlap->indexB = node2->index;
1220 }
1221 return (--data_thread->max_interactions) == 0;
1222 }
1223 }
1224 else {
1225 for (j = 0; j < node2->node_num; j++) {
1226 if (tree_overlap_traverse_num(data_thread, node1, node2->children[j])) {
1227 return true;
1228 }
1229 }
1230 }
1231 }
1232 else {
1233 const uint max_interactions = data_thread->max_interactions;
1234 for (j = 0; j < node1->node_num; j++) {
1235 if (tree_overlap_traverse_num(data_thread, node1->children[j], node2)) {
1236 data_thread->max_interactions = max_interactions;
1237 }
1238 }
1239 }
1240 }
1241 return false;
1242}
1243
1246 const BVHNode *node1,
1247 const BVHNode *node2)
1248{
1249 if (data->max_interactions) {
1250 tree_overlap_traverse_num(data, node1, node2);
1251 }
1252 else if (data->shared->callback) {
1253 tree_overlap_traverse_cb(data, node1, node2);
1254 }
1255 else {
1256 tree_overlap_traverse(data, node1, node2);
1257 }
1258}
1259
1262{
1263 for (int i = 0; i < node->node_num; i++) {
1264 /* Recursively compute self-overlap within each child. */
1265 tree_overlap_traverse_self_cb(data_thread, node->children[i]);
1266
1267 /* Compute overlap of pairs of children, testing each one only once (assume symmetry). */
1268 for (int j = i + 1; j < node->node_num; j++) {
1269 tree_overlap_traverse_cb(data_thread, node->children[i], node->children[j]);
1270 }
1271 }
1272}
1273
1275static void tree_overlap_traverse_self(BVHOverlapData_Thread *data_thread, const BVHNode *node)
1276{
1277 for (int i = 0; i < node->node_num; i++) {
1278 /* Recursively compute self-overlap within each child. */
1279 tree_overlap_traverse_self(data_thread, node->children[i]);
1280
1281 /* Compute overlap of pairs of children, testing each one only once (assume symmetry). */
1282 for (int j = i + 1; j < node->node_num; j++) {
1283 tree_overlap_traverse(data_thread, node->children[i], node->children[j]);
1284 }
1285 }
1286}
1287
1290 const BVHNode *node)
1291{
1292 if (data_thread->shared->callback) {
1293 tree_overlap_traverse_self_cb(data_thread, node);
1294 }
1295 else {
1296 tree_overlap_traverse_self(data_thread, node);
1297 }
1298}
1299
1301{
1302 return (int)MIN2(tree->tree_type, tree->nodes[tree->leaf_num]->node_num);
1303}
1304
1305static void bvhtree_overlap_task_cb(void *__restrict userdata,
1306 const int j,
1307 const TaskParallelTLS *__restrict UNUSED(tls))
1308{
1309 BVHOverlapData_Thread *data = &((BVHOverlapData_Thread *)userdata)[j];
1310 BVHOverlapData_Shared *data_shared = data->shared;
1311
1312 const BVHNode *root1 = data_shared->tree1->nodes[data_shared->tree1->leaf_num];
1313
1314 if (data_shared->use_self) {
1315 /* This code matches one outer loop iteration within traverse_self. */
1317
1318 for (int k = j + 1; k < root1->node_num; k++) {
1319 tree_overlap_invoke_traverse(data, root1->children[j], root1->children[k]);
1320 }
1321 }
1322 else {
1323 const BVHNode *root2 = data_shared->tree2->nodes[data_shared->tree2->leaf_num];
1324
1325 tree_overlap_invoke_traverse(data, root1->children[j], root2);
1326 }
1327}
1328
1330 const BVHTree *tree1,
1331 const BVHTree *tree2,
1332 uint *r_overlap_num,
1333 /* optional callback to test the overlap before adding (must be thread-safe!) */
1335 void *userdata,
1336 const uint max_interactions,
1337 const int flag)
1338{
1339 bool overlap_pairs = (flag & BVH_OVERLAP_RETURN_PAIRS) != 0;
1340 bool use_threading = (flag & BVH_OVERLAP_USE_THREADING) != 0 &&
1342 bool use_self = (flag & BVH_OVERLAP_SELF) != 0;
1343
1344 /* 'RETURN_PAIRS' was not implemented without 'max_interactions'. */
1345 BLI_assert(overlap_pairs || max_interactions);
1346 /* Self-overlap does not support max interactions (it's not symmetrical). */
1347 BLI_assert(!use_self || (tree1 == tree2 && !max_interactions));
1348
1349 const int root_node_len = BLI_bvhtree_overlap_thread_num(tree1);
1350 const int thread_num = use_threading ? root_node_len : 1;
1351 int j;
1352 size_t total = 0;
1353 BVHTreeOverlap *overlap = NULL, *to = NULL;
1354 BVHOverlapData_Shared data_shared;
1355 BVHOverlapData_Thread *data = BLI_array_alloca(data, (size_t)thread_num);
1356 axis_t start_axis, stop_axis;
1357
1358 /* check for compatibility of both trees (can't compare 14-DOP with 18-DOP) */
1359 if (UNLIKELY((tree1->axis != tree2->axis) && (tree1->axis == 14 || tree2->axis == 14) &&
1360 (tree1->axis == 18 || tree2->axis == 18)))
1361 {
1362 BLI_assert(0);
1363 return NULL;
1364 }
1365
1366 if (UNLIKELY(use_self && tree1 != tree2)) {
1367 use_self = false;
1368 }
1369
1370 const BVHNode *root1 = tree1->nodes[tree1->leaf_num];
1371 const BVHNode *root2 = tree2->nodes[tree2->leaf_num];
1372
1373 start_axis = min_axis(tree1->start_axis, tree2->start_axis);
1374 stop_axis = min_axis(tree1->stop_axis, tree2->stop_axis);
1375
1376 /* fast check root nodes for collision before doing big splitting + traversal */
1377 if (!tree_overlap_test(root1, root2, start_axis, stop_axis)) {
1378 return NULL;
1379 }
1380
1381 data_shared.tree1 = tree1;
1382 data_shared.tree2 = tree2;
1383 data_shared.start_axis = start_axis;
1384 data_shared.stop_axis = stop_axis;
1385 data_shared.use_self = use_self;
1386
1387 /* can be NULL */
1388 data_shared.callback = callback;
1389 data_shared.userdata = userdata;
1390
1391 for (j = 0; j < thread_num; j++) {
1392 /* init BVHOverlapData_Thread */
1393 data[j].shared = &data_shared;
1394 data[j].overlap = overlap_pairs ? BLI_stack_new(sizeof(BVHTreeOverlap), __func__) : NULL;
1395 data[j].max_interactions = use_self ? 0 : max_interactions;
1396
1397 /* for callback */
1398 data[j].thread = j;
1399 }
1400
1401 if (use_threading) {
1402 TaskParallelSettings settings;
1404 settings.min_iter_per_thread = 1;
1405 BLI_task_parallel_range(0, root_node_len, data, bvhtree_overlap_task_cb, &settings);
1406 }
1407 else if (use_self) {
1409 }
1410 else {
1411 tree_overlap_invoke_traverse(data, root1, root2);
1412 }
1413
1414 if (overlap_pairs) {
1415 for (j = 0; j < thread_num; j++) {
1416 total += BLI_stack_count(data[j].overlap);
1417 }
1418
1419 to = overlap = MEM_mallocN(sizeof(BVHTreeOverlap) * total, "BVHTreeOverlap");
1420
1421 for (j = 0; j < thread_num; j++) {
1422 uint count = (uint)BLI_stack_count(data[j].overlap);
1423 BLI_stack_pop_n(data[j].overlap, to, count);
1424 BLI_stack_free(data[j].overlap);
1425 to += count;
1426 }
1427 *r_overlap_num = (uint)total;
1428 }
1429
1430 return overlap;
1431}
1432
1434 const BVHTree *tree1,
1435 const BVHTree *tree2,
1436 uint *r_overlap_num,
1437 /* optional callback to test the overlap before adding (must be thread-safe!) */
1439 void *userdata)
1440{
1441 return BLI_bvhtree_overlap_ex(tree1,
1442 tree2,
1443 r_overlap_num,
1444 callback,
1445 userdata,
1446 0,
1448}
1449
1451 const BVHTree *tree,
1452 uint *r_overlap_num,
1453 /* optional callback to test the overlap before adding (must be thread-safe!) */
1455 void *userdata)
1456{
1458 tree,
1459 r_overlap_num,
1460 callback,
1461 userdata,
1462 0,
1465}
1466
1469/* -------------------------------------------------------------------- */
1473static bool tree_intersect_plane_test(const float *bv, const float plane[4])
1474{
1475 /* TODO(@germano): Support other KDOP geometries. */
1476 const float bb_min[3] = {bv[0], bv[2], bv[4]};
1477 const float bb_max[3] = {bv[1], bv[3], bv[5]};
1478 float bb_near[3], bb_far[3];
1479 aabb_get_near_far_from_plane(plane, bb_min, bb_max, bb_near, bb_far);
1480 if ((plane_point_side_v3(plane, bb_near) > 0.0f) != (plane_point_side_v3(plane, bb_far) > 0.0f))
1481 {
1482 return true;
1483 }
1484
1485 return false;
1486}
1487
1489 const BVHNode *node)
1490{
1491 if (tree_intersect_plane_test(node->bv, data->plane)) {
1492 /* check if node is a leaf */
1493 if (!node->node_num) {
1494 int *intersect = BLI_stack_push_r(data->intersect);
1495 *intersect = node->index;
1496 }
1497 else {
1498 for (int j = 0; j < data->tree->tree_type; j++) {
1499 if (node->children[j]) {
1500 bvhtree_intersect_plane_dfs_recursive(data, node->children[j]);
1501 }
1502 }
1503 }
1504 }
1505}
1506
1507int *BLI_bvhtree_intersect_plane(const BVHTree *tree, float plane[4], uint *r_intersect_num)
1508{
1509 int *intersect = NULL;
1510 size_t total = 0;
1511
1512 if (tree->leaf_num) {
1514 data.tree = tree;
1515 copy_v4_v4(data.plane, plane);
1516 data.intersect = BLI_stack_new(sizeof(int), __func__);
1517
1518 const BVHNode *root = tree->nodes[tree->leaf_num];
1520
1521 total = BLI_stack_count(data.intersect);
1522 if (total) {
1523 intersect = MEM_mallocN(sizeof(int) * total, __func__);
1524 BLI_stack_pop_n(data.intersect, intersect, (uint)total);
1525 }
1526 BLI_stack_free(data.intersect);
1527 }
1528 *r_intersect_num = (uint)total;
1529 return intersect;
1530}
1531
1534/* -------------------------------------------------------------------- */
1538/* Determines the nearest point of the given node BV.
1539 * Returns the squared distance to that point. */
1540static float calc_nearest_point_squared(const float proj[3], BVHNode *node, float nearest[3])
1541{
1542 int i;
1543 const float *bv = node->bv;
1544
1545 /* nearest on AABB hull */
1546 for (i = 0; i != 3; i++, bv += 2) {
1547 float val = proj[i];
1548 if (bv[0] > val) {
1549 val = bv[0];
1550 }
1551 if (bv[1] < val) {
1552 val = bv[1];
1553 }
1554 nearest[i] = val;
1555 }
1556
1557 return len_squared_v3v3(proj, nearest);
1558}
1559
1560/* Depth first search method */
1562{
1563 if (node->node_num == 0) {
1564 if (data->callback) {
1565 data->callback(data->userdata, node->index, data->co, &data->nearest);
1566 }
1567 else {
1568 data->nearest.index = node->index;
1569 data->nearest.dist_sq = calc_nearest_point_squared(data->proj, node, data->nearest.co);
1570 }
1571 }
1572 else {
1573 /* Better heuristic to pick the closest node to dive on */
1574 int i;
1575 float nearest[3];
1576
1577 if (data->proj[node->main_axis] <= node->children[0]->bv[node->main_axis * 2 + 1]) {
1578
1579 for (i = 0; i != node->node_num; i++) {
1580 if (calc_nearest_point_squared(data->proj, node->children[i], nearest) >=
1581 data->nearest.dist_sq)
1582 {
1583 continue;
1584 }
1585 dfs_find_nearest_dfs(data, node->children[i]);
1586 }
1587 }
1588 else {
1589 for (i = node->node_num - 1; i >= 0; i--) {
1590 if (calc_nearest_point_squared(data->proj, node->children[i], nearest) >=
1591 data->nearest.dist_sq)
1592 {
1593 continue;
1594 }
1595 dfs_find_nearest_dfs(data, node->children[i]);
1596 }
1597 }
1598 }
1599}
1600
1602{
1603 float nearest[3], dist_sq;
1604 dist_sq = calc_nearest_point_squared(data->proj, node, nearest);
1605 if (dist_sq >= data->nearest.dist_sq) {
1606 return;
1607 }
1608 dfs_find_nearest_dfs(data, node);
1609}
1610
1611/* Priority queue method */
1613{
1614 if (node->node_num == 0) {
1615 if (data->callback) {
1616 data->callback(data->userdata, node->index, data->co, &data->nearest);
1617 }
1618 else {
1619 data->nearest.index = node->index;
1620 data->nearest.dist_sq = calc_nearest_point_squared(data->proj, node, data->nearest.co);
1621 }
1622 }
1623 else {
1624 float nearest[3];
1625
1626 for (int i = 0; i != node->node_num; i++) {
1627 float dist_sq = calc_nearest_point_squared(data->proj, node->children[i], nearest);
1628
1629 if (dist_sq < data->nearest.dist_sq) {
1630 BLI_heapsimple_insert(heap, dist_sq, node->children[i]);
1631 }
1632 }
1633 }
1634}
1635
1637{
1638 float nearest[3];
1639 float dist_sq = calc_nearest_point_squared(data->proj, root, nearest);
1640
1641 if (dist_sq < data->nearest.dist_sq) {
1643
1644 heap_find_nearest_inner(data, heap, root);
1645
1646 while (!BLI_heapsimple_is_empty(heap) &&
1647 BLI_heapsimple_top_value(heap) < data->nearest.dist_sq)
1648 {
1649 BVHNode *node = BLI_heapsimple_pop_min(heap);
1650 heap_find_nearest_inner(data, heap, node);
1651 }
1652
1654 }
1655}
1656
1658 const float co[3],
1659 BVHTreeNearest *nearest,
1661 void *userdata,
1662 int flag)
1663{
1664 axis_t axis_iter;
1665
1667 BVHNode *root = tree->nodes[tree->leaf_num];
1668
1669 /* init data to search */
1670 data.tree = tree;
1671 data.co = co;
1672
1673 data.callback = callback;
1674 data.userdata = userdata;
1675
1676 for (axis_iter = data.tree->start_axis; axis_iter != data.tree->stop_axis; axis_iter++) {
1677 data.proj[axis_iter] = dot_v3v3(data.co, bvhtree_kdop_axes[axis_iter]);
1678 }
1679
1680 if (nearest) {
1681 memcpy(&data.nearest, nearest, sizeof(*nearest));
1682 }
1683 else {
1684 data.nearest.index = -1;
1685 data.nearest.dist_sq = FLT_MAX;
1686 }
1687
1688 /* dfs search */
1689 if (root) {
1691 heap_find_nearest_begin(&data, root);
1692 }
1693 else {
1694 dfs_find_nearest_begin(&data, root);
1695 }
1696 }
1697
1698 /* copy back results */
1699 if (nearest) {
1700 memcpy(nearest, &data.nearest, sizeof(*nearest));
1701 }
1702
1703 return data.nearest.index;
1704}
1705
1707 const float co[3],
1708 BVHTreeNearest *nearest,
1710 void *userdata)
1711{
1712 return BLI_bvhtree_find_nearest_ex(tree, co, nearest, callback, userdata, 0);
1713}
1714
1717/* -------------------------------------------------------------------- */
1721static bool isect_aabb_v3(BVHNode *node, const float co[3])
1722{
1723 const BVHTreeAxisRange *bv = (const BVHTreeAxisRange *)node->bv;
1724
1725 if (co[0] > bv[0].min && co[0] < bv[0].max && co[1] > bv[1].min && co[1] < bv[1].max &&
1726 co[2] > bv[2].min && co[2] < bv[2].max)
1727 {
1728 return true;
1729 }
1730
1731 return false;
1732}
1733
1735{
1736 if (node->node_num == 0) {
1737 if (isect_aabb_v3(node, data->co)) {
1738 if (data->callback) {
1739 const float dist_sq = data->nearest.dist_sq;
1740 data->callback(data->userdata, node->index, data->co, &data->nearest);
1741 return (data->nearest.dist_sq < dist_sq);
1742 }
1743 data->nearest.index = node->index;
1744 return true;
1745 }
1746 }
1747 else {
1748 /* Better heuristic to pick the closest node to dive on */
1749 int i;
1750
1751 if (data->proj[node->main_axis] <= node->children[0]->bv[node->main_axis * 2 + 1]) {
1752 for (i = 0; i != node->node_num; i++) {
1753 if (isect_aabb_v3(node->children[i], data->co)) {
1754 if (dfs_find_duplicate_fast_dfs(data, node->children[i])) {
1755 return true;
1756 }
1757 }
1758 }
1759 }
1760 else {
1761 for (i = node->node_num; i--;) {
1762 if (isect_aabb_v3(node->children[i], data->co)) {
1763 if (dfs_find_duplicate_fast_dfs(data, node->children[i])) {
1764 return true;
1765 }
1766 }
1767 }
1768 }
1769 }
1770 return false;
1771}
1772
1774 const float co[3],
1775 const float dist_sq,
1777 void *userdata)
1778{
1780 BVHNode *root = tree->nodes[tree->leaf_num];
1781
1782 /* init data to search */
1783 data.tree = tree;
1784 data.co = co;
1785
1786 data.callback = callback;
1787 data.userdata = userdata;
1788 data.nearest.index = -1;
1789 data.nearest.dist_sq = dist_sq;
1790
1791 /* dfs search */
1792 if (root) {
1793 dfs_find_duplicate_fast_dfs(&data, root);
1794 }
1795
1796 return data.nearest.index;
1797}
1798
1801/* -------------------------------------------------------------------- */
1808/* Determines the distance that the ray must travel to hit the bounding volume of the given node */
1809static float ray_nearest_hit(const BVHRayCastData *data, const float bv[6])
1810{
1811 int i;
1812
1813 float low = 0, upper = data->hit.dist;
1814
1815 for (i = 0; i != 3; i++, bv += 2) {
1816 if (data->ray_dot_axis[i] == 0.0f) {
1817 /* axis aligned ray */
1818 if (data->ray.origin[i] < bv[0] - data->ray.radius ||
1819 data->ray.origin[i] > bv[1] + data->ray.radius)
1820 {
1821 return FLT_MAX;
1822 }
1823 }
1824 else {
1825 float ll = (bv[0] - data->ray.radius - data->ray.origin[i]) / data->ray_dot_axis[i];
1826 float lu = (bv[1] + data->ray.radius - data->ray.origin[i]) / data->ray_dot_axis[i];
1827
1828 if (data->ray_dot_axis[i] > 0.0f) {
1829 if (ll > low) {
1830 low = ll;
1831 }
1832 if (lu < upper) {
1833 upper = lu;
1834 }
1835 }
1836 else {
1837 if (lu > low) {
1838 low = lu;
1839 }
1840 if (ll < upper) {
1841 upper = ll;
1842 }
1843 }
1844
1845 if (low > upper) {
1846 return FLT_MAX;
1847 }
1848 }
1849 }
1850 return low;
1851}
1852
1859static float fast_ray_nearest_hit(const BVHRayCastData *data, const BVHNode *node)
1860{
1861 const float *bv = node->bv;
1862
1863 float t1x = (bv[data->index[0]] - data->ray.origin[0]) * data->idot_axis[0];
1864 float t2x = (bv[data->index[1]] - data->ray.origin[0]) * data->idot_axis[0];
1865 float t1y = (bv[data->index[2]] - data->ray.origin[1]) * data->idot_axis[1];
1866 float t2y = (bv[data->index[3]] - data->ray.origin[1]) * data->idot_axis[1];
1867 float t1z = (bv[data->index[4]] - data->ray.origin[2]) * data->idot_axis[2];
1868 float t2z = (bv[data->index[5]] - data->ray.origin[2]) * data->idot_axis[2];
1869
1870 if ((t1x > t2y || t2x < t1y || t1x > t2z || t2x < t1z || t1y > t2z || t2y < t1z) ||
1871 (t2x < 0.0f || t2y < 0.0f || t2z < 0.0f) ||
1872 (t1x > data->hit.dist || t1y > data->hit.dist || t1z > data->hit.dist))
1873 {
1874 return FLT_MAX;
1875 }
1876 return max_fff(t1x, t1y, t1z);
1877}
1878
1879static void dfs_raycast(BVHRayCastData *data, BVHNode *node)
1880{
1881 int i;
1882
1883 /* ray-bv is really fast.. and simple tests revealed its worth to test it
1884 * before calling the ray-primitive functions */
1885 /* XXX: temporary solution for particles until fast_ray_nearest_hit supports ray.radius */
1886 float dist = (data->ray.radius == 0.0f) ? fast_ray_nearest_hit(data, node) :
1887 ray_nearest_hit(data, node->bv);
1888 if (dist >= data->hit.dist) {
1889 return;
1890 }
1891
1892 if (node->node_num == 0) {
1893 if (data->callback) {
1894 data->callback(data->userdata, node->index, &data->ray, &data->hit);
1895 }
1896 else {
1897 data->hit.index = node->index;
1898 data->hit.dist = dist;
1899 madd_v3_v3v3fl(data->hit.co, data->ray.origin, data->ray.direction, dist);
1900 }
1901 }
1902 else {
1903 /* pick loop direction to dive into the tree (based on ray direction and split axis) */
1904 if (data->ray_dot_axis[node->main_axis] > 0.0f) {
1905 for (i = 0; i != node->node_num; i++) {
1906 dfs_raycast(data, node->children[i]);
1907 }
1908 }
1909 else {
1910 for (i = node->node_num - 1; i >= 0; i--) {
1911 dfs_raycast(data, node->children[i]);
1912 }
1913 }
1914 }
1915}
1916
1920static void dfs_raycast_all(BVHRayCastData *data, BVHNode *node)
1921{
1922 int i;
1923
1924 /* ray-bv is really fast.. and simple tests revealed its worth to test it
1925 * before calling the ray-primitive functions */
1926 /* XXX: temporary solution for particles until fast_ray_nearest_hit supports ray.radius */
1927 float dist = (data->ray.radius == 0.0f) ? fast_ray_nearest_hit(data, node) :
1928 ray_nearest_hit(data, node->bv);
1929 if (dist >= data->hit.dist) {
1930 return;
1931 }
1932
1933 if (node->node_num == 0) {
1934 /* no need to check for 'data->callback' (using 'all' only makes sense with a callback). */
1935 dist = data->hit.dist;
1936 data->callback(data->userdata, node->index, &data->ray, &data->hit);
1937 data->hit.index = -1;
1938 data->hit.dist = dist;
1939 }
1940 else {
1941 /* pick loop direction to dive into the tree (based on ray direction and split axis) */
1942 if (data->ray_dot_axis[node->main_axis] > 0.0f) {
1943 for (i = 0; i != node->node_num; i++) {
1944 dfs_raycast_all(data, node->children[i]);
1945 }
1946 }
1947 else {
1948 for (i = node->node_num - 1; i >= 0; i--) {
1949 dfs_raycast_all(data, node->children[i]);
1950 }
1951 }
1952 }
1953}
1954
1956{
1957 int i;
1958
1959 for (i = 0; i < 3; i++) {
1960 data->ray_dot_axis[i] = dot_v3v3(data->ray.direction, bvhtree_kdop_axes[i]);
1961
1962 if (fabsf(data->ray_dot_axis[i]) < FLT_EPSILON) {
1963 data->ray_dot_axis[i] = 0.0f;
1964 /* Sign is not important in this case, `data->index` is adjusted anyway. */
1965 data->idot_axis[i] = FLT_MAX;
1966 }
1967 else {
1968 data->idot_axis[i] = 1.0f / data->ray_dot_axis[i];
1969 }
1970
1971 data->index[2 * i] = data->idot_axis[i] < 0.0f ? 1 : 0;
1972 data->index[2 * i + 1] = 1 - data->index[2 * i];
1973 data->index[2 * i] += 2 * i;
1974 data->index[2 * i + 1] += 2 * i;
1975 }
1976
1977#ifdef USE_KDOPBVH_WATERTIGHT
1979 isect_ray_tri_watertight_v3_precalc(&data->isect_precalc, data->ray.direction);
1980 data->ray.isect_precalc = &data->isect_precalc;
1981 }
1982 else {
1983 data->ray.isect_precalc = NULL;
1984 }
1985#else
1987#endif
1988}
1989
1991 const float co[3],
1992 const float dir[3],
1993 float radius,
1994 BVHTreeRayHit *hit,
1996 void *userdata,
1997 int flag)
1998{
2000 BVHNode *root = tree->nodes[tree->leaf_num];
2001
2002 BLI_ASSERT_UNIT_V3(dir);
2003
2004 data.tree = tree;
2005
2006 data.callback = callback;
2007 data.userdata = userdata;
2008
2009 copy_v3_v3(data.ray.origin, co);
2010 copy_v3_v3(data.ray.direction, dir);
2011 data.ray.radius = radius;
2012
2014
2015 if (hit) {
2016 memcpy(&data.hit, hit, sizeof(*hit));
2017 }
2018 else {
2019 data.hit.index = -1;
2020 data.hit.dist = BVH_RAYCAST_DIST_MAX;
2021 }
2022
2023 if (root) {
2024 dfs_raycast(&data, root);
2025 // iterative_raycast(&data, root);
2026 }
2027
2028 if (hit) {
2029 memcpy(hit, &data.hit, sizeof(*hit));
2030 }
2031
2032 return data.hit.index;
2033}
2034
2036 const float co[3],
2037 const float dir[3],
2038 float radius,
2039 BVHTreeRayHit *hit,
2041 void *userdata)
2042{
2044 tree, co, dir, radius, hit, callback, userdata, BVH_RAYCAST_DEFAULT);
2045}
2046
2047float BLI_bvhtree_bb_raycast(const float bv[6],
2048 const float light_start[3],
2049 const float light_end[3],
2050 float pos[3])
2051{
2053 float dist;
2054
2056
2057 /* get light direction */
2058 sub_v3_v3v3(data.ray.direction, light_end, light_start);
2059
2060 data.ray.radius = 0.0;
2061
2062 copy_v3_v3(data.ray.origin, light_start);
2063
2064 normalize_v3(data.ray.direction);
2065 copy_v3_v3(data.ray_dot_axis, data.ray.direction);
2066
2067 dist = ray_nearest_hit(&data, bv);
2068
2069 madd_v3_v3v3fl(pos, light_start, data.ray.direction, dist);
2070
2071 return dist;
2072}
2073
2075 const float co[3],
2076 const float dir[3],
2077 float radius,
2078 float hit_dist,
2080 void *userdata,
2081 int flag)
2082{
2084 BVHNode *root = tree->nodes[tree->leaf_num];
2085
2086 BLI_ASSERT_UNIT_V3(dir);
2088
2089 data.tree = tree;
2090
2091 data.callback = callback;
2092 data.userdata = userdata;
2093
2094 copy_v3_v3(data.ray.origin, co);
2095 copy_v3_v3(data.ray.direction, dir);
2096 data.ray.radius = radius;
2097
2099
2100 data.hit.index = -1;
2101 data.hit.dist = hit_dist;
2102
2103 if (root) {
2104 dfs_raycast_all(&data, root);
2105 }
2106}
2107
2109 const float co[3],
2110 const float dir[3],
2111 float radius,
2112 float hit_dist,
2114 void *userdata)
2115{
2117 tree, co, dir, radius, hit_dist, callback, userdata, BVH_RAYCAST_DEFAULT);
2118}
2119
2122/* -------------------------------------------------------------------- */
2131typedef struct RangeQueryData {
2133 const float *center;
2134 float radius_sq; /* squared radius */
2135
2136 int hits;
2137
2141
2142static void dfs_range_query(RangeQueryData *data, BVHNode *node)
2143{
2144 if (node->node_num == 0) {
2145#if 0 /*UNUSED*/
2146 /* Calculate the node min-coords
2147 * (if the node was a point then this is the point coordinates) */
2148 float co[3];
2149 co[0] = node->bv[0];
2150 co[1] = node->bv[2];
2151 co[2] = node->bv[4];
2152#endif
2153 }
2154 else {
2155 int i;
2156 for (i = 0; i != node->node_num; i++) {
2157 float nearest[3];
2158 float dist_sq = calc_nearest_point_squared(data->center, node->children[i], nearest);
2159 if (dist_sq < data->radius_sq) {
2160 /* Its a leaf.. call the callback */
2161 if (node->children[i]->node_num == 0) {
2162 data->hits++;
2163 data->callback(data->userdata, node->children[i]->index, data->center, dist_sq);
2164 }
2165 else {
2166 dfs_range_query(data, node->children[i]);
2167 }
2168 }
2169 }
2170 }
2171}
2172
2174 const float co[3],
2175 float radius,
2177 void *userdata)
2178{
2179 BVHNode *root = tree->nodes[tree->leaf_num];
2180
2182 data.tree = tree;
2183 data.center = co;
2184 data.radius_sq = radius * radius;
2185 data.hits = 0;
2186
2187 data.callback = callback;
2188 data.userdata = userdata;
2189
2190 if (root != NULL) {
2191 float nearest[3];
2192 float dist_sq = calc_nearest_point_squared(data.center, root, nearest);
2193 if (dist_sq < data.radius_sq) {
2194 /* Its a leaf.. call the callback */
2195 if (root->node_num == 0) {
2196 data.hits++;
2197 data.callback(data.userdata, root->index, co, dist_sq);
2198 }
2199 else {
2200 dfs_range_query(&data, root);
2201 }
2202 }
2203 }
2204
2205 return data.hits;
2206}
2207
2210/* -------------------------------------------------------------------- */
2215 const BVHNode *node)
2216{
2217 if (node->node_num == 0) {
2218 if (data->callback) {
2219 data->callback(data->userdata, node->index, &data->precalc, NULL, 0, &data->nearest);
2220 }
2221 else {
2222 data->nearest.index = node->index;
2223 data->nearest.dist_sq = dist_squared_to_projected_aabb(
2224 &data->precalc,
2225 (float[3]){node->bv[0], node->bv[2], node->bv[4]},
2226 (float[3]){node->bv[1], node->bv[3], node->bv[5]},
2227 data->closest_axis);
2228 }
2229 }
2230 else {
2231 /* First pick the closest node to recurse into */
2232 if (data->closest_axis[node->main_axis]) {
2233 for (int i = 0; i != node->node_num; i++) {
2234 const float *bv = node->children[i]->bv;
2235
2236 if (dist_squared_to_projected_aabb(&data->precalc,
2237 (float[3]){bv[0], bv[2], bv[4]},
2238 (float[3]){bv[1], bv[3], bv[5]},
2239 data->closest_axis) <= data->nearest.dist_sq)
2240 {
2241 bvhtree_nearest_projected_dfs_recursive(data, node->children[i]);
2242 }
2243 }
2244 }
2245 else {
2246 for (int i = node->node_num; i--;) {
2247 const float *bv = node->children[i]->bv;
2248
2249 if (dist_squared_to_projected_aabb(&data->precalc,
2250 (float[3]){bv[0], bv[2], bv[4]},
2251 (float[3]){bv[1], bv[3], bv[5]},
2252 data->closest_axis) <= data->nearest.dist_sq)
2253 {
2254 bvhtree_nearest_projected_dfs_recursive(data, node->children[i]);
2255 }
2256 }
2257 }
2258 }
2259}
2260
2262 BVHNearestProjectedData *__restrict data, const BVHNode *node)
2263{
2264 if (node->node_num == 0) {
2265 if (data->callback) {
2266 data->callback(data->userdata,
2267 node->index,
2268 &data->precalc,
2269 data->clip_plane,
2270 data->clip_plane_len,
2271 &data->nearest);
2272 }
2273 else {
2274 data->nearest.index = node->index;
2275 data->nearest.dist_sq = dist_squared_to_projected_aabb(
2276 &data->precalc,
2277 (float[3]){node->bv[0], node->bv[2], node->bv[4]},
2278 (float[3]){node->bv[1], node->bv[3], node->bv[5]},
2279 data->closest_axis);
2280 }
2281 }
2282 else {
2283 /* First pick the closest node to recurse into */
2284 if (data->closest_axis[node->main_axis]) {
2285 for (int i = 0; i != node->node_num; i++) {
2286 const float *bv = node->children[i]->bv;
2287 const float bb_min[3] = {bv[0], bv[2], bv[4]};
2288 const float bb_max[3] = {bv[1], bv[3], bv[5]};
2289
2290 int isect_type = isect_aabb_planes_v3(
2291 data->clip_plane, data->clip_plane_len, bb_min, bb_max);
2292
2293 if ((isect_type != ISECT_AABB_PLANE_BEHIND_ANY) &&
2294 dist_squared_to_projected_aabb(&data->precalc, bb_min, bb_max, data->closest_axis) <=
2295 data->nearest.dist_sq)
2296 {
2297 if (isect_type == ISECT_AABB_PLANE_CROSS_ANY) {
2299 }
2300 else {
2301 /* ISECT_AABB_PLANE_IN_FRONT_ALL */
2302 bvhtree_nearest_projected_dfs_recursive(data, node->children[i]);
2303 }
2304 }
2305 }
2306 }
2307 else {
2308 for (int i = node->node_num; i--;) {
2309 const float *bv = node->children[i]->bv;
2310 const float bb_min[3] = {bv[0], bv[2], bv[4]};
2311 const float bb_max[3] = {bv[1], bv[3], bv[5]};
2312
2313 int isect_type = isect_aabb_planes_v3(
2314 data->clip_plane, data->clip_plane_len, bb_min, bb_max);
2315
2316 if (isect_type != ISECT_AABB_PLANE_BEHIND_ANY &&
2317 dist_squared_to_projected_aabb(&data->precalc, bb_min, bb_max, data->closest_axis) <=
2318 data->nearest.dist_sq)
2319 {
2320 if (isect_type == ISECT_AABB_PLANE_CROSS_ANY) {
2322 }
2323 else {
2324 /* ISECT_AABB_PLANE_IN_FRONT_ALL */
2325 bvhtree_nearest_projected_dfs_recursive(data, node->children[i]);
2326 }
2327 }
2328 }
2329 }
2330 }
2331}
2332
2334 float projmat[4][4],
2335 float winsize[2],
2336 float mval[2],
2337 float (*clip_plane)[4],
2338 int clip_plane_len,
2339 BVHTreeNearest *nearest,
2341 void *userdata)
2342{
2343 const BVHNode *root = tree->nodes[tree->leaf_num];
2344 if (root != NULL) {
2346 sizeof(*data) + (sizeof(*clip_plane) * (size_t)max_ii(1, clip_plane_len)));
2347
2348 dist_squared_to_projected_aabb_precalc(&data->precalc, projmat, winsize, mval);
2349
2350 data->callback = callback;
2351 data->userdata = userdata;
2352
2353 if (clip_plane) {
2354 data->clip_plane_len = clip_plane_len;
2355 for (int i = 0; i < clip_plane_len; i++) {
2356 copy_v4_v4(data->clip_plane[i], clip_plane[i]);
2357 }
2358 }
2359 else {
2360 data->clip_plane_len = 1;
2361 planes_from_projmat(projmat, NULL, NULL, NULL, NULL, data->clip_plane[0], NULL);
2362 }
2363
2364 if (nearest) {
2365 memcpy(&data->nearest, nearest, sizeof(*nearest));
2366 }
2367 else {
2368 data->nearest.index = -1;
2369 data->nearest.dist_sq = FLT_MAX;
2370 }
2371 {
2372 const float bb_min[3] = {root->bv[0], root->bv[2], root->bv[4]};
2373 const float bb_max[3] = {root->bv[1], root->bv[3], root->bv[5]};
2374
2375 int isect_type = isect_aabb_planes_v3(
2376 data->clip_plane, data->clip_plane_len, bb_min, bb_max);
2377
2378 if (isect_type != 0 &&
2379 dist_squared_to_projected_aabb(&data->precalc, bb_min, bb_max, data->closest_axis) <=
2380 data->nearest.dist_sq)
2381 {
2382 if (isect_type == 1) {
2384 }
2385 else {
2387 }
2388 }
2389 }
2390
2391 if (nearest) {
2392 memcpy(nearest, &data->nearest, sizeof(*nearest));
2393 }
2394
2395 return data->nearest.index;
2396 }
2397 return -1;
2398}
2399
#define BLI_array_alloca(arr, realsize)
Definition BLI_alloca.h:25
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_STATIC_ASSERT(a, msg)
Definition BLI_assert.h:87
#define BLI_assert(a)
Definition BLI_assert.h:50
A min-heap / priority queue ADT.
void BLI_heapsimple_free(HeapSimple *heap, HeapSimpleFreeFP ptrfreefp) ATTR_NONNULL(1)
HeapSimple * BLI_heapsimple_new_ex(unsigned int reserve_num) ATTR_WARN_UNUSED_RESULT
float BLI_heapsimple_top_value(const HeapSimple *heap) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void * BLI_heapsimple_pop_min(HeapSimple *heap) ATTR_NONNULL(1)
bool BLI_heapsimple_is_empty(const HeapSimple *heap) ATTR_NONNULL(1)
void BLI_heapsimple_insert(HeapSimple *heap, float value, void *ptr) ATTR_NONNULL(1)
static void bvhtree_nearest_projected_with_clipplane_test_dfs_recursive(BVHNearestProjectedData *__restrict data, const BVHNode *node)
static void dfs_raycast_all(BVHRayCastData *data, BVHNode *node)
BVHTree * BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis)
int * BLI_bvhtree_intersect_plane(const BVHTree *tree, float plane[4], uint *r_intersect_num)
int BLI_bvhtree_find_nearest_first(const BVHTree *tree, const float co[3], const float dist_sq, BVHTree_NearestPointCallback callback, void *userdata)
static void bvhtree_ray_cast_data_precalc(BVHRayCastData *data, int flag)
static void bvhtree_node_inflate(const BVHTree *tree, BVHNode *node, const float dist)
int BLI_bvhtree_get_tree_type(const BVHTree *tree)
void BLI_bvhtree_get_bounding_box(const BVHTree *tree, float r_bb_min[3], float r_bb_max[3])
struct BVHNearestProjectedData BVHNearestProjectedData
struct BVHIntersectPlaneData BVHIntersectPlaneData
struct RangeQueryData RangeQueryData
struct BVHRayCastData BVHRayCastData
static void heap_find_nearest_begin(BVHNearestData *data, BVHNode *root)
static void bvh_insertionsort(BVHNode **a, int lo, int hi, int axis)
#define KDOPBVH_THREAD_LEAF_THRESHOLD
Definition BLI_kdopbvh.c:53
static void non_recursive_bvh_div_nodes(const BVHTree *tree, BVHNode *branches_array, BVHNode **leafs_array, int leafs_num)
static void tree_overlap_traverse_self(BVHOverlapData_Thread *data_thread, const BVHNode *node)
static bool tree_intersect_plane_test(const float *bv, const float plane[4])
static void tree_overlap_traverse_cb(BVHOverlapData_Thread *data_thread, const BVHNode *node1, const BVHNode *node2)
static char get_largest_axis(const float *bv)
const float bvhtree_kdop_axes[13][3]
static void build_implicit_tree_helper(const BVHTree *tree, BVHBuildHelper *data)
static void dfs_find_nearest_begin(BVHNearestData *data, BVHNode *node)
static bool tree_overlap_test(const BVHNode *node1, const BVHNode *node2, axis_t start_axis, axis_t stop_axis)
static bool tree_overlap_traverse_num(BVHOverlapData_Thread *data_thread, const BVHNode *node1, const BVHNode *node2)
void BLI_bvhtree_balance(BVHTree *tree)
static int bvh_partition(BVHNode **a, int lo, int hi, const BVHNode *x, int axis)
static void heap_find_nearest_inner(BVHNearestData *data, HeapSimple *heap, BVHNode *node)
void BLI_bvhtree_update_tree(BVHTree *tree)
uchar axis_t
Definition BLI_kdopbvh.c:62
static bool isect_aabb_v3(BVHNode *node, const float co[3])
MINLINE axis_t min_axis(axis_t a, axis_t b)
int BLI_bvhtree_find_nearest_projected(const BVHTree *tree, float projmat[4][4], float winsize[2], float mval[2], float(*clip_plane)[4], int clip_plane_len, BVHTreeNearest *nearest, BVHTree_NearestProjectedCallback callback, void *userdata)
float BLI_bvhtree_bb_raycast(const float bv[6], const float light_start[3], const float light_end[3], float pos[3])
static void dfs_raycast(BVHRayCastData *data, BVHNode *node)
static float ray_nearest_hit(const BVHRayCastData *data, const float bv[6])
struct BVHOverlapData_Thread BVHOverlapData_Thread
void BLI_bvhtree_ray_cast_all_ex(const BVHTree *tree, const float co[3], const float dir[3], float radius, float hit_dist, BVHTree_RayCastCallback callback, void *userdata, int flag)
struct BVHNearestData BVHNearestData
void BLI_bvhtree_free(BVHTree *tree)
static void dfs_range_query(RangeQueryData *data, BVHNode *node)
static void refit_kdop_hull(const BVHTree *tree, BVHNode *node, int start, int end)
static float fast_ray_nearest_hit(const BVHRayCastData *data, const BVHNode *node)
static bool dfs_find_duplicate_fast_dfs(BVHNearestData *data, BVHNode *node)
void BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints)
static void node_join(BVHTree *tree, BVHNode *node)
BVHTreeOverlap * BLI_bvhtree_overlap(const BVHTree *tree1, const BVHTree *tree2, uint *r_overlap_num, BVHTree_OverlapCallback callback, void *userdata)
static void tree_overlap_traverse_self_cb(BVHOverlapData_Thread *data_thread, const BVHNode *node)
bool BLI_bvhtree_update_node(BVHTree *tree, int index, const float co[3], const float co_moving[3], int numpoints)
static void tree_overlap_traverse(BVHOverlapData_Thread *data_thread, const BVHNode *node1, const BVHNode *node2)
void BLI_bvhtree_ray_cast_all(const BVHTree *tree, const float co[3], const float dir[3], float radius, float hit_dist, BVHTree_RayCastCallback callback, void *userdata)
struct BVHDivNodesData BVHDivNodesData
static void non_recursive_bvh_div_nodes_task_cb(void *__restrict userdata, const int j, const TaskParallelTLS *__restrict UNUSED(tls))
static void node_minmax_init(const BVHTree *tree, BVHNode *node)
int BLI_bvhtree_get_len(const BVHTree *tree)
static const float bvhtree_kdop_axes_length[13]
static void tree_overlap_invoke_traverse(BVHOverlapData_Thread *data, const BVHNode *node1, const BVHNode *node2)
int BLI_bvhtree_overlap_thread_num(const BVHTree *tree)
#define MAX_TREETYPE
Definition BLI_kdopbvh.c:47
static void partition_nth_element(BVHNode **a, int begin, int end, const int n, const int axis)
int BLI_bvhtree_ray_cast_ex(const BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata, int flag)
static void split_leafs(BVHNode **leafs_array, const int nth[], const int partitions, const int split_axis)
BVHTreeOverlap * BLI_bvhtree_overlap_self(const BVHTree *tree, uint *r_overlap_num, BVHTree_OverlapCallback callback, void *userdata)
BVHTreeOverlap * BLI_bvhtree_overlap_ex(const BVHTree *tree1, const BVHTree *tree2, uint *r_overlap_num, BVHTree_OverlapCallback callback, void *userdata, const uint max_interactions, const int flag)
int BLI_bvhtree_find_nearest(const BVHTree *tree, const float co[3], BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata)
static BVHNode * bvh_medianof3(BVHNode **a, int lo, int mid, int hi, int axis)
float BLI_bvhtree_get_epsilon(const BVHTree *tree)
static void bvhtree_nearest_projected_dfs_recursive(BVHNearestProjectedData *__restrict data, const BVHNode *node)
BVHOverlapData_Shared
static float calc_nearest_point_squared(const float proj[3], BVHNode *node, float nearest[3])
struct BVHNode BVHNode
static int implicit_needed_branches(int tree_type, int leafs)
static void dfs_find_nearest_dfs(BVHNearestData *data, BVHNode *node)
int BLI_bvhtree_ray_cast(const BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata)
int BLI_bvhtree_find_nearest_ex(const BVHTree *tree, const float co[3], BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata, int flag)
static void bvhtree_overlap_task_cb(void *__restrict userdata, const int j, const TaskParallelTLS *__restrict UNUSED(tls))
struct BVHBuildHelper BVHBuildHelper
int BLI_bvhtree_range_query(const BVHTree *tree, const float co[3], float radius, BVHTree_RangeQuery callback, void *userdata)
static void create_kdop_hull(const BVHTree *tree, BVHNode *node, const float *co, int numpoints, int moving)
static void bvhtree_intersect_plane_dfs_recursive(BVHIntersectPlaneData *__restrict data, const BVHNode *node)
static int implicit_leafs_index(const BVHBuildHelper *data, const int depth, const int child_index)
static void tree_overlap_invoke_traverse_self(BVHOverlapData_Thread *data_thread, const BVHNode *node)
@ BVH_RAYCAST_WATERTIGHT
Definition BLI_kdopbvh.h:89
@ BVH_OVERLAP_USE_THREADING
Definition BLI_kdopbvh.h:77
@ BVH_OVERLAP_RETURN_PAIRS
Definition BLI_kdopbvh.h:78
@ BVH_OVERLAP_SELF
Definition BLI_kdopbvh.h:81
@ BVH_NEAREST_OPTIMAL_ORDER
Definition BLI_kdopbvh.h:85
#define BVH_RAYCAST_DIST_MAX
Definition BLI_kdopbvh.h:92
#define BVH_RAYCAST_DEFAULT
Definition BLI_kdopbvh.h:91
void(* BVHTree_RayCastCallback)(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
void(* BVHTree_NearestPointCallback)(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
Definition BLI_kdopbvh.h:97
bool(* BVHTree_OverlapCallback)(void *userdata, int index_a, int index_b, int thread)
void(* BVHTree_RangeQuery)(void *userdata, int index, const float co[3], float dist_sq)
void(* BVHTree_NearestProjectedCallback)(void *userdata, int index, const struct DistProjectedAABBPrecalc *precalc, const float(*clip_plane)[4], int clip_plane_len, BVHTreeNearest *nearest)
MINLINE float max_fff(float a, float b, float c)
MINLINE float max_ff(float a, float b)
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
#define BLI_ASSERT_UNIT_V3(v)
void isect_ray_tri_watertight_v3_precalc(struct IsectRayPrecalc *isect_precalc, const float ray_direction[3])
float dist_squared_to_projected_aabb(struct DistProjectedAABBPrecalc *data, const float bbmin[3], const float bbmax[3], bool r_axis_closest[3])
Definition math_geom.cc:856
MINLINE float plane_point_side_v3(const float plane[4], const float co[3])
#define ISECT_AABB_PLANE_CROSS_ANY
#define ISECT_AABB_PLANE_BEHIND_ANY
void dist_squared_to_projected_aabb_precalc(struct DistProjectedAABBPrecalc *precalc, const float projmat[4][4], const float winsize[2], const float mval[2])
Definition math_geom.cc:804
void aabb_get_near_far_from_plane(const float plane_no[3], const float bbmin[3], const float bbmax[3], float bb_near[3], float bb_afar[3])
Definition math_geom.cc:647
int isect_aabb_planes_v3(const float(*planes)[4], int totplane, const float bbmin[3], const float bbmax[3])
void planes_from_projmat(const float mat[4][4], float left[4], float right[4], float bottom[4], float top[4], float near[4], float far[4])
#define MINLINE
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], float f)
MINLINE void zero_v3(float r[3])
MINLINE float normalize_v3(float n[3])
void BLI_stack_pop_n(BLI_Stack *stack, void *dst, unsigned int n) ATTR_NONNULL()
Definition stack.c:146
size_t BLI_stack_count(const BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition stack.c:227
void BLI_stack_free(BLI_Stack *stack) ATTR_NONNULL()
Definition stack.c:96
void * BLI_stack_push_r(BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition stack.c:103
#define BLI_stack_new(esize, descr)
unsigned char uchar
unsigned int uint
void BLI_task_parallel_range(int start, int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition task_range.cc:99
BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings)
Definition BLI_task.h:230
#define UNUSED_VARS(...)
#define SWAP(type, a, b)
#define UNUSED(x)
#define UNLIKELY(x)
#define MIN2(a, b)
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
__forceinline BoundBox intersect(const BoundBox &a, const BoundBox &b)
Definition boundbox.h:178
local_group_size(16, 16) .push_constant(Type b
#define printf
DEGForeachIDComponentCallback callback
#define NULL
#define fabsf(x)
KDTree_3d * tree
draw_view in_light_buf[] float
int count
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
size_t(* MEM_allocN_len)(const void *vmemh)
Definition mallocn.cc:36
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
static int left
#define min(a, b)
Definition sort.c:32
#define FLT_MAX
Definition stdcycles.h:14
int leafs_per_child[32]
int branches_on_level[32]
BVHNode ** leafs_array
const BVHTree * tree
const BVHBuildHelper * data
BVHNode * branches_array
const BVHTree * tree
const BVHTree * tree
const float * co
float proj[13]
BVHTreeNearest nearest
BVHTree_NearestPointCallback callback
struct DistProjectedAABBPrecalc precalc
BVHTree_NearestProjectedCallback callback
BVHTreeNearest nearest
struct BVHNode * parent
Definition BLI_kdopbvh.c:66
struct BVHNode ** children
Definition BLI_kdopbvh.c:65
char node_num
Definition BLI_kdopbvh.c:72
char main_axis
Definition BLI_kdopbvh.c:73
int index
Definition BLI_kdopbvh.c:71
float * bv
Definition BLI_kdopbvh.c:70
BVHOverlapData_Shared * shared
BVHTree_RayCastCallback callback
const BVHTree * tree
float idot_axis[13]
BVHTreeRayHit hit
float ray_dot_axis[13]
BVHTreeRay ray
axis_t axis
Definition BLI_kdopbvh.c:86
float * nodebv
Definition BLI_kdopbvh.c:81
axis_t start_axis
Definition BLI_kdopbvh.c:85
int leaf_num
Definition BLI_kdopbvh.c:83
BVHNode * nodearray
Definition BLI_kdopbvh.c:79
float epsilon
Definition BLI_kdopbvh.c:82
int branch_num
Definition BLI_kdopbvh.c:84
BVHNode ** nodechild
Definition BLI_kdopbvh.c:80
BVHNode ** nodes
Definition BLI_kdopbvh.c:78
axis_t stop_axis
Definition BLI_kdopbvh.c:85
char tree_type
Definition BLI_kdopbvh.c:87
const BVHTree * tree
BVHTree_RangeQuery callback
const float * center
uint8_t flag
Definition wm_window.cc:138