Blender V4.5
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(
487 "Memory per node = %ubytes\n",
488 (uint)(sizeof(BVHNode) + sizeof(BVHNode *) * tree->tree_type + sizeof(float) * tree->axis));
489 printf("BV memory = %ubytes\n", (uint)MEM_allocN_len(tree->nodebv));
490
491 printf("Total memory = %ubytes\n",
492 (uint)(sizeof(BVHTree) + MEM_allocN_len(tree->nodes) + MEM_allocN_len(tree->nodearray) +
493 MEM_allocN_len(tree->nodechild) + MEM_allocN_len(tree->nodebv)));
494
495 bvhtree_print_tree(tree, tree->nodes[tree->leaf_num], 0);
496}
497
499
500#endif /* USE_PRINT_TREE */
501
502#ifdef USE_VERIFY_TREE
503
504static void bvhtree_verify(BVHTree *tree)
505{
506 int i, j, check = 0;
507
508 /* check the pointer list */
509 for (i = 0; i < tree->leaf_num; i++) {
510 if (tree->nodes[i]->parent == nullptr) {
511 printf("Leaf has no parent: %d\n", i);
512 }
513 else {
514 for (j = 0; j < tree->tree_type; j++) {
515 if (tree->nodes[i]->parent->children[j] == tree->nodes[i]) {
516 check = 1;
517 }
518 }
519 if (!check) {
520 printf("Parent child relationship doesn't match: %d\n", i);
521 }
522 check = 0;
523 }
524 }
525
526 /* check the leaf list */
527 for (i = 0; i < tree->leaf_num; i++) {
528 if (tree->nodearray[i].parent == nullptr) {
529 printf("Leaf has no parent: %d\n", i);
530 }
531 else {
532 for (j = 0; j < tree->tree_type; j++) {
533 if (tree->nodearray[i].parent->children[j] == &tree->nodearray[i]) {
534 check = 1;
535 }
536 }
537 if (!check) {
538 printf("Parent child relationship doesn't match: %d\n", i);
539 }
540 check = 0;
541 }
542 }
543
544 printf("branches: %d, leafs: %d, total: %d\n",
545 tree->branch_num,
546 tree->leaf_num,
547 tree->branch_num + tree->leaf_num);
548}
549#endif /* USE_VERIFY_TREE */
550
551/* Helper data and structures to build a min-leaf generalized implicit tree
552 * This code can be easily reduced
553 * (basically this is only method to calculate pow(k, n) in O(1).. and stuff like that) */
566
568{
569 int depth = 0;
570 int remain;
571 int nnodes;
572
573 data->leafs_num = tree->leaf_num;
574 data->tree_type = tree->tree_type;
575
576 /* Calculate the smallest tree_type^n such that tree_type^n >= leafs_num */
577 for (data->leafs_per_child[0] = 1; data->leafs_per_child[0] < data->leafs_num;
578 data->leafs_per_child[0] *= data->tree_type)
579 {
580 /* pass */
581 }
582
583 data->branches_on_level[0] = 1;
584
585 for (depth = 1; (depth < 32) && data->leafs_per_child[depth - 1]; depth++) {
586 data->branches_on_level[depth] = data->branches_on_level[depth - 1] * data->tree_type;
587 data->leafs_per_child[depth] = data->leafs_per_child[depth - 1] / data->tree_type;
588 }
589
590 remain = data->leafs_num - data->leafs_per_child[1];
591 nnodes = (remain + data->tree_type - 2) / (data->tree_type - 1);
592 data->remain_leafs = remain + nnodes;
593}
594
598static int implicit_leafs_index(const BVHBuildHelper *data, const int depth, const int child_index)
599{
600 int min_leaf_index = child_index * data->leafs_per_child[depth - 1];
601 if (min_leaf_index <= data->remain_leafs) {
602 return min_leaf_index;
603 }
604 if (data->leafs_per_child[depth]) {
605 return data->leafs_num -
606 (data->branches_on_level[depth - 1] - child_index) * data->leafs_per_child[depth];
607 }
608 return data->remain_leafs;
609}
610
639
640/* This functions returns the number of branches needed to have the requested number of leafs. */
641static int implicit_needed_branches(int tree_type, int leafs)
642{
643 return max_ii(1, (leafs + tree_type - 3) / (tree_type - 1));
644}
645
658static void split_leafs(BVHNode **leafs_array,
659 const int nth[],
660 const int partitions,
661 const int split_axis)
662{
663 int i;
664 for (i = 0; i < partitions - 1; i++) {
665 if (nth[i] >= nth[partitions]) {
666 break;
667 }
668
669 partition_nth_element(leafs_array, nth[i], nth[partitions], nth[i + 1], split_axis);
670 }
671}
672
687
688static void non_recursive_bvh_div_nodes_task_cb(void *__restrict userdata,
689 const int j,
690 const TaskParallelTLS *__restrict /*tls*/)
691{
692 BVHDivNodesData *data = static_cast<BVHDivNodesData *>(userdata);
693
694 int k;
695 const int parent_level_index = j - data->i;
696 BVHNode *parent = &data->branches_array[j];
697 int nth_positions[MAX_TREETYPE + 1];
698 char split_axis;
699
700 int parent_leafs_begin = implicit_leafs_index(data->data, data->depth, parent_level_index);
701 int parent_leafs_end = implicit_leafs_index(data->data, data->depth, parent_level_index + 1);
702
703 /* This calculates the bounding box of this branch
704 * and chooses the largest axis as the axis to divide leafs */
705 refit_kdop_hull(data->tree, parent, parent_leafs_begin, parent_leafs_end);
706 split_axis = get_largest_axis(parent->bv);
707
708 /* Save split axis (this can be used on ray-tracing to speedup the query time) */
709 parent->main_axis = split_axis / 2;
710
711 /* Split the children along the split_axis, NOTE: its not needed to sort the whole leafs array
712 * Only to assure that the elements are partitioned on a way that each child takes the elements
713 * it would take in case the whole array was sorted.
714 * Split_leafs takes care of that "sort" problem. */
715 nth_positions[0] = parent_leafs_begin;
716 nth_positions[data->tree_type] = parent_leafs_end;
717 for (k = 1; k < data->tree_type; k++) {
718 const int child_index = j * data->tree_type + data->tree_offset + k;
719 /* child level index */
720 const int child_level_index = child_index - data->first_of_next_level;
721 nth_positions[k] = implicit_leafs_index(data->data, data->depth + 1, child_level_index);
722 }
723
724 split_leafs(data->leafs_array, nth_positions, data->tree_type, split_axis);
725
726 /* Setup `children` and `node_num` counters
727 * Not really needed but currently most of BVH code
728 * relies on having an explicit children structure */
729 for (k = 0; k < data->tree_type; k++) {
730 const int child_index = j * data->tree_type + data->tree_offset + k;
731 /* child level index */
732 const int child_level_index = child_index - data->first_of_next_level;
733
734 const int child_leafs_begin = implicit_leafs_index(
735 data->data, data->depth + 1, child_level_index);
736 const int child_leafs_end = implicit_leafs_index(
737 data->data, data->depth + 1, child_level_index + 1);
738
739 if (child_leafs_end - child_leafs_begin > 1) {
740 parent->children[k] = &data->branches_array[child_index];
741 parent->children[k]->parent = parent;
742 }
743 else if (child_leafs_end - child_leafs_begin == 1) {
744 parent->children[k] = data->leafs_array[child_leafs_begin];
745 parent->children[k]->parent = parent;
746 }
747 else {
748 break;
749 }
750 }
751 parent->node_num = char(k);
752}
753
773 BVHNode *branches_array,
774 BVHNode **leafs_array,
775 int leafs_num)
776{
777 int i;
778
779 const int tree_type = tree->tree_type;
780 /* this value is 0 (on binary trees) and negative on the others */
781 const int tree_offset = 2 - tree->tree_type;
782
783 const int branches_num = implicit_needed_branches(tree_type, leafs_num);
784
786 int depth;
787
788 {
789 /* set parent from root node to nullptr */
790 BVHNode *root = &branches_array[1];
791 root->parent = nullptr;
792
793 /* Most of bvhtree code relies on 1-leaf trees having at least one branch
794 * We handle that special case here */
795 if (leafs_num == 1) {
796 refit_kdop_hull(tree, root, 0, leafs_num);
797 root->main_axis = get_largest_axis(root->bv) / 2;
798 root->node_num = 1;
799 root->children[0] = leafs_array[0];
800 root->children[0]->parent = root;
801 return;
802 }
803 }
804
806
807 BVHDivNodesData cb_data{};
808 cb_data.tree = tree;
809 cb_data.branches_array = branches_array;
810 cb_data.leafs_array = leafs_array;
811 cb_data.tree_type = tree_type;
812 cb_data.tree_offset = tree_offset;
813 cb_data.data = &data;
814 cb_data.first_of_next_level = 0;
815 cb_data.depth = 0;
816 cb_data.i = 0;
817
818 /* Loop tree levels (log N) loops */
819 for (i = 1, depth = 1; i <= branches_num; i = i * tree_type + tree_offset, depth++) {
820 const int first_of_next_level = i * tree_type + tree_offset;
821 /* index of last branch on this level */
822 const int i_stop = min_ii(first_of_next_level, branches_num + 1);
823
824 /* Loop all branches on this level */
825 cb_data.first_of_next_level = first_of_next_level;
826 cb_data.i = i;
827 cb_data.depth = depth;
828
829 if (true) {
830 TaskParallelSettings settings;
832 settings.use_threading = (leafs_num > KDOPBVH_THREAD_LEAF_THRESHOLD);
834 }
835 else {
836 /* Less hassle for debugging. */
837 TaskParallelTLS tls = {nullptr};
838 for (int i_task = i; i_task < i_stop; i_task++) {
839 non_recursive_bvh_div_nodes_task_cb(&cb_data, i_task, &tls);
840 }
841 }
842 }
843}
844
846
847/* -------------------------------------------------------------------- */
850
851BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis)
852{
853 int numnodes, i;
854
855 BLI_assert(tree_type >= 2 && tree_type <= MAX_TREETYPE);
856
857 BVHTree *tree = MEM_callocN<BVHTree>(__func__);
858
859 /* tree epsilon must be >= FLT_EPSILON
860 * so that tangent rays can still hit a bounding volume..
861 * this bug would show up when casting a ray aligned with a KDOP-axis
862 * and with an edge of 2 faces */
863 epsilon = max_ff(FLT_EPSILON, epsilon);
864
865 if (tree) {
866 tree->epsilon = epsilon;
867 tree->tree_type = tree_type;
868 tree->axis = axis;
869
870 if (axis == 26) {
871 tree->start_axis = 0;
872 tree->stop_axis = 13;
873 }
874 else if (axis == 18) {
875 tree->start_axis = 7;
876 tree->stop_axis = 13;
877 }
878 else if (axis == 14) {
879 tree->start_axis = 0;
880 tree->stop_axis = 7;
881 }
882 else if (axis == 8) { /* AABB */
883 tree->start_axis = 0;
884 tree->stop_axis = 4;
885 }
886 else if (axis == 6) { /* OBB */
887 tree->start_axis = 0;
888 tree->stop_axis = 3;
889 }
890 else {
891 /* should never happen! */
893
894 goto fail;
895 }
896
897 /* Allocate arrays */
898 numnodes = maxsize + implicit_needed_branches(tree_type, maxsize) + tree_type;
899
900 tree->nodes = MEM_calloc_arrayN<BVHNode *>(size_t(numnodes), "BVHNodes");
901 tree->nodebv = MEM_calloc_arrayN<float>(axis * size_t(numnodes), "BVHNodeBV");
902 tree->nodechild = MEM_calloc_arrayN<BVHNode *>(tree_type * size_t(numnodes), "BVHNodeBV");
903 tree->nodearray = MEM_calloc_arrayN<BVHNode>(size_t(numnodes), "BVHNodeArray");
904
905 if (UNLIKELY((!tree->nodes) || (!tree->nodebv) || (!tree->nodechild) || (!tree->nodearray))) {
906 goto fail;
907 }
908
909 /* link the dynamic bv and child links */
910 for (i = 0; i < numnodes; i++) {
911 tree->nodearray[i].bv = &tree->nodebv[i * axis];
912 tree->nodearray[i].children = &tree->nodechild[i * tree_type];
913 }
914 }
915 return tree;
916
917fail:
919 return nullptr;
920}
921
923{
924 if (tree) {
925 MEM_SAFE_FREE(tree->nodes);
926 MEM_SAFE_FREE(tree->nodearray);
927 MEM_SAFE_FREE(tree->nodebv);
928 MEM_SAFE_FREE(tree->nodechild);
930 }
931}
932
934{
935 BVHNode **leafs_array = tree->nodes;
936
937 /* This function should only be called once
938 * (some big bug goes here if its being called more than once per tree) */
939 BLI_assert(tree->branch_num == 0);
940
941 /* Build the implicit tree */
943 tree, tree->nodearray + (tree->leaf_num - 1), leafs_array, tree->leaf_num);
944
945 /* current code expects the branches to be linked to the nodes array
946 * we perform that linkage here */
947 tree->branch_num = implicit_needed_branches(tree->tree_type, tree->leaf_num);
948 for (int i = 0; i < tree->branch_num; i++) {
949 tree->nodes[tree->leaf_num + i] = &tree->nodearray[tree->leaf_num + i];
950 }
951
952#ifdef USE_SKIP_LINKS
953 build_skip_links(tree, tree->nodes[tree->leaf_num], nullptr, nullptr);
954#endif
955
956#ifdef USE_VERIFY_TREE
957 bvhtree_verify(tree);
958#endif
959
960#ifdef USE_PRINT_TREE
961 bvhtree_info(tree);
962#endif
963}
964
965static void bvhtree_node_inflate(const BVHTree *tree, BVHNode *node, const float dist)
966{
967 axis_t axis_iter;
968 for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) {
969 float dist_corrected = dist * bvhtree_kdop_axes_length[axis_iter];
970 node->bv[(2 * axis_iter)] -= dist_corrected; /* minimum */
971 node->bv[(2 * axis_iter) + 1] += dist_corrected; /* maximum */
972 }
973}
974
975void BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints)
976{
977 BVHNode *node = nullptr;
978
979 /* insert should only possible as long as tree->branch_num is 0 */
980 BLI_assert(tree->branch_num <= 0);
981 BLI_assert((size_t)tree->leaf_num < MEM_allocN_len(tree->nodes) / sizeof(*(tree->nodes)));
982
983 node = tree->nodes[tree->leaf_num] = &(tree->nodearray[tree->leaf_num]);
984 tree->leaf_num++;
985
986 create_kdop_hull(tree, node, co, numpoints, 0);
987 node->index = index;
988
989 /* inflate the bv with some epsilon */
990 bvhtree_node_inflate(tree, node, tree->epsilon);
991}
992
994 BVHTree *tree, int index, const float co[3], const float co_moving[3], int numpoints)
995{
996 BVHNode *node = nullptr;
997
998 /* check if index exists */
999 if (index > tree->leaf_num) {
1000 return false;
1001 }
1002
1003 node = tree->nodearray + index;
1004
1005 create_kdop_hull(tree, node, co, numpoints, 0);
1006
1007 if (co_moving) {
1008 create_kdop_hull(tree, node, co_moving, numpoints, 1);
1009 }
1010
1011 /* inflate the bv with some epsilon */
1012 bvhtree_node_inflate(tree, node, tree->epsilon);
1013
1014 return true;
1015}
1016
1018{
1019 /* Update bottom=>top
1020 * TRICKY: the way we build the tree all the children have an index greater than the parent
1021 * This allows us todo a bottom up update by starting on the bigger numbered branch. */
1022
1023 BVHNode **root = tree->nodes + tree->leaf_num;
1024 BVHNode **index = tree->nodes + tree->leaf_num + tree->branch_num - 1;
1025
1026 for (; index >= root; index--) {
1027 node_join(tree, *index);
1028 }
1029}
1031{
1032 return tree->leaf_num;
1033}
1034
1036{
1037 return tree->tree_type;
1038}
1039
1041{
1042 return tree->epsilon;
1043}
1044
1045void BLI_bvhtree_get_bounding_box(const BVHTree *tree, float r_bb_min[3], float r_bb_max[3])
1046{
1047 const BVHNode *root = tree->nodes[tree->leaf_num];
1048 if (root != nullptr) {
1049 const float bb_min[3] = {root->bv[0], root->bv[2], root->bv[4]};
1050 const float bb_max[3] = {root->bv[1], root->bv[3], root->bv[5]};
1051 copy_v3_v3(r_bb_min, bb_min);
1052 copy_v3_v3(r_bb_max, bb_max);
1053 }
1054 else {
1055 BLI_assert(false);
1056 zero_v3(r_bb_min);
1057 zero_v3(r_bb_max);
1058 }
1059}
1060
1062
1063/* -------------------------------------------------------------------- */
1066
1070static bool tree_overlap_test(const BVHNode *node1,
1071 const BVHNode *node2,
1072 axis_t start_axis,
1073 axis_t stop_axis)
1074{
1075 const float *bv1 = node1->bv + (start_axis << 1);
1076 const float *bv2 = node2->bv + (start_axis << 1);
1077 const float *bv1_end = node1->bv + (stop_axis << 1);
1078
1079 /* test all axis if min + max overlap */
1080 for (; bv1 != bv1_end; bv1 += 2, bv2 += 2) {
1081 if ((bv1[0] > bv2[1]) || (bv2[0] > bv1[1])) {
1082 return false;
1083 }
1084 }
1085
1086 return true;
1087}
1088
1090 const BVHNode *node1,
1091 const BVHNode *node2)
1092{
1093 const BVHOverlapData_Shared *data = data_thread->shared;
1094 int j;
1095
1096 if (tree_overlap_test(node1, node2, data->start_axis, data->stop_axis)) {
1097 /* check if node1 is a leaf */
1098 if (!node1->node_num) {
1099 /* check if node2 is a leaf */
1100 if (!node2->node_num) {
1101 BVHTreeOverlap *overlap;
1102
1103 if (UNLIKELY(node1 == node2)) {
1104 return;
1105 }
1106
1107 /* both leafs, insert overlap! */
1108 overlap = static_cast<BVHTreeOverlap *>(BLI_stack_push_r(data_thread->overlap));
1109 overlap->indexA = node1->index;
1110 overlap->indexB = node2->index;
1111 }
1112 else {
1113 for (j = 0; j < data->tree2->tree_type; j++) {
1114 if (node2->children[j]) {
1115 tree_overlap_traverse(data_thread, node1, node2->children[j]);
1116 }
1117 }
1118 }
1119 }
1120 else {
1121 for (j = 0; j < data->tree1->tree_type; j++) {
1122 if (node1->children[j]) {
1123 tree_overlap_traverse(data_thread, node1->children[j], node2);
1124 }
1125 }
1126 }
1127 }
1128}
1129
1134 const BVHNode *node1,
1135 const BVHNode *node2)
1136{
1137 BVHOverlapData_Shared *data = data_thread->shared;
1138 int j;
1139
1140 if (tree_overlap_test(node1, node2, data->start_axis, data->stop_axis)) {
1141 /* check if node1 is a leaf */
1142 if (!node1->node_num) {
1143 /* check if node2 is a leaf */
1144 if (!node2->node_num) {
1145 BVHTreeOverlap *overlap;
1146
1147 if (UNLIKELY(node1 == node2)) {
1148 return;
1149 }
1150
1151 /* only difference to tree_overlap_traverse! */
1152 if (data->callback(data->userdata, node1->index, node2->index, data_thread->thread)) {
1153 /* both leafs, insert overlap! */
1154 overlap = static_cast<BVHTreeOverlap *>(BLI_stack_push_r(data_thread->overlap));
1155 overlap->indexA = node1->index;
1156 overlap->indexB = node2->index;
1157 }
1158 }
1159 else {
1160 for (j = 0; j < data->tree2->tree_type; j++) {
1161 if (node2->children[j]) {
1162 tree_overlap_traverse_cb(data_thread, node1, node2->children[j]);
1163 }
1164 }
1165 }
1166 }
1167 else {
1168 for (j = 0; j < data->tree1->tree_type; j++) {
1169 if (node1->children[j]) {
1170 tree_overlap_traverse_cb(data_thread, node1->children[j], node2);
1171 }
1172 }
1173 }
1174 }
1175}
1176
1181 const BVHNode *node1,
1182 const BVHNode *node2)
1183{
1184 BVHOverlapData_Shared *data = data_thread->shared;
1185 int j;
1186
1187 if (tree_overlap_test(node1, node2, data->start_axis, data->stop_axis)) {
1188 /* check if node1 is a leaf */
1189 if (!node1->node_num) {
1190 /* check if node2 is a leaf */
1191 if (!node2->node_num) {
1192 BVHTreeOverlap *overlap;
1193
1194 if (UNLIKELY(node1 == node2)) {
1195 return false;
1196 }
1197
1198 /* only difference to tree_overlap_traverse! */
1199 if (!data->callback ||
1200 data->callback(data->userdata, node1->index, node2->index, data_thread->thread))
1201 {
1202 /* both leafs, insert overlap! */
1203 if (data_thread->overlap) {
1204 overlap = static_cast<BVHTreeOverlap *>(BLI_stack_push_r(data_thread->overlap));
1205 overlap->indexA = node1->index;
1206 overlap->indexB = node2->index;
1207 }
1208 return (--data_thread->max_interactions) == 0;
1209 }
1210 }
1211 else {
1212 for (j = 0; j < node2->node_num; j++) {
1213 if (tree_overlap_traverse_num(data_thread, node1, node2->children[j])) {
1214 return true;
1215 }
1216 }
1217 }
1218 }
1219 else {
1220 const uint max_interactions = data_thread->max_interactions;
1221 for (j = 0; j < node1->node_num; j++) {
1222 if (tree_overlap_traverse_num(data_thread, node1->children[j], node2)) {
1223 data_thread->max_interactions = max_interactions;
1224 }
1225 }
1226 }
1227 }
1228 return false;
1229}
1230
1233 const BVHNode *node1,
1234 const BVHNode *node2)
1235{
1236 if (data->max_interactions) {
1237 tree_overlap_traverse_num(data, node1, node2);
1238 }
1239 else if (data->shared->callback) {
1240 tree_overlap_traverse_cb(data, node1, node2);
1241 }
1242 else {
1243 tree_overlap_traverse(data, node1, node2);
1244 }
1245}
1246
1249{
1250 for (int i = 0; i < node->node_num; i++) {
1251 /* Recursively compute self-overlap within each child. */
1252 tree_overlap_traverse_self_cb(data_thread, node->children[i]);
1253
1254 /* Compute overlap of pairs of children, testing each one only once (assume symmetry). */
1255 for (int j = i + 1; j < node->node_num; j++) {
1256 tree_overlap_traverse_cb(data_thread, node->children[i], node->children[j]);
1257 }
1258 }
1259}
1260
1262static void tree_overlap_traverse_self(BVHOverlapData_Thread *data_thread, const BVHNode *node)
1263{
1264 for (int i = 0; i < node->node_num; i++) {
1265 /* Recursively compute self-overlap within each child. */
1266 tree_overlap_traverse_self(data_thread, node->children[i]);
1267
1268 /* Compute overlap of pairs of children, testing each one only once (assume symmetry). */
1269 for (int j = i + 1; j < node->node_num; j++) {
1270 tree_overlap_traverse(data_thread, node->children[i], node->children[j]);
1271 }
1272 }
1273}
1274
1277 const BVHNode *node)
1278{
1279 if (data_thread->shared->callback) {
1280 tree_overlap_traverse_self_cb(data_thread, node);
1281 }
1282 else {
1283 tree_overlap_traverse_self(data_thread, node);
1284 }
1285}
1286
1288{
1289 return std::min<int>(tree->tree_type, tree->nodes[tree->leaf_num]->node_num);
1290}
1291
1292static void bvhtree_overlap_task_cb(void *__restrict userdata,
1293 const int j,
1294 const TaskParallelTLS *__restrict /*tls*/)
1295{
1297 BVHOverlapData_Shared *data_shared = data->shared;
1298
1299 const BVHNode *root1 = data_shared->tree1->nodes[data_shared->tree1->leaf_num];
1300
1301 if (data_shared->use_self) {
1302 /* This code matches one outer loop iteration within traverse_self. */
1304
1305 for (int k = j + 1; k < root1->node_num; k++) {
1306 tree_overlap_invoke_traverse(data, root1->children[j], root1->children[k]);
1307 }
1308 }
1309 else {
1310 const BVHNode *root2 = data_shared->tree2->nodes[data_shared->tree2->leaf_num];
1311
1312 tree_overlap_invoke_traverse(data, root1->children[j], root2);
1313 }
1314}
1315
1317 const BVHTree *tree1,
1318 const BVHTree *tree2,
1319 uint *r_overlap_num,
1320 /* optional callback to test the overlap before adding (must be thread-safe!) */
1321 BVHTree_OverlapCallback callback,
1322 void *userdata,
1323 const uint max_interactions,
1324 const int flag)
1325{
1326 bool overlap_pairs = (flag & BVH_OVERLAP_RETURN_PAIRS) != 0;
1327 bool use_threading = (flag & BVH_OVERLAP_USE_THREADING) != 0 &&
1329 bool use_self = (flag & BVH_OVERLAP_SELF) != 0;
1330
1331 /* 'RETURN_PAIRS' was not implemented without 'max_interactions'. */
1332 BLI_assert(overlap_pairs || max_interactions);
1333 /* Self-overlap does not support max interactions (it's not symmetrical). */
1334 BLI_assert(!use_self || (tree1 == tree2 && !max_interactions));
1335
1336 const int root_node_len = BLI_bvhtree_overlap_thread_num(tree1);
1337 const int thread_num = use_threading ? root_node_len : 1;
1338 int j;
1339 size_t total = 0;
1340 BVHTreeOverlap *overlap = nullptr, *to = nullptr;
1341 BVHOverlapData_Shared data_shared;
1342 BVHOverlapData_Thread *data = BLI_array_alloca(data, size_t(thread_num));
1343 axis_t start_axis, stop_axis;
1344
1345 /* check for compatibility of both trees (can't compare 14-DOP with 18-DOP) */
1346 if (UNLIKELY((tree1->axis != tree2->axis) && (tree1->axis == 14 || tree2->axis == 14) &&
1347 (tree1->axis == 18 || tree2->axis == 18)))
1348 {
1349 BLI_assert(0);
1350 return nullptr;
1351 }
1352
1353 if (UNLIKELY(use_self && tree1 != tree2)) {
1354 use_self = false;
1355 }
1356
1357 const BVHNode *root1 = tree1->nodes[tree1->leaf_num];
1358 const BVHNode *root2 = tree2->nodes[tree2->leaf_num];
1359
1360 start_axis = min_axis(tree1->start_axis, tree2->start_axis);
1361 stop_axis = min_axis(tree1->stop_axis, tree2->stop_axis);
1362
1363 /* fast check root nodes for collision before doing big splitting + traversal */
1364 if (!tree_overlap_test(root1, root2, start_axis, stop_axis)) {
1365 return nullptr;
1366 }
1367
1368 data_shared.tree1 = tree1;
1369 data_shared.tree2 = tree2;
1370 data_shared.start_axis = start_axis;
1371 data_shared.stop_axis = stop_axis;
1372 data_shared.use_self = use_self;
1373
1374 /* can be nullptr */
1375 data_shared.callback = callback;
1376 data_shared.userdata = userdata;
1377
1378 for (j = 0; j < thread_num; j++) {
1379 /* init BVHOverlapData_Thread */
1380 data[j].shared = &data_shared;
1381 data[j].overlap = overlap_pairs ? BLI_stack_new(sizeof(BVHTreeOverlap), __func__) : nullptr;
1382 data[j].max_interactions = use_self ? 0 : max_interactions;
1383
1384 /* for callback */
1385 data[j].thread = j;
1386 }
1387
1388 if (use_threading) {
1389 TaskParallelSettings settings;
1391 settings.min_iter_per_thread = 1;
1392 BLI_task_parallel_range(0, root_node_len, data, bvhtree_overlap_task_cb, &settings);
1393 }
1394 else if (use_self) {
1396 }
1397 else {
1398 tree_overlap_invoke_traverse(data, root1, root2);
1399 }
1400
1401 if (overlap_pairs) {
1402 for (j = 0; j < thread_num; j++) {
1403 total += BLI_stack_count(data[j].overlap);
1404 }
1405
1406 to = overlap = MEM_malloc_arrayN<BVHTreeOverlap>(total, "BVHTreeOverlap");
1407
1408 for (j = 0; j < thread_num; j++) {
1409 uint count = uint(BLI_stack_count(data[j].overlap));
1410 BLI_stack_pop_n(data[j].overlap, to, count);
1411 BLI_stack_free(data[j].overlap);
1412 to += count;
1413 }
1414 *r_overlap_num = uint(total);
1415 }
1416
1417 return overlap;
1418}
1419
1421 const BVHTree *tree1,
1422 const BVHTree *tree2,
1423 uint *r_overlap_num,
1424 /* optional callback to test the overlap before adding (must be thread-safe!) */
1425 BVHTree_OverlapCallback callback,
1426 void *userdata)
1427{
1428 return BLI_bvhtree_overlap_ex(tree1,
1429 tree2,
1430 r_overlap_num,
1431 callback,
1432 userdata,
1433 0,
1435}
1436
1438 const BVHTree *tree,
1439 uint *r_overlap_num,
1440 /* optional callback to test the overlap before adding (must be thread-safe!) */
1441 BVHTree_OverlapCallback callback,
1442 void *userdata)
1443{
1445 tree,
1446 r_overlap_num,
1447 callback,
1448 userdata,
1449 0,
1452}
1453
1455
1456/* -------------------------------------------------------------------- */
1459
1460static bool tree_intersect_plane_test(const float *bv, const float plane[4])
1461{
1462 /* TODO(@germano): Support other KDOP geometries. */
1463 const float bb_min[3] = {bv[0], bv[2], bv[4]};
1464 const float bb_max[3] = {bv[1], bv[3], bv[5]};
1465 float bb_near[3], bb_far[3];
1466 aabb_get_near_far_from_plane(plane, bb_min, bb_max, bb_near, bb_far);
1467 if ((plane_point_side_v3(plane, bb_near) > 0.0f) != (plane_point_side_v3(plane, bb_far) > 0.0f))
1468 {
1469 return true;
1470 }
1471
1472 return false;
1473}
1474
1476 const BVHNode *node)
1477{
1478 if (tree_intersect_plane_test(node->bv, data->plane)) {
1479 /* check if node is a leaf */
1480 if (!node->node_num) {
1481 int *intersect = static_cast<int *>(BLI_stack_push_r(data->intersect));
1482 *intersect = node->index;
1483 }
1484 else {
1485 for (int j = 0; j < data->tree->tree_type; j++) {
1486 if (node->children[j]) {
1488 }
1489 }
1490 }
1491 }
1492}
1493
1494int *BLI_bvhtree_intersect_plane(const BVHTree *tree, float plane[4], uint *r_intersect_num)
1495{
1496 int *intersect = nullptr;
1497 size_t total = 0;
1498
1499 if (tree->leaf_num) {
1501 data.tree = tree;
1502 copy_v4_v4(data.plane, plane);
1503 data.intersect = BLI_stack_new(sizeof(int), __func__);
1504
1505 const BVHNode *root = tree->nodes[tree->leaf_num];
1507
1508 total = BLI_stack_count(data.intersect);
1509 if (total) {
1510 intersect = MEM_malloc_arrayN<int>(total, __func__);
1511 BLI_stack_pop_n(data.intersect, intersect, uint(total));
1512 }
1513 BLI_stack_free(data.intersect);
1514 }
1515 *r_intersect_num = uint(total);
1516 return intersect;
1517}
1518
1520
1521/* -------------------------------------------------------------------- */
1524
1525/* Determines the nearest point of the given node BV.
1526 * Returns the squared distance to that point. */
1527static float calc_nearest_point_squared(const float proj[3], BVHNode *node, float nearest[3])
1528{
1529 int i;
1530 const float *bv = node->bv;
1531
1532 /* nearest on AABB hull */
1533 for (i = 0; i != 3; i++, bv += 2) {
1534 float val = proj[i];
1535 val = std::max(bv[0], val);
1536 val = std::min(bv[1], val);
1537 nearest[i] = val;
1538 }
1539
1540 return len_squared_v3v3(proj, nearest);
1541}
1542
1543/* Depth first search method */
1545{
1546 if (node->node_num == 0) {
1547 if (data->callback) {
1548 data->callback(data->userdata, node->index, data->co, &data->nearest);
1549 }
1550 else {
1551 data->nearest.index = node->index;
1552 data->nearest.dist_sq = calc_nearest_point_squared(data->proj, node, data->nearest.co);
1553 }
1554 }
1555 else {
1556 /* Better heuristic to pick the closest node to dive on */
1557 int i;
1558 float nearest[3];
1559
1560 if (data->proj[node->main_axis] <= node->children[0]->bv[node->main_axis * 2 + 1]) {
1561
1562 for (i = 0; i != node->node_num; i++) {
1563 if (calc_nearest_point_squared(data->proj, node->children[i], nearest) >=
1564 data->nearest.dist_sq)
1565 {
1566 continue;
1567 }
1569 }
1570 }
1571 else {
1572 for (i = node->node_num - 1; i >= 0; i--) {
1573 if (calc_nearest_point_squared(data->proj, node->children[i], nearest) >=
1574 data->nearest.dist_sq)
1575 {
1576 continue;
1577 }
1579 }
1580 }
1581 }
1582}
1583
1585{
1586 float nearest[3], dist_sq;
1587 dist_sq = calc_nearest_point_squared(data->proj, node, nearest);
1588 if (dist_sq >= data->nearest.dist_sq) {
1589 return;
1590 }
1592}
1593
1594/* Priority queue method */
1596{
1597 if (node->node_num == 0) {
1598 if (data->callback) {
1599 data->callback(data->userdata, node->index, data->co, &data->nearest);
1600 }
1601 else {
1602 data->nearest.index = node->index;
1603 data->nearest.dist_sq = calc_nearest_point_squared(data->proj, node, data->nearest.co);
1604 }
1605 }
1606 else {
1607 float nearest[3];
1608
1609 for (int i = 0; i != node->node_num; i++) {
1610 float dist_sq = calc_nearest_point_squared(data->proj, node->children[i], nearest);
1611
1612 if (dist_sq < data->nearest.dist_sq) {
1613 BLI_heapsimple_insert(heap, dist_sq, node->children[i]);
1614 }
1615 }
1616 }
1617}
1618
1620{
1621 float nearest[3];
1622 float dist_sq = calc_nearest_point_squared(data->proj, root, nearest);
1623
1624 if (dist_sq < data->nearest.dist_sq) {
1626
1627 heap_find_nearest_inner(data, heap, root);
1628
1629 while (!BLI_heapsimple_is_empty(heap) &&
1630 BLI_heapsimple_top_value(heap) < data->nearest.dist_sq)
1631 {
1632 BVHNode *node = static_cast<BVHNode *>(BLI_heapsimple_pop_min(heap));
1633 heap_find_nearest_inner(data, heap, node);
1634 }
1635
1636 BLI_heapsimple_free(heap, nullptr);
1637 }
1638}
1639
1641 const float co[3],
1642 BVHTreeNearest *nearest,
1644 void *userdata,
1645 int flag)
1646{
1647 axis_t axis_iter;
1648
1650 BVHNode *root = tree->nodes[tree->leaf_num];
1651
1652 /* init data to search */
1653 data.tree = tree;
1654 data.co = co;
1655
1656 data.callback = callback;
1657 data.userdata = userdata;
1658
1659 for (axis_iter = data.tree->start_axis; axis_iter != data.tree->stop_axis; axis_iter++) {
1660 data.proj[axis_iter] = dot_v3v3(data.co, bvhtree_kdop_axes[axis_iter]);
1661 }
1662
1663 if (nearest) {
1664 memcpy(&data.nearest, nearest, sizeof(*nearest));
1665 }
1666 else {
1667 data.nearest.index = -1;
1668 data.nearest.dist_sq = FLT_MAX;
1669 }
1670
1671 /* dfs search */
1672 if (root) {
1675 }
1676 else {
1678 }
1679 }
1680
1681 /* copy back results */
1682 if (nearest) {
1683 memcpy(nearest, &data.nearest, sizeof(*nearest));
1684 }
1685
1686 return data.nearest.index;
1687}
1688
1690 const float co[3],
1691 BVHTreeNearest *nearest,
1693 void *userdata)
1694{
1695 return BLI_bvhtree_find_nearest_ex(tree, co, nearest, callback, userdata, 0);
1696}
1697
1699
1700/* -------------------------------------------------------------------- */
1703
1704static bool isect_aabb_v3(BVHNode *node, const float co[3])
1705{
1706 const BVHTreeAxisRange *bv = (const BVHTreeAxisRange *)node->bv;
1707
1708 if (co[0] > bv[0].min && co[0] < bv[0].max && co[1] > bv[1].min && co[1] < bv[1].max &&
1709 co[2] > bv[2].min && co[2] < bv[2].max)
1710 {
1711 return true;
1712 }
1713
1714 return false;
1715}
1716
1718{
1719 if (node->node_num == 0) {
1720 if (isect_aabb_v3(node, data->co)) {
1721 if (data->callback) {
1722 const float dist_sq = data->nearest.dist_sq;
1723 data->callback(data->userdata, node->index, data->co, &data->nearest);
1724 return (data->nearest.dist_sq < dist_sq);
1725 }
1726 data->nearest.index = node->index;
1727 return true;
1728 }
1729 }
1730 else {
1731 /* Better heuristic to pick the closest node to dive on */
1732 int i;
1733
1734 if (data->proj[node->main_axis] <= node->children[0]->bv[node->main_axis * 2 + 1]) {
1735 for (i = 0; i != node->node_num; i++) {
1736 if (isect_aabb_v3(node->children[i], data->co)) {
1738 return true;
1739 }
1740 }
1741 }
1742 }
1743 else {
1744 for (i = node->node_num; i--;) {
1745 if (isect_aabb_v3(node->children[i], data->co)) {
1747 return true;
1748 }
1749 }
1750 }
1751 }
1752 }
1753 return false;
1754}
1755
1757 const float co[3],
1758 const float dist_sq,
1760 void *userdata)
1761{
1763 BVHNode *root = tree->nodes[tree->leaf_num];
1764
1765 /* init data to search */
1766 data.tree = tree;
1767 data.co = co;
1768
1769 data.callback = callback;
1770 data.userdata = userdata;
1771 data.nearest.index = -1;
1772 data.nearest.dist_sq = dist_sq;
1773
1774 /* dfs search */
1775 if (root) {
1777 }
1778
1779 return data.nearest.index;
1780}
1781
1783
1784/* -------------------------------------------------------------------- */
1790
1791/* Determines the distance that the ray must travel to hit the bounding volume of the given node */
1792static float ray_nearest_hit(const BVHRayCastData *data, const float bv[6])
1793{
1794 int i;
1795
1796 float low = 0, upper = data->hit.dist;
1797
1798 for (i = 0; i != 3; i++, bv += 2) {
1799 if (data->ray_dot_axis[i] == 0.0f) {
1800 /* axis aligned ray */
1801 if (data->ray.origin[i] < bv[0] - data->ray.radius ||
1802 data->ray.origin[i] > bv[1] + data->ray.radius)
1803 {
1804 return FLT_MAX;
1805 }
1806 }
1807 else {
1808 float ll = (bv[0] - data->ray.radius - data->ray.origin[i]) / data->ray_dot_axis[i];
1809 float lu = (bv[1] + data->ray.radius - data->ray.origin[i]) / data->ray_dot_axis[i];
1810
1811 if (data->ray_dot_axis[i] > 0.0f) {
1812 low = std::max(ll, low);
1813 upper = std::min(lu, upper);
1814 }
1815 else {
1816 low = std::max(lu, low);
1817 upper = std::min(ll, upper);
1818 }
1819
1820 if (low > upper) {
1821 return FLT_MAX;
1822 }
1823 }
1824 }
1825 return low;
1826}
1827
1834static float fast_ray_nearest_hit(const BVHRayCastData *data, const BVHNode *node)
1835{
1836 const float *bv = node->bv;
1837
1838 float t1x = (bv[data->index[0]] - data->ray.origin[0]) * data->idot_axis[0];
1839 float t2x = (bv[data->index[1]] - data->ray.origin[0]) * data->idot_axis[0];
1840 float t1y = (bv[data->index[2]] - data->ray.origin[1]) * data->idot_axis[1];
1841 float t2y = (bv[data->index[3]] - data->ray.origin[1]) * data->idot_axis[1];
1842 float t1z = (bv[data->index[4]] - data->ray.origin[2]) * data->idot_axis[2];
1843 float t2z = (bv[data->index[5]] - data->ray.origin[2]) * data->idot_axis[2];
1844
1845 if ((t1x > t2y || t2x < t1y || t1x > t2z || t2x < t1z || t1y > t2z || t2y < t1z) ||
1846 (t2x < 0.0f || t2y < 0.0f || t2z < 0.0f) ||
1847 (t1x > data->hit.dist || t1y > data->hit.dist || t1z > data->hit.dist))
1848 {
1849 return FLT_MAX;
1850 }
1851 return max_fff(t1x, t1y, t1z);
1852}
1853
1855{
1856 int i;
1857
1858 /* ray-bv is really fast.. and simple tests revealed its worth to test it
1859 * before calling the ray-primitive functions */
1860 /* XXX: temporary solution for particles until fast_ray_nearest_hit supports ray.radius */
1861 float dist = (data->ray.radius == 0.0f) ? fast_ray_nearest_hit(data, node) :
1862 ray_nearest_hit(data, node->bv);
1863 if (dist >= data->hit.dist) {
1864 return;
1865 }
1866
1867 if (node->node_num == 0) {
1868 if (data->callback) {
1869 data->callback(data->userdata, node->index, &data->ray, &data->hit);
1870 }
1871 else {
1872 data->hit.index = node->index;
1873 data->hit.dist = dist;
1874 madd_v3_v3v3fl(data->hit.co, data->ray.origin, data->ray.direction, dist);
1875 }
1876 }
1877 else {
1878 /* pick loop direction to dive into the tree (based on ray direction and split axis) */
1879 if (data->ray_dot_axis[node->main_axis] > 0.0f) {
1880 for (i = 0; i != node->node_num; i++) {
1881 dfs_raycast(data, node->children[i]);
1882 }
1883 }
1884 else {
1885 for (i = node->node_num - 1; i >= 0; i--) {
1886 dfs_raycast(data, node->children[i]);
1887 }
1888 }
1889 }
1890}
1891
1896{
1897 int i;
1898
1899 /* ray-bv is really fast.. and simple tests revealed its worth to test it
1900 * before calling the ray-primitive functions */
1901 /* XXX: temporary solution for particles until fast_ray_nearest_hit supports ray.radius */
1902 float dist = (data->ray.radius == 0.0f) ? fast_ray_nearest_hit(data, node) :
1903 ray_nearest_hit(data, node->bv);
1904 if (dist >= data->hit.dist) {
1905 return;
1906 }
1907
1908 if (node->node_num == 0) {
1909 /* no need to check for 'data->callback' (using 'all' only makes sense with a callback). */
1910 dist = data->hit.dist;
1911 data->callback(data->userdata, node->index, &data->ray, &data->hit);
1912 data->hit.index = -1;
1913 data->hit.dist = dist;
1914 }
1915 else {
1916 /* pick loop direction to dive into the tree (based on ray direction and split axis) */
1917 if (data->ray_dot_axis[node->main_axis] > 0.0f) {
1918 for (i = 0; i != node->node_num; i++) {
1919 dfs_raycast_all(data, node->children[i]);
1920 }
1921 }
1922 else {
1923 for (i = node->node_num - 1; i >= 0; i--) {
1924 dfs_raycast_all(data, node->children[i]);
1925 }
1926 }
1927 }
1928}
1929
1931{
1932 int i;
1933
1934 for (i = 0; i < 3; i++) {
1935 data->ray_dot_axis[i] = dot_v3v3(data->ray.direction, bvhtree_kdop_axes[i]);
1936
1937 if (fabsf(data->ray_dot_axis[i]) < FLT_EPSILON) {
1938 data->ray_dot_axis[i] = 0.0f;
1939 /* Sign is not important in this case, `data->index` is adjusted anyway. */
1940 data->idot_axis[i] = FLT_MAX;
1941 }
1942 else {
1943 data->idot_axis[i] = 1.0f / data->ray_dot_axis[i];
1944 }
1945
1946 data->index[2 * i] = data->idot_axis[i] < 0.0f ? 1 : 0;
1947 data->index[2 * i + 1] = 1 - data->index[2 * i];
1948 data->index[2 * i] += 2 * i;
1949 data->index[2 * i + 1] += 2 * i;
1950 }
1951
1952#ifdef USE_KDOPBVH_WATERTIGHT
1954 isect_ray_tri_watertight_v3_precalc(&data->isect_precalc, data->ray.direction);
1955 data->ray.isect_precalc = &data->isect_precalc;
1956 }
1957 else {
1958 data->ray.isect_precalc = nullptr;
1959 }
1960#else
1962#endif
1963}
1964
1966 const float co[3],
1967 const float dir[3],
1968 float radius,
1969 BVHTreeRayHit *hit,
1970 BVHTree_RayCastCallback callback,
1971 void *userdata,
1972 int flag)
1973{
1975 BVHNode *root = tree->nodes[tree->leaf_num];
1976
1977 BLI_ASSERT_UNIT_V3(dir);
1978
1979 data.tree = tree;
1980
1981 data.callback = callback;
1982 data.userdata = userdata;
1983
1984 copy_v3_v3(data.ray.origin, co);
1985 copy_v3_v3(data.ray.direction, dir);
1986 data.ray.radius = radius;
1987
1989
1990 if (hit) {
1991 memcpy(&data.hit, hit, sizeof(*hit));
1992 }
1993 else {
1994 data.hit.index = -1;
1995 data.hit.dist = BVH_RAYCAST_DIST_MAX;
1996 }
1997
1998 if (root) {
1999 dfs_raycast(&data, root);
2000 // iterative_raycast(&data, root);
2001 }
2002
2003 if (hit) {
2004 memcpy(hit, &data.hit, sizeof(*hit));
2005 }
2006
2007 return data.hit.index;
2008}
2009
2011 const float co[3],
2012 const float dir[3],
2013 float radius,
2014 BVHTreeRayHit *hit,
2015 BVHTree_RayCastCallback callback,
2016 void *userdata)
2017{
2019 tree, co, dir, radius, hit, callback, userdata, BVH_RAYCAST_DEFAULT);
2020}
2021
2022float BLI_bvhtree_bb_raycast(const float bv[6],
2023 const float light_start[3],
2024 const float light_end[3],
2025 float pos[3])
2026{
2028 float dist;
2029
2030 data.hit.dist = BVH_RAYCAST_DIST_MAX;
2031
2032 /* get light direction */
2033 sub_v3_v3v3(data.ray.direction, light_end, light_start);
2034
2035 data.ray.radius = 0.0;
2036
2037 copy_v3_v3(data.ray.origin, light_start);
2038
2039 normalize_v3(data.ray.direction);
2040 copy_v3_v3(data.ray_dot_axis, data.ray.direction);
2041
2042 dist = ray_nearest_hit(&data, bv);
2043
2044 madd_v3_v3v3fl(pos, light_start, data.ray.direction, dist);
2045
2046 return dist;
2047}
2048
2050 const float co[3],
2051 const float dir[3],
2052 float radius,
2053 float hit_dist,
2054 BVHTree_RayCastCallback callback,
2055 void *userdata,
2056 int flag)
2057{
2059 BVHNode *root = tree->nodes[tree->leaf_num];
2060
2061 BLI_ASSERT_UNIT_V3(dir);
2062 BLI_assert(callback != nullptr);
2063
2064 data.tree = tree;
2065
2066 data.callback = callback;
2067 data.userdata = userdata;
2068
2069 copy_v3_v3(data.ray.origin, co);
2070 copy_v3_v3(data.ray.direction, dir);
2071 data.ray.radius = radius;
2072
2074
2075 data.hit.index = -1;
2076 data.hit.dist = hit_dist;
2077
2078 if (root) {
2079 dfs_raycast_all(&data, root);
2080 }
2081}
2082
2084 const float co[3],
2085 const float dir[3],
2086 float radius,
2087 float hit_dist,
2088 BVHTree_RayCastCallback callback,
2089 void *userdata)
2090{
2092 tree, co, dir, radius, hit_dist, callback, userdata, BVH_RAYCAST_DEFAULT);
2093}
2094
2096
2097/* -------------------------------------------------------------------- */
2105
2108 const float *center;
2109 float radius_sq; /* squared radius */
2110
2111 int hits;
2112
2115};
2116
2118{
2119 if (node->node_num == 0) {
2120#if 0 /*UNUSED*/
2121 /* Calculate the node min-coords
2122 * (if the node was a point then this is the point coordinates) */
2123 float co[3];
2124 co[0] = node->bv[0];
2125 co[1] = node->bv[2];
2126 co[2] = node->bv[4];
2127#endif
2128 }
2129 else {
2130 int i;
2131 for (i = 0; i != node->node_num; i++) {
2132 float nearest[3];
2133 float dist_sq = calc_nearest_point_squared(data->center, node->children[i], nearest);
2134 if (dist_sq < data->radius_sq) {
2135 /* Its a leaf.. call the callback */
2136 if (node->children[i]->node_num == 0) {
2137 data->hits++;
2138 data->callback(data->userdata, node->children[i]->index, data->center, dist_sq);
2139 }
2140 else {
2141 dfs_range_query(data, node->children[i]);
2142 }
2143 }
2144 }
2145 }
2146}
2147
2149 const float co[3],
2150 float radius,
2151 BVHTree_RangeQuery callback,
2152 void *userdata)
2153{
2154 BVHNode *root = tree->nodes[tree->leaf_num];
2155
2157 data.tree = tree;
2158 data.center = co;
2159 data.radius_sq = radius * radius;
2160 data.hits = 0;
2161
2162 data.callback = callback;
2163 data.userdata = userdata;
2164
2165 if (root != nullptr) {
2166 float nearest[3];
2167 float dist_sq = calc_nearest_point_squared(data.center, root, nearest);
2168 if (dist_sq < data.radius_sq) {
2169 /* Its a leaf.. call the callback */
2170 if (root->node_num == 0) {
2171 data.hits++;
2172 data.callback(data.userdata, root->index, co, dist_sq);
2173 }
2174 else {
2175 dfs_range_query(&data, root);
2176 }
2177 }
2178 }
2179
2180 return data.hits;
2181}
2182
2184
2185/* -------------------------------------------------------------------- */
2188
2190 const BVHNode *node)
2191{
2192 if (node->node_num == 0) {
2193 if (data->callback) {
2194 data->callback(data->userdata, node->index, &data->precalc, nullptr, 0, &data->nearest);
2195 }
2196 else {
2197 data->nearest.index = node->index;
2198 data->nearest.dist_sq = dist_squared_to_projected_aabb(
2199 &data->precalc,
2200 blender::float3{node->bv[0], node->bv[2], node->bv[4]},
2201 blender::float3{node->bv[1], node->bv[3], node->bv[5]},
2202 data->closest_axis);
2203 }
2204 }
2205 else {
2206 /* First pick the closest node to recurse into */
2207 if (data->closest_axis[node->main_axis]) {
2208 for (int i = 0; i != node->node_num; i++) {
2209 const float *bv = node->children[i]->bv;
2210
2212 blender::float3{bv[0], bv[2], bv[4]},
2213 blender::float3{bv[1], bv[3], bv[5]},
2214 data->closest_axis) <= data->nearest.dist_sq)
2215 {
2217 }
2218 }
2219 }
2220 else {
2221 for (int i = node->node_num; i--;) {
2222 const float *bv = node->children[i]->bv;
2223
2225 blender::float3{bv[0], bv[2], bv[4]},
2226 blender::float3{bv[1], bv[3], bv[5]},
2227 data->closest_axis) <= data->nearest.dist_sq)
2228 {
2230 }
2231 }
2232 }
2233 }
2234}
2235
2237 BVHNearestProjectedData *__restrict data, const BVHNode *node)
2238{
2239 if (node->node_num == 0) {
2240 if (data->callback) {
2241 data->callback(data->userdata,
2242 node->index,
2243 &data->precalc,
2244 data->clip_plane,
2245 data->clip_plane_len,
2246 &data->nearest);
2247 }
2248 else {
2249 data->nearest.index = node->index;
2250 data->nearest.dist_sq = dist_squared_to_projected_aabb(
2251 &data->precalc,
2252 blender::float3{node->bv[0], node->bv[2], node->bv[4]},
2253 blender::float3{node->bv[1], node->bv[3], node->bv[5]},
2254 data->closest_axis);
2255 }
2256 }
2257 else {
2258 /* First pick the closest node to recurse into */
2259 if (data->closest_axis[node->main_axis]) {
2260 for (int i = 0; i != node->node_num; i++) {
2261 const float *bv = node->children[i]->bv;
2262 const float bb_min[3] = {bv[0], bv[2], bv[4]};
2263 const float bb_max[3] = {bv[1], bv[3], bv[5]};
2264
2265 int isect_type = isect_aabb_planes_v3(
2266 data->clip_plane, data->clip_plane_len, bb_min, bb_max);
2267
2268 if ((isect_type != ISECT_AABB_PLANE_BEHIND_ANY) &&
2269 dist_squared_to_projected_aabb(&data->precalc, bb_min, bb_max, data->closest_axis) <=
2270 data->nearest.dist_sq)
2271 {
2272 if (isect_type == ISECT_AABB_PLANE_CROSS_ANY) {
2274 }
2275 else {
2276 /* ISECT_AABB_PLANE_IN_FRONT_ALL */
2278 }
2279 }
2280 }
2281 }
2282 else {
2283 for (int i = node->node_num; i--;) {
2284 const float *bv = node->children[i]->bv;
2285 const float bb_min[3] = {bv[0], bv[2], bv[4]};
2286 const float bb_max[3] = {bv[1], bv[3], bv[5]};
2287
2288 int isect_type = isect_aabb_planes_v3(
2289 data->clip_plane, data->clip_plane_len, bb_min, bb_max);
2290
2291 if (isect_type != ISECT_AABB_PLANE_BEHIND_ANY &&
2292 dist_squared_to_projected_aabb(&data->precalc, bb_min, bb_max, data->closest_axis) <=
2293 data->nearest.dist_sq)
2294 {
2295 if (isect_type == ISECT_AABB_PLANE_CROSS_ANY) {
2297 }
2298 else {
2299 /* ISECT_AABB_PLANE_IN_FRONT_ALL */
2301 }
2302 }
2303 }
2304 }
2305 }
2306}
2307
2309 float projmat[4][4],
2310 float winsize[2],
2311 float mval[2],
2312 float (*clip_plane)[4],
2313 int clip_plane_len,
2314 BVHTreeNearest *nearest,
2316 void *userdata)
2317{
2318 const BVHNode *root = tree->nodes[tree->leaf_num];
2319 if (root != nullptr) {
2321 sizeof(*data) + (sizeof(*clip_plane) * size_t(max_ii(1, clip_plane_len))));
2322
2323 dist_squared_to_projected_aabb_precalc(&data->precalc, projmat, winsize, mval);
2324
2325 data->callback = callback;
2326 data->userdata = userdata;
2327
2328#ifdef __GNUC__ /* Invalid `data->clip_plane` warning with GCC 14.2.1. */
2329# pragma GCC diagnostic push
2330# pragma GCC diagnostic ignored "-Warray-bounds"
2331#endif
2332 if (clip_plane) {
2333 data->clip_plane_len = clip_plane_len;
2334 for (int i = 0; i < clip_plane_len; i++) {
2335 copy_v4_v4(data->clip_plane[i], clip_plane[i]);
2336 }
2337 }
2338 else {
2339 data->clip_plane_len = 1;
2341 projmat, nullptr, nullptr, nullptr, nullptr, data->clip_plane[0], nullptr);
2342 }
2343#ifdef __GNUC__
2344# pragma GCC diagnostic pop
2345#endif
2346
2347 if (nearest) {
2348 memcpy(&data->nearest, nearest, sizeof(*nearest));
2349 }
2350 else {
2351 data->nearest.index = -1;
2352 data->nearest.dist_sq = FLT_MAX;
2353 }
2354 {
2355 const float bb_min[3] = {root->bv[0], root->bv[2], root->bv[4]};
2356 const float bb_max[3] = {root->bv[1], root->bv[3], root->bv[5]};
2357
2358 int isect_type = isect_aabb_planes_v3(
2359 data->clip_plane, data->clip_plane_len, bb_min, bb_max);
2360
2361 if (isect_type != 0 &&
2362 dist_squared_to_projected_aabb(&data->precalc, bb_min, bb_max, data->closest_axis) <=
2363 data->nearest.dist_sq)
2364 {
2365 if (isect_type == 1) {
2367 }
2368 else {
2370 }
2371 }
2372 }
2373
2374 if (nearest) {
2375 memcpy(nearest, &data->nearest, sizeof(*nearest));
2376 }
2377
2378 return data->nearest.index;
2379 }
2380 return -1;
2381}
2382
#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)
@ BVH_NEAREST_OPTIMAL_ORDER
#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
void(*)(void *userdata, int index, const DistProjectedAABBPrecalc *precalc, const float(*clip_plane)[4], int clip_plane_len, BVHTreeNearest *nearest) BVHTree_NearestProjectedCallback
@ BVH_OVERLAP_USE_THREADING
@ BVH_OVERLAP_RETURN_PAIRS
@ BVH_OVERLAP_SELF
void(*)(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) BVHTree_RayCastCallback
void(*)(void *userdata, int index, const float co[3], float dist_sq) BVHTree_RangeQuery
@ BVH_RAYCAST_WATERTIGHT
void(*)(void *userdata, int index, const float co[3], BVHTreeNearest *nearest) BVHTree_NearestPointCallback
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.
iter begin(iter)
BMesh const char void * data
__forceinline BoundBox intersect(const BoundBox &a, const BoundBox &b)
Definition boundbox.h:184
#define fabsf(x)
KDTree_3d * tree
uint pos
#define printf(...)
#define MEM_SAFE_FREE(v)
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 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:139