Blender V5.0
BLI_kdopbvh.cc
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
25
26#include <algorithm>
27
28#include "MEM_guardedalloc.h"
29
30#include "BLI_alloca.h"
31#include "BLI_heap_simple.h"
32#include "BLI_kdopbvh.hh"
33#include "BLI_math_geom.h"
35#include "BLI_stack.h"
36#include "BLI_task.h"
37#include "BLI_utildefines.h"
38
39#include "BLI_strict_flags.h" /* IWYU pragma: keep. Keep last. */
40
41/* used for iterative_raycast */
42// #define USE_SKIP_LINKS
43
44/* Use to print balanced output. */
45// #define USE_PRINT_TREE
46
47/* Check tree is valid. */
48// #define USE_VERIFY_TREE
49
50#define MAX_TREETYPE 32
51
52#ifndef NDEBUG
53/* Setting zero so we can catch bugs in BLI_task/KDOPBVH. */
54# define KDOPBVH_THREAD_LEAF_THRESHOLD 0
55#else
56# define KDOPBVH_THREAD_LEAF_THRESHOLD 1024
57#endif
58
59/* -------------------------------------------------------------------- */
62
63using axis_t = uchar;
64
65struct BVHNode {
67 BVHNode *parent; /* some user defined traversed need that */
68#ifdef USE_SKIP_LINKS
69 BVHNode *skip[2];
70#endif
71 float *bv; /* Bounding volume of all nodes, max 13 axis */
72 int index; /* face, edge, vertex index */
73 char node_num; /* how many nodes are used, used for speedup */
74 char main_axis; /* Axis used to split this node */
75};
76
77/* keep under 26 bytes for speed purposes */
78struct BVHTree {
80 BVHNode *nodearray; /* Pre-allocate branch nodes. */
81 BVHNode **nodechild; /* Pre-allocate children for nodes. */
82 float *nodebv; /* Pre-allocate bounding-volumes for nodes. */
83 float epsilon; /* Epsilon is used for inflation of the K-DOP. */
84 int leaf_num; /* Leafs. */
86 axis_t start_axis, stop_axis; /* bvhtree_kdop_axes array indices according to axis */
87 axis_t axis; /* KDOP type (6 => OBB, 7 => AABB, ...) */
88 char tree_type; /* type of tree (4 => quad-tree). */
89};
90
91/* optimization, ensure we stay small */
92BLI_STATIC_ASSERT((sizeof(void *) == 8 && sizeof(BVHTree) <= 48) ||
93 (sizeof(void *) == 4 && sizeof(BVHTree) <= 32),
94 "over sized")
95
96/* avoid duplicating vars in BVHOverlapData_Thread */
97struct BVHOverlapData_Shared {
98 const BVHTree *tree1, *tree2;
99 axis_t start_axis, stop_axis;
100 bool use_self;
101
102 /* use for callbacks */
104 void *userdata;
105};
106
108 BVHOverlapData_Shared *shared;
109 BLI_Stack *overlap; /* store BVHTreeOverlap */
111 /* use for callbacks */
113};
114
116 const BVHTree *tree;
117 const float *co;
119 void *userdata;
120 float proj[13]; /* coordinates projection over axis */
122};
123
125 const BVHTree *tree;
126
128 void *userdata;
129
131
132#ifdef USE_KDOPBVH_WATERTIGHT
133 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
142};
143
154
156 const BVHTree *tree;
157 float plane[4];
158 BLI_Stack *intersect; /* Store indexes. */
159};
160
162
170
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/* -------------------------------------------------------------------- */
207
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
225
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
238
239/* -------------------------------------------------------------------- */
242
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 (true) {
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 bv[2 * axis_iter] = std::min(newminmax, bv[2 * axis_iter]);
364 bv[(2 * axis_iter) + 1] = std::max(newminmax, bv[(2 * axis_iter) + 1]);
365 }
366 }
367}
368
372static void refit_kdop_hull(const BVHTree *tree, BVHNode *node, int start, int end)
373{
374 float newmin, newmax;
375 float *__restrict bv = node->bv;
376 int j;
377 axis_t axis_iter;
378
379 node_minmax_init(tree, node);
380
381 for (j = start; j < end; j++) {
382 const float *__restrict node_bv = tree->nodes[j]->bv;
383
384 /* for all Axes. */
385 for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) {
386 newmin = node_bv[(2 * axis_iter)];
387 bv[(2 * axis_iter)] = std::min(newmin, bv[(2 * axis_iter)]);
388
389 newmax = node_bv[(2 * axis_iter) + 1];
390 bv[(2 * axis_iter) + 1] = std::max(newmax, bv[(2 * axis_iter) + 1]);
391 }
392 }
393}
394
399static char get_largest_axis(const float *bv)
400{
401 float middle_point[3];
402
403 middle_point[0] = (bv[1]) - (bv[0]); /* x axis */
404 middle_point[1] = (bv[3]) - (bv[2]); /* y axis */
405 middle_point[2] = (bv[5]) - (bv[4]); /* z axis */
406 if (middle_point[0] > middle_point[1]) {
407 if (middle_point[0] > middle_point[2]) {
408 return 1; /* max x axis */
409 }
410 return 5; /* max z axis */
411 }
412 if (middle_point[1] > middle_point[2]) {
413 return 3; /* max y axis */
414 }
415 return 5; /* max z axis */
416}
417
422static void node_join(BVHTree *tree, BVHNode *node)
423{
424 int i;
425 axis_t axis_iter;
426
427 node_minmax_init(tree, node);
428
429 for (i = 0; i < tree->tree_type; i++) {
430 if (node->children[i]) {
431 for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) {
432 /* update minimum */
433 node->bv[(2 * axis_iter)] = std::min(node->children[i]->bv[(2 * axis_iter)],
434 node->bv[(2 * axis_iter)]);
435
436 /* update maximum */
437 node->bv[(2 * axis_iter) + 1] = std::max(node->children[i]->bv[(2 * axis_iter) + 1],
438 node->bv[(2 * axis_iter) + 1]);
439 }
440 }
441 else {
442 break;
443 }
444 }
445}
446
447#ifdef USE_PRINT_TREE
448
449/* -------------------------------------------------------------------- */
452
453static void bvhtree_print_tree(BVHTree *tree, BVHNode *node, int depth)
454{
455 int i;
456 axis_t axis_iter;
457
458 for (i = 0; i < depth; i++) {
459 printf(" ");
460 }
461 printf(" - %d (%ld): ", node->index, (long int)(node - tree->nodearray));
462 for (axis_iter = (axis_t)(2 * tree->start_axis); axis_iter < (axis_t)(2 * tree->stop_axis);
463 axis_iter++)
464 {
465 printf("%.3f ", node->bv[axis_iter]);
466 }
467 printf("\n");
468
469 for (i = 0; i < tree->tree_type; i++) {
470 if (node->children[i]) {
471 bvhtree_print_tree(tree, node->children[i], depth + 1);
472 }
473 }
474}
475
476static void bvhtree_info(BVHTree *tree)
477{
478 printf("BVHTree Info: tree_type = %d, axis = %d, epsilon = %f\n",
479 tree->tree_type,
480 tree->axis,
481 tree->epsilon);
482 printf("nodes = %d, branches = %d, leafs = %d\n",
483 tree->branch_num + tree->leaf_num,
484 tree->branch_num,
485 tree->leaf_num);
486 printf("Memory per node = %ubytes\n",
487 uint(sizeof(BVHNode) + sizeof(BVHNode *) * tree->tree_type + sizeof(float) * tree->axis));
488 printf("BV memory = %ubytes\n", uint(MEM_allocN_len(tree->nodebv)));
489
490 printf("Total memory = %ubytes\n",
491 uint(sizeof(BVHTree) + MEM_allocN_len(tree->nodes) + MEM_allocN_len(tree->nodearray) +
492 MEM_allocN_len(tree->nodechild) + MEM_allocN_len(tree->nodebv)));
493
494 bvhtree_print_tree(tree, tree->nodes[tree->leaf_num], 0);
495}
496
498
499#endif /* USE_PRINT_TREE */
500
501#ifdef USE_VERIFY_TREE
502
503static void bvhtree_verify(BVHTree *tree)
504{
505 int i, j, check = 0;
506
507 /* check the pointer list */
508 for (i = 0; i < tree->leaf_num; i++) {
509 if (tree->nodes[i]->parent == nullptr) {
510 printf("Leaf has no parent: %d\n", i);
511 }
512 else {
513 for (j = 0; j < tree->tree_type; j++) {
514 if (tree->nodes[i]->parent->children[j] == tree->nodes[i]) {
515 check = 1;
516 }
517 }
518 if (!check) {
519 printf("Parent child relationship doesn't match: %d\n", i);
520 }
521 check = 0;
522 }
523 }
524
525 /* check the leaf list */
526 for (i = 0; i < tree->leaf_num; i++) {
527 if (tree->nodearray[i].parent == nullptr) {
528 printf("Leaf has no parent: %d\n", i);
529 }
530 else {
531 for (j = 0; j < tree->tree_type; j++) {
532 if (tree->nodearray[i].parent->children[j] == &tree->nodearray[i]) {
533 check = 1;
534 }
535 }
536 if (!check) {
537 printf("Parent child relationship doesn't match: %d\n", i);
538 }
539 check = 0;
540 }
541 }
542
543 printf("branches: %d, leafs: %d, total: %d\n",
544 tree->branch_num,
545 tree->leaf_num,
546 tree->branch_num + tree->leaf_num);
547}
548#endif /* USE_VERIFY_TREE */
549
550/* Helper data and structures to build a min-leaf generalized implicit tree
551 * This code can be easily reduced
552 * (basically this is only method to calculate pow(k, n) in O(1).. and stuff like that) */
565
567{
568 int depth = 0;
569 int remain;
570 int nnodes;
571
572 data->leafs_num = tree->leaf_num;
573 data->tree_type = tree->tree_type;
574
575 /* Calculate the smallest tree_type^n such that tree_type^n >= leafs_num */
576 for (data->leafs_per_child[0] = 1; data->leafs_per_child[0] < data->leafs_num;
577 data->leafs_per_child[0] *= data->tree_type)
578 {
579 /* pass */
580 }
581
582 data->branches_on_level[0] = 1;
583
584 for (depth = 1; (depth < 32) && data->leafs_per_child[depth - 1]; depth++) {
585 data->branches_on_level[depth] = data->branches_on_level[depth - 1] * data->tree_type;
586 data->leafs_per_child[depth] = data->leafs_per_child[depth - 1] / data->tree_type;
587 }
588
589 remain = data->leafs_num - data->leafs_per_child[1];
590 nnodes = (remain + data->tree_type - 2) / (data->tree_type - 1);
591 data->remain_leafs = remain + nnodes;
592}
593
597static int implicit_leafs_index(const BVHBuildHelper *data, const int depth, const int child_index)
598{
599 int min_leaf_index = child_index * data->leafs_per_child[depth - 1];
600 if (min_leaf_index <= data->remain_leafs) {
601 return min_leaf_index;
602 }
603 if (data->leafs_per_child[depth]) {
604 return data->leafs_num -
605 (data->branches_on_level[depth - 1] - child_index) * data->leafs_per_child[depth];
606 }
607 return data->remain_leafs;
608}
609
638
639/* This functions returns the number of branches needed to have the requested number of leafs. */
640static int implicit_needed_branches(int tree_type, int leafs)
641{
642 return max_ii(1, (leafs + tree_type - 3) / (tree_type - 1));
643}
644
657static void split_leafs(BVHNode **leafs_array,
658 const int nth[],
659 const int partitions,
660 const int split_axis)
661{
662 int i;
663 for (i = 0; i < partitions - 1; i++) {
664 if (nth[i] >= nth[partitions]) {
665 break;
666 }
667
668 partition_nth_element(leafs_array, nth[i], nth[partitions], nth[i + 1], split_axis);
669 }
670}
671
686
687static void non_recursive_bvh_div_nodes_task_cb(void *__restrict userdata,
688 const int j,
689 const TaskParallelTLS *__restrict /*tls*/)
690{
691 BVHDivNodesData *data = static_cast<BVHDivNodesData *>(userdata);
692
693 int k;
694 const int parent_level_index = j - data->i;
695 BVHNode *parent = &data->branches_array[j];
696 int nth_positions[MAX_TREETYPE + 1];
697 char split_axis;
698
699 int parent_leafs_begin = implicit_leafs_index(data->data, data->depth, parent_level_index);
700 int parent_leafs_end = implicit_leafs_index(data->data, data->depth, parent_level_index + 1);
701
702 /* This calculates the bounding box of this branch
703 * and chooses the largest axis as the axis to divide leafs */
704 refit_kdop_hull(data->tree, parent, parent_leafs_begin, parent_leafs_end);
705 split_axis = get_largest_axis(parent->bv);
706
707 /* Save split axis (this can be used on ray-tracing to speedup the query time) */
708 parent->main_axis = split_axis / 2;
709
710 /* Split the children along the split_axis, NOTE: its not needed to sort the whole leafs array
711 * Only to assure that the elements are partitioned on a way that each child takes the elements
712 * it would take in case the whole array was sorted.
713 * Split_leafs takes care of that "sort" problem. */
714 nth_positions[0] = parent_leafs_begin;
715 nth_positions[data->tree_type] = parent_leafs_end;
716 for (k = 1; k < data->tree_type; k++) {
717 const int child_index = j * data->tree_type + data->tree_offset + k;
718 /* child level index */
719 const int child_level_index = child_index - data->first_of_next_level;
720 nth_positions[k] = implicit_leafs_index(data->data, data->depth + 1, child_level_index);
721 }
722
723 split_leafs(data->leafs_array, nth_positions, data->tree_type, split_axis);
724
725 /* Setup `children` and `node_num` counters
726 * Not really needed but currently most of BVH code
727 * relies on having an explicit children structure */
728 for (k = 0; 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
733 const int child_leafs_begin = implicit_leafs_index(
734 data->data, data->depth + 1, child_level_index);
735 const int child_leafs_end = implicit_leafs_index(
736 data->data, data->depth + 1, child_level_index + 1);
737
738 if (child_leafs_end - child_leafs_begin > 1) {
739 parent->children[k] = &data->branches_array[child_index];
740 parent->children[k]->parent = parent;
741 }
742 else if (child_leafs_end - child_leafs_begin == 1) {
743 parent->children[k] = data->leafs_array[child_leafs_begin];
744 parent->children[k]->parent = parent;
745 }
746 else {
747 break;
748 }
749 }
750 parent->node_num = char(k);
751}
752
772 BVHNode *branches_array,
773 BVHNode **leafs_array,
774 int leafs_num)
775{
776 int i;
777
778 const int tree_type = tree->tree_type;
779 /* this value is 0 (on binary trees) and negative on the others */
780 const int tree_offset = 2 - tree->tree_type;
781
782 const int branches_num = implicit_needed_branches(tree_type, leafs_num);
783
785 int depth;
786
787 {
788 /* set parent from root node to nullptr */
789 BVHNode *root = &branches_array[1];
790 root->parent = nullptr;
791
792 /* Most of bvhtree code relies on 1-leaf trees having at least one branch
793 * We handle that special case here */
794 if (leafs_num == 1) {
795 refit_kdop_hull(tree, root, 0, leafs_num);
796 root->main_axis = get_largest_axis(root->bv) / 2;
797 root->node_num = 1;
798 root->children[0] = leafs_array[0];
799 root->children[0]->parent = root;
800 return;
801 }
802 }
803
805
806 BVHDivNodesData cb_data{};
807 cb_data.tree = tree;
808 cb_data.branches_array = branches_array;
809 cb_data.leafs_array = leafs_array;
810 cb_data.tree_type = tree_type;
811 cb_data.tree_offset = tree_offset;
812 cb_data.data = &data;
813 cb_data.first_of_next_level = 0;
814 cb_data.depth = 0;
815 cb_data.i = 0;
816
817 /* Loop tree levels (log N) loops */
818 for (i = 1, depth = 1; i <= branches_num; i = i * tree_type + tree_offset, depth++) {
819 const int first_of_next_level = i * tree_type + tree_offset;
820 /* index of last branch on this level */
821 const int i_stop = min_ii(first_of_next_level, branches_num + 1);
822
823 /* Loop all branches on this level */
824 cb_data.first_of_next_level = first_of_next_level;
825 cb_data.i = i;
826 cb_data.depth = depth;
827
828 if (true) {
829 TaskParallelSettings settings;
831 settings.use_threading = (leafs_num > KDOPBVH_THREAD_LEAF_THRESHOLD);
833 }
834 else {
835 /* Less hassle for debugging. */
836 TaskParallelTLS tls = {nullptr};
837 for (int i_task = i; i_task < i_stop; i_task++) {
838 non_recursive_bvh_div_nodes_task_cb(&cb_data, i_task, &tls);
839 }
840 }
841 }
842}
843
845
846/* -------------------------------------------------------------------- */
849
850BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis)
851{
852 int numnodes, i;
853
854 BLI_assert(tree_type >= 2 && tree_type <= MAX_TREETYPE);
855
856 BVHTree *tree = MEM_callocN<BVHTree>(__func__);
857
858 /* tree epsilon must be >= FLT_EPSILON
859 * so that tangent rays can still hit a bounding volume..
860 * this bug would show up when casting a ray aligned with a KDOP-axis
861 * and with an edge of 2 faces */
862 epsilon = max_ff(FLT_EPSILON, epsilon);
863
864 if (tree) {
865 tree->epsilon = epsilon;
866 tree->tree_type = tree_type;
867 tree->axis = axis;
868
869 if (axis == 26) {
870 tree->start_axis = 0;
871 tree->stop_axis = 13;
872 }
873 else if (axis == 18) {
874 tree->start_axis = 7;
875 tree->stop_axis = 13;
876 }
877 else if (axis == 14) {
878 tree->start_axis = 0;
879 tree->stop_axis = 7;
880 }
881 else if (axis == 8) { /* AABB */
882 tree->start_axis = 0;
883 tree->stop_axis = 4;
884 }
885 else if (axis == 6) { /* OBB */
886 tree->start_axis = 0;
887 tree->stop_axis = 3;
888 }
889 else {
890 /* should never happen! */
892
893 goto fail;
894 }
895
896 /* Allocate arrays */
897 numnodes = maxsize + implicit_needed_branches(tree_type, maxsize) + tree_type;
898
899 tree->nodes = MEM_calloc_arrayN<BVHNode *>(size_t(numnodes), "BVHNodes");
900 tree->nodebv = MEM_calloc_arrayN<float>(axis * size_t(numnodes), "BVHNodeBV");
901 tree->nodechild = MEM_calloc_arrayN<BVHNode *>(tree_type * size_t(numnodes), "BVHNodeBV");
902 tree->nodearray = MEM_calloc_arrayN<BVHNode>(size_t(numnodes), "BVHNodeArray");
903
904 if (UNLIKELY((!tree->nodes) || (!tree->nodebv) || (!tree->nodechild) || (!tree->nodearray))) {
905 goto fail;
906 }
907
908 /* link the dynamic bv and child links */
909 for (i = 0; i < numnodes; i++) {
910 tree->nodearray[i].bv = &tree->nodebv[i * axis];
911 tree->nodearray[i].children = &tree->nodechild[i * tree_type];
912 }
913 }
914 return tree;
915
916fail:
918 return nullptr;
919}
920
922{
923 if (tree) {
924 MEM_SAFE_FREE(tree->nodes);
925 MEM_SAFE_FREE(tree->nodearray);
926 MEM_SAFE_FREE(tree->nodebv);
927 MEM_SAFE_FREE(tree->nodechild);
929 }
930}
931
933{
934 BVHNode **leafs_array = tree->nodes;
935
936 /* This function should only be called once
937 * (some big bug goes here if its being called more than once per tree) */
938 BLI_assert(tree->branch_num == 0);
939
940 /* Build the implicit tree */
942 tree, tree->nodearray + (tree->leaf_num - 1), leafs_array, tree->leaf_num);
943
944 /* current code expects the branches to be linked to the nodes array
945 * we perform that linkage here */
946 tree->branch_num = implicit_needed_branches(tree->tree_type, tree->leaf_num);
947 for (int i = 0; i < tree->branch_num; i++) {
948 tree->nodes[tree->leaf_num + i] = &tree->nodearray[tree->leaf_num + i];
949 }
950
951#ifdef USE_SKIP_LINKS
952 build_skip_links(tree, tree->nodes[tree->leaf_num], nullptr, nullptr);
953#endif
954
955#ifdef USE_VERIFY_TREE
956 bvhtree_verify(tree);
957#endif
958
959#ifdef USE_PRINT_TREE
960 bvhtree_info(tree);
961#endif
962}
963
964static void bvhtree_node_inflate(const BVHTree *tree, BVHNode *node, const float dist)
965{
966 axis_t axis_iter;
967 for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) {
968 float dist_corrected = dist * bvhtree_kdop_axes_length[axis_iter];
969 node->bv[(2 * axis_iter)] -= dist_corrected; /* minimum */
970 node->bv[(2 * axis_iter) + 1] += dist_corrected; /* maximum */
971 }
972}
973
974void BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints)
975{
976 BVHNode *node = nullptr;
977
978 /* insert should only possible as long as tree->branch_num is 0 */
979 BLI_assert(tree->branch_num <= 0);
980 BLI_assert((size_t)tree->leaf_num < MEM_allocN_len(tree->nodes) / sizeof(*(tree->nodes)));
981
982 node = tree->nodes[tree->leaf_num] = &(tree->nodearray[tree->leaf_num]);
983 tree->leaf_num++;
984
985 create_kdop_hull(tree, node, co, numpoints, 0);
986 node->index = index;
987
988 /* inflate the bv with some epsilon */
989 bvhtree_node_inflate(tree, node, tree->epsilon);
990}
991
993 BVHTree *tree, int index, const float co[3], const float co_moving[3], int numpoints)
994{
995 BVHNode *node = nullptr;
996
997 /* check if index exists */
998 if (index > tree->leaf_num) {
999 return false;
1000 }
1001
1002 node = tree->nodearray + index;
1003
1004 create_kdop_hull(tree, node, co, numpoints, 0);
1005
1006 if (co_moving) {
1007 create_kdop_hull(tree, node, co_moving, numpoints, 1);
1008 }
1009
1010 /* inflate the bv with some epsilon */
1011 bvhtree_node_inflate(tree, node, tree->epsilon);
1012
1013 return true;
1014}
1015
1017{
1018 /* Update bottom=>top
1019 * TRICKY: the way we build the tree all the children have an index greater than the parent
1020 * This allows us todo a bottom up update by starting on the bigger numbered branch. */
1021
1022 BVHNode **root = tree->nodes + tree->leaf_num;
1023 BVHNode **index = tree->nodes + tree->leaf_num + tree->branch_num - 1;
1024
1025 for (; index >= root; index--) {
1026 node_join(tree, *index);
1027 }
1028}
1030{
1031 return tree->leaf_num;
1032}
1033
1035{
1036 return tree->tree_type;
1037}
1038
1040{
1041 return tree->epsilon;
1042}
1043
1044void BLI_bvhtree_get_bounding_box(const BVHTree *tree, float r_bb_min[3], float r_bb_max[3])
1045{
1046 const BVHNode *root = tree->nodes[tree->leaf_num];
1047 if (root != nullptr) {
1048 const float bb_min[3] = {root->bv[0], root->bv[2], root->bv[4]};
1049 const float bb_max[3] = {root->bv[1], root->bv[3], root->bv[5]};
1050 copy_v3_v3(r_bb_min, bb_min);
1051 copy_v3_v3(r_bb_max, bb_max);
1052 }
1053 else {
1054 BLI_assert(false);
1055 zero_v3(r_bb_min);
1056 zero_v3(r_bb_max);
1057 }
1058}
1059
1061
1062/* -------------------------------------------------------------------- */
1065
1069static bool tree_overlap_test(const BVHNode *node1,
1070 const BVHNode *node2,
1071 axis_t start_axis,
1072 axis_t stop_axis)
1073{
1074 const float *bv1 = node1->bv + (start_axis << 1);
1075 const float *bv2 = node2->bv + (start_axis << 1);
1076 const float *bv1_end = node1->bv + (stop_axis << 1);
1077
1078 /* test all axis if min + max overlap */
1079 for (; bv1 != bv1_end; bv1 += 2, bv2 += 2) {
1080 if ((bv1[0] > bv2[1]) || (bv2[0] > bv1[1])) {
1081 return false;
1082 }
1083 }
1084
1085 return true;
1086}
1087
1089 const BVHNode *node1,
1090 const BVHNode *node2)
1091{
1092 const BVHOverlapData_Shared *data = data_thread->shared;
1093 int j;
1094
1095 if (tree_overlap_test(node1, node2, data->start_axis, data->stop_axis)) {
1096 /* check if node1 is a leaf */
1097 if (!node1->node_num) {
1098 /* check if node2 is a leaf */
1099 if (!node2->node_num) {
1100 BVHTreeOverlap *overlap;
1101
1102 if (UNLIKELY(node1 == node2)) {
1103 return;
1104 }
1105
1106 /* both leafs, insert overlap! */
1107 overlap = static_cast<BVHTreeOverlap *>(BLI_stack_push_r(data_thread->overlap));
1108 overlap->indexA = node1->index;
1109 overlap->indexB = node2->index;
1110 }
1111 else {
1112 for (j = 0; j < data->tree2->tree_type; j++) {
1113 if (node2->children[j]) {
1114 tree_overlap_traverse(data_thread, node1, node2->children[j]);
1115 }
1116 }
1117 }
1118 }
1119 else {
1120 for (j = 0; j < data->tree1->tree_type; j++) {
1121 if (node1->children[j]) {
1122 tree_overlap_traverse(data_thread, node1->children[j], node2);
1123 }
1124 }
1125 }
1126 }
1127}
1128
1133 const BVHNode *node1,
1134 const BVHNode *node2)
1135{
1136 BVHOverlapData_Shared *data = data_thread->shared;
1137 int j;
1138
1139 if (tree_overlap_test(node1, node2, data->start_axis, data->stop_axis)) {
1140 /* check if node1 is a leaf */
1141 if (!node1->node_num) {
1142 /* check if node2 is a leaf */
1143 if (!node2->node_num) {
1144 BVHTreeOverlap *overlap;
1145
1146 if (UNLIKELY(node1 == node2)) {
1147 return;
1148 }
1149
1150 /* only difference to tree_overlap_traverse! */
1151 if (data->callback(data->userdata, node1->index, node2->index, data_thread->thread)) {
1152 /* both leafs, insert overlap! */
1153 overlap = static_cast<BVHTreeOverlap *>(BLI_stack_push_r(data_thread->overlap));
1154 overlap->indexA = node1->index;
1155 overlap->indexB = node2->index;
1156 }
1157 }
1158 else {
1159 for (j = 0; j < data->tree2->tree_type; j++) {
1160 if (node2->children[j]) {
1161 tree_overlap_traverse_cb(data_thread, node1, node2->children[j]);
1162 }
1163 }
1164 }
1165 }
1166 else {
1167 for (j = 0; j < data->tree1->tree_type; j++) {
1168 if (node1->children[j]) {
1169 tree_overlap_traverse_cb(data_thread, node1->children[j], node2);
1170 }
1171 }
1172 }
1173 }
1174}
1175
1180 const BVHNode *node1,
1181 const BVHNode *node2)
1182{
1183 BVHOverlapData_Shared *data = data_thread->shared;
1184 int j;
1185
1186 if (tree_overlap_test(node1, node2, data->start_axis, data->stop_axis)) {
1187 /* check if node1 is a leaf */
1188 if (!node1->node_num) {
1189 /* check if node2 is a leaf */
1190 if (!node2->node_num) {
1191 BVHTreeOverlap *overlap;
1192
1193 if (UNLIKELY(node1 == node2)) {
1194 return false;
1195 }
1196
1197 /* only difference to tree_overlap_traverse! */
1198 if (!data->callback ||
1199 data->callback(data->userdata, node1->index, node2->index, data_thread->thread))
1200 {
1201 /* both leafs, insert overlap! */
1202 if (data_thread->overlap) {
1203 overlap = static_cast<BVHTreeOverlap *>(BLI_stack_push_r(data_thread->overlap));
1204 overlap->indexA = node1->index;
1205 overlap->indexB = node2->index;
1206 }
1207 return (--data_thread->max_interactions) == 0;
1208 }
1209 }
1210 else {
1211 for (j = 0; j < node2->node_num; j++) {
1212 if (tree_overlap_traverse_num(data_thread, node1, node2->children[j])) {
1213 return true;
1214 }
1215 }
1216 }
1217 }
1218 else {
1219 const uint max_interactions = data_thread->max_interactions;
1220 for (j = 0; j < node1->node_num; j++) {
1221 if (tree_overlap_traverse_num(data_thread, node1->children[j], node2)) {
1222 data_thread->max_interactions = max_interactions;
1223 }
1224 }
1225 }
1226 }
1227 return false;
1228}
1229
1232 const BVHNode *node1,
1233 const BVHNode *node2)
1234{
1235 if (data->max_interactions) {
1236 tree_overlap_traverse_num(data, node1, node2);
1237 }
1238 else if (data->shared->callback) {
1239 tree_overlap_traverse_cb(data, node1, node2);
1240 }
1241 else {
1242 tree_overlap_traverse(data, node1, node2);
1243 }
1244}
1245
1248{
1249 for (int i = 0; i < node->node_num; i++) {
1250 /* Recursively compute self-overlap within each child. */
1251 tree_overlap_traverse_self_cb(data_thread, node->children[i]);
1252
1253 /* Compute overlap of pairs of children, testing each one only once (assume symmetry). */
1254 for (int j = i + 1; j < node->node_num; j++) {
1255 tree_overlap_traverse_cb(data_thread, node->children[i], node->children[j]);
1256 }
1257 }
1258}
1259
1261static void tree_overlap_traverse_self(BVHOverlapData_Thread *data_thread, const BVHNode *node)
1262{
1263 for (int i = 0; i < node->node_num; i++) {
1264 /* Recursively compute self-overlap within each child. */
1265 tree_overlap_traverse_self(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(data_thread, node->children[i], node->children[j]);
1270 }
1271 }
1272}
1273
1276 const BVHNode *node)
1277{
1278 if (data_thread->shared->callback) {
1279 tree_overlap_traverse_self_cb(data_thread, node);
1280 }
1281 else {
1282 tree_overlap_traverse_self(data_thread, node);
1283 }
1284}
1285
1287{
1288 return std::min<int>(tree->tree_type, tree->nodes[tree->leaf_num]->node_num);
1289}
1290
1291static void bvhtree_overlap_task_cb(void *__restrict userdata,
1292 const int j,
1293 const TaskParallelTLS *__restrict /*tls*/)
1294{
1296 BVHOverlapData_Shared *data_shared = data->shared;
1297
1298 const BVHNode *root1 = data_shared->tree1->nodes[data_shared->tree1->leaf_num];
1299
1300 if (data_shared->use_self) {
1301 /* This code matches one outer loop iteration within traverse_self. */
1303
1304 for (int k = j + 1; k < root1->node_num; k++) {
1305 tree_overlap_invoke_traverse(data, root1->children[j], root1->children[k]);
1306 }
1307 }
1308 else {
1309 const BVHNode *root2 = data_shared->tree2->nodes[data_shared->tree2->leaf_num];
1310
1311 tree_overlap_invoke_traverse(data, root1->children[j], root2);
1312 }
1313}
1314
1316 const BVHTree *tree1,
1317 const BVHTree *tree2,
1318 uint *r_overlap_num,
1319 /* optional callback to test the overlap before adding (must be thread-safe!) */
1320 BVHTree_OverlapCallback callback,
1321 void *userdata,
1322 const uint max_interactions,
1323 const int flag)
1324{
1325 bool overlap_pairs = (flag & BVH_OVERLAP_RETURN_PAIRS) != 0;
1326 bool use_threading = (flag & BVH_OVERLAP_USE_THREADING) != 0 &&
1328 bool use_self = (flag & BVH_OVERLAP_SELF) != 0;
1329
1330 /* 'RETURN_PAIRS' was not implemented without 'max_interactions'. */
1331 BLI_assert(overlap_pairs || max_interactions);
1332 /* Self-overlap does not support max interactions (it's not symmetrical). */
1333 BLI_assert(!use_self || (tree1 == tree2 && !max_interactions));
1334
1335 const int root_node_len = BLI_bvhtree_overlap_thread_num(tree1);
1336 const int thread_num = use_threading ? root_node_len : 1;
1337 int j;
1338 size_t total = 0;
1339 BVHTreeOverlap *overlap = nullptr, *to = nullptr;
1340 BVHOverlapData_Shared data_shared;
1341 BVHOverlapData_Thread *data = BLI_array_alloca(data, size_t(thread_num));
1342 axis_t start_axis, stop_axis;
1343
1344 /* check for compatibility of both trees (can't compare 14-DOP with 18-DOP) */
1345 if (UNLIKELY((tree1->axis != tree2->axis) && (tree1->axis == 14 || tree2->axis == 14) &&
1346 (tree1->axis == 18 || tree2->axis == 18)))
1347 {
1348 BLI_assert(0);
1349 return nullptr;
1350 }
1351
1352 if (UNLIKELY(use_self && tree1 != tree2)) {
1353 use_self = false;
1354 }
1355
1356 const BVHNode *root1 = tree1->nodes[tree1->leaf_num];
1357 const BVHNode *root2 = tree2->nodes[tree2->leaf_num];
1358
1359 start_axis = min_axis(tree1->start_axis, tree2->start_axis);
1360 stop_axis = min_axis(tree1->stop_axis, tree2->stop_axis);
1361
1362 /* fast check root nodes for collision before doing big splitting + traversal */
1363 if (!tree_overlap_test(root1, root2, start_axis, stop_axis)) {
1364 return nullptr;
1365 }
1366
1367 data_shared.tree1 = tree1;
1368 data_shared.tree2 = tree2;
1369 data_shared.start_axis = start_axis;
1370 data_shared.stop_axis = stop_axis;
1371 data_shared.use_self = use_self;
1372
1373 /* can be nullptr */
1374 data_shared.callback = callback;
1375 data_shared.userdata = userdata;
1376
1377 for (j = 0; j < thread_num; j++) {
1378 /* init BVHOverlapData_Thread */
1379 data[j].shared = &data_shared;
1380 data[j].overlap = overlap_pairs ? BLI_stack_new(sizeof(BVHTreeOverlap), __func__) : nullptr;
1381 data[j].max_interactions = use_self ? 0 : max_interactions;
1382
1383 /* for callback */
1384 data[j].thread = j;
1385 }
1386
1387 if (use_threading) {
1388 TaskParallelSettings settings;
1390 settings.min_iter_per_thread = 1;
1391 BLI_task_parallel_range(0, root_node_len, data, bvhtree_overlap_task_cb, &settings);
1392 }
1393 else if (use_self) {
1395 }
1396 else {
1397 tree_overlap_invoke_traverse(data, root1, root2);
1398 }
1399
1400 if (overlap_pairs) {
1401 for (j = 0; j < thread_num; j++) {
1402 total += BLI_stack_count(data[j].overlap);
1403 }
1404
1405 to = overlap = MEM_malloc_arrayN<BVHTreeOverlap>(total, "BVHTreeOverlap");
1406
1407 for (j = 0; j < thread_num; j++) {
1408 uint count = uint(BLI_stack_count(data[j].overlap));
1409 BLI_stack_pop_n(data[j].overlap, to, count);
1410 BLI_stack_free(data[j].overlap);
1411 to += count;
1412 }
1413 *r_overlap_num = uint(total);
1414 }
1415
1416 return overlap;
1417}
1418
1420 const BVHTree *tree1,
1421 const BVHTree *tree2,
1422 uint *r_overlap_num,
1423 /* optional callback to test the overlap before adding (must be thread-safe!) */
1424 BVHTree_OverlapCallback callback,
1425 void *userdata)
1426{
1427 return BLI_bvhtree_overlap_ex(tree1,
1428 tree2,
1429 r_overlap_num,
1430 callback,
1431 userdata,
1432 0,
1434}
1435
1437 const BVHTree *tree,
1438 uint *r_overlap_num,
1439 /* optional callback to test the overlap before adding (must be thread-safe!) */
1440 BVHTree_OverlapCallback callback,
1441 void *userdata)
1442{
1444 tree,
1445 r_overlap_num,
1446 callback,
1447 userdata,
1448 0,
1451}
1452
1454
1455/* -------------------------------------------------------------------- */
1458
1459static bool tree_intersect_plane_test(const float *bv, const float plane[4])
1460{
1461 /* TODO(@germano): Support other KDOP geometries. */
1462 const float bb_min[3] = {bv[0], bv[2], bv[4]};
1463 const float bb_max[3] = {bv[1], bv[3], bv[5]};
1464 float bb_near[3], bb_far[3];
1465 aabb_get_near_far_from_plane(plane, bb_min, bb_max, bb_near, bb_far);
1466 if ((plane_point_side_v3(plane, bb_near) > 0.0f) != (plane_point_side_v3(plane, bb_far) > 0.0f))
1467 {
1468 return true;
1469 }
1470
1471 return false;
1472}
1473
1475 const BVHNode *node)
1476{
1477 if (tree_intersect_plane_test(node->bv, data->plane)) {
1478 /* check if node is a leaf */
1479 if (!node->node_num) {
1480 int *intersect = static_cast<int *>(BLI_stack_push_r(data->intersect));
1481 *intersect = node->index;
1482 }
1483 else {
1484 for (int j = 0; j < data->tree->tree_type; j++) {
1485 if (node->children[j]) {
1487 }
1488 }
1489 }
1490 }
1491}
1492
1493int *BLI_bvhtree_intersect_plane(const BVHTree *tree, float plane[4], uint *r_intersect_num)
1494{
1495 int *intersect = nullptr;
1496 size_t total = 0;
1497
1498 if (tree->leaf_num) {
1500 data.tree = tree;
1501 copy_v4_v4(data.plane, plane);
1502 data.intersect = BLI_stack_new(sizeof(int), __func__);
1503
1504 const BVHNode *root = tree->nodes[tree->leaf_num];
1506
1507 total = BLI_stack_count(data.intersect);
1508 if (total) {
1509 intersect = MEM_malloc_arrayN<int>(total, __func__);
1510 BLI_stack_pop_n(data.intersect, intersect, uint(total));
1511 }
1512 BLI_stack_free(data.intersect);
1513 }
1514 *r_intersect_num = uint(total);
1515 return intersect;
1516}
1517
1519
1520/* -------------------------------------------------------------------- */
1523
1524/* Determines the nearest point of the given node BV.
1525 * Returns the squared distance to that point. */
1526static float calc_nearest_point_squared(const float proj[3], BVHNode *node, float nearest[3])
1527{
1528 int i;
1529 const float *bv = node->bv;
1530
1531 /* nearest on AABB hull */
1532 for (i = 0; i != 3; i++, bv += 2) {
1533 float val = proj[i];
1534 val = std::max(bv[0], val);
1535 val = std::min(bv[1], val);
1536 nearest[i] = val;
1537 }
1538
1539 return len_squared_v3v3(proj, nearest);
1540}
1541
1542/* Depth first search method */
1544{
1545 if (node->node_num == 0) {
1546 if (data->callback) {
1547 data->callback(data->userdata, node->index, data->co, &data->nearest);
1548 }
1549 else {
1550 data->nearest.index = node->index;
1551 data->nearest.dist_sq = calc_nearest_point_squared(data->proj, node, data->nearest.co);
1552 }
1553 }
1554 else {
1555 /* Better heuristic to pick the closest node to dive on */
1556 int i;
1557 float nearest[3];
1558
1559 if (data->proj[node->main_axis] <= node->children[0]->bv[node->main_axis * 2 + 1]) {
1560
1561 for (i = 0; i != node->node_num; i++) {
1562 if (calc_nearest_point_squared(data->proj, node->children[i], nearest) >=
1563 data->nearest.dist_sq)
1564 {
1565 continue;
1566 }
1568 }
1569 }
1570 else {
1571 for (i = node->node_num - 1; i >= 0; i--) {
1572 if (calc_nearest_point_squared(data->proj, node->children[i], nearest) >=
1573 data->nearest.dist_sq)
1574 {
1575 continue;
1576 }
1578 }
1579 }
1580 }
1581}
1582
1584{
1585 float nearest[3], dist_sq;
1586 dist_sq = calc_nearest_point_squared(data->proj, node, nearest);
1587 if (dist_sq >= data->nearest.dist_sq) {
1588 return;
1589 }
1591}
1592
1593/* Priority queue method */
1595{
1596 if (node->node_num == 0) {
1597 if (data->callback) {
1598 data->callback(data->userdata, node->index, data->co, &data->nearest);
1599 }
1600 else {
1601 data->nearest.index = node->index;
1602 data->nearest.dist_sq = calc_nearest_point_squared(data->proj, node, data->nearest.co);
1603 }
1604 }
1605 else {
1606 float nearest[3];
1607
1608 for (int i = 0; i != node->node_num; i++) {
1609 float dist_sq = calc_nearest_point_squared(data->proj, node->children[i], nearest);
1610
1611 if (dist_sq < data->nearest.dist_sq) {
1612 BLI_heapsimple_insert(heap, dist_sq, node->children[i]);
1613 }
1614 }
1615 }
1616}
1617
1619{
1620 float nearest[3];
1621 float dist_sq = calc_nearest_point_squared(data->proj, root, nearest);
1622
1623 if (dist_sq < data->nearest.dist_sq) {
1625
1626 heap_find_nearest_inner(data, heap, root);
1627
1628 while (!BLI_heapsimple_is_empty(heap) &&
1629 BLI_heapsimple_top_value(heap) < data->nearest.dist_sq)
1630 {
1631 BVHNode *node = static_cast<BVHNode *>(BLI_heapsimple_pop_min(heap));
1632 heap_find_nearest_inner(data, heap, node);
1633 }
1634
1635 BLI_heapsimple_free(heap, nullptr);
1636 }
1637}
1638
1640 const float co[3],
1641 BVHTreeNearest *nearest,
1643 void *userdata,
1644 int flag)
1645{
1646 axis_t axis_iter;
1647
1649 BVHNode *root = tree->nodes[tree->leaf_num];
1650
1651 /* init data to search */
1652 data.tree = tree;
1653 data.co = co;
1654
1655 data.callback = callback;
1656 data.userdata = userdata;
1657
1658 for (axis_iter = data.tree->start_axis; axis_iter != data.tree->stop_axis; axis_iter++) {
1659 data.proj[axis_iter] = dot_v3v3(data.co, bvhtree_kdop_axes[axis_iter]);
1660 }
1661
1662 if (nearest) {
1663 memcpy(&data.nearest, nearest, sizeof(*nearest));
1664 }
1665 else {
1666 data.nearest.index = -1;
1667 data.nearest.dist_sq = FLT_MAX;
1668 }
1669
1670 /* dfs search */
1671 if (root) {
1674 }
1675 else {
1677 }
1678 }
1679
1680 /* copy back results */
1681 if (nearest) {
1682 memcpy(nearest, &data.nearest, sizeof(*nearest));
1683 }
1684
1685 return data.nearest.index;
1686}
1687
1689 const float co[3],
1690 BVHTreeNearest *nearest,
1692 void *userdata)
1693{
1694 return BLI_bvhtree_find_nearest_ex(tree, co, nearest, callback, userdata, 0);
1695}
1696
1698
1699/* -------------------------------------------------------------------- */
1702
1703static bool isect_aabb_v3(BVHNode *node, const float co[3])
1704{
1705 const BVHTreeAxisRange *bv = (const BVHTreeAxisRange *)node->bv;
1706
1707 if (co[0] > bv[0].min && co[0] < bv[0].max && co[1] > bv[1].min && co[1] < bv[1].max &&
1708 co[2] > bv[2].min && co[2] < bv[2].max)
1709 {
1710 return true;
1711 }
1712
1713 return false;
1714}
1715
1717{
1718 if (node->node_num == 0) {
1719 if (isect_aabb_v3(node, data->co)) {
1720 if (data->callback) {
1721 const float dist_sq = data->nearest.dist_sq;
1722 data->callback(data->userdata, node->index, data->co, &data->nearest);
1723 return (data->nearest.dist_sq < dist_sq);
1724 }
1725 data->nearest.index = node->index;
1726 return true;
1727 }
1728 }
1729 else {
1730 /* Better heuristic to pick the closest node to dive on */
1731 int i;
1732
1733 if (data->proj[node->main_axis] <= node->children[0]->bv[node->main_axis * 2 + 1]) {
1734 for (i = 0; i != node->node_num; i++) {
1735 if (isect_aabb_v3(node->children[i], data->co)) {
1737 return true;
1738 }
1739 }
1740 }
1741 }
1742 else {
1743 for (i = node->node_num; i--;) {
1744 if (isect_aabb_v3(node->children[i], data->co)) {
1746 return true;
1747 }
1748 }
1749 }
1750 }
1751 }
1752 return false;
1753}
1754
1756 const float co[3],
1757 const float dist_sq,
1759 void *userdata)
1760{
1762 BVHNode *root = tree->nodes[tree->leaf_num];
1763
1764 /* init data to search */
1765 data.tree = tree;
1766 data.co = co;
1767
1768 data.callback = callback;
1769 data.userdata = userdata;
1770 data.nearest.index = -1;
1771 data.nearest.dist_sq = dist_sq;
1772
1773 /* dfs search */
1774 if (root) {
1776 }
1777
1778 return data.nearest.index;
1779}
1780
1782
1783/* -------------------------------------------------------------------- */
1789
1790/* Determines the distance that the ray must travel to hit the bounding volume of the given node */
1791static float ray_nearest_hit(const BVHRayCastData *data, const float bv[6])
1792{
1793 int i;
1794
1795 float low = 0, upper = data->hit.dist;
1796
1797 for (i = 0; i != 3; i++, bv += 2) {
1798 if (data->ray_dot_axis[i] == 0.0f) {
1799 /* axis aligned ray */
1800 if (data->ray.origin[i] < bv[0] - data->ray.radius ||
1801 data->ray.origin[i] > bv[1] + data->ray.radius)
1802 {
1803 return FLT_MAX;
1804 }
1805 }
1806 else {
1807 float ll = (bv[0] - data->ray.radius - data->ray.origin[i]) / data->ray_dot_axis[i];
1808 float lu = (bv[1] + data->ray.radius - data->ray.origin[i]) / data->ray_dot_axis[i];
1809
1810 if (data->ray_dot_axis[i] > 0.0f) {
1811 low = std::max(ll, low);
1812 upper = std::min(lu, upper);
1813 }
1814 else {
1815 low = std::max(lu, low);
1816 upper = std::min(ll, upper);
1817 }
1818
1819 if (low > upper) {
1820 return FLT_MAX;
1821 }
1822 }
1823 }
1824 return low;
1825}
1826
1833static float fast_ray_nearest_hit(const BVHRayCastData *data, const BVHNode *node)
1834{
1835 const float *bv = node->bv;
1836
1837 float t1x = (bv[data->index[0]] - data->ray.origin[0]) * data->idot_axis[0];
1838 float t2x = (bv[data->index[1]] - data->ray.origin[0]) * data->idot_axis[0];
1839 float t1y = (bv[data->index[2]] - data->ray.origin[1]) * data->idot_axis[1];
1840 float t2y = (bv[data->index[3]] - data->ray.origin[1]) * data->idot_axis[1];
1841 float t1z = (bv[data->index[4]] - data->ray.origin[2]) * data->idot_axis[2];
1842 float t2z = (bv[data->index[5]] - data->ray.origin[2]) * data->idot_axis[2];
1843
1844 if ((t1x > t2y || t2x < t1y || t1x > t2z || t2x < t1z || t1y > t2z || t2y < t1z) ||
1845 (t2x < 0.0f || t2y < 0.0f || t2z < 0.0f) ||
1846 (t1x > data->hit.dist || t1y > data->hit.dist || t1z > data->hit.dist))
1847 {
1848 return FLT_MAX;
1849 }
1850 return max_fff(t1x, t1y, t1z);
1851}
1852
1854{
1855 int i;
1856
1857 /* ray-bv is really fast.. and simple tests revealed its worth to test it
1858 * before calling the ray-primitive functions */
1859 /* XXX: temporary solution for particles until fast_ray_nearest_hit supports ray.radius */
1860 float dist = (data->ray.radius == 0.0f) ? fast_ray_nearest_hit(data, node) :
1861 ray_nearest_hit(data, node->bv);
1862 if (dist >= data->hit.dist) {
1863 return;
1864 }
1865
1866 if (node->node_num == 0) {
1867 if (data->callback) {
1868 data->callback(data->userdata, node->index, &data->ray, &data->hit);
1869 }
1870 else {
1871 data->hit.index = node->index;
1872 data->hit.dist = dist;
1873 madd_v3_v3v3fl(data->hit.co, data->ray.origin, data->ray.direction, dist);
1874 }
1875 }
1876 else {
1877 /* pick loop direction to dive into the tree (based on ray direction and split axis) */
1878 if (data->ray_dot_axis[node->main_axis] > 0.0f) {
1879 for (i = 0; i != node->node_num; i++) {
1880 dfs_raycast(data, node->children[i]);
1881 }
1882 }
1883 else {
1884 for (i = node->node_num - 1; i >= 0; i--) {
1885 dfs_raycast(data, node->children[i]);
1886 }
1887 }
1888 }
1889}
1890
1895{
1896 int i;
1897
1898 /* ray-bv is really fast.. and simple tests revealed its worth to test it
1899 * before calling the ray-primitive functions */
1900 /* XXX: temporary solution for particles until fast_ray_nearest_hit supports ray.radius */
1901 float dist = (data->ray.radius == 0.0f) ? fast_ray_nearest_hit(data, node) :
1902 ray_nearest_hit(data, node->bv);
1903 if (dist >= data->hit.dist) {
1904 return;
1905 }
1906
1907 if (node->node_num == 0) {
1908 /* no need to check for 'data->callback' (using 'all' only makes sense with a callback). */
1909 dist = data->hit.dist;
1910 data->callback(data->userdata, node->index, &data->ray, &data->hit);
1911 data->hit.index = -1;
1912 data->hit.dist = dist;
1913 }
1914 else {
1915 /* pick loop direction to dive into the tree (based on ray direction and split axis) */
1916 if (data->ray_dot_axis[node->main_axis] > 0.0f) {
1917 for (i = 0; i != node->node_num; i++) {
1918 dfs_raycast_all(data, node->children[i]);
1919 }
1920 }
1921 else {
1922 for (i = node->node_num - 1; i >= 0; i--) {
1923 dfs_raycast_all(data, node->children[i]);
1924 }
1925 }
1926 }
1927}
1928
1930{
1931 int i;
1932
1933 for (i = 0; i < 3; i++) {
1934 data->ray_dot_axis[i] = dot_v3v3(data->ray.direction, bvhtree_kdop_axes[i]);
1935
1936 if (fabsf(data->ray_dot_axis[i]) < FLT_EPSILON) {
1937 data->ray_dot_axis[i] = 0.0f;
1938 /* Sign is not important in this case, `data->index` is adjusted anyway. */
1939 data->idot_axis[i] = FLT_MAX;
1940 }
1941 else {
1942 data->idot_axis[i] = 1.0f / data->ray_dot_axis[i];
1943 }
1944
1945 data->index[2 * i] = data->idot_axis[i] < 0.0f ? 1 : 0;
1946 data->index[2 * i + 1] = 1 - data->index[2 * i];
1947 data->index[2 * i] += 2 * i;
1948 data->index[2 * i + 1] += 2 * i;
1949 }
1950
1951#ifdef USE_KDOPBVH_WATERTIGHT
1953 isect_ray_tri_watertight_v3_precalc(&data->isect_precalc, data->ray.direction);
1954 data->ray.isect_precalc = &data->isect_precalc;
1955 }
1956 else {
1957 data->ray.isect_precalc = nullptr;
1958 }
1959#else
1961#endif
1962}
1963
1965 const float co[3],
1966 const float dir[3],
1967 float radius,
1968 BVHTreeRayHit *hit,
1969 BVHTree_RayCastCallback callback,
1970 void *userdata,
1971 int flag)
1972{
1974 BVHNode *root = tree->nodes[tree->leaf_num];
1975
1976 BLI_ASSERT_UNIT_V3(dir);
1977
1978 data.tree = tree;
1979
1980 data.callback = callback;
1981 data.userdata = userdata;
1982
1983 copy_v3_v3(data.ray.origin, co);
1984 copy_v3_v3(data.ray.direction, dir);
1985 data.ray.radius = radius;
1986
1988
1989 if (hit) {
1990 memcpy(&data.hit, hit, sizeof(*hit));
1991 }
1992 else {
1993 data.hit.index = -1;
1994 data.hit.dist = BVH_RAYCAST_DIST_MAX;
1995 }
1996
1997 if (root) {
1998 dfs_raycast(&data, root);
1999 // iterative_raycast(&data, root);
2000 }
2001
2002 if (hit) {
2003 memcpy(hit, &data.hit, sizeof(*hit));
2004 }
2005
2006 return data.hit.index;
2007}
2008
2010 const float co[3],
2011 const float dir[3],
2012 float radius,
2013 BVHTreeRayHit *hit,
2014 BVHTree_RayCastCallback callback,
2015 void *userdata)
2016{
2018 tree, co, dir, radius, hit, callback, userdata, BVH_RAYCAST_DEFAULT);
2019}
2020
2021float BLI_bvhtree_bb_raycast(const float bv[6],
2022 const float light_start[3],
2023 const float light_end[3],
2024 float pos[3])
2025{
2027 float dist;
2028
2029 data.hit.dist = BVH_RAYCAST_DIST_MAX;
2030
2031 /* get light direction */
2032 sub_v3_v3v3(data.ray.direction, light_end, light_start);
2033
2034 data.ray.radius = 0.0;
2035
2036 copy_v3_v3(data.ray.origin, light_start);
2037
2038 normalize_v3(data.ray.direction);
2039 copy_v3_v3(data.ray_dot_axis, data.ray.direction);
2040
2041 dist = ray_nearest_hit(&data, bv);
2042
2043 madd_v3_v3v3fl(pos, light_start, data.ray.direction, dist);
2044
2045 return dist;
2046}
2047
2049 const float co[3],
2050 const float dir[3],
2051 float radius,
2052 float hit_dist,
2053 BVHTree_RayCastCallback callback,
2054 void *userdata,
2055 int flag)
2056{
2058 BVHNode *root = tree->nodes[tree->leaf_num];
2059
2060 BLI_ASSERT_UNIT_V3(dir);
2061 BLI_assert(callback != nullptr);
2062
2063 data.tree = tree;
2064
2065 data.callback = callback;
2066 data.userdata = userdata;
2067
2068 copy_v3_v3(data.ray.origin, co);
2069 copy_v3_v3(data.ray.direction, dir);
2070 data.ray.radius = radius;
2071
2073
2074 data.hit.index = -1;
2075 data.hit.dist = hit_dist;
2076
2077 if (root) {
2078 dfs_raycast_all(&data, root);
2079 }
2080}
2081
2083 const float co[3],
2084 const float dir[3],
2085 float radius,
2086 float hit_dist,
2087 BVHTree_RayCastCallback callback,
2088 void *userdata)
2089{
2091 tree, co, dir, radius, hit_dist, callback, userdata, BVH_RAYCAST_DEFAULT);
2092}
2093
2095
2096/* -------------------------------------------------------------------- */
2104
2107 const float *center;
2108 float radius_sq; /* squared radius */
2109
2110 int hits;
2111
2114};
2115
2117{
2118 if (node->node_num == 0) {
2119#if 0 /*UNUSED*/
2120 /* Calculate the node min-coords
2121 * (if the node was a point then this is the point coordinates) */
2122 float co[3];
2123 co[0] = node->bv[0];
2124 co[1] = node->bv[2];
2125 co[2] = node->bv[4];
2126#endif
2127 }
2128 else {
2129 int i;
2130 for (i = 0; i != node->node_num; i++) {
2131 float nearest[3];
2132 float dist_sq = calc_nearest_point_squared(data->center, node->children[i], nearest);
2133 if (dist_sq < data->radius_sq) {
2134 /* Its a leaf.. call the callback */
2135 if (node->children[i]->node_num == 0) {
2136 data->hits++;
2137 data->callback(data->userdata, node->children[i]->index, data->center, dist_sq);
2138 }
2139 else {
2140 dfs_range_query(data, node->children[i]);
2141 }
2142 }
2143 }
2144 }
2145}
2146
2148 const float co[3],
2149 float radius,
2150 BVHTree_RangeQuery callback,
2151 void *userdata)
2152{
2153 BVHNode *root = tree->nodes[tree->leaf_num];
2154
2156 data.tree = tree;
2157 data.center = co;
2158 data.radius_sq = radius * radius;
2159 data.hits = 0;
2160
2161 data.callback = callback;
2162 data.userdata = userdata;
2163
2164 if (root != nullptr) {
2165 float nearest[3];
2166 float dist_sq = calc_nearest_point_squared(data.center, root, nearest);
2167 if (dist_sq < data.radius_sq) {
2168 /* Its a leaf.. call the callback */
2169 if (root->node_num == 0) {
2170 data.hits++;
2171 data.callback(data.userdata, root->index, co, dist_sq);
2172 }
2173 else {
2174 dfs_range_query(&data, root);
2175 }
2176 }
2177 }
2178
2179 return data.hits;
2180}
2181
2183
2184/* -------------------------------------------------------------------- */
2187
2189 const BVHNode *node)
2190{
2191 if (node->node_num == 0) {
2192 if (data->callback) {
2193 data->callback(data->userdata, node->index, &data->precalc, nullptr, 0, &data->nearest);
2194 }
2195 else {
2196 data->nearest.index = node->index;
2197 data->nearest.dist_sq = dist_squared_to_projected_aabb(
2198 &data->precalc,
2199 blender::float3{node->bv[0], node->bv[2], node->bv[4]},
2200 blender::float3{node->bv[1], node->bv[3], node->bv[5]},
2201 data->closest_axis);
2202 }
2203 }
2204 else {
2205 /* First pick the closest node to recurse into */
2206 if (data->closest_axis[node->main_axis]) {
2207 for (int i = 0; i != node->node_num; i++) {
2208 const float *bv = node->children[i]->bv;
2209
2211 blender::float3{bv[0], bv[2], bv[4]},
2212 blender::float3{bv[1], bv[3], bv[5]},
2213 data->closest_axis) <= data->nearest.dist_sq)
2214 {
2216 }
2217 }
2218 }
2219 else {
2220 for (int i = node->node_num; i--;) {
2221 const float *bv = node->children[i]->bv;
2222
2224 blender::float3{bv[0], bv[2], bv[4]},
2225 blender::float3{bv[1], bv[3], bv[5]},
2226 data->closest_axis) <= data->nearest.dist_sq)
2227 {
2229 }
2230 }
2231 }
2232 }
2233}
2234
2236 BVHNearestProjectedData *__restrict data, const BVHNode *node)
2237{
2238 if (node->node_num == 0) {
2239 if (data->callback) {
2240 data->callback(data->userdata,
2241 node->index,
2242 &data->precalc,
2243 data->clip_plane,
2244 data->clip_plane_len,
2245 &data->nearest);
2246 }
2247 else {
2248 data->nearest.index = node->index;
2249 data->nearest.dist_sq = dist_squared_to_projected_aabb(
2250 &data->precalc,
2251 blender::float3{node->bv[0], node->bv[2], node->bv[4]},
2252 blender::float3{node->bv[1], node->bv[3], node->bv[5]},
2253 data->closest_axis);
2254 }
2255 }
2256 else {
2257 /* First pick the closest node to recurse into */
2258 if (data->closest_axis[node->main_axis]) {
2259 for (int i = 0; i != node->node_num; i++) {
2260 const float *bv = node->children[i]->bv;
2261 const float bb_min[3] = {bv[0], bv[2], bv[4]};
2262 const float bb_max[3] = {bv[1], bv[3], bv[5]};
2263
2264 int isect_type = isect_aabb_planes_v3(
2265 data->clip_plane, data->clip_plane_len, bb_min, bb_max);
2266
2267 if ((isect_type != ISECT_AABB_PLANE_BEHIND_ANY) &&
2268 dist_squared_to_projected_aabb(&data->precalc, bb_min, bb_max, data->closest_axis) <=
2269 data->nearest.dist_sq)
2270 {
2271 if (isect_type == ISECT_AABB_PLANE_CROSS_ANY) {
2273 }
2274 else {
2275 /* ISECT_AABB_PLANE_IN_FRONT_ALL */
2277 }
2278 }
2279 }
2280 }
2281 else {
2282 for (int i = node->node_num; i--;) {
2283 const float *bv = node->children[i]->bv;
2284 const float bb_min[3] = {bv[0], bv[2], bv[4]};
2285 const float bb_max[3] = {bv[1], bv[3], bv[5]};
2286
2287 int isect_type = isect_aabb_planes_v3(
2288 data->clip_plane, data->clip_plane_len, bb_min, bb_max);
2289
2290 if (isect_type != ISECT_AABB_PLANE_BEHIND_ANY &&
2291 dist_squared_to_projected_aabb(&data->precalc, bb_min, bb_max, data->closest_axis) <=
2292 data->nearest.dist_sq)
2293 {
2294 if (isect_type == ISECT_AABB_PLANE_CROSS_ANY) {
2296 }
2297 else {
2298 /* ISECT_AABB_PLANE_IN_FRONT_ALL */
2300 }
2301 }
2302 }
2303 }
2304 }
2305}
2306
2308 float projmat[4][4],
2309 float winsize[2],
2310 float mval[2],
2311 float (*clip_plane)[4],
2312 int clip_plane_len,
2313 BVHTreeNearest *nearest,
2315 void *userdata)
2316{
2317 const BVHNode *root = tree->nodes[tree->leaf_num];
2318 if (root != nullptr) {
2320 sizeof(*data) + (sizeof(*clip_plane) * size_t(max_ii(1, clip_plane_len))));
2321
2322 dist_squared_to_projected_aabb_precalc(&data->precalc, projmat, winsize, mval);
2323
2324 data->callback = callback;
2325 data->userdata = userdata;
2326
2327#ifdef __GNUC__ /* Invalid `data->clip_plane` warning with GCC 14.2.1. */
2328# pragma GCC diagnostic push
2329# pragma GCC diagnostic ignored "-Warray-bounds"
2330#endif
2331 if (clip_plane) {
2332 data->clip_plane_len = clip_plane_len;
2333 for (int i = 0; i < clip_plane_len; i++) {
2334 copy_v4_v4(data->clip_plane[i], clip_plane[i]);
2335 }
2336 }
2337 else {
2338 data->clip_plane_len = 1;
2340 projmat, nullptr, nullptr, nullptr, nullptr, data->clip_plane[0], nullptr);
2341 }
2342#ifdef __GNUC__
2343# pragma GCC diagnostic pop
2344#endif
2345
2346 if (nearest) {
2347 memcpy(&data->nearest, nearest, sizeof(*nearest));
2348 }
2349 else {
2350 data->nearest.index = -1;
2351 data->nearest.dist_sq = FLT_MAX;
2352 }
2353 {
2354 const float bb_min[3] = {root->bv[0], root->bv[2], root->bv[4]};
2355 const float bb_max[3] = {root->bv[1], root->bv[3], root->bv[5]};
2356
2357 int isect_type = isect_aabb_planes_v3(
2358 data->clip_plane, data->clip_plane_len, bb_min, bb_max);
2359
2360 if (isect_type != 0 &&
2361 dist_squared_to_projected_aabb(&data->precalc, bb_min, bb_max, data->closest_axis) <=
2362 data->nearest.dist_sq)
2363 {
2364 if (isect_type == 1) {
2366 }
2367 else {
2369 }
2370 }
2371 }
2372
2373 if (nearest) {
2374 memcpy(nearest, &data->nearest, sizeof(*nearest));
2375 }
2376
2377 return data->nearest.index;
2378 }
2379 return -1;
2380}
2381
#define BLI_array_alloca(arr, realsize)
Definition BLI_alloca.h:18
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_STATIC_ASSERT(a, msg)
Definition BLI_assert.h:83
#define BLI_assert(a)
Definition BLI_assert.h:46
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])
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
uchar axis_t
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)
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)
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])
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)
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 non_recursive_bvh_div_nodes_task_cb(void *__restrict userdata, const int j, const TaskParallelTLS *__restrict)
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)
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
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)
static float calc_nearest_point_squared(const float proj[3], BVHNode *node, float nearest[3])
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)
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_overlap_task_cb(void *__restrict userdata, const int j, const TaskParallelTLS *__restrict)
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)
#define BVH_RAYCAST_DIST_MAX
#define BVH_RAYCAST_DEFAULT
const float bvhtree_kdop_axes[13][3]
bool(*)(void *userdata, int index_a, int index_b, int thread) BVHTree_OverlapCallback
@ BVH_RAYCAST_WATERTIGHT
void(*)(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) BVHTree_RayCastCallback
@ BVH_OVERLAP_USE_THREADING
@ BVH_OVERLAP_RETURN_PAIRS
@ BVH_OVERLAP_SELF
void(*)(void *userdata, int index, const float co[3], BVHTreeNearest *nearest) BVHTree_NearestPointCallback
void(*)(void *userdata, int index, const float co[3], float dist_sq) BVHTree_RangeQuery
void(*)(void *userdata, int index, const DistProjectedAABBPrecalc *precalc, const float(*clip_plane)[4], int clip_plane_len, BVHTreeNearest *nearest) BVHTree_NearestProjectedCallback
@ BVH_NEAREST_OPTIMAL_ORDER
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:858
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:806
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:649
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.cc:147
size_t BLI_stack_count(const BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition stack.cc:228
void BLI_stack_free(BLI_Stack *stack) ATTR_NONNULL()
Definition stack.cc:96
void * BLI_stack_push_r(BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition stack.cc: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:221
#define UNUSED_VARS(...)
#define SWAP(type, a, b)
#define UNLIKELY(x)
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
iter begin(iter)
BMesh const char void * data
__forceinline BoundBox intersect(const BoundBox &a, const BoundBox &b)
Definition boundbox.h:184
nullptr float
KDTree_3d * tree
uint pos
#define printf(...)
int count
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
size_t(* MEM_allocN_len)(const void *vmemh)
Definition mallocn.cc:36
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
static int left
VecBase< float, 3 > float3
#define fabsf
#define min(a, b)
Definition sort.cc:36
#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
BVHTreeNearest nearest
BVHTree_NearestPointCallback callback
DistProjectedAABBPrecalc precalc
BVHTree_NearestProjectedCallback callback
BVHNode ** children
BVHNode * parent
BVHNode(const BoundBox &bounds)
Definition bvh/node.h:102
char node_num
char main_axis
float * bv
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
float * nodebv
axis_t start_axis
int leaf_num
BVHNode * nodearray
float epsilon
int branch_num
BVHNode ** nodechild
BVHNode ** nodes
axis_t stop_axis
char tree_type
const BVHTree * tree
BVHTree_RangeQuery callback
const float * center
i
Definition text_draw.cc:230
max
Definition text_draw.cc:251
uint8_t flag
Definition wm_window.cc:145