diff options
author | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:17:24 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:21:24 +0300 |
commit | e12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch) | |
tree | 8cf3453d12edb177a218ef8009357518ec6cab6a /source/blender/blenlib/intern/BLI_kdopbvh.c | |
parent | b3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff) |
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211.
For details on usage and instructions for migrating branches
without conflicts, see:
https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'source/blender/blenlib/intern/BLI_kdopbvh.c')
-rw-r--r-- | source/blender/blenlib/intern/BLI_kdopbvh.c | 2934 |
1 files changed, 1476 insertions, 1458 deletions
diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 7887c55a907..22e64d6717b 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -61,7 +61,6 @@ /* Check tree is valid. */ // #define USE_VERIFY_TREE - #define MAX_TREETYPE 32 /* Setting zero so we can catch bugs in BLI_task/KDOPBVH. @@ -73,7 +72,6 @@ # define KDOPBVH_THREAD_LEAF_THRESHOLD 1024 #endif - /* -------------------------------------------------------------------- */ /** \name Struct Definitions * \{ */ @@ -81,99 +79,97 @@ typedef unsigned char axis_t; typedef struct BVHNode { - struct BVHNode **children; - struct BVHNode *parent; /* some user defined traversed need that */ + struct BVHNode **children; + struct BVHNode *parent; /* some user defined traversed need that */ #ifdef USE_SKIP_LINKS - struct BVHNode *skip[2]; + struct BVHNode *skip[2]; #endif - float *bv; /* Bounding volume of all nodes, max 13 axis */ - int index; /* face, edge, vertex index */ - char totnode; /* how many nodes are used, used for speedup */ - char main_axis; /* Axis used to split this node */ + float *bv; /* Bounding volume of all nodes, max 13 axis */ + int index; /* face, edge, vertex index */ + char totnode; /* how many nodes are used, used for speedup */ + char main_axis; /* Axis used to split this node */ } BVHNode; /* keep under 26 bytes for speed purposes */ struct BVHTree { - BVHNode **nodes; - BVHNode *nodearray; /* pre-alloc branch nodes */ - BVHNode **nodechild; /* pre-alloc childs for nodes */ - float *nodebv; /* pre-alloc bounding-volumes for nodes */ - float epsilon; /* epslion is used for inflation of the k-dop */ - int totleaf; /* leafs */ - int totbranch; - axis_t start_axis, stop_axis; /* bvhtree_kdop_axes array indices according to axis */ - axis_t axis; /* kdop type (6 => OBB, 7 => AABB, ...) */ - char tree_type; /* type of tree (4 => quadtree) */ + BVHNode **nodes; + BVHNode *nodearray; /* pre-alloc branch nodes */ + BVHNode **nodechild; /* pre-alloc childs for nodes */ + float *nodebv; /* pre-alloc bounding-volumes for nodes */ + float epsilon; /* epslion is used for inflation of the k-dop */ + int totleaf; /* leafs */ + int totbranch; + axis_t start_axis, stop_axis; /* bvhtree_kdop_axes array indices according to axis */ + axis_t axis; /* kdop type (6 => OBB, 7 => AABB, ...) */ + char tree_type; /* type of tree (4 => quadtree) */ }; /* optimization, ensure we stay small */ BLI_STATIC_ASSERT((sizeof(void *) == 8 && sizeof(BVHTree) <= 48) || - (sizeof(void *) == 4 && sizeof(BVHTree) <= 32), + (sizeof(void *) == 4 && sizeof(BVHTree) <= 32), "over sized") /* avoid duplicating vars in BVHOverlapData_Thread */ typedef struct BVHOverlapData_Shared { - const BVHTree *tree1, *tree2; - axis_t start_axis, stop_axis; + const BVHTree *tree1, *tree2; + axis_t start_axis, stop_axis; - /* use for callbacks */ - BVHTree_OverlapCallback callback; - void *userdata; + /* use for callbacks */ + BVHTree_OverlapCallback callback; + void *userdata; } BVHOverlapData_Shared; typedef struct BVHOverlapData_Thread { - BVHOverlapData_Shared *shared; - struct BLI_Stack *overlap; /* store BVHTreeOverlap */ - /* use for callbacks */ - int thread; + BVHOverlapData_Shared *shared; + struct BLI_Stack *overlap; /* store BVHTreeOverlap */ + /* use for callbacks */ + int thread; } BVHOverlapData_Thread; typedef struct BVHNearestData { - const BVHTree *tree; - const float *co; - BVHTree_NearestPointCallback callback; - void *userdata; - float proj[13]; /* coordinates projection over axis */ - BVHTreeNearest nearest; + const BVHTree *tree; + const float *co; + BVHTree_NearestPointCallback callback; + void *userdata; + float proj[13]; /* coordinates projection over axis */ + BVHTreeNearest nearest; } BVHNearestData; typedef struct BVHRayCastData { - const BVHTree *tree; + const BVHTree *tree; - BVHTree_RayCastCallback callback; - void *userdata; + BVHTree_RayCastCallback callback; + void *userdata; - - BVHTreeRay ray; + BVHTreeRay ray; #ifdef USE_KDOPBVH_WATERTIGHT - struct IsectRayPrecalc isect_precalc; + struct IsectRayPrecalc isect_precalc; #endif - /* initialized by bvhtree_ray_cast_data_precalc */ - float ray_dot_axis[13]; - float idot_axis[13]; - int index[6]; + /* initialized by bvhtree_ray_cast_data_precalc */ + float ray_dot_axis[13]; + float idot_axis[13]; + int index[6]; - BVHTreeRayHit hit; + BVHTreeRayHit hit; } BVHRayCastData; typedef struct BVHNearestProjectedData { - const BVHTree *tree; - struct DistProjectedAABBPrecalc precalc; - bool closest_axis[3]; - float clip_plane[6][4]; - int clip_plane_len; - BVHTree_NearestProjectedCallback callback; - void *userdata; - BVHTreeNearest nearest; + const BVHTree *tree; + struct DistProjectedAABBPrecalc precalc; + bool closest_axis[3]; + float clip_plane[6][4]; + int clip_plane_len; + BVHTree_NearestProjectedCallback callback; + void *userdata; + BVHTreeNearest nearest; } BVHNearestProjectedData; /** \} */ - /** * Bounding Volume Hierarchy Definition * @@ -183,24 +179,33 @@ typedef struct BVHNearestProjectedData { */ const float bvhtree_kdop_axes[13][3] = { - {1.0, 0, 0}, {0, 1.0, 0}, {0, 0, 1.0}, - {1.0, 1.0, 1.0}, {1.0, -1.0, 1.0}, {1.0, 1.0, -1.0}, {1.0, -1.0, -1.0}, - {1.0, 1.0, 0}, {1.0, 0, 1.0}, {0, 1.0, 1.0}, {1.0, -1.0, 0}, {1.0, 0, -1.0}, {0, 1.0, -1.0}, + {1.0, 0, 0}, + {0, 1.0, 0}, + {0, 0, 1.0}, + {1.0, 1.0, 1.0}, + {1.0, -1.0, 1.0}, + {1.0, 1.0, -1.0}, + {1.0, -1.0, -1.0}, + {1.0, 1.0, 0}, + {1.0, 0, 1.0}, + {0, 1.0, 1.0}, + {1.0, -1.0, 0}, + {1.0, 0, -1.0}, + {0, 1.0, -1.0}, }; - /* -------------------------------------------------------------------- */ /** \name Utility Functions * \{ */ MINLINE axis_t min_axis(axis_t a, axis_t b) { - return (a < b) ? a : b; + return (a < b) ? a : b; } #if 0 MINLINE axis_t max_axis(axis_t a, axis_t b) { - return (b < a) ? a : b; + return (b < a) ? a : b; } #endif @@ -211,22 +216,19 @@ MINLINE axis_t max_axis(axis_t a, axis_t b) * and he derived it from the SUN STL */ - - static void node_minmax_init(const BVHTree *tree, BVHNode *node) { - axis_t axis_iter; - float (*bv)[2] = (float (*)[2])node->bv; + axis_t axis_iter; + float(*bv)[2] = (float(*)[2])node->bv; - for (axis_iter = tree->start_axis; axis_iter != tree->stop_axis; axis_iter++) { - bv[axis_iter][0] = FLT_MAX; - bv[axis_iter][1] = -FLT_MAX; - } + for (axis_iter = tree->start_axis; axis_iter != tree->stop_axis; axis_iter++) { + bv[axis_iter][0] = FLT_MAX; + bv[axis_iter][1] = -FLT_MAX; + } } /** \} */ - /* -------------------------------------------------------------------- */ /** \name Balance Utility Functions * \{ */ @@ -236,67 +238,67 @@ static void node_minmax_init(const BVHTree *tree, BVHNode *node) */ static void bvh_insertionsort(BVHNode **a, int lo, int hi, int axis) { - int i, j; - BVHNode *t; - for (i = lo; i < hi; i++) { - j = i; - t = a[i]; - while ((j != lo) && (t->bv[axis] < (a[j - 1])->bv[axis])) { - a[j] = a[j - 1]; - j--; - } - a[j] = t; - } + int i, j; + BVHNode *t; + for (i = lo; i < hi; i++) { + j = i; + t = a[i]; + while ((j != lo) && (t->bv[axis] < (a[j - 1])->bv[axis])) { + a[j] = a[j - 1]; + j--; + } + a[j] = t; + } } static int bvh_partition(BVHNode **a, int lo, int hi, BVHNode *x, int axis) { - int i = lo, j = hi; - while (1) { - while (a[i]->bv[axis] < x->bv[axis]) { - i++; - } - j--; - while (x->bv[axis] < a[j]->bv[axis]) { - j--; - } - if (!(i < j)) { - return i; - } - SWAP(BVHNode *, a[i], a[j]); - i++; - } + int i = lo, j = hi; + while (1) { + while (a[i]->bv[axis] < x->bv[axis]) { + i++; + } + j--; + while (x->bv[axis] < a[j]->bv[axis]) { + j--; + } + if (!(i < j)) { + return i; + } + SWAP(BVHNode *, a[i], a[j]); + i++; + } } /* returns Sortable */ static BVHNode *bvh_medianof3(BVHNode **a, int lo, int mid, int hi, int axis) { - if ((a[mid])->bv[axis] < (a[lo])->bv[axis]) { - if ((a[hi])->bv[axis] < (a[mid])->bv[axis]) { - return a[mid]; - } - else { - if ((a[hi])->bv[axis] < (a[lo])->bv[axis]) { - return a[hi]; - } - else { - return a[lo]; - } - } - } - else { - if ((a[hi])->bv[axis] < (a[mid])->bv[axis]) { - if ((a[hi])->bv[axis] < (a[lo])->bv[axis]) { - return a[lo]; - } - else { - return a[hi]; - } - } - else { - return a[mid]; - } - } + if ((a[mid])->bv[axis] < (a[lo])->bv[axis]) { + if ((a[hi])->bv[axis] < (a[mid])->bv[axis]) { + return a[mid]; + } + else { + if ((a[hi])->bv[axis] < (a[lo])->bv[axis]) { + return a[hi]; + } + else { + return a[lo]; + } + } + } + else { + if ((a[hi])->bv[axis] < (a[mid])->bv[axis]) { + if ((a[hi])->bv[axis] < (a[lo])->bv[axis]) { + return a[lo]; + } + else { + return a[hi]; + } + } + else { + return a[mid]; + } + } } /** @@ -305,66 +307,68 @@ static BVHNode *bvh_medianof3(BVHNode **a, int lo, int mid, int hi, int axis) * - every node to the right of a[n] are greater or equal to it */ static void partition_nth_element(BVHNode **a, int begin, int end, const int n, const int axis) { - while (end - begin > 3) { - const int cut = bvh_partition(a, begin, end, bvh_medianof3(a, begin, (begin + end) / 2, end - 1, axis), axis); - if (cut <= n) { - begin = cut; - } - else { - end = cut; - } - } - bvh_insertionsort(a, begin, end, axis); + while (end - begin > 3) { + const int cut = bvh_partition( + a, begin, end, bvh_medianof3(a, begin, (begin + end) / 2, end - 1, axis), axis); + if (cut <= n) { + begin = cut; + } + else { + end = cut; + } + } + bvh_insertionsort(a, begin, end, axis); } #ifdef USE_SKIP_LINKS static void build_skip_links(BVHTree *tree, BVHNode *node, BVHNode *left, BVHNode *right) { - int i; + int i; - node->skip[0] = left; - node->skip[1] = right; + node->skip[0] = left; + node->skip[1] = right; - for (i = 0; i < node->totnode; i++) { - if (i + 1 < node->totnode) { - build_skip_links(tree, node->children[i], left, node->children[i + 1]); - } - else { - build_skip_links(tree, node->children[i], left, right); - } + for (i = 0; i < node->totnode; i++) { + if (i + 1 < node->totnode) { + build_skip_links(tree, node->children[i], left, node->children[i + 1]); + } + else { + build_skip_links(tree, node->children[i], left, right); + } - left = node->children[i]; - } + left = node->children[i]; + } } #endif /* * BVHTree bounding volumes functions */ -static void create_kdop_hull(const BVHTree *tree, BVHNode *node, const float *co, int numpoints, int moving) +static void create_kdop_hull( + const BVHTree *tree, BVHNode *node, const float *co, int numpoints, int moving) { - float newminmax; - float *bv = node->bv; - int k; - axis_t axis_iter; - - /* don't init boudings for the moving case */ - if (!moving) { - node_minmax_init(tree, node); - } - - for (k = 0; k < numpoints; k++) { - /* for all Axes. */ - for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) { - newminmax = dot_v3v3(&co[k * 3], bvhtree_kdop_axes[axis_iter]); - if (newminmax < bv[2 * axis_iter]) { - bv[2 * axis_iter] = newminmax; - } - if (newminmax > bv[(2 * axis_iter) + 1]) { - bv[(2 * axis_iter) + 1] = newminmax; - } - } - } + float newminmax; + float *bv = node->bv; + int k; + axis_t axis_iter; + + /* don't init boudings for the moving case */ + if (!moving) { + node_minmax_init(tree, node); + } + + for (k = 0; k < numpoints; k++) { + /* for all Axes. */ + for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) { + newminmax = dot_v3v3(&co[k * 3], bvhtree_kdop_axes[axis_iter]); + if (newminmax < bv[2 * axis_iter]) { + bv[2 * axis_iter] = newminmax; + } + if (newminmax > bv[(2 * axis_iter) + 1]) { + bv[(2 * axis_iter) + 1] = newminmax; + } + } + } } /** @@ -372,30 +376,29 @@ static void create_kdop_hull(const BVHTree *tree, BVHNode *node, const float *co */ static void refit_kdop_hull(const BVHTree *tree, BVHNode *node, int start, int end) { - float newmin, newmax; - float *__restrict bv = node->bv; - int j; - axis_t axis_iter; - - node_minmax_init(tree, node); - - for (j = start; j < end; j++) { - float *__restrict node_bv = tree->nodes[j]->bv; - - /* for all Axes. */ - for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) { - newmin = node_bv[(2 * axis_iter)]; - if ((newmin < bv[(2 * axis_iter)])) { - bv[(2 * axis_iter)] = newmin; - } - - newmax = node_bv[(2 * axis_iter) + 1]; - if ((newmax > bv[(2 * axis_iter) + 1])) { - bv[(2 * axis_iter) + 1] = newmax; - } - } - } - + float newmin, newmax; + float *__restrict bv = node->bv; + int j; + axis_t axis_iter; + + node_minmax_init(tree, node); + + for (j = start; j < end; j++) { + float *__restrict node_bv = tree->nodes[j]->bv; + + /* for all Axes. */ + for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) { + newmin = node_bv[(2 * axis_iter)]; + if ((newmin < bv[(2 * axis_iter)])) { + bv[(2 * axis_iter)] = newmin; + } + + newmax = node_bv[(2 * axis_iter) + 1]; + if ((newmax > bv[(2 * axis_iter) + 1])) { + bv[(2 * axis_iter) + 1] = newmax; + } + } + } } /** @@ -403,27 +406,27 @@ static void refit_kdop_hull(const BVHTree *tree, BVHNode *node, int start, int e * but we should use a plain and simple function here for speed sake */ static char get_largest_axis(const float *bv) { - float middle_point[3]; - - middle_point[0] = (bv[1]) - (bv[0]); /* x axis */ - middle_point[1] = (bv[3]) - (bv[2]); /* y axis */ - middle_point[2] = (bv[5]) - (bv[4]); /* z axis */ - if (middle_point[0] > middle_point[1]) { - if (middle_point[0] > middle_point[2]) { - return 1; /* max x axis */ - } - else { - return 5; /* max z axis */ - } - } - else { - if (middle_point[1] > middle_point[2]) { - return 3; /* max y axis */ - } - else { - return 5; /* max z axis */ - } - } + float middle_point[3]; + + middle_point[0] = (bv[1]) - (bv[0]); /* x axis */ + middle_point[1] = (bv[3]) - (bv[2]); /* y axis */ + middle_point[2] = (bv[5]) - (bv[4]); /* z axis */ + if (middle_point[0] > middle_point[1]) { + if (middle_point[0] > middle_point[2]) { + return 1; /* max x axis */ + } + else { + return 5; /* max z axis */ + } + } + else { + if (middle_point[1] > middle_point[2]) { + return 3; /* max y axis */ + } + else { + return 5; /* max z axis */ + } + } } /** @@ -431,29 +434,29 @@ static char get_largest_axis(const float *bv) * join the children on the parent BV */ static void node_join(BVHTree *tree, BVHNode *node) { - int i; - axis_t axis_iter; - - node_minmax_init(tree, node); - - for (i = 0; i < tree->tree_type; i++) { - if (node->children[i]) { - for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) { - /* update minimum */ - if (node->children[i]->bv[(2 * axis_iter)] < node->bv[(2 * axis_iter)]) { - node->bv[(2 * axis_iter)] = node->children[i]->bv[(2 * axis_iter)]; - } - - /* update maximum */ - if (node->children[i]->bv[(2 * axis_iter) + 1] > node->bv[(2 * axis_iter) + 1]) { - node->bv[(2 * axis_iter) + 1] = node->children[i]->bv[(2 * axis_iter) + 1]; - } - } - } - else { - break; - } - } + int i; + axis_t axis_iter; + + node_minmax_init(tree, node); + + for (i = 0; i < tree->tree_type; i++) { + if (node->children[i]) { + for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) { + /* update minimum */ + if (node->children[i]->bv[(2 * axis_iter)] < node->bv[(2 * axis_iter)]) { + node->bv[(2 * axis_iter)] = node->children[i]->bv[(2 * axis_iter)]; + } + + /* update maximum */ + if (node->children[i]->bv[(2 * axis_iter) + 1] > node->bv[(2 * axis_iter) + 1]) { + node->bv[(2 * axis_iter) + 1] = node->children[i]->bv[(2 * axis_iter) + 1]; + } + } + } + else { + break; + } + } } #ifdef USE_PRINT_TREE @@ -464,156 +467,156 @@ static void node_join(BVHTree *tree, BVHNode *node) static void bvhtree_print_tree(BVHTree *tree, BVHNode *node, int depth) { - int i; - axis_t axis_iter; - - for (i = 0; i < depth; i++) { - printf(" "); - } - printf(" - %d (%ld): ", node->index, (long int)(node - tree->nodearray)); - for (axis_iter = (axis_t)(2 * tree->start_axis); - axis_iter < (axis_t)(2 * tree->stop_axis); - axis_iter++) - { - printf("%.3f ", node->bv[axis_iter]); - } - printf("\n"); - - for (i = 0; i < tree->tree_type; i++) { - if (node->children[i]) { - bvhtree_print_tree(tree, node->children[i], depth + 1); - } - } + int i; + axis_t axis_iter; + + for (i = 0; i < depth; i++) { + printf(" "); + } + printf(" - %d (%ld): ", node->index, (long int)(node - tree->nodearray)); + for (axis_iter = (axis_t)(2 * tree->start_axis); axis_iter < (axis_t)(2 * tree->stop_axis); + axis_iter++) { + printf("%.3f ", node->bv[axis_iter]); + } + printf("\n"); + + for (i = 0; i < tree->tree_type; i++) { + if (node->children[i]) { + bvhtree_print_tree(tree, node->children[i], depth + 1); + } + } } static void bvhtree_info(BVHTree *tree) { - printf("BVHTree Info: tree_type = %d, axis = %d, epsilon = %f\n", - tree->tree_type, tree->axis, tree->epsilon); - printf("nodes = %d, branches = %d, leafs = %d\n", - tree->totbranch + tree->totleaf, tree->totbranch, tree->totleaf); - printf("Memory per node = %ubytes\n", - (uint)(sizeof(BVHNode) + sizeof(BVHNode *) * tree->tree_type + sizeof(float) * tree->axis)); - printf("BV memory = %ubytes\n", - (uint)MEM_allocN_len(tree->nodebv)); - - printf("Total memory = %ubytes\n", - (uint)(sizeof(BVHTree) + - MEM_allocN_len(tree->nodes) + - MEM_allocN_len(tree->nodearray) + - MEM_allocN_len(tree->nodechild) + - MEM_allocN_len(tree->nodebv))); - - bvhtree_print_tree(tree, tree->nodes[tree->totleaf], 0); + printf("BVHTree Info: tree_type = %d, axis = %d, epsilon = %f\n", + tree->tree_type, + tree->axis, + tree->epsilon); + printf("nodes = %d, branches = %d, leafs = %d\n", + tree->totbranch + tree->totleaf, + tree->totbranch, + tree->totleaf); + printf( + "Memory per node = %ubytes\n", + (uint)(sizeof(BVHNode) + sizeof(BVHNode *) * tree->tree_type + sizeof(float) * tree->axis)); + printf("BV memory = %ubytes\n", (uint)MEM_allocN_len(tree->nodebv)); + + printf("Total memory = %ubytes\n", + (uint)(sizeof(BVHTree) + MEM_allocN_len(tree->nodes) + MEM_allocN_len(tree->nodearray) + + MEM_allocN_len(tree->nodechild) + MEM_allocN_len(tree->nodebv))); + + bvhtree_print_tree(tree, tree->nodes[tree->totleaf], 0); } -#endif /* USE_PRINT_TREE */ +#endif /* USE_PRINT_TREE */ #ifdef USE_VERIFY_TREE static void bvhtree_verify(BVHTree *tree) { - int i, j, check = 0; - - /* check the pointer list */ - for (i = 0; i < tree->totleaf; i++) { - if (tree->nodes[i]->parent == NULL) { - printf("Leaf has no parent: %d\n", i); - } - else { - for (j = 0; j < tree->tree_type; j++) { - if (tree->nodes[i]->parent->children[j] == tree->nodes[i]) { - check = 1; - } - } - if (!check) { - printf("Parent child relationship doesn't match: %d\n", i); - } - check = 0; - } - } - - /* check the leaf list */ - for (i = 0; i < tree->totleaf; i++) { - if (tree->nodearray[i].parent == NULL) { - printf("Leaf has no parent: %d\n", i); - } - else { - for (j = 0; j < tree->tree_type; j++) { - if (tree->nodearray[i].parent->children[j] == &tree->nodearray[i]) { - check = 1; - } - } - if (!check) { - printf("Parent child relationship doesn't match: %d\n", i); - } - check = 0; - } - } - - printf("branches: %d, leafs: %d, total: %d\n", - tree->totbranch, tree->totleaf, tree->totbranch + tree->totleaf); + int i, j, check = 0; + + /* check the pointer list */ + for (i = 0; i < tree->totleaf; i++) { + if (tree->nodes[i]->parent == NULL) { + printf("Leaf has no parent: %d\n", i); + } + else { + for (j = 0; j < tree->tree_type; j++) { + if (tree->nodes[i]->parent->children[j] == tree->nodes[i]) { + check = 1; + } + } + if (!check) { + printf("Parent child relationship doesn't match: %d\n", i); + } + check = 0; + } + } + + /* check the leaf list */ + for (i = 0; i < tree->totleaf; i++) { + if (tree->nodearray[i].parent == NULL) { + printf("Leaf has no parent: %d\n", i); + } + else { + for (j = 0; j < tree->tree_type; j++) { + if (tree->nodearray[i].parent->children[j] == &tree->nodearray[i]) { + check = 1; + } + } + if (!check) { + printf("Parent child relationship doesn't match: %d\n", i); + } + check = 0; + } + } + + printf("branches: %d, leafs: %d, total: %d\n", + tree->totbranch, + tree->totleaf, + tree->totbranch + tree->totleaf); } -#endif /* USE_VERIFY_TREE */ +#endif /* USE_VERIFY_TREE */ /* Helper data and structures to build a min-leaf generalized implicit tree * This code can be easily reduced * (basicly this is only method to calculate pow(k, n) in O(1).. and stuff like that) */ typedef struct BVHBuildHelper { - int tree_type; - int totleafs; + int tree_type; + int totleafs; - /** Min number of leafs that are archievable from a node at depth N */ - int leafs_per_child[32]; - /** Number of nodes at depth N (tree_type^N) */ - int branches_on_level[32]; + /** Min number of leafs that are archievable from a node at depth N */ + int leafs_per_child[32]; + /** Number of nodes at depth N (tree_type^N) */ + int branches_on_level[32]; - /** Number of leafs that are placed on the level that is not 100% filled */ - int remain_leafs; + /** Number of leafs that are placed on the level that is not 100% filled */ + int remain_leafs; } BVHBuildHelper; static void build_implicit_tree_helper(const BVHTree *tree, BVHBuildHelper *data) { - int depth = 0; - int remain; - int nnodes; - - data->totleafs = tree->totleaf; - data->tree_type = tree->tree_type; - - /* Calculate the smallest tree_type^n such that tree_type^n >= num_leafs */ - for (data->leafs_per_child[0] = 1; - data->leafs_per_child[0] < data->totleafs; - data->leafs_per_child[0] *= data->tree_type) - { - /* pass */ - } - - data->branches_on_level[0] = 1; - - for (depth = 1; (depth < 32) && data->leafs_per_child[depth - 1]; depth++) { - data->branches_on_level[depth] = data->branches_on_level[depth - 1] * data->tree_type; - data->leafs_per_child[depth] = data->leafs_per_child[depth - 1] / data->tree_type; - } - - remain = data->totleafs - data->leafs_per_child[1]; - nnodes = (remain + data->tree_type - 2) / (data->tree_type - 1); - data->remain_leafs = remain + nnodes; + int depth = 0; + int remain; + int nnodes; + + data->totleafs = tree->totleaf; + data->tree_type = tree->tree_type; + + /* Calculate the smallest tree_type^n such that tree_type^n >= num_leafs */ + for (data->leafs_per_child[0] = 1; data->leafs_per_child[0] < data->totleafs; + data->leafs_per_child[0] *= data->tree_type) { + /* pass */ + } + + data->branches_on_level[0] = 1; + + for (depth = 1; (depth < 32) && data->leafs_per_child[depth - 1]; depth++) { + data->branches_on_level[depth] = data->branches_on_level[depth - 1] * data->tree_type; + data->leafs_per_child[depth] = data->leafs_per_child[depth - 1] / data->tree_type; + } + + remain = data->totleafs - data->leafs_per_child[1]; + nnodes = (remain + data->tree_type - 2) / (data->tree_type - 1); + data->remain_leafs = remain + nnodes; } // return the min index of all the leafs archivable with the given branch static int implicit_leafs_index(const BVHBuildHelper *data, const int depth, const int child_index) { - int min_leaf_index = child_index * data->leafs_per_child[depth - 1]; - if (min_leaf_index <= data->remain_leafs) { - return min_leaf_index; - } - else if (data->leafs_per_child[depth]) { - return data->totleafs - (data->branches_on_level[depth - 1] - child_index) * data->leafs_per_child[depth]; - } - else { - return data->remain_leafs; - } + int min_leaf_index = child_index * data->leafs_per_child[depth - 1]; + if (min_leaf_index <= data->remain_leafs) { + return min_leaf_index; + } + else if (data->leafs_per_child[depth]) { + return data->totleafs - + (data->branches_on_level[depth - 1] - child_index) * data->leafs_per_child[depth]; + } + else { + return data->remain_leafs; + } } /** @@ -645,7 +648,7 @@ static int implicit_leafs_index(const BVHBuildHelper *data, const int depth, con /* This functions returns the number of branches needed to have the requested number of leafs. */ static int implicit_needed_branches(int tree_type, int leafs) { - return max_ii(1, (leafs + tree_type - 3) / (tree_type - 1)); + return max_ii(1, (leafs + tree_type - 3) / (tree_type - 1)); } /** @@ -660,96 +663,100 @@ static int implicit_needed_branches(int tree_type, int leafs) * * TODO: This can be optimized a bit by doing a specialized nth_element instead of K nth_elements */ -static void split_leafs(BVHNode **leafs_array, const int nth[], const int partitions, const int split_axis) +static void split_leafs(BVHNode **leafs_array, + const int nth[], + const int partitions, + const int split_axis) { - int i; - for (i = 0; i < partitions - 1; i++) { - if (nth[i] >= nth[partitions]) { - break; - } - - partition_nth_element(leafs_array, nth[i], nth[partitions], nth[i + 1], split_axis); - } + int i; + for (i = 0; i < partitions - 1; i++) { + if (nth[i] >= nth[partitions]) { + break; + } + + partition_nth_element(leafs_array, nth[i], nth[partitions], nth[i + 1], split_axis); + } } typedef struct BVHDivNodesData { - const BVHTree *tree; - BVHNode *branches_array; - BVHNode **leafs_array; + const BVHTree *tree; + BVHNode *branches_array; + BVHNode **leafs_array; - int tree_type; - int tree_offset; + int tree_type; + int tree_offset; - const BVHBuildHelper *data; + const BVHBuildHelper *data; - int depth; - int i; - int first_of_next_level; + int depth; + int i; + int first_of_next_level; } BVHDivNodesData; -static void non_recursive_bvh_div_nodes_task_cb( - void *__restrict userdata, - const int j, - const ParallelRangeTLS *__restrict UNUSED(tls)) +static void non_recursive_bvh_div_nodes_task_cb(void *__restrict userdata, + const int j, + const ParallelRangeTLS *__restrict UNUSED(tls)) { - BVHDivNodesData *data = userdata; - - int k; - const int parent_level_index = j - data->i; - BVHNode *parent = &data->branches_array[j]; - int nth_positions[MAX_TREETYPE + 1]; - char split_axis; - - int parent_leafs_begin = implicit_leafs_index(data->data, data->depth, parent_level_index); - int parent_leafs_end = implicit_leafs_index(data->data, data->depth, parent_level_index + 1); - - /* This calculates the bounding box of this branch - * and chooses the largest axis as the axis to divide leafs */ - refit_kdop_hull(data->tree, parent, parent_leafs_begin, parent_leafs_end); - split_axis = get_largest_axis(parent->bv); - - /* Save split axis (this can be used on raytracing to speedup the query time) */ - parent->main_axis = split_axis / 2; - - /* Split the childs along the split_axis, note: its not needed to sort the whole leafs array - * Only to assure that the elements are partitioned on a way that each child takes the elements - * it would take in case the whole array was sorted. - * Split_leafs takes care of that "sort" problem. */ - nth_positions[0] = parent_leafs_begin; - nth_positions[data->tree_type] = parent_leafs_end; - for (k = 1; k < data->tree_type; k++) { - const int child_index = j * data->tree_type + data->tree_offset + k; - /* child level index */ - const int child_level_index = child_index - data->first_of_next_level; - nth_positions[k] = implicit_leafs_index(data->data, data->depth + 1, child_level_index); - } - - split_leafs(data->leafs_array, nth_positions, data->tree_type, split_axis); - - /* Setup children and totnode counters - * Not really needed but currently most of BVH code - * relies on having an explicit children structure */ - for (k = 0; k < data->tree_type; k++) { - const int child_index = j * data->tree_type + data->tree_offset + k; - /* child level index */ - const int child_level_index = child_index - data->first_of_next_level; - - const int child_leafs_begin = implicit_leafs_index(data->data, data->depth + 1, child_level_index); - const int child_leafs_end = implicit_leafs_index(data->data, data->depth + 1, child_level_index + 1); - - if (child_leafs_end - child_leafs_begin > 1) { - parent->children[k] = &data->branches_array[child_index]; - parent->children[k]->parent = parent; - } - else if (child_leafs_end - child_leafs_begin == 1) { - parent->children[k] = data->leafs_array[child_leafs_begin]; - parent->children[k]->parent = parent; - } - else { - break; - } - } - parent->totnode = (char)k; + BVHDivNodesData *data = userdata; + + int k; + const int parent_level_index = j - data->i; + BVHNode *parent = &data->branches_array[j]; + int nth_positions[MAX_TREETYPE + 1]; + char split_axis; + + int parent_leafs_begin = implicit_leafs_index(data->data, data->depth, parent_level_index); + int parent_leafs_end = implicit_leafs_index(data->data, data->depth, parent_level_index + 1); + + /* This calculates the bounding box of this branch + * and chooses the largest axis as the axis to divide leafs */ + refit_kdop_hull(data->tree, parent, parent_leafs_begin, parent_leafs_end); + split_axis = get_largest_axis(parent->bv); + + /* Save split axis (this can be used on raytracing to speedup the query time) */ + parent->main_axis = split_axis / 2; + + /* Split the childs along the split_axis, note: its not needed to sort the whole leafs array + * Only to assure that the elements are partitioned on a way that each child takes the elements + * it would take in case the whole array was sorted. + * Split_leafs takes care of that "sort" problem. */ + nth_positions[0] = parent_leafs_begin; + nth_positions[data->tree_type] = parent_leafs_end; + for (k = 1; k < data->tree_type; k++) { + const int child_index = j * data->tree_type + data->tree_offset + k; + /* child level index */ + const int child_level_index = child_index - data->first_of_next_level; + nth_positions[k] = implicit_leafs_index(data->data, data->depth + 1, child_level_index); + } + + split_leafs(data->leafs_array, nth_positions, data->tree_type, split_axis); + + /* Setup children and totnode counters + * Not really needed but currently most of BVH code + * relies on having an explicit children structure */ + for (k = 0; k < data->tree_type; k++) { + const int child_index = j * data->tree_type + data->tree_offset + k; + /* child level index */ + const int child_level_index = child_index - data->first_of_next_level; + + const int child_leafs_begin = implicit_leafs_index( + data->data, data->depth + 1, child_level_index); + const int child_leafs_end = implicit_leafs_index( + data->data, data->depth + 1, child_level_index + 1); + + if (child_leafs_end - child_leafs_begin > 1) { + parent->children[k] = &data->branches_array[child_index]; + parent->children[k]->parent = parent; + } + else if (child_leafs_end - child_leafs_begin == 1) { + parent->children[k] = data->leafs_array[child_leafs_begin]; + parent->children[k]->parent = parent; + } + else { + break; + } + } + parent->totnode = (char)k; } /** @@ -768,79 +775,82 @@ static void non_recursive_bvh_div_nodes_task_cb( * To archive this is necessary to find how much leafs are accessible from a certain branch, BVHBuildHelper * #implicit_needed_branches and #implicit_leafs_index are auxiliary functions to solve that "optimal-split". */ -static void non_recursive_bvh_div_nodes( - const BVHTree *tree, BVHNode *branches_array, BVHNode **leafs_array, int num_leafs) +static void non_recursive_bvh_div_nodes(const BVHTree *tree, + BVHNode *branches_array, + BVHNode **leafs_array, + int num_leafs) { - int i; - - const int tree_type = tree->tree_type; - /* this value is 0 (on binary trees) and negative on the others */ - const int tree_offset = 2 - tree->tree_type; - - const int num_branches = implicit_needed_branches(tree_type, num_leafs); - - BVHBuildHelper data; - int depth; - - { - /* set parent from root node to NULL */ - BVHNode *root = &branches_array[1]; - root->parent = NULL; - - /* Most of bvhtree code relies on 1-leaf trees having at least one branch - * We handle that special case here */ - if (num_leafs == 1) { - refit_kdop_hull(tree, root, 0, num_leafs); - root->main_axis = get_largest_axis(root->bv) / 2; - root->totnode = 1; - root->children[0] = leafs_array[0]; - root->children[0]->parent = root; - return; - } - } - - build_implicit_tree_helper(tree, &data); - - BVHDivNodesData cb_data = { - .tree = tree, .branches_array = branches_array, .leafs_array = leafs_array, - .tree_type = tree_type, .tree_offset = tree_offset, .data = &data, - .first_of_next_level = 0, .depth = 0, .i = 0, - }; - - /* Loop tree levels (log N) loops */ - for (i = 1, depth = 1; i <= num_branches; i = i * tree_type + tree_offset, depth++) { - const int first_of_next_level = i * tree_type + tree_offset; - /* index of last branch on this level */ - const int i_stop = min_ii(first_of_next_level, num_branches + 1); - - /* Loop all branches on this level */ - cb_data.first_of_next_level = first_of_next_level; - cb_data.i = i; - cb_data.depth = depth; - - if (true) { - ParallelRangeSettings settings; - BLI_parallel_range_settings_defaults(&settings); - settings.use_threading = (num_leafs > KDOPBVH_THREAD_LEAF_THRESHOLD); - BLI_task_parallel_range( - i, i_stop, - &cb_data, - non_recursive_bvh_div_nodes_task_cb, - &settings); - } - else { - /* Less hassle for debugging. */ - ParallelRangeTLS tls = {0}; - for (int i_task = i; i_task < i_stop; i_task++) { - non_recursive_bvh_div_nodes_task_cb(&cb_data, i_task, &tls); - } - } - } + int i; + + const int tree_type = tree->tree_type; + /* this value is 0 (on binary trees) and negative on the others */ + const int tree_offset = 2 - tree->tree_type; + + const int num_branches = implicit_needed_branches(tree_type, num_leafs); + + BVHBuildHelper data; + int depth; + + { + /* set parent from root node to NULL */ + BVHNode *root = &branches_array[1]; + root->parent = NULL; + + /* Most of bvhtree code relies on 1-leaf trees having at least one branch + * We handle that special case here */ + if (num_leafs == 1) { + refit_kdop_hull(tree, root, 0, num_leafs); + root->main_axis = get_largest_axis(root->bv) / 2; + root->totnode = 1; + root->children[0] = leafs_array[0]; + root->children[0]->parent = root; + return; + } + } + + build_implicit_tree_helper(tree, &data); + + BVHDivNodesData cb_data = { + .tree = tree, + .branches_array = branches_array, + .leafs_array = leafs_array, + .tree_type = tree_type, + .tree_offset = tree_offset, + .data = &data, + .first_of_next_level = 0, + .depth = 0, + .i = 0, + }; + + /* Loop tree levels (log N) loops */ + for (i = 1, depth = 1; i <= num_branches; i = i * tree_type + tree_offset, depth++) { + const int first_of_next_level = i * tree_type + tree_offset; + /* index of last branch on this level */ + const int i_stop = min_ii(first_of_next_level, num_branches + 1); + + /* Loop all branches on this level */ + cb_data.first_of_next_level = first_of_next_level; + cb_data.i = i; + cb_data.depth = depth; + + if (true) { + ParallelRangeSettings settings; + BLI_parallel_range_settings_defaults(&settings); + settings.use_threading = (num_leafs > KDOPBVH_THREAD_LEAF_THRESHOLD); + BLI_task_parallel_range(i, i_stop, &cb_data, non_recursive_bvh_div_nodes_task_cb, &settings); + } + else { + /* Less hassle for debugging. */ + ParallelRangeTLS tls = {0}; + for (int i_task = i; i_task < i_stop; i_task++) { + non_recursive_bvh_div_nodes_task_cb(&cb_data, i_task, &tls); + } + } + } } /** \} */ - /* -------------------------------------------------------------------- */ /** \name BLI_bvhtree API * \{ */ @@ -850,189 +860,183 @@ static void non_recursive_bvh_div_nodes( */ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis) { - BVHTree *tree; - int numnodes, i; - - BLI_assert(tree_type >= 2 && tree_type <= MAX_TREETYPE); - - tree = MEM_callocN(sizeof(BVHTree), "BVHTree"); - - /* tree epsilon must be >= FLT_EPSILON - * so that tangent rays can still hit a bounding volume.. - * this bug would show up when casting a ray aligned with a kdop-axis - * and with an edge of 2 faces */ - epsilon = max_ff(FLT_EPSILON, epsilon); - - if (tree) { - tree->epsilon = epsilon; - tree->tree_type = tree_type; - tree->axis = axis; - - if (axis == 26) { - tree->start_axis = 0; - tree->stop_axis = 13; - } - else if (axis == 18) { - tree->start_axis = 7; - tree->stop_axis = 13; - } - else if (axis == 14) { - tree->start_axis = 0; - tree->stop_axis = 7; - } - else if (axis == 8) { /* AABB */ - tree->start_axis = 0; - tree->stop_axis = 4; - } - else if (axis == 6) { /* OBB */ - tree->start_axis = 0; - tree->stop_axis = 3; - } - else { - /* should never happen! */ - BLI_assert(0); - - goto fail; - } - - - /* Allocate arrays */ - numnodes = maxsize + implicit_needed_branches(tree_type, maxsize) + tree_type; - - tree->nodes = MEM_callocN(sizeof(BVHNode *) * (size_t)numnodes, "BVHNodes"); - tree->nodebv = MEM_callocN(sizeof(float) * (size_t)(axis * numnodes), "BVHNodeBV"); - tree->nodechild = MEM_callocN(sizeof(BVHNode *) * (size_t)(tree_type * numnodes), "BVHNodeBV"); - tree->nodearray = MEM_callocN(sizeof(BVHNode) * (size_t)numnodes, "BVHNodeArray"); - - if (UNLIKELY((!tree->nodes) || - (!tree->nodebv) || - (!tree->nodechild) || - (!tree->nodearray))) - { - goto fail; - } - - /* link the dynamic bv and child links */ - for (i = 0; i < numnodes; i++) { - tree->nodearray[i].bv = &tree->nodebv[i * axis]; - tree->nodearray[i].children = &tree->nodechild[i * tree_type]; - } - - } - return tree; - + BVHTree *tree; + int numnodes, i; + + BLI_assert(tree_type >= 2 && tree_type <= MAX_TREETYPE); + + tree = MEM_callocN(sizeof(BVHTree), "BVHTree"); + + /* tree epsilon must be >= FLT_EPSILON + * so that tangent rays can still hit a bounding volume.. + * this bug would show up when casting a ray aligned with a kdop-axis + * and with an edge of 2 faces */ + epsilon = max_ff(FLT_EPSILON, epsilon); + + if (tree) { + tree->epsilon = epsilon; + tree->tree_type = tree_type; + tree->axis = axis; + + if (axis == 26) { + tree->start_axis = 0; + tree->stop_axis = 13; + } + else if (axis == 18) { + tree->start_axis = 7; + tree->stop_axis = 13; + } + else if (axis == 14) { + tree->start_axis = 0; + tree->stop_axis = 7; + } + else if (axis == 8) { /* AABB */ + tree->start_axis = 0; + tree->stop_axis = 4; + } + else if (axis == 6) { /* OBB */ + tree->start_axis = 0; + tree->stop_axis = 3; + } + else { + /* should never happen! */ + BLI_assert(0); + + goto fail; + } + + /* Allocate arrays */ + numnodes = maxsize + implicit_needed_branches(tree_type, maxsize) + tree_type; + + tree->nodes = MEM_callocN(sizeof(BVHNode *) * (size_t)numnodes, "BVHNodes"); + tree->nodebv = MEM_callocN(sizeof(float) * (size_t)(axis * numnodes), "BVHNodeBV"); + tree->nodechild = MEM_callocN(sizeof(BVHNode *) * (size_t)(tree_type * numnodes), "BVHNodeBV"); + tree->nodearray = MEM_callocN(sizeof(BVHNode) * (size_t)numnodes, "BVHNodeArray"); + + if (UNLIKELY((!tree->nodes) || (!tree->nodebv) || (!tree->nodechild) || (!tree->nodearray))) { + goto fail; + } + + /* link the dynamic bv and child links */ + for (i = 0; i < numnodes; i++) { + tree->nodearray[i].bv = &tree->nodebv[i * axis]; + tree->nodearray[i].children = &tree->nodechild[i * tree_type]; + } + } + return tree; fail: - BLI_bvhtree_free(tree); - return NULL; + BLI_bvhtree_free(tree); + return NULL; } void BLI_bvhtree_free(BVHTree *tree) { - if (tree) { - MEM_SAFE_FREE(tree->nodes); - MEM_SAFE_FREE(tree->nodearray); - MEM_SAFE_FREE(tree->nodebv); - MEM_SAFE_FREE(tree->nodechild); - MEM_freeN(tree); - } + if (tree) { + MEM_SAFE_FREE(tree->nodes); + MEM_SAFE_FREE(tree->nodearray); + MEM_SAFE_FREE(tree->nodebv); + MEM_SAFE_FREE(tree->nodechild); + MEM_freeN(tree); + } } void BLI_bvhtree_balance(BVHTree *tree) { - BVHNode **leafs_array = tree->nodes; + BVHNode **leafs_array = tree->nodes; - /* This function should only be called once - * (some big bug goes here if its being called more than once per tree) */ - BLI_assert(tree->totbranch == 0); + /* This function should only be called once + * (some big bug goes here if its being called more than once per tree) */ + BLI_assert(tree->totbranch == 0); - /* Build the implicit tree */ - non_recursive_bvh_div_nodes(tree, tree->nodearray + (tree->totleaf - 1), leafs_array, tree->totleaf); + /* Build the implicit tree */ + non_recursive_bvh_div_nodes( + tree, tree->nodearray + (tree->totleaf - 1), leafs_array, tree->totleaf); - /* current code expects the branches to be linked to the nodes array - * we perform that linkage here */ - tree->totbranch = implicit_needed_branches(tree->tree_type, tree->totleaf); - for (int i = 0; i < tree->totbranch; i++) { - tree->nodes[tree->totleaf + i] = &tree->nodearray[tree->totleaf + i]; - } + /* current code expects the branches to be linked to the nodes array + * we perform that linkage here */ + tree->totbranch = implicit_needed_branches(tree->tree_type, tree->totleaf); + for (int i = 0; i < tree->totbranch; i++) { + tree->nodes[tree->totleaf + i] = &tree->nodearray[tree->totleaf + i]; + } #ifdef USE_SKIP_LINKS - build_skip_links(tree, tree->nodes[tree->totleaf], NULL, NULL); + build_skip_links(tree, tree->nodes[tree->totleaf], NULL, NULL); #endif #ifdef USE_VERIFY_TREE - bvhtree_verify(tree); + bvhtree_verify(tree); #endif #ifdef USE_PRINT_TREE - bvhtree_info(tree); + bvhtree_info(tree); #endif } void BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints) { - axis_t axis_iter; - BVHNode *node = NULL; + axis_t axis_iter; + BVHNode *node = NULL; - /* insert should only possible as long as tree->totbranch is 0 */ - BLI_assert(tree->totbranch <= 0); - BLI_assert((size_t)tree->totleaf < MEM_allocN_len(tree->nodes) / sizeof(*(tree->nodes))); + /* insert should only possible as long as tree->totbranch is 0 */ + BLI_assert(tree->totbranch <= 0); + BLI_assert((size_t)tree->totleaf < MEM_allocN_len(tree->nodes) / sizeof(*(tree->nodes))); - node = tree->nodes[tree->totleaf] = &(tree->nodearray[tree->totleaf]); - tree->totleaf++; + node = tree->nodes[tree->totleaf] = &(tree->nodearray[tree->totleaf]); + tree->totleaf++; - create_kdop_hull(tree, node, co, numpoints, 0); - node->index = index; + create_kdop_hull(tree, node, co, numpoints, 0); + node->index = index; - /* inflate the bv with some epsilon */ - for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) { - node->bv[(2 * axis_iter)] -= tree->epsilon; /* minimum */ - node->bv[(2 * axis_iter) + 1] += tree->epsilon; /* maximum */ - } + /* inflate the bv with some epsilon */ + for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) { + node->bv[(2 * axis_iter)] -= tree->epsilon; /* minimum */ + node->bv[(2 * axis_iter) + 1] += tree->epsilon; /* maximum */ + } } - /* call before BLI_bvhtree_update_tree() */ -bool BLI_bvhtree_update_node(BVHTree *tree, int index, const float co[3], const float co_moving[3], int numpoints) +bool BLI_bvhtree_update_node( + BVHTree *tree, int index, const float co[3], const float co_moving[3], int numpoints) { - BVHNode *node = NULL; - axis_t axis_iter; + BVHNode *node = NULL; + axis_t axis_iter; - /* check if index exists */ - if (index > tree->totleaf) { - return false; - } + /* check if index exists */ + if (index > tree->totleaf) { + return false; + } - node = tree->nodearray + index; + node = tree->nodearray + index; - create_kdop_hull(tree, node, co, numpoints, 0); + create_kdop_hull(tree, node, co, numpoints, 0); - if (co_moving) { - create_kdop_hull(tree, node, co_moving, numpoints, 1); - } + if (co_moving) { + create_kdop_hull(tree, node, co_moving, numpoints, 1); + } - /* inflate the bv with some epsilon */ - for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) { - node->bv[(2 * axis_iter)] -= tree->epsilon; /* minimum */ - node->bv[(2 * axis_iter) + 1] += tree->epsilon; /* maximum */ - } + /* inflate the bv with some epsilon */ + for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) { + node->bv[(2 * axis_iter)] -= tree->epsilon; /* minimum */ + node->bv[(2 * axis_iter) + 1] += tree->epsilon; /* maximum */ + } - return true; + return true; } /* call BLI_bvhtree_update_node() first for every node/point/triangle */ void BLI_bvhtree_update_tree(BVHTree *tree) { - /* Update bottom=>top - * TRICKY: the way we build the tree all the childs have an index greater than the parent - * This allows us todo a bottom up update by starting on the bigger numbered branch */ + /* Update bottom=>top + * TRICKY: the way we build the tree all the childs have an index greater than the parent + * This allows us todo a bottom up update by starting on the bigger numbered branch */ - BVHNode **root = tree->nodes + tree->totleaf; - BVHNode **index = tree->nodes + tree->totleaf + tree->totbranch - 1; + BVHNode **root = tree->nodes + tree->totleaf; + BVHNode **index = tree->nodes + tree->totleaf + tree->totbranch - 1; - for (; index >= root; index--) { - node_join(tree, *index); - } + for (; index >= root; index--) { + node_join(tree, *index); + } } /** * Number of times #BLI_bvhtree_insert has been called. @@ -1040,7 +1044,7 @@ void BLI_bvhtree_update_tree(BVHTree *tree) */ int BLI_bvhtree_get_len(const BVHTree *tree) { - return tree->totleaf; + return tree->totleaf; } /** @@ -1048,17 +1052,16 @@ int BLI_bvhtree_get_len(const BVHTree *tree) */ int BLI_bvhtree_get_tree_type(const BVHTree *tree) { - return tree->tree_type; + return tree->tree_type; } float BLI_bvhtree_get_epsilon(const BVHTree *tree) { - return tree->epsilon; + return tree->epsilon; } /** \} */ - /* -------------------------------------------------------------------- */ /** \name BLI_bvhtree_overlap * \{ */ @@ -1066,108 +1069,111 @@ float BLI_bvhtree_get_epsilon(const BVHTree *tree) /** * overlap - is it possible for 2 bv's to collide ? */ -static bool tree_overlap_test(const BVHNode *node1, const BVHNode *node2, axis_t start_axis, axis_t stop_axis) +static bool tree_overlap_test(const BVHNode *node1, + const BVHNode *node2, + axis_t start_axis, + axis_t stop_axis) { - const float *bv1 = node1->bv + (start_axis << 1); - const float *bv2 = node2->bv + (start_axis << 1); - const float *bv1_end = node1->bv + (stop_axis << 1); - - /* test all axis if min + max overlap */ - for (; bv1 != bv1_end; bv1 += 2, bv2 += 2) { - if ((bv1[0] > bv2[1]) || (bv2[0] > bv1[1])) { - return 0; - } - } - - return 1; + const float *bv1 = node1->bv + (start_axis << 1); + const float *bv2 = node2->bv + (start_axis << 1); + const float *bv1_end = node1->bv + (stop_axis << 1); + + /* test all axis if min + max overlap */ + for (; bv1 != bv1_end; bv1 += 2, bv2 += 2) { + if ((bv1[0] > bv2[1]) || (bv2[0] > bv1[1])) { + return 0; + } + } + + return 1; } -static void tree_overlap_traverse( - BVHOverlapData_Thread *data_thread, - const BVHNode *node1, const BVHNode *node2) +static void tree_overlap_traverse(BVHOverlapData_Thread *data_thread, + const BVHNode *node1, + const BVHNode *node2) { - BVHOverlapData_Shared *data = data_thread->shared; - int j; - - if (tree_overlap_test(node1, node2, data->start_axis, data->stop_axis)) { - /* check if node1 is a leaf */ - if (!node1->totnode) { - /* check if node2 is a leaf */ - if (!node2->totnode) { - BVHTreeOverlap *overlap; - - if (UNLIKELY(node1 == node2)) { - return; - } - - /* both leafs, insert overlap! */ - overlap = BLI_stack_push_r(data_thread->overlap); - overlap->indexA = node1->index; - overlap->indexB = node2->index; - } - else { - for (j = 0; j < data->tree2->tree_type; j++) { - if (node2->children[j]) { - tree_overlap_traverse(data_thread, node1, node2->children[j]); - } - } - } - } - else { - for (j = 0; j < data->tree2->tree_type; j++) { - if (node1->children[j]) { - tree_overlap_traverse(data_thread, node1->children[j], node2); - } - } - } - } + BVHOverlapData_Shared *data = data_thread->shared; + int j; + + if (tree_overlap_test(node1, node2, data->start_axis, data->stop_axis)) { + /* check if node1 is a leaf */ + if (!node1->totnode) { + /* check if node2 is a leaf */ + if (!node2->totnode) { + BVHTreeOverlap *overlap; + + if (UNLIKELY(node1 == node2)) { + return; + } + + /* both leafs, insert overlap! */ + overlap = BLI_stack_push_r(data_thread->overlap); + overlap->indexA = node1->index; + overlap->indexB = node2->index; + } + else { + for (j = 0; j < data->tree2->tree_type; j++) { + if (node2->children[j]) { + tree_overlap_traverse(data_thread, node1, node2->children[j]); + } + } + } + } + else { + for (j = 0; j < data->tree2->tree_type; j++) { + if (node1->children[j]) { + tree_overlap_traverse(data_thread, node1->children[j], node2); + } + } + } + } } /** * a version of #tree_overlap_traverse that runs a callback to check if the nodes really intersect. */ -static void tree_overlap_traverse_cb( - BVHOverlapData_Thread *data_thread, - const BVHNode *node1, const BVHNode *node2) +static void tree_overlap_traverse_cb(BVHOverlapData_Thread *data_thread, + const BVHNode *node1, + const BVHNode *node2) { - BVHOverlapData_Shared *data = data_thread->shared; - int j; - - if (tree_overlap_test(node1, node2, data->start_axis, data->stop_axis)) { - /* check if node1 is a leaf */ - if (!node1->totnode) { - /* check if node2 is a leaf */ - if (!node2->totnode) { - BVHTreeOverlap *overlap; - - if (UNLIKELY(node1 == node2)) { - return; - } - - /* only difference to tree_overlap_traverse! */ - if (data->callback(data->userdata, node1->index, node2->index, data_thread->thread)) { - /* both leafs, insert overlap! */ - overlap = BLI_stack_push_r(data_thread->overlap); - overlap->indexA = node1->index; - overlap->indexB = node2->index; - } - } - else { - for (j = 0; j < data->tree2->tree_type; j++) { - if (node2->children[j]) { - tree_overlap_traverse_cb(data_thread, node1, node2->children[j]); - } - } - } - } - else { - for (j = 0; j < data->tree2->tree_type; j++) { - if (node1->children[j]) { - tree_overlap_traverse_cb(data_thread, node1->children[j], node2); - } - } - } - } + BVHOverlapData_Shared *data = data_thread->shared; + int j; + + if (tree_overlap_test(node1, node2, data->start_axis, data->stop_axis)) { + /* check if node1 is a leaf */ + if (!node1->totnode) { + /* check if node2 is a leaf */ + if (!node2->totnode) { + BVHTreeOverlap *overlap; + + if (UNLIKELY(node1 == node2)) { + return; + } + + /* only difference to tree_overlap_traverse! */ + if (data->callback(data->userdata, node1->index, node2->index, data_thread->thread)) { + /* both leafs, insert overlap! */ + overlap = BLI_stack_push_r(data_thread->overlap); + overlap->indexA = node1->index; + overlap->indexB = node2->index; + } + } + else { + for (j = 0; j < data->tree2->tree_type; j++) { + if (node2->children[j]) { + tree_overlap_traverse_cb(data_thread, node1, node2->children[j]); + } + } + } + } + else { + for (j = 0; j < data->tree2->tree_type; j++) { + if (node1->children[j]) { + tree_overlap_traverse_cb(data_thread, node1->children[j], node2); + } + } + } + } } /** @@ -1177,106 +1183,102 @@ static void tree_overlap_traverse_cb( */ int BLI_bvhtree_overlap_thread_num(const BVHTree *tree) { - return (int)MIN2(tree->tree_type, tree->nodes[tree->totleaf]->totnode); + return (int)MIN2(tree->tree_type, tree->nodes[tree->totleaf]->totnode); } -static void bvhtree_overlap_task_cb( - void *__restrict userdata, - const int j, - const ParallelRangeTLS *__restrict UNUSED(tls)) +static void bvhtree_overlap_task_cb(void *__restrict userdata, + const int j, + const ParallelRangeTLS *__restrict UNUSED(tls)) { - BVHOverlapData_Thread *data = &((BVHOverlapData_Thread *)userdata)[j]; - BVHOverlapData_Shared *data_shared = data->shared; - - if (data_shared->callback) { - tree_overlap_traverse_cb( - data, data_shared->tree1->nodes[data_shared->tree1->totleaf]->children[j], - data_shared->tree2->nodes[data_shared->tree2->totleaf]); - } - else { - tree_overlap_traverse( - data, data_shared->tree1->nodes[data_shared->tree1->totleaf]->children[j], - data_shared->tree2->nodes[data_shared->tree2->totleaf]); - } + BVHOverlapData_Thread *data = &((BVHOverlapData_Thread *)userdata)[j]; + BVHOverlapData_Shared *data_shared = data->shared; + + if (data_shared->callback) { + tree_overlap_traverse_cb(data, + data_shared->tree1->nodes[data_shared->tree1->totleaf]->children[j], + data_shared->tree2->nodes[data_shared->tree2->totleaf]); + } + else { + tree_overlap_traverse(data, + data_shared->tree1->nodes[data_shared->tree1->totleaf]->children[j], + data_shared->tree2->nodes[data_shared->tree2->totleaf]); + } } BVHTreeOverlap *BLI_bvhtree_overlap( - const BVHTree *tree1, const BVHTree *tree2, uint *r_overlap_tot, - /* optional callback to test the overlap before adding (must be thread-safe!) */ - BVHTree_OverlapCallback callback, void *userdata) + const BVHTree *tree1, + const BVHTree *tree2, + uint *r_overlap_tot, + /* optional callback to test the overlap before adding (must be thread-safe!) */ + BVHTree_OverlapCallback callback, + void *userdata) { - const int thread_num = BLI_bvhtree_overlap_thread_num(tree1); - int j; - size_t total = 0; - BVHTreeOverlap *overlap = NULL, *to = NULL; - BVHOverlapData_Shared data_shared; - BVHOverlapData_Thread *data = BLI_array_alloca(data, (size_t)thread_num); - axis_t start_axis, stop_axis; - - /* check for compatibility of both trees (can't compare 14-DOP with 18-DOP) */ - if (UNLIKELY((tree1->axis != tree2->axis) && - (tree1->axis == 14 || tree2->axis == 14) && - (tree1->axis == 18 || tree2->axis == 18))) - { - BLI_assert(0); - return NULL; - } - - start_axis = min_axis(tree1->start_axis, tree2->start_axis); - stop_axis = min_axis(tree1->stop_axis, tree2->stop_axis); - - /* fast check root nodes for collision before doing big splitting + traversal */ - if (!tree_overlap_test(tree1->nodes[tree1->totleaf], tree2->nodes[tree2->totleaf], start_axis, stop_axis)) { - return NULL; - } - - data_shared.tree1 = tree1; - data_shared.tree2 = tree2; - data_shared.start_axis = start_axis; - data_shared.stop_axis = stop_axis; - - /* can be NULL */ - data_shared.callback = callback; - data_shared.userdata = userdata; - - for (j = 0; j < thread_num; j++) { - /* init BVHOverlapData_Thread */ - data[j].shared = &data_shared; - data[j].overlap = BLI_stack_new(sizeof(BVHTreeOverlap), __func__); - - /* for callback */ - data[j].thread = j; - } - - ParallelRangeSettings settings; - BLI_parallel_range_settings_defaults(&settings); - settings.use_threading = (tree1->totleaf > KDOPBVH_THREAD_LEAF_THRESHOLD); - BLI_task_parallel_range( - 0, thread_num, - data, - bvhtree_overlap_task_cb, - &settings); - - for (j = 0; j < thread_num; j++) { - total += BLI_stack_count(data[j].overlap); - } - - to = overlap = MEM_mallocN(sizeof(BVHTreeOverlap) * total, "BVHTreeOverlap"); - - for (j = 0; j < thread_num; j++) { - uint count = (uint)BLI_stack_count(data[j].overlap); - BLI_stack_pop_n(data[j].overlap, to, count); - BLI_stack_free(data[j].overlap); - to += count; - } - - *r_overlap_tot = (uint)total; - return overlap; + const int thread_num = BLI_bvhtree_overlap_thread_num(tree1); + int j; + size_t total = 0; + BVHTreeOverlap *overlap = NULL, *to = NULL; + BVHOverlapData_Shared data_shared; + BVHOverlapData_Thread *data = BLI_array_alloca(data, (size_t)thread_num); + axis_t start_axis, stop_axis; + + /* check for compatibility of both trees (can't compare 14-DOP with 18-DOP) */ + if (UNLIKELY((tree1->axis != tree2->axis) && (tree1->axis == 14 || tree2->axis == 14) && + (tree1->axis == 18 || tree2->axis == 18))) { + BLI_assert(0); + return NULL; + } + + start_axis = min_axis(tree1->start_axis, tree2->start_axis); + stop_axis = min_axis(tree1->stop_axis, tree2->stop_axis); + + /* fast check root nodes for collision before doing big splitting + traversal */ + if (!tree_overlap_test( + tree1->nodes[tree1->totleaf], tree2->nodes[tree2->totleaf], start_axis, stop_axis)) { + return NULL; + } + + data_shared.tree1 = tree1; + data_shared.tree2 = tree2; + data_shared.start_axis = start_axis; + data_shared.stop_axis = stop_axis; + + /* can be NULL */ + data_shared.callback = callback; + data_shared.userdata = userdata; + + for (j = 0; j < thread_num; j++) { + /* init BVHOverlapData_Thread */ + data[j].shared = &data_shared; + data[j].overlap = BLI_stack_new(sizeof(BVHTreeOverlap), __func__); + + /* for callback */ + data[j].thread = j; + } + + ParallelRangeSettings settings; + BLI_parallel_range_settings_defaults(&settings); + settings.use_threading = (tree1->totleaf > KDOPBVH_THREAD_LEAF_THRESHOLD); + BLI_task_parallel_range(0, thread_num, data, bvhtree_overlap_task_cb, &settings); + + for (j = 0; j < thread_num; j++) { + total += BLI_stack_count(data[j].overlap); + } + + to = overlap = MEM_mallocN(sizeof(BVHTreeOverlap) * total, "BVHTreeOverlap"); + + for (j = 0; j < thread_num; j++) { + uint count = (uint)BLI_stack_count(data[j].overlap); + BLI_stack_pop_n(data[j].overlap, to, count); + BLI_stack_free(data[j].overlap); + to += count; + } + + *r_overlap_tot = (uint)total; + return overlap; } /** \} */ - /* -------------------------------------------------------------------- */ /** \name BLI_bvhtree_find_nearest * \{ */ @@ -1285,172 +1287,178 @@ BVHTreeOverlap *BLI_bvhtree_overlap( * Returns the squared distance to that point. */ static float calc_nearest_point_squared(const float proj[3], BVHNode *node, float nearest[3]) { - int i; - const float *bv = node->bv; - - /* nearest on AABB hull */ - for (i = 0; i != 3; i++, bv += 2) { - float val = proj[i]; - if (bv[0] > val) { - val = bv[0]; - } - if (bv[1] < val) { - val = bv[1]; - } - nearest[i] = val; - } - - return len_squared_v3v3(proj, nearest); + int i; + const float *bv = node->bv; + + /* nearest on AABB hull */ + for (i = 0; i != 3; i++, bv += 2) { + float val = proj[i]; + if (bv[0] > val) { + val = bv[0]; + } + if (bv[1] < val) { + val = bv[1]; + } + nearest[i] = val; + } + + return len_squared_v3v3(proj, nearest); } /* Depth first search method */ static void dfs_find_nearest_dfs(BVHNearestData *data, BVHNode *node) { - if (node->totnode == 0) { - if (data->callback) { - data->callback(data->userdata, node->index, data->co, &data->nearest); - } - else { - data->nearest.index = node->index; - data->nearest.dist_sq = calc_nearest_point_squared(data->proj, node, data->nearest.co); - } - } - else { - /* Better heuristic to pick the closest node to dive on */ - int i; - float nearest[3]; - - if (data->proj[node->main_axis] <= node->children[0]->bv[node->main_axis * 2 + 1]) { - - for (i = 0; i != node->totnode; i++) { - if (calc_nearest_point_squared(data->proj, node->children[i], nearest) >= data->nearest.dist_sq) { - continue; - } - dfs_find_nearest_dfs(data, node->children[i]); - } - } - else { - for (i = node->totnode - 1; i >= 0; i--) { - if (calc_nearest_point_squared(data->proj, node->children[i], nearest) >= data->nearest.dist_sq) { - continue; - } - dfs_find_nearest_dfs(data, node->children[i]); - } - } - } + if (node->totnode == 0) { + if (data->callback) { + data->callback(data->userdata, node->index, data->co, &data->nearest); + } + else { + data->nearest.index = node->index; + data->nearest.dist_sq = calc_nearest_point_squared(data->proj, node, data->nearest.co); + } + } + else { + /* Better heuristic to pick the closest node to dive on */ + int i; + float nearest[3]; + + if (data->proj[node->main_axis] <= node->children[0]->bv[node->main_axis * 2 + 1]) { + + for (i = 0; i != node->totnode; i++) { + if (calc_nearest_point_squared(data->proj, node->children[i], nearest) >= + data->nearest.dist_sq) { + continue; + } + dfs_find_nearest_dfs(data, node->children[i]); + } + } + else { + for (i = node->totnode - 1; i >= 0; i--) { + if (calc_nearest_point_squared(data->proj, node->children[i], nearest) >= + data->nearest.dist_sq) { + continue; + } + dfs_find_nearest_dfs(data, node->children[i]); + } + } + } } static void dfs_find_nearest_begin(BVHNearestData *data, BVHNode *node) { - float nearest[3], dist_sq; - dist_sq = calc_nearest_point_squared(data->proj, node, nearest); - if (dist_sq >= data->nearest.dist_sq) { - return; - } - dfs_find_nearest_dfs(data, node); + float nearest[3], dist_sq; + dist_sq = calc_nearest_point_squared(data->proj, node, nearest); + if (dist_sq >= data->nearest.dist_sq) { + return; + } + dfs_find_nearest_dfs(data, node); } /* Priority queue method */ static void heap_find_nearest_inner(BVHNearestData *data, HeapSimple *heap, BVHNode *node) { - if (node->totnode == 0) { - if (data->callback) { - data->callback(data->userdata, node->index, data->co, &data->nearest); - } - else { - data->nearest.index = node->index; - data->nearest.dist_sq = calc_nearest_point_squared(data->proj, node, data->nearest.co); - } - } - else { - float nearest[3]; - - for (int i = 0; i != node->totnode; i++) { - float dist_sq = calc_nearest_point_squared(data->proj, node->children[i], nearest); - - if (dist_sq < data->nearest.dist_sq) { - BLI_heapsimple_insert(heap, dist_sq, node->children[i]); - } - } - } + if (node->totnode == 0) { + if (data->callback) { + data->callback(data->userdata, node->index, data->co, &data->nearest); + } + else { + data->nearest.index = node->index; + data->nearest.dist_sq = calc_nearest_point_squared(data->proj, node, data->nearest.co); + } + } + else { + float nearest[3]; + + for (int i = 0; i != node->totnode; i++) { + float dist_sq = calc_nearest_point_squared(data->proj, node->children[i], nearest); + + if (dist_sq < data->nearest.dist_sq) { + BLI_heapsimple_insert(heap, dist_sq, node->children[i]); + } + } + } } static void heap_find_nearest_begin(BVHNearestData *data, BVHNode *root) { - float nearest[3]; - float dist_sq = calc_nearest_point_squared(data->proj, root, nearest); + float nearest[3]; + float dist_sq = calc_nearest_point_squared(data->proj, root, nearest); - if (dist_sq < data->nearest.dist_sq) { - HeapSimple *heap = BLI_heapsimple_new_ex(32); + if (dist_sq < data->nearest.dist_sq) { + HeapSimple *heap = BLI_heapsimple_new_ex(32); - heap_find_nearest_inner(data, heap, root); + heap_find_nearest_inner(data, heap, root); - while (!BLI_heapsimple_is_empty(heap) && BLI_heapsimple_top_value(heap) < data->nearest.dist_sq) { - BVHNode *node = BLI_heapsimple_pop_min(heap); - heap_find_nearest_inner(data, heap, node); - } + while (!BLI_heapsimple_is_empty(heap) && + BLI_heapsimple_top_value(heap) < data->nearest.dist_sq) { + BVHNode *node = BLI_heapsimple_pop_min(heap); + heap_find_nearest_inner(data, heap, node); + } - BLI_heapsimple_free(heap, NULL); - } + BLI_heapsimple_free(heap, NULL); + } } -int BLI_bvhtree_find_nearest_ex( - BVHTree *tree, const float co[3], BVHTreeNearest *nearest, - BVHTree_NearestPointCallback callback, void *userdata, - int flag) +int BLI_bvhtree_find_nearest_ex(BVHTree *tree, + const float co[3], + BVHTreeNearest *nearest, + BVHTree_NearestPointCallback callback, + void *userdata, + int flag) { - axis_t axis_iter; - - BVHNearestData data; - BVHNode *root = tree->nodes[tree->totleaf]; - - /* init data to search */ - data.tree = tree; - data.co = co; - - data.callback = callback; - data.userdata = userdata; - - for (axis_iter = data.tree->start_axis; axis_iter != data.tree->stop_axis; axis_iter++) { - data.proj[axis_iter] = dot_v3v3(data.co, bvhtree_kdop_axes[axis_iter]); - } - - if (nearest) { - memcpy(&data.nearest, nearest, sizeof(*nearest)); - } - else { - data.nearest.index = -1; - data.nearest.dist_sq = FLT_MAX; - } - - /* dfs search */ - if (root) { - if (flag & BVH_NEAREST_OPTIMAL_ORDER) { - heap_find_nearest_begin(&data, root); - } - else { - dfs_find_nearest_begin(&data, root); - } - } - - /* copy back results */ - if (nearest) { - memcpy(nearest, &data.nearest, sizeof(*nearest)); - } - - return data.nearest.index; + axis_t axis_iter; + + BVHNearestData data; + BVHNode *root = tree->nodes[tree->totleaf]; + + /* init data to search */ + data.tree = tree; + data.co = co; + + data.callback = callback; + data.userdata = userdata; + + for (axis_iter = data.tree->start_axis; axis_iter != data.tree->stop_axis; axis_iter++) { + data.proj[axis_iter] = dot_v3v3(data.co, bvhtree_kdop_axes[axis_iter]); + } + + if (nearest) { + memcpy(&data.nearest, nearest, sizeof(*nearest)); + } + else { + data.nearest.index = -1; + data.nearest.dist_sq = FLT_MAX; + } + + /* dfs search */ + if (root) { + if (flag & BVH_NEAREST_OPTIMAL_ORDER) { + heap_find_nearest_begin(&data, root); + } + else { + dfs_find_nearest_begin(&data, root); + } + } + + /* copy back results */ + if (nearest) { + memcpy(nearest, &data.nearest, sizeof(*nearest)); + } + + return data.nearest.index; } -int BLI_bvhtree_find_nearest( - BVHTree *tree, const float co[3], BVHTreeNearest *nearest, - BVHTree_NearestPointCallback callback, void *userdata) +int BLI_bvhtree_find_nearest(BVHTree *tree, + const float co[3], + BVHTreeNearest *nearest, + BVHTree_NearestPointCallback callback, + void *userdata) { - return BLI_bvhtree_find_nearest_ex(tree, co, nearest, callback, userdata, 0); + return BLI_bvhtree_find_nearest_ex(tree, co, nearest, callback, userdata, 0); } /** \} */ - /* -------------------------------------------------------------------- */ /** \name BLI_bvhtree_ray_cast * @@ -1458,50 +1466,48 @@ int BLI_bvhtree_find_nearest( * * \{ */ - /* Determines the distance that the ray must travel to hit the bounding volume of the given node */ static float ray_nearest_hit(const BVHRayCastData *data, const float bv[6]) { - int i; - - float low = 0, upper = data->hit.dist; - - for (i = 0; i != 3; i++, bv += 2) { - if (data->ray_dot_axis[i] == 0.0f) { - /* axis aligned ray */ - if (data->ray.origin[i] < bv[0] - data->ray.radius || - data->ray.origin[i] > bv[1] + data->ray.radius) - { - return FLT_MAX; - } - } - else { - float ll = (bv[0] - data->ray.radius - data->ray.origin[i]) / data->ray_dot_axis[i]; - float lu = (bv[1] + data->ray.radius - data->ray.origin[i]) / data->ray_dot_axis[i]; - - if (data->ray_dot_axis[i] > 0.0f) { - if (ll > low) { - low = ll; - } - if (lu < upper) { - upper = lu; - } - } - else { - if (lu > low) { - low = lu; - } - if (ll < upper) { - upper = ll; - } - } - - if (low > upper) { - return FLT_MAX; - } - } - } - return low; + int i; + + float low = 0, upper = data->hit.dist; + + for (i = 0; i != 3; i++, bv += 2) { + if (data->ray_dot_axis[i] == 0.0f) { + /* axis aligned ray */ + if (data->ray.origin[i] < bv[0] - data->ray.radius || + data->ray.origin[i] > bv[1] + data->ray.radius) { + return FLT_MAX; + } + } + else { + float ll = (bv[0] - data->ray.radius - data->ray.origin[i]) / data->ray_dot_axis[i]; + float lu = (bv[1] + data->ray.radius - data->ray.origin[i]) / data->ray_dot_axis[i]; + + if (data->ray_dot_axis[i] > 0.0f) { + if (ll > low) { + low = ll; + } + if (lu < upper) { + upper = lu; + } + } + else { + if (lu > low) { + low = lu; + } + if (ll < upper) { + upper = ll; + } + } + + if (low > upper) { + return FLT_MAX; + } + } + } + return low; } /** @@ -1512,61 +1518,61 @@ static float ray_nearest_hit(const BVHRayCastData *data, const float bv[6]) * TODO this doesn't take data->ray.radius into consideration */ static float fast_ray_nearest_hit(const BVHRayCastData *data, const BVHNode *node) { - const float *bv = node->bv; - - float t1x = (bv[data->index[0]] - data->ray.origin[0]) * data->idot_axis[0]; - float t2x = (bv[data->index[1]] - data->ray.origin[0]) * data->idot_axis[0]; - float t1y = (bv[data->index[2]] - data->ray.origin[1]) * data->idot_axis[1]; - float t2y = (bv[data->index[3]] - data->ray.origin[1]) * data->idot_axis[1]; - float t1z = (bv[data->index[4]] - data->ray.origin[2]) * data->idot_axis[2]; - float t2z = (bv[data->index[5]] - data->ray.origin[2]) * data->idot_axis[2]; - - if ((t1x > t2y || t2x < t1y || t1x > t2z || t2x < t1z || t1y > t2z || t2y < t1z) || - (t2x < 0.0f || t2y < 0.0f || t2z < 0.0f) || - (t1x > data->hit.dist || t1y > data->hit.dist || t1z > data->hit.dist)) - { - return FLT_MAX; - } - else { - return max_fff(t1x, t1y, t1z); - } + const float *bv = node->bv; + + float t1x = (bv[data->index[0]] - data->ray.origin[0]) * data->idot_axis[0]; + float t2x = (bv[data->index[1]] - data->ray.origin[0]) * data->idot_axis[0]; + float t1y = (bv[data->index[2]] - data->ray.origin[1]) * data->idot_axis[1]; + float t2y = (bv[data->index[3]] - data->ray.origin[1]) * data->idot_axis[1]; + float t1z = (bv[data->index[4]] - data->ray.origin[2]) * data->idot_axis[2]; + float t2z = (bv[data->index[5]] - data->ray.origin[2]) * data->idot_axis[2]; + + if ((t1x > t2y || t2x < t1y || t1x > t2z || t2x < t1z || t1y > t2z || t2y < t1z) || + (t2x < 0.0f || t2y < 0.0f || t2z < 0.0f) || + (t1x > data->hit.dist || t1y > data->hit.dist || t1z > data->hit.dist)) { + return FLT_MAX; + } + else { + return max_fff(t1x, t1y, t1z); + } } static void dfs_raycast(BVHRayCastData *data, BVHNode *node) { - int i; - - /* ray-bv is really fast.. and simple tests revealed its worth to test it - * before calling the ray-primitive functions */ - /* XXX: temporary solution for particles until fast_ray_nearest_hit supports ray.radius */ - float dist = (data->ray.radius == 0.0f) ? fast_ray_nearest_hit(data, node) : ray_nearest_hit(data, node->bv); - if (dist >= data->hit.dist) { - return; - } - - if (node->totnode == 0) { - if (data->callback) { - data->callback(data->userdata, node->index, &data->ray, &data->hit); - } - else { - data->hit.index = node->index; - data->hit.dist = dist; - madd_v3_v3v3fl(data->hit.co, data->ray.origin, data->ray.direction, dist); - } - } - else { - /* pick loop direction to dive into the tree (based on ray direction and split axis) */ - if (data->ray_dot_axis[node->main_axis] > 0.0f) { - for (i = 0; i != node->totnode; i++) { - dfs_raycast(data, node->children[i]); - } - } - else { - for (i = node->totnode - 1; i >= 0; i--) { - dfs_raycast(data, node->children[i]); - } - } - } + int i; + + /* ray-bv is really fast.. and simple tests revealed its worth to test it + * before calling the ray-primitive functions */ + /* XXX: temporary solution for particles until fast_ray_nearest_hit supports ray.radius */ + float dist = (data->ray.radius == 0.0f) ? fast_ray_nearest_hit(data, node) : + ray_nearest_hit(data, node->bv); + if (dist >= data->hit.dist) { + return; + } + + if (node->totnode == 0) { + if (data->callback) { + data->callback(data->userdata, node->index, &data->ray, &data->hit); + } + else { + data->hit.index = node->index; + data->hit.dist = dist; + madd_v3_v3v3fl(data->hit.co, data->ray.origin, data->ray.direction, dist); + } + } + else { + /* pick loop direction to dive into the tree (based on ray direction and split axis) */ + if (data->ray_dot_axis[node->main_axis] > 0.0f) { + for (i = 0; i != node->totnode; i++) { + dfs_raycast(data, node->children[i]); + } + } + else { + for (i = node->totnode - 1; i >= 0; i--) { + dfs_raycast(data, node->children[i]); + } + } + } } /** @@ -1574,140 +1580,151 @@ static void dfs_raycast(BVHRayCastData *data, BVHNode *node) */ static void dfs_raycast_all(BVHRayCastData *data, BVHNode *node) { - int i; - - /* ray-bv is really fast.. and simple tests revealed its worth to test it - * before calling the ray-primitive functions */ - /* XXX: temporary solution for particles until fast_ray_nearest_hit supports ray.radius */ - float dist = (data->ray.radius == 0.0f) ? fast_ray_nearest_hit(data, node) : ray_nearest_hit(data, node->bv); - if (dist >= data->hit.dist) { - return; - } - - if (node->totnode == 0) { - /* no need to check for 'data->callback' (using 'all' only makes sense with a callback). */ - dist = data->hit.dist; - data->callback(data->userdata, node->index, &data->ray, &data->hit); - data->hit.index = -1; - data->hit.dist = dist; - } - else { - /* pick loop direction to dive into the tree (based on ray direction and split axis) */ - if (data->ray_dot_axis[node->main_axis] > 0.0f) { - for (i = 0; i != node->totnode; i++) { - dfs_raycast_all(data, node->children[i]); - } - } - else { - for (i = node->totnode - 1; i >= 0; i--) { - dfs_raycast_all(data, node->children[i]); - } - } - } + int i; + + /* ray-bv is really fast.. and simple tests revealed its worth to test it + * before calling the ray-primitive functions */ + /* XXX: temporary solution for particles until fast_ray_nearest_hit supports ray.radius */ + float dist = (data->ray.radius == 0.0f) ? fast_ray_nearest_hit(data, node) : + ray_nearest_hit(data, node->bv); + if (dist >= data->hit.dist) { + return; + } + + if (node->totnode == 0) { + /* no need to check for 'data->callback' (using 'all' only makes sense with a callback). */ + dist = data->hit.dist; + data->callback(data->userdata, node->index, &data->ray, &data->hit); + data->hit.index = -1; + data->hit.dist = dist; + } + else { + /* pick loop direction to dive into the tree (based on ray direction and split axis) */ + if (data->ray_dot_axis[node->main_axis] > 0.0f) { + for (i = 0; i != node->totnode; i++) { + dfs_raycast_all(data, node->children[i]); + } + } + else { + for (i = node->totnode - 1; i >= 0; i--) { + dfs_raycast_all(data, node->children[i]); + } + } + } } static void bvhtree_ray_cast_data_precalc(BVHRayCastData *data, int flag) { - int i; + int i; - for (i = 0; i < 3; i++) { - data->ray_dot_axis[i] = dot_v3v3(data->ray.direction, bvhtree_kdop_axes[i]); - data->idot_axis[i] = 1.0f / data->ray_dot_axis[i]; + for (i = 0; i < 3; i++) { + data->ray_dot_axis[i] = dot_v3v3(data->ray.direction, bvhtree_kdop_axes[i]); + data->idot_axis[i] = 1.0f / data->ray_dot_axis[i]; - if (fabsf(data->ray_dot_axis[i]) < FLT_EPSILON) { - data->ray_dot_axis[i] = 0.0; - } - data->index[2 * i] = data->idot_axis[i] < 0.0f ? 1 : 0; - data->index[2 * i + 1] = 1 - data->index[2 * i]; - data->index[2 * i] += 2 * i; - data->index[2 * i + 1] += 2 * i; - } + if (fabsf(data->ray_dot_axis[i]) < FLT_EPSILON) { + data->ray_dot_axis[i] = 0.0; + } + data->index[2 * i] = data->idot_axis[i] < 0.0f ? 1 : 0; + data->index[2 * i + 1] = 1 - data->index[2 * i]; + data->index[2 * i] += 2 * i; + data->index[2 * i + 1] += 2 * i; + } #ifdef USE_KDOPBVH_WATERTIGHT - if (flag & BVH_RAYCAST_WATERTIGHT) { - isect_ray_tri_watertight_v3_precalc(&data->isect_precalc, data->ray.direction); - data->ray.isect_precalc = &data->isect_precalc; - } - else { - data->ray.isect_precalc = NULL; - } + if (flag & BVH_RAYCAST_WATERTIGHT) { + isect_ray_tri_watertight_v3_precalc(&data->isect_precalc, data->ray.direction); + data->ray.isect_precalc = &data->isect_precalc; + } + else { + data->ray.isect_precalc = NULL; + } #else - UNUSED_VARS(flag); + UNUSED_VARS(flag); #endif } -int BLI_bvhtree_ray_cast_ex( - BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit, - BVHTree_RayCastCallback callback, void *userdata, - int flag) +int BLI_bvhtree_ray_cast_ex(BVHTree *tree, + const float co[3], + const float dir[3], + float radius, + BVHTreeRayHit *hit, + BVHTree_RayCastCallback callback, + void *userdata, + int flag) { - BVHRayCastData data; - BVHNode *root = tree->nodes[tree->totleaf]; - - BLI_ASSERT_UNIT_V3(dir); + BVHRayCastData data; + BVHNode *root = tree->nodes[tree->totleaf]; - data.tree = tree; + BLI_ASSERT_UNIT_V3(dir); - data.callback = callback; - data.userdata = userdata; + data.tree = tree; - copy_v3_v3(data.ray.origin, co); - copy_v3_v3(data.ray.direction, dir); - data.ray.radius = radius; + data.callback = callback; + data.userdata = userdata; - bvhtree_ray_cast_data_precalc(&data, flag); + copy_v3_v3(data.ray.origin, co); + copy_v3_v3(data.ray.direction, dir); + data.ray.radius = radius; - if (hit) { - memcpy(&data.hit, hit, sizeof(*hit)); - } - else { - data.hit.index = -1; - data.hit.dist = BVH_RAYCAST_DIST_MAX; - } + bvhtree_ray_cast_data_precalc(&data, flag); - if (root) { - dfs_raycast(&data, root); -// iterative_raycast(&data, root); - } + if (hit) { + memcpy(&data.hit, hit, sizeof(*hit)); + } + else { + data.hit.index = -1; + data.hit.dist = BVH_RAYCAST_DIST_MAX; + } + if (root) { + dfs_raycast(&data, root); + // iterative_raycast(&data, root); + } - if (hit) { - memcpy(hit, &data.hit, sizeof(*hit)); - } + if (hit) { + memcpy(hit, &data.hit, sizeof(*hit)); + } - return data.hit.index; + return data.hit.index; } -int BLI_bvhtree_ray_cast( - BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit, - BVHTree_RayCastCallback callback, void *userdata) +int BLI_bvhtree_ray_cast(BVHTree *tree, + const float co[3], + const float dir[3], + float radius, + BVHTreeRayHit *hit, + BVHTree_RayCastCallback callback, + void *userdata) { - return BLI_bvhtree_ray_cast_ex(tree, co, dir, radius, hit, callback, userdata, BVH_RAYCAST_DEFAULT); + return BLI_bvhtree_ray_cast_ex( + tree, co, dir, radius, hit, callback, userdata, BVH_RAYCAST_DEFAULT); } -float BLI_bvhtree_bb_raycast(const float bv[6], const float light_start[3], const float light_end[3], float pos[3]) +float BLI_bvhtree_bb_raycast(const float bv[6], + const float light_start[3], + const float light_end[3], + float pos[3]) { - BVHRayCastData data; - float dist; - - data.hit.dist = BVH_RAYCAST_DIST_MAX; + BVHRayCastData data; + float dist; - /* get light direction */ - sub_v3_v3v3(data.ray.direction, light_end, light_start); + data.hit.dist = BVH_RAYCAST_DIST_MAX; - data.ray.radius = 0.0; + /* get light direction */ + sub_v3_v3v3(data.ray.direction, light_end, light_start); - copy_v3_v3(data.ray.origin, light_start); + data.ray.radius = 0.0; - normalize_v3(data.ray.direction); - copy_v3_v3(data.ray_dot_axis, data.ray.direction); + copy_v3_v3(data.ray.origin, light_start); - dist = ray_nearest_hit(&data, bv); + normalize_v3(data.ray.direction); + copy_v3_v3(data.ray_dot_axis, data.ray.direction); - madd_v3_v3v3fl(pos, light_start, data.ray.direction, dist); + dist = ray_nearest_hit(&data, bv); - return dist; + madd_v3_v3v3fl(pos, light_start, data.ray.direction, dist); + return dist; } /** @@ -1718,41 +1735,50 @@ float BLI_bvhtree_bb_raycast(const float bv[6], const float light_start[3], cons * having to handle resetting the hit beforehand. * It also avoid redundant argument and return value which aren't meaningful when collecting multiple hits. */ -void BLI_bvhtree_ray_cast_all_ex( - 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_ray_cast_all_ex(BVHTree *tree, + const float co[3], + const float dir[3], + float radius, + float hit_dist, + BVHTree_RayCastCallback callback, + void *userdata, + int flag) { - BVHRayCastData data; - BVHNode *root = tree->nodes[tree->totleaf]; + BVHRayCastData data; + BVHNode *root = tree->nodes[tree->totleaf]; - BLI_ASSERT_UNIT_V3(dir); - BLI_assert(callback != NULL); + BLI_ASSERT_UNIT_V3(dir); + BLI_assert(callback != NULL); - data.tree = tree; + data.tree = tree; - data.callback = callback; - data.userdata = userdata; + data.callback = callback; + data.userdata = userdata; - copy_v3_v3(data.ray.origin, co); - copy_v3_v3(data.ray.direction, dir); - data.ray.radius = radius; + copy_v3_v3(data.ray.origin, co); + copy_v3_v3(data.ray.direction, dir); + data.ray.radius = radius; - bvhtree_ray_cast_data_precalc(&data, flag); + bvhtree_ray_cast_data_precalc(&data, flag); - data.hit.index = -1; - data.hit.dist = hit_dist; + data.hit.index = -1; + data.hit.dist = hit_dist; - if (root) { - dfs_raycast_all(&data, root); - } + if (root) { + dfs_raycast_all(&data, root); + } } -void BLI_bvhtree_ray_cast_all( - BVHTree *tree, const float co[3], const float dir[3], float radius, float hit_dist, - BVHTree_RayCastCallback callback, void *userdata) +void BLI_bvhtree_ray_cast_all(BVHTree *tree, + const float co[3], + const float dir[3], + float radius, + float hit_dist, + BVHTree_RayCastCallback callback, + void *userdata) { - BLI_bvhtree_ray_cast_all_ex(tree, co, dir, radius, hit_dist, callback, userdata, BVH_RAYCAST_DEFAULT); + BLI_bvhtree_ray_cast_all_ex( + tree, co, dir, radius, hit_dist, callback, userdata, BVH_RAYCAST_DEFAULT); } /** \} */ @@ -1766,284 +1792,274 @@ void BLI_bvhtree_ray_cast_all( * \{ */ typedef struct RangeQueryData { - BVHTree *tree; - const float *center; - float radius_sq; /* squared radius */ + BVHTree *tree; + const float *center; + float radius_sq; /* squared radius */ - int hits; + int hits; - BVHTree_RangeQuery callback; - void *userdata; + BVHTree_RangeQuery callback; + void *userdata; } RangeQueryData; - static void dfs_range_query(RangeQueryData *data, BVHNode *node) { - if (node->totnode == 0) { -#if 0 /*UNUSED*/ - /* Calculate the node min-coords - * (if the node was a point then this is the point coordinates) */ - float co[3]; - co[0] = node->bv[0]; - co[1] = node->bv[2]; - co[2] = node->bv[4]; + if (node->totnode == 0) { +#if 0 /*UNUSED*/ + /* Calculate the node min-coords + * (if the node was a point then this is the point coordinates) */ + float co[3]; + co[0] = node->bv[0]; + co[1] = node->bv[2]; + co[2] = node->bv[4]; #endif - } - else { - int i; - for (i = 0; i != node->totnode; i++) { - float nearest[3]; - float dist_sq = calc_nearest_point_squared(data->center, node->children[i], nearest); - if (dist_sq < data->radius_sq) { - /* Its a leaf.. call the callback */ - if (node->children[i]->totnode == 0) { - data->hits++; - data->callback(data->userdata, node->children[i]->index, data->center, dist_sq); - } - else { - dfs_range_query(data, node->children[i]); - } - } - } - } + } + else { + int i; + for (i = 0; i != node->totnode; i++) { + float nearest[3]; + float dist_sq = calc_nearest_point_squared(data->center, node->children[i], nearest); + if (dist_sq < data->radius_sq) { + /* Its a leaf.. call the callback */ + if (node->children[i]->totnode == 0) { + data->hits++; + data->callback(data->userdata, node->children[i]->index, data->center, dist_sq); + } + else { + dfs_range_query(data, node->children[i]); + } + } + } + } } int BLI_bvhtree_range_query( - BVHTree *tree, const float co[3], float radius, - BVHTree_RangeQuery callback, void *userdata) + BVHTree *tree, const float co[3], float radius, BVHTree_RangeQuery callback, void *userdata) { - BVHNode *root = tree->nodes[tree->totleaf]; - - RangeQueryData data; - data.tree = tree; - data.center = co; - data.radius_sq = radius * radius; - data.hits = 0; - - data.callback = callback; - data.userdata = userdata; - - if (root != NULL) { - float nearest[3]; - float dist_sq = calc_nearest_point_squared(data.center, root, nearest); - if (dist_sq < data.radius_sq) { - /* Its a leaf.. call the callback */ - if (root->totnode == 0) { - data.hits++; - data.callback(data.userdata, root->index, co, dist_sq); - } - else { - dfs_range_query(&data, root); - } - } - } - - return data.hits; + BVHNode *root = tree->nodes[tree->totleaf]; + + RangeQueryData data; + data.tree = tree; + data.center = co; + data.radius_sq = radius * radius; + data.hits = 0; + + data.callback = callback; + data.userdata = userdata; + + if (root != NULL) { + float nearest[3]; + float dist_sq = calc_nearest_point_squared(data.center, root, nearest); + if (dist_sq < data.radius_sq) { + /* Its a leaf.. call the callback */ + if (root->totnode == 0) { + data.hits++; + data.callback(data.userdata, root->index, co, dist_sq); + } + else { + dfs_range_query(&data, root); + } + } + } + + return data.hits; } /** \} */ - /* -------------------------------------------------------------------- */ /** \name BLI_bvhtree_nearest_projected * \{ */ -static void bvhtree_nearest_projected_dfs_recursive( - BVHNearestProjectedData *__restrict data, const BVHNode *node) +static void bvhtree_nearest_projected_dfs_recursive(BVHNearestProjectedData *__restrict data, + const BVHNode *node) { - if (node->totnode == 0) { - if (data->callback) { - data->callback( - data->userdata, node->index, &data->precalc, - NULL, 0, - &data->nearest); - } - else { - data->nearest.index = node->index; - data->nearest.dist_sq = dist_squared_to_projected_aabb( - &data->precalc, - (float[3]) {node->bv[0], node->bv[2], node->bv[4]}, - (float[3]) {node->bv[1], node->bv[3], node->bv[5]}, - data->closest_axis); - } - } - else { - /* First pick the closest node to recurse into */ - if (data->closest_axis[node->main_axis]) { - for (int i = 0; i != node->totnode; i++) { - const float *bv = node->children[i]->bv; - - if (dist_squared_to_projected_aabb( - &data->precalc, - (float[3]) {bv[0], bv[2], bv[4]}, - (float[3]) {bv[1], bv[3], bv[5]}, - data->closest_axis) <= data->nearest.dist_sq) - { - bvhtree_nearest_projected_dfs_recursive(data, node->children[i]); - } - } - } - else { - for (int i = node->totnode; i--;) { - const float *bv = node->children[i]->bv; - - if (dist_squared_to_projected_aabb( - &data->precalc, - (float[3]) {bv[0], bv[2], bv[4]}, - (float[3]) {bv[1], bv[3], bv[5]}, - data->closest_axis) <= data->nearest.dist_sq) - { - bvhtree_nearest_projected_dfs_recursive(data, node->children[i]); - } - } - } - } + if (node->totnode == 0) { + if (data->callback) { + data->callback(data->userdata, node->index, &data->precalc, NULL, 0, &data->nearest); + } + else { + data->nearest.index = node->index; + data->nearest.dist_sq = dist_squared_to_projected_aabb( + &data->precalc, + (float[3]){node->bv[0], node->bv[2], node->bv[4]}, + (float[3]){node->bv[1], node->bv[3], node->bv[5]}, + data->closest_axis); + } + } + else { + /* First pick the closest node to recurse into */ + if (data->closest_axis[node->main_axis]) { + for (int i = 0; i != node->totnode; i++) { + const float *bv = node->children[i]->bv; + + if (dist_squared_to_projected_aabb(&data->precalc, + (float[3]){bv[0], bv[2], bv[4]}, + (float[3]){bv[1], bv[3], bv[5]}, + data->closest_axis) <= data->nearest.dist_sq) { + bvhtree_nearest_projected_dfs_recursive(data, node->children[i]); + } + } + } + else { + for (int i = node->totnode; i--;) { + const float *bv = node->children[i]->bv; + + if (dist_squared_to_projected_aabb(&data->precalc, + (float[3]){bv[0], bv[2], bv[4]}, + (float[3]){bv[1], bv[3], bv[5]}, + data->closest_axis) <= data->nearest.dist_sq) { + bvhtree_nearest_projected_dfs_recursive(data, node->children[i]); + } + } + } + } } static void bvhtree_nearest_projected_with_clipplane_test_dfs_recursive( - BVHNearestProjectedData *__restrict data, const BVHNode *node) + BVHNearestProjectedData *__restrict data, const BVHNode *node) { - if (node->totnode == 0) { - if (data->callback) { - data->callback( - data->userdata, node->index, &data->precalc, - data->clip_plane, data->clip_plane_len, - &data->nearest); - } - else { - data->nearest.index = node->index; - data->nearest.dist_sq = dist_squared_to_projected_aabb( - &data->precalc, - (float[3]) {node->bv[0], node->bv[2], node->bv[4]}, - (float[3]) {node->bv[1], node->bv[3], node->bv[5]}, - data->closest_axis); - } - } - else { - /* First pick the closest node to recurse into */ - if (data->closest_axis[node->main_axis]) { - for (int i = 0; i != node->totnode; i++) { - const float *bv = node->children[i]->bv; - const float bb_min[3] = {bv[0], bv[2], bv[4]}; - const float bb_max[3] = {bv[1], bv[3], bv[5]}; - - int isect_type = isect_aabb_planes_v3(data->clip_plane, data->clip_plane_len, bb_min, bb_max); - - if ((isect_type != ISECT_AABB_PLANE_BEHIND_ANY) && dist_squared_to_projected_aabb( - &data->precalc, bb_min, bb_max, - data->closest_axis) <= data->nearest.dist_sq) - { - if (isect_type == ISECT_AABB_PLANE_CROSS_ANY) { - bvhtree_nearest_projected_with_clipplane_test_dfs_recursive(data, node->children[i]); - } - else { - /* ISECT_AABB_PLANE_IN_FRONT_ALL */ - bvhtree_nearest_projected_dfs_recursive(data, node->children[i]); - } - } - } - } - else { - for (int i = node->totnode; i--;) { - const float *bv = node->children[i]->bv; - const float bb_min[3] = {bv[0], bv[2], bv[4]}; - const float bb_max[3] = {bv[1], bv[3], bv[5]}; - - int isect_type = isect_aabb_planes_v3(data->clip_plane, data->clip_plane_len, bb_min, bb_max); - - if (isect_type != ISECT_AABB_PLANE_BEHIND_ANY && dist_squared_to_projected_aabb( - &data->precalc, bb_min, bb_max, - data->closest_axis) <= data->nearest.dist_sq) - { - if (isect_type == ISECT_AABB_PLANE_CROSS_ANY) { - bvhtree_nearest_projected_with_clipplane_test_dfs_recursive(data, node->children[i]); - } - else { - /* ISECT_AABB_PLANE_IN_FRONT_ALL */ - bvhtree_nearest_projected_dfs_recursive(data, node->children[i]); - } - } - } - } - } + if (node->totnode == 0) { + if (data->callback) { + data->callback(data->userdata, + node->index, + &data->precalc, + data->clip_plane, + data->clip_plane_len, + &data->nearest); + } + else { + data->nearest.index = node->index; + data->nearest.dist_sq = dist_squared_to_projected_aabb( + &data->precalc, + (float[3]){node->bv[0], node->bv[2], node->bv[4]}, + (float[3]){node->bv[1], node->bv[3], node->bv[5]}, + data->closest_axis); + } + } + else { + /* First pick the closest node to recurse into */ + if (data->closest_axis[node->main_axis]) { + for (int i = 0; i != node->totnode; i++) { + const float *bv = node->children[i]->bv; + const float bb_min[3] = {bv[0], bv[2], bv[4]}; + const float bb_max[3] = {bv[1], bv[3], bv[5]}; + + int isect_type = isect_aabb_planes_v3( + data->clip_plane, data->clip_plane_len, bb_min, bb_max); + + if ((isect_type != ISECT_AABB_PLANE_BEHIND_ANY) && + dist_squared_to_projected_aabb(&data->precalc, bb_min, bb_max, data->closest_axis) <= + data->nearest.dist_sq) { + if (isect_type == ISECT_AABB_PLANE_CROSS_ANY) { + bvhtree_nearest_projected_with_clipplane_test_dfs_recursive(data, node->children[i]); + } + else { + /* ISECT_AABB_PLANE_IN_FRONT_ALL */ + bvhtree_nearest_projected_dfs_recursive(data, node->children[i]); + } + } + } + } + else { + for (int i = node->totnode; i--;) { + const float *bv = node->children[i]->bv; + const float bb_min[3] = {bv[0], bv[2], bv[4]}; + const float bb_max[3] = {bv[1], bv[3], bv[5]}; + + int isect_type = isect_aabb_planes_v3( + data->clip_plane, data->clip_plane_len, bb_min, bb_max); + + if (isect_type != ISECT_AABB_PLANE_BEHIND_ANY && + dist_squared_to_projected_aabb(&data->precalc, bb_min, bb_max, data->closest_axis) <= + data->nearest.dist_sq) { + if (isect_type == ISECT_AABB_PLANE_CROSS_ANY) { + bvhtree_nearest_projected_with_clipplane_test_dfs_recursive(data, node->children[i]); + } + else { + /* ISECT_AABB_PLANE_IN_FRONT_ALL */ + bvhtree_nearest_projected_dfs_recursive(data, node->children[i]); + } + } + } + } + } } -int BLI_bvhtree_find_nearest_projected( - BVHTree *tree, float projmat[4][4], float winsize[2], float mval[2], - float clip_plane[6][4], int clip_plane_len, - BVHTreeNearest *nearest, - BVHTree_NearestProjectedCallback callback, void *userdata) +int BLI_bvhtree_find_nearest_projected(BVHTree *tree, + float projmat[4][4], + float winsize[2], + float mval[2], + float clip_plane[6][4], + int clip_plane_len, + BVHTreeNearest *nearest, + BVHTree_NearestProjectedCallback callback, + void *userdata) { - BVHNode *root = tree->nodes[tree->totleaf]; - if (root != NULL) { - BVHNearestProjectedData data; - dist_squared_to_projected_aabb_precalc( - &data.precalc, projmat, winsize, mval); - - data.callback = callback; - data.userdata = userdata; - - if (clip_plane) { - data.clip_plane_len = clip_plane_len; - for (int i = 0; i < data.clip_plane_len; i++) { - copy_v4_v4(data.clip_plane[i], clip_plane[i]); - } - } - else { - data.clip_plane_len = 1; - planes_from_projmat( - projmat, - NULL, NULL, NULL, NULL, - data.clip_plane[0], NULL); - } - - if (nearest) { - memcpy(&data.nearest, nearest, sizeof(*nearest)); - } - else { - data.nearest.index = -1; - data.nearest.dist_sq = FLT_MAX; - } - { - const float bb_min[3] = {root->bv[0], root->bv[2], root->bv[4]}; - const float bb_max[3] = {root->bv[1], root->bv[3], root->bv[5]}; - - int isect_type = isect_aabb_planes_v3(data.clip_plane, data.clip_plane_len, bb_min, bb_max); - - if (isect_type != 0 && dist_squared_to_projected_aabb( - &data.precalc, bb_min, bb_max, - data.closest_axis) <= data.nearest.dist_sq) - { - if (isect_type == 1) { - bvhtree_nearest_projected_with_clipplane_test_dfs_recursive(&data, root); - } - else { - bvhtree_nearest_projected_dfs_recursive(&data, root); - } - } - } - - if (nearest) { - memcpy(nearest, &data.nearest, sizeof(*nearest)); - } - - return data.nearest.index; - } - return -1; + BVHNode *root = tree->nodes[tree->totleaf]; + if (root != NULL) { + BVHNearestProjectedData data; + dist_squared_to_projected_aabb_precalc(&data.precalc, projmat, winsize, mval); + + data.callback = callback; + data.userdata = userdata; + + if (clip_plane) { + data.clip_plane_len = clip_plane_len; + for (int i = 0; i < data.clip_plane_len; i++) { + copy_v4_v4(data.clip_plane[i], clip_plane[i]); + } + } + else { + data.clip_plane_len = 1; + planes_from_projmat(projmat, NULL, NULL, NULL, NULL, data.clip_plane[0], NULL); + } + + if (nearest) { + memcpy(&data.nearest, nearest, sizeof(*nearest)); + } + else { + data.nearest.index = -1; + data.nearest.dist_sq = FLT_MAX; + } + { + const float bb_min[3] = {root->bv[0], root->bv[2], root->bv[4]}; + const float bb_max[3] = {root->bv[1], root->bv[3], root->bv[5]}; + + int isect_type = isect_aabb_planes_v3(data.clip_plane, data.clip_plane_len, bb_min, bb_max); + + if (isect_type != 0 && + dist_squared_to_projected_aabb(&data.precalc, bb_min, bb_max, data.closest_axis) <= + data.nearest.dist_sq) { + if (isect_type == 1) { + bvhtree_nearest_projected_with_clipplane_test_dfs_recursive(&data, root); + } + else { + bvhtree_nearest_projected_dfs_recursive(&data, root); + } + } + } + + if (nearest) { + memcpy(nearest, &data.nearest, sizeof(*nearest)); + } + + return data.nearest.index; + } + return -1; } /** \} */ - /* -------------------------------------------------------------------- */ /** \name BLI_bvhtree_walk_dfs * \{ */ typedef struct BVHTree_WalkData { - BVHTree_WalkParentCallback walk_parent_cb; - BVHTree_WalkLeafCallback walk_leaf_cb; - BVHTree_WalkOrderCallback walk_order_cb; - void *userdata; + BVHTree_WalkParentCallback walk_parent_cb; + BVHTree_WalkLeafCallback walk_leaf_cb; + BVHTree_WalkOrderCallback walk_order_cb; + void *userdata; } BVHTree_WalkData; /** @@ -2051,35 +2067,37 @@ typedef struct BVHTree_WalkData { * * \return false to break out of the search early. */ -static bool bvhtree_walk_dfs_recursive( - BVHTree_WalkData *walk_data, - const BVHNode *node) +static bool bvhtree_walk_dfs_recursive(BVHTree_WalkData *walk_data, const BVHNode *node) { - if (node->totnode == 0) { - return walk_data->walk_leaf_cb((const BVHTreeAxisRange *)node->bv, node->index, walk_data->userdata); - } - else { - /* First pick the closest node to recurse into */ - if (walk_data->walk_order_cb((const BVHTreeAxisRange *)node->bv, node->main_axis, walk_data->userdata)) { - for (int i = 0; i != node->totnode; i++) { - if (walk_data->walk_parent_cb((const BVHTreeAxisRange *)node->children[i]->bv, walk_data->userdata)) { - if (!bvhtree_walk_dfs_recursive(walk_data, node->children[i])) { - return false; - } - } - } - } - else { - for (int i = node->totnode - 1; i >= 0; i--) { - if (walk_data->walk_parent_cb((const BVHTreeAxisRange *)node->children[i]->bv, walk_data->userdata)) { - if (!bvhtree_walk_dfs_recursive(walk_data, node->children[i])) { - return false; - } - } - } - } - } - return true; + if (node->totnode == 0) { + return walk_data->walk_leaf_cb( + (const BVHTreeAxisRange *)node->bv, node->index, walk_data->userdata); + } + else { + /* First pick the closest node to recurse into */ + if (walk_data->walk_order_cb( + (const BVHTreeAxisRange *)node->bv, node->main_axis, walk_data->userdata)) { + for (int i = 0; i != node->totnode; i++) { + if (walk_data->walk_parent_cb((const BVHTreeAxisRange *)node->children[i]->bv, + walk_data->userdata)) { + if (!bvhtree_walk_dfs_recursive(walk_data, node->children[i])) { + return false; + } + } + } + } + else { + for (int i = node->totnode - 1; i >= 0; i--) { + if (walk_data->walk_parent_cb((const BVHTreeAxisRange *)node->children[i]->bv, + walk_data->userdata)) { + if (!bvhtree_walk_dfs_recursive(walk_data, node->children[i])) { + return false; + } + } + } + } + } + return true; } /** @@ -2094,20 +2112,20 @@ static bool bvhtree_walk_dfs_recursive( * either from the node with the lower or higher k-dop axis value. * \param userdata: Argument passed to all callbacks. */ -void BLI_bvhtree_walk_dfs( - BVHTree *tree, - BVHTree_WalkParentCallback walk_parent_cb, - BVHTree_WalkLeafCallback walk_leaf_cb, - BVHTree_WalkOrderCallback walk_order_cb, void *userdata) +void BLI_bvhtree_walk_dfs(BVHTree *tree, + BVHTree_WalkParentCallback walk_parent_cb, + BVHTree_WalkLeafCallback walk_leaf_cb, + BVHTree_WalkOrderCallback walk_order_cb, + void *userdata) { - const BVHNode *root = tree->nodes[tree->totleaf]; - if (root != NULL) { - BVHTree_WalkData walk_data = {walk_parent_cb, walk_leaf_cb, walk_order_cb, userdata}; - /* first make sure the bv of root passes in the test too */ - if (walk_parent_cb((const BVHTreeAxisRange *)root->bv, userdata)) { - bvhtree_walk_dfs_recursive(&walk_data, root); - } - } + const BVHNode *root = tree->nodes[tree->totleaf]; + if (root != NULL) { + BVHTree_WalkData walk_data = {walk_parent_cb, walk_leaf_cb, walk_order_cb, userdata}; + /* first make sure the bv of root passes in the test too */ + if (walk_parent_cb((const BVHTreeAxisRange *)root->bv, userdata)) { + bvhtree_walk_dfs_recursive(&walk_data, root); + } + } } /** \} */ |