Blender  V2.59
BLI_kdopbvh.c
Go to the documentation of this file.
00001 /*
00002  *
00003  * ***** BEGIN GPL LICENSE BLOCK *****
00004  *
00005  * This program is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * as published by the Free Software Foundation; either version 2
00008  * of the License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software Foundation,
00017  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00018  *
00019  * The Original Code is Copyright (C) 2006 by NaN Holding BV.
00020  * All rights reserved.
00021  *
00022  * The Original Code is: all of this file.
00023  *
00024  * Contributor(s): Daniel Genrich, Andre Pinto
00025  *
00026  * ***** END GPL LICENSE BLOCK *****
00027  */
00028 
00034 #include <assert.h>
00035 
00036 #include "MEM_guardedalloc.h"
00037 
00038 #include "BLI_utildefines.h"
00039 
00040 
00041 
00042 #include "BLI_kdopbvh.h"
00043 #include "BLI_math.h"
00044 
00045 #ifdef _OPENMP
00046 #include <omp.h>
00047 #endif
00048 
00049 
00050 
00051 #define MAX_TREETYPE 32
00052 #define DEFAULT_FIND_NEAREST_HEAP_SIZE 1024
00053 
00054 typedef struct BVHNode
00055 {
00056         struct BVHNode **children;
00057         struct BVHNode *parent; // some user defined traversed need that
00058         struct BVHNode *skip[2];
00059         float *bv;              // Bounding volume of all nodes, max 13 axis
00060         int index;              // face, edge, vertex index
00061         char totnode;   // how many nodes are used, used for speedup
00062         char main_axis; // Axis used to split this node
00063 } BVHNode;
00064 
00065 struct BVHTree
00066 {
00067         BVHNode **nodes;
00068         BVHNode *nodearray; /* pre-alloc branch nodes */
00069         BVHNode **nodechild;    // pre-alloc childs for nodes
00070         float   *nodebv;                // pre-alloc bounding-volumes for nodes
00071         float   epsilon; /* epslion is used for inflation of the k-dop     */
00072         int     totleaf; // leafs
00073         int     totbranch;
00074         char    tree_type; // type of tree (4 => quadtree)
00075         char    axis; // kdop type (6 => OBB, 7 => AABB, ...)
00076         char    start_axis, stop_axis; // KDOP_AXES array indices according to axis
00077 };
00078 
00079 typedef struct BVHOverlapData 
00080 {  
00081         BVHTree *tree1, *tree2; 
00082         BVHTreeOverlap *overlap; 
00083         int i, max_overlap; /* i is number of overlaps */
00084         int start_axis, stop_axis;
00085 } BVHOverlapData;
00086 
00087 typedef struct BVHNearestData
00088 {
00089         BVHTree *tree;
00090         const float     *co;
00091         BVHTree_NearestPointCallback callback;
00092         void    *userdata;
00093         float proj[13];                 //coordinates projection over axis
00094         BVHTreeNearest nearest;
00095 
00096 } BVHNearestData;
00097 
00098 typedef struct BVHRayCastData
00099 {
00100         BVHTree *tree;
00101 
00102         BVHTree_RayCastCallback callback;
00103         void    *userdata;
00104 
00105 
00106         BVHTreeRay    ray;
00107         float ray_dot_axis[13];
00108         float idot_axis[13];
00109         int index[6];
00110 
00111         BVHTreeRayHit hit;
00112 } BVHRayCastData;
00114 
00115 
00117 // Bounding Volume Hierarchy Definition
00118 // 
00119 // Notes: From OBB until 26-DOP --> all bounding volumes possible, just choose type below
00120 // Notes: You have to choose the type at compile time ITM
00121 // Notes: You can choose the tree type --> binary, quad, octree, choose below
00123 
00124 static float KDOP_AXES[13][3] =
00125 { {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},
00126 {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},
00127 {0, 1.0, -1.0}
00128 };
00129 
00130 /*
00131  * Generic push and pop heap
00132  */
00133 #define PUSH_HEAP_BODY(HEAP_TYPE,PRIORITY,heap,heap_size)       \
00134 {                                                                                                       \
00135         HEAP_TYPE element = heap[heap_size-1];                  \
00136         int child = heap_size-1;                                                \
00137         while(child != 0)                                                               \
00138         {                                                                                               \
00139                 int parent = (child-1) / 2;                                     \
00140                 if(PRIORITY(element, heap[parent]))                     \
00141                 {                                                                                       \
00142                         heap[child] = heap[parent];                             \
00143                         child = parent;                                                 \
00144                 }                                                                                       \
00145                 else break;                                                                     \
00146         }                                                                                               \
00147         heap[child] = element;                                                  \
00148 }
00149 
00150 #define POP_HEAP_BODY(HEAP_TYPE, PRIORITY,heap,heap_size)       \
00151 {                                                                                                       \
00152         HEAP_TYPE element = heap[heap_size-1];                  \
00153         int parent = 0;                                                                 \
00154         while(parent < (heap_size-1)/2 )                                \
00155         {                                                                                               \
00156                 int child2 = (parent+1)*2;                                      \
00157                 if(PRIORITY(heap[child2-1], heap[child2]))      \
00158                         --child2;                                                               \
00159                                                                                                         \
00160                 if(PRIORITY(element, heap[child2]))                     \
00161                         break;                                                                  \
00162                                                                                                         \
00163                 heap[parent] = heap[child2];                            \
00164                 parent = child2;                                                        \
00165         }                                                                                               \
00166         heap[parent] = element;                                                 \
00167 }
00168 
00169 #if 0
00170 static int ADJUST_MEMORY(void *local_memblock, void **memblock, int new_size, int *max_size, int size_per_item)
00171 {
00172         int   new_max_size = *max_size * 2;
00173         void *new_memblock = NULL;
00174 
00175         if(new_size <= *max_size)
00176                 return TRUE;
00177 
00178         if(*memblock == local_memblock)
00179         {
00180                 new_memblock = malloc( size_per_item * new_max_size );
00181                 memcpy( new_memblock, *memblock, size_per_item * *max_size );
00182         }
00183         else
00184                 new_memblock = realloc(*memblock, size_per_item * new_max_size );
00185 
00186         if(new_memblock)
00187         {
00188                 *memblock = new_memblock;
00189                 *max_size = new_max_size;
00190                 return TRUE;
00191         }
00192         else
00193                 return FALSE;
00194 }
00195 #endif
00196 
00198 // Introsort 
00199 // with permission deriven from the following Java code:
00200 // http://ralphunden.net/content/tutorials/a-guide-to-introsort/
00201 // and he derived it from the SUN STL 
00203 //static int size_threshold = 16;
00204 /*
00205 * Common methods for all algorithms
00206 */
00207 /*static int floor_lg(int a)
00208 {
00209         return (int)(floor(log(a)/log(2)));
00210 }*/
00211 
00212 /*
00213 * Insertion sort algorithm
00214 */
00215 static void bvh_insertionsort(BVHNode **a, int lo, int hi, int axis)
00216 {
00217         int i,j;
00218         BVHNode *t;
00219         for (i=lo; i < hi; i++)
00220         {
00221                 j=i;
00222                 t = a[i];
00223                 while((j!=lo) && (t->bv[axis] < (a[j-1])->bv[axis]))
00224                 {
00225                         a[j] = a[j-1];
00226                         j--;
00227                 }
00228                 a[j] = t;
00229         }
00230 }
00231 
00232 static int bvh_partition(BVHNode **a, int lo, int hi, BVHNode * x, int axis)
00233 {
00234         int i=lo, j=hi;
00235         while (1)
00236         {
00237                 while ((a[i])->bv[axis] < x->bv[axis]) i++;
00238                 j--;
00239                 while (x->bv[axis] < (a[j])->bv[axis]) j--;
00240                 if(!(i < j))
00241                         return i;
00242                 SWAP( BVHNode* , a[i], a[j]);
00243                 i++;
00244         }
00245 }
00246 
00247 /*
00248 * Heapsort algorithm
00249 */
00250 #if 0
00251 static void bvh_downheap(BVHNode **a, int i, int n, int lo, int axis)
00252 {
00253         BVHNode * d = a[lo+i-1];
00254         int child;
00255         while (i<=n/2)
00256         {
00257                 child = 2*i;
00258                 if ((child < n) && ((a[lo+child-1])->bv[axis] < (a[lo+child])->bv[axis]))
00259                 {
00260                         child++;
00261                 }
00262                 if (!(d->bv[axis] < (a[lo+child-1])->bv[axis])) break;
00263                 a[lo+i-1] = a[lo+child-1];
00264                 i = child;
00265         }
00266         a[lo+i-1] = d;
00267 }
00268 
00269 static void bvh_heapsort(BVHNode **a, int lo, int hi, int axis)
00270 {
00271         int n = hi-lo, i;
00272         for (i=n/2; i>=1; i=i-1)
00273         {
00274                 bvh_downheap(a, i,n,lo, axis);
00275         }
00276         for (i=n; i>1; i=i-1)
00277         {
00278                 SWAP(BVHNode*, a[lo],a[lo+i-1]);
00279                 bvh_downheap(a, 1,i-1,lo, axis);
00280         }
00281 }
00282 #endif
00283 
00284 static BVHNode *bvh_medianof3(BVHNode **a, int lo, int mid, int hi, int axis) // returns Sortable
00285 {
00286         if ((a[mid])->bv[axis] < (a[lo])->bv[axis])
00287         {
00288                 if ((a[hi])->bv[axis] < (a[mid])->bv[axis])
00289                         return a[mid];
00290                 else
00291                 {
00292                         if ((a[hi])->bv[axis] < (a[lo])->bv[axis])
00293                                 return a[hi];
00294                         else
00295                                 return a[lo];
00296                 }
00297         }
00298         else
00299         {
00300                 if ((a[hi])->bv[axis] < (a[mid])->bv[axis])
00301                 {
00302                         if ((a[hi])->bv[axis] < (a[lo])->bv[axis])
00303                                 return a[lo];
00304                         else
00305                                 return a[hi];
00306                 }
00307                 else
00308                         return a[mid];
00309         }
00310 }
00311 
00312 #if 0
00313 /*
00314 * Quicksort algorithm modified for Introsort
00315 */
00316 static void bvh_introsort_loop (BVHNode **a, int lo, int hi, int depth_limit, int axis)
00317 {
00318         int p;
00319 
00320         while (hi-lo > size_threshold)
00321         {
00322                 if (depth_limit == 0)
00323                 {
00324                         bvh_heapsort(a, lo, hi, axis);
00325                         return;
00326                 }
00327                 depth_limit=depth_limit-1;
00328                 p=bvh_partition(a, lo, hi, bvh_medianof3(a, lo, lo+((hi-lo)/2)+1, hi-1, axis), axis);
00329                 bvh_introsort_loop(a, p, hi, depth_limit, axis);
00330                 hi=p;
00331         }
00332 }
00333 
00334 static void sort(BVHNode **a0, int begin, int end, int axis)
00335 {
00336         if (begin < end)
00337         {
00338                 BVHNode **a=a0;
00339                 bvh_introsort_loop(a, begin, end, 2*floor_lg(end-begin), axis);
00340                 bvh_insertionsort(a, begin, end, axis);
00341         }
00342 }
00343 
00344 static void sort_along_axis(BVHTree *tree, int start, int end, int axis)
00345 {
00346         sort(tree->nodes, start, end, axis);
00347 }
00348 #endif
00349 
00350 //after a call to this function you can expect one of:
00351 //      every node to left of a[n] are smaller or equal to it
00352 //      every node to the right of a[n] are greater or equal to it
00353 static int partition_nth_element(BVHNode **a, int _begin, int _end, int n, int axis){
00354         int begin = _begin, end = _end, cut;
00355         while(end-begin > 3)
00356         {
00357                 cut = bvh_partition(a, begin, end, bvh_medianof3(a, begin, (begin+end)/2, end-1, axis), axis );
00358                 if(cut <= n)
00359                         begin = cut;
00360                 else
00361                         end = cut;
00362         }
00363         bvh_insertionsort(a, begin, end, axis);
00364 
00365         return n;
00366 }
00367 
00369 static void build_skip_links(BVHTree *tree, BVHNode *node, BVHNode *left, BVHNode *right)
00370 {
00371         int i;
00372         
00373         node->skip[0] = left;
00374         node->skip[1] = right;
00375         
00376         for (i = 0; i < node->totnode; i++)
00377         {
00378                 if(i+1 < node->totnode)
00379                         build_skip_links(tree, node->children[i], left, node->children[i+1] );
00380                 else
00381                         build_skip_links(tree, node->children[i], left, right );
00382 
00383                 left = node->children[i];
00384         }
00385 }
00386 
00387 /*
00388  * BVHTree bounding volumes functions
00389  */
00390 static void create_kdop_hull(BVHTree *tree, BVHNode *node, float *co, int numpoints, int moving)
00391 {
00392         float newminmax;
00393         float *bv = node->bv;
00394         int i, k;
00395         
00396         // don't init boudings for the moving case
00397         if(!moving)
00398         {
00399                 for (i = tree->start_axis; i < tree->stop_axis; i++)
00400                 {
00401                         bv[2*i] = FLT_MAX;
00402                         bv[2*i + 1] = -FLT_MAX;
00403                 }
00404         }
00405         
00406         for(k = 0; k < numpoints; k++)
00407         {
00408                 // for all Axes.
00409                 for (i = tree->start_axis; i < tree->stop_axis; i++)
00410                 {
00411                         newminmax = INPR(&co[k * 3], KDOP_AXES[i]);
00412                         if (newminmax < bv[2 * i])
00413                                 bv[2 * i] = newminmax;
00414                         if (newminmax > bv[(2 * i) + 1])
00415                                 bv[(2 * i) + 1] = newminmax;
00416                 }
00417         }
00418 }
00419 
00420 // depends on the fact that the BVH's for each face is already build
00421 static void refit_kdop_hull(BVHTree *tree, BVHNode *node, int start, int end)
00422 {
00423         float newmin,newmax;
00424         int i, j;
00425         float *bv = node->bv;
00426 
00427         
00428         for (i = tree->start_axis; i < tree->stop_axis; i++)
00429         {
00430                 bv[2*i] = FLT_MAX;
00431                 bv[2*i + 1] = -FLT_MAX;
00432         }
00433 
00434         for (j = start; j < end; j++)
00435         {
00436 // for all Axes.
00437                 for (i = tree->start_axis; i < tree->stop_axis; i++)
00438                 {
00439                         newmin = tree->nodes[j]->bv[(2 * i)];   
00440                         if ((newmin < bv[(2 * i)]))
00441                                 bv[(2 * i)] = newmin;
00442  
00443                         newmax = tree->nodes[j]->bv[(2 * i) + 1];
00444                         if ((newmax > bv[(2 * i) + 1]))
00445                                 bv[(2 * i) + 1] = newmax;
00446                 }
00447         }
00448 
00449 }
00450 
00451 // only supports x,y,z axis in the moment
00452 // but we should use a plain and simple function here for speed sake
00453 static char get_largest_axis(float *bv)
00454 {
00455         float middle_point[3];
00456 
00457         middle_point[0] = (bv[1]) - (bv[0]); // x axis
00458         middle_point[1] = (bv[3]) - (bv[2]); // y axis
00459         middle_point[2] = (bv[5]) - (bv[4]); // z axis
00460         if (middle_point[0] > middle_point[1]) 
00461         {
00462                 if (middle_point[0] > middle_point[2])
00463                         return 1; // max x axis
00464                 else
00465                         return 5; // max z axis
00466         }
00467         else 
00468         {
00469                 if (middle_point[1] > middle_point[2])
00470                         return 3; // max y axis
00471                 else
00472                         return 5; // max z axis
00473         }
00474 }
00475 
00476 // bottom-up update of bvh node BV
00477 // join the children on the parent BV
00478 static void node_join(BVHTree *tree, BVHNode *node)
00479 {
00480         int i, j;
00481         
00482         for (i = tree->start_axis; i < tree->stop_axis; i++)
00483         {
00484                 node->bv[2*i] = FLT_MAX;
00485                 node->bv[2*i + 1] = -FLT_MAX;
00486         }
00487         
00488         for (i = 0; i < tree->tree_type; i++)
00489         {
00490                 if (node->children[i]) 
00491                 {
00492                         for (j = tree->start_axis; j < tree->stop_axis; j++)
00493                         {
00494                                 // update minimum 
00495                                 if (node->children[i]->bv[(2 * j)] < node->bv[(2 * j)]) 
00496                                         node->bv[(2 * j)] = node->children[i]->bv[(2 * j)];
00497                                 
00498                                 // update maximum 
00499                                 if (node->children[i]->bv[(2 * j) + 1] > node->bv[(2 * j) + 1])
00500                                         node->bv[(2 * j) + 1] = node->children[i]->bv[(2 * j) + 1];
00501                         }
00502                 }
00503                 else
00504                         break;
00505         }
00506 }
00507 
00508 /*
00509  * Debug and information functions
00510  */
00511 #if 0
00512 static void bvhtree_print_tree(BVHTree *tree, BVHNode *node, int depth)
00513 {
00514         int i;
00515         for(i=0; i<depth; i++) printf(" ");
00516         printf(" - %d (%ld): ", node->index, node - tree->nodearray);
00517         for(i=2*tree->start_axis; i<2*tree->stop_axis; i++)
00518                 printf("%.3f ", node->bv[i]);
00519         printf("\n");
00520 
00521         for(i=0; i<tree->tree_type; i++)
00522                 if(node->children[i])
00523                         bvhtree_print_tree(tree, node->children[i], depth+1);
00524 }
00525 
00526 static void bvhtree_info(BVHTree *tree)
00527 {
00528         printf("BVHTree info\n");
00529         printf("tree_type = %d, axis = %d, epsilon = %f\n", tree->tree_type, tree->axis, tree->epsilon);
00530         printf("nodes = %d, branches = %d, leafs = %d\n", tree->totbranch + tree->totleaf,  tree->totbranch, tree->totleaf);
00531         printf("Memory per node = %ldbytes\n", sizeof(BVHNode) + sizeof(BVHNode*)*tree->tree_type + sizeof(float)*tree->axis);
00532         printf("BV memory = %dbytes\n", MEM_allocN_len(tree->nodebv));
00533 
00534         printf("Total memory = %ldbytes\n", sizeof(BVHTree)
00535                 + MEM_allocN_len(tree->nodes)
00536                 + MEM_allocN_len(tree->nodearray)
00537                 + MEM_allocN_len(tree->nodechild)
00538                 + MEM_allocN_len(tree->nodebv)
00539                 );
00540 
00541 //      bvhtree_print_tree(tree, tree->nodes[tree->totleaf], 0);
00542 }
00543 #endif
00544 
00545 #if 0
00546 
00547 
00548 static void verify_tree(BVHTree *tree)
00549 {
00550         int i, j, check = 0;
00551         
00552         // check the pointer list
00553         for(i = 0; i < tree->totleaf; i++)
00554         {
00555                 if(tree->nodes[i]->parent == NULL)
00556                         printf("Leaf has no parent: %d\n", i);
00557                 else
00558                 {
00559                         for(j = 0; j < tree->tree_type; j++)
00560                         {
00561                                 if(tree->nodes[i]->parent->children[j] == tree->nodes[i])
00562                                         check = 1;
00563                         }
00564                         if(!check)
00565                         {
00566                                 printf("Parent child relationship doesn't match: %d\n", i);
00567                         }
00568                         check = 0;
00569                 }
00570         }
00571         
00572         // check the leaf list
00573         for(i = 0; i < tree->totleaf; i++)
00574         {
00575                 if(tree->nodearray[i].parent == NULL)
00576                         printf("Leaf has no parent: %d\n", i);
00577                 else
00578                 {
00579                         for(j = 0; j < tree->tree_type; j++)
00580                         {
00581                                 if(tree->nodearray[i].parent->children[j] == &tree->nodearray[i])
00582                                         check = 1;
00583                         }
00584                         if(!check)
00585                         {
00586                                 printf("Parent child relationship doesn't match: %d\n", i);
00587                         }
00588                         check = 0;
00589                 }
00590         }
00591         
00592         printf("branches: %d, leafs: %d, total: %d\n", tree->totbranch, tree->totleaf, tree->totbranch + tree->totleaf);
00593 }
00594 #endif
00595 
00596 //Helper data and structures to build a min-leaf generalized implicit tree
00597 //This code can be easily reduced (basicly this is only method to calculate pow(k, n) in O(1).. and stuff like that)
00598 typedef struct BVHBuildHelper
00599 {
00600         int tree_type;                          //
00601         int totleafs;                           //
00602 
00603         int leafs_per_child  [32];      //Min number of leafs that are archievable from a node at depth N
00604         int branches_on_level[32];      //Number of nodes at depth N (tree_type^N)
00605 
00606         int remain_leafs;                       //Number of leafs that are placed on the level that is not 100% filled
00607 
00608 } BVHBuildHelper;
00609 
00610 static void build_implicit_tree_helper(BVHTree *tree, BVHBuildHelper *data)
00611 {
00612         int depth = 0;
00613         int remain;
00614         int nnodes;
00615 
00616         data->totleafs = tree->totleaf;
00617         data->tree_type= tree->tree_type;
00618 
00619         //Calculate the smallest tree_type^n such that tree_type^n >= num_leafs
00620         for(
00621                 data->leafs_per_child[0] = 1;
00622                 data->leafs_per_child[0] <  data->totleafs;
00623                 data->leafs_per_child[0] *= data->tree_type
00624         );
00625 
00626         data->branches_on_level[0] = 1;
00627 
00628         //We could stop the loop first (but I am lazy to find out when)
00629         for(depth = 1; depth < 32; depth++)
00630         {
00631                 data->branches_on_level[depth] = data->branches_on_level[depth-1] * data->tree_type;
00632                 data->leafs_per_child  [depth] = data->leafs_per_child  [depth-1] / data->tree_type;
00633         }
00634 
00635         remain = data->totleafs - data->leafs_per_child[1];
00636         nnodes = (remain + data->tree_type - 2) / (data->tree_type - 1);
00637         data->remain_leafs = remain + nnodes;
00638 }
00639 
00640 // return the min index of all the leafs archivable with the given branch
00641 static int implicit_leafs_index(BVHBuildHelper *data, int depth, int child_index)
00642 {
00643         int min_leaf_index = child_index * data->leafs_per_child[depth-1];
00644         if(min_leaf_index <= data->remain_leafs)
00645                 return min_leaf_index;
00646         else if(data->leafs_per_child[depth])
00647                 return data->totleafs - (data->branches_on_level[depth-1] - child_index) * data->leafs_per_child[depth];
00648         else
00649                 return data->remain_leafs;
00650 }
00651 
00680 // This functions returns the number of branches needed to have the requested number of leafs.
00681 static int implicit_needed_branches(int tree_type, int leafs)
00682 {
00683         return MAX2(1, (leafs + tree_type - 3) / (tree_type-1) );
00684 }
00685 
00686 /*
00687  * This function handles the problem of "sorting" the leafs (along the split_axis).
00688  *
00689  * It arranges the elements in the given partitions such that:
00690  *  - any element in partition N is less or equal to any element in partition N+1.
00691  *  - if all elements are diferent all partition will get the same subset of elements
00692  *    as if the array was sorted.
00693  *
00694  * partition P is described as the elements in the range ( nth[P] , nth[P+1] ]
00695  *
00696  * TODO: This can be optimized a bit by doing a specialized nth_element instead of K nth_elements
00697  */
00698 static void split_leafs(BVHNode **leafs_array, int *nth, int partitions, int split_axis)
00699 {
00700         int i;
00701         for(i=0; i < partitions-1; i++)
00702         {
00703                 if(nth[i] >= nth[partitions])
00704                         break;
00705 
00706                 partition_nth_element(leafs_array, nth[i], nth[partitions], nth[i+1], split_axis);
00707         }
00708 }
00709 
00710 /*
00711  * This functions builds an optimal implicit tree from the given leafs.
00712  * Where optimal stands for:
00713  *  - The resulting tree will have the smallest number of branches;
00714  *  - At most only one branch will have NULL childs;
00715  *  - All leafs will be stored at level N or N+1.
00716  *
00717  * This function creates an implicit tree on branches_array, the leafs are given on the leafs_array.
00718  *
00719  * The tree is built per depth levels. First branchs at depth 1.. then branches at depth 2.. etc..
00720  * The reason is that we can build level N+1 from level N witouth any data dependencies.. thus it allows
00721  * to use multithread building.
00722  *
00723  * To archieve this is necessary to find how much leafs are accessible from a certain branch, BVHBuildHelper
00724  * implicit_needed_branches and implicit_leafs_index are auxiliar functions to solve that "optimal-split".
00725  */
00726 static void non_recursive_bvh_div_nodes(BVHTree *tree, BVHNode *branches_array, BVHNode **leafs_array, int num_leafs)
00727 {
00728         int i;
00729 
00730         const int tree_type   = tree->tree_type;
00731         const int tree_offset = 2 - tree->tree_type; //this value is 0 (on binary trees) and negative on the others
00732         const int num_branches= implicit_needed_branches(tree_type, num_leafs);
00733 
00734         BVHBuildHelper data;
00735         int depth;
00736         
00737         // set parent from root node to NULL
00738         BVHNode *tmp = branches_array+0;
00739         tmp->parent = NULL;
00740 
00741         //Most of bvhtree code relies on 1-leaf trees having at least one branch
00742         //We handle that special case here
00743         if(num_leafs == 1)
00744         {
00745                 BVHNode *root = branches_array+0;
00746                 refit_kdop_hull(tree, root, 0, num_leafs);
00747                 root->main_axis = get_largest_axis(root->bv) / 2;
00748                 root->totnode = 1;
00749                 root->children[0] = leafs_array[0];
00750                 root->children[0]->parent = root;
00751                 return;
00752         }
00753 
00754         branches_array--;       //Implicit trees use 1-based indexs
00755         
00756         build_implicit_tree_helper(tree, &data);
00757 
00758         //Loop tree levels (log N) loops
00759         for(i=1, depth = 1; i <= num_branches; i = i*tree_type + tree_offset, depth++)
00760         {
00761                 const int first_of_next_level = i*tree_type + tree_offset;
00762                 const int  end_j = MIN2(first_of_next_level, num_branches + 1); //index of last branch on this level
00763                 int j;
00764 
00765                 //Loop all branches on this level
00766 #pragma omp parallel for private(j) schedule(static)
00767                 for(j = i; j < end_j; j++)
00768                 {
00769                         int k;
00770                         const int parent_level_index= j-i;
00771                         BVHNode* parent = branches_array + j;
00772                         int nth_positions[ MAX_TREETYPE + 1];
00773                         char split_axis;
00774 
00775                         int parent_leafs_begin = implicit_leafs_index(&data, depth, parent_level_index);
00776                         int parent_leafs_end   = implicit_leafs_index(&data, depth, parent_level_index+1);
00777 
00778                         //This calculates the bounding box of this branch
00779                         //and chooses the largest axis as the axis to divide leafs
00780                         refit_kdop_hull(tree, parent, parent_leafs_begin, parent_leafs_end);
00781                         split_axis = get_largest_axis(parent->bv);
00782 
00783                         //Save split axis (this can be used on raytracing to speedup the query time)
00784                         parent->main_axis = split_axis / 2;
00785 
00786                         //Split the childs along the split_axis, note: its not needed to sort the whole leafs array
00787                         //Only to assure that the elements are partioned on a way that each child takes the elements
00788                         //it would take in case the whole array was sorted.
00789                         //Split_leafs takes care of that "sort" problem.
00790                         nth_positions[        0] = parent_leafs_begin;
00791                         nth_positions[tree_type] = parent_leafs_end;
00792                         for(k = 1; k < tree_type; k++)
00793                         {
00794                                 int child_index = j * tree_type + tree_offset + k;
00795                                 int child_level_index = child_index - first_of_next_level; //child level index
00796                                 nth_positions[k] = implicit_leafs_index(&data, depth+1, child_level_index);
00797                         }
00798 
00799                         split_leafs(leafs_array, nth_positions, tree_type, split_axis);
00800 
00801 
00802                         //Setup children and totnode counters
00803                         //Not really needed but currently most of BVH code relies on having an explicit children structure
00804                         for(k = 0; k < tree_type; k++)
00805                         {
00806                                 int child_index = j * tree_type + tree_offset + k;
00807                                 int child_level_index = child_index - first_of_next_level; //child level index
00808 
00809                                 int child_leafs_begin = implicit_leafs_index(&data, depth+1, child_level_index);
00810                                 int child_leafs_end   = implicit_leafs_index(&data, depth+1, child_level_index+1);
00811 
00812                                 if(child_leafs_end - child_leafs_begin > 1)
00813                                 {
00814                                         parent->children[k] = branches_array + child_index;
00815                                         parent->children[k]->parent = parent;
00816                                 }
00817                                 else if(child_leafs_end - child_leafs_begin == 1)
00818                                 {
00819                                         parent->children[k] = leafs_array[ child_leafs_begin ];
00820                                         parent->children[k]->parent = parent;
00821                                 }
00822                                 else
00823                                         break;
00824 
00825                                 parent->totnode = k+1;
00826                         }
00827                 }
00828         }
00829 }
00830 
00831 
00832 /*
00833  * BLI_bvhtree api
00834  */
00835 BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis)
00836 {
00837         BVHTree *tree;
00838         int numnodes, i;
00839         
00840         // theres not support for trees below binary-trees :P
00841         if(tree_type < 2)
00842                 return NULL;
00843         
00844         if(tree_type > MAX_TREETYPE)
00845                 return NULL;
00846 
00847         tree = (BVHTree *)MEM_callocN(sizeof(BVHTree), "BVHTree");
00848 
00849         //tree epsilon must be >= FLT_EPSILON
00850         //so that tangent rays can still hit a bounding volume..
00851         //this bug would show up when casting a ray aligned with a kdop-axis and with an edge of 2 faces
00852         epsilon = MAX2(FLT_EPSILON, epsilon);
00853         
00854         if(tree)
00855         {
00856                 tree->epsilon = epsilon;
00857                 tree->tree_type = tree_type; 
00858                 tree->axis = axis;
00859                 
00860                 if(axis == 26)
00861                 {
00862                         tree->start_axis = 0;
00863                         tree->stop_axis = 13;
00864                 }
00865                 else if(axis == 18)
00866                 {
00867                         tree->start_axis = 7;
00868                         tree->stop_axis = 13;
00869                 }
00870                 else if(axis == 14)
00871                 {
00872                         tree->start_axis = 0;
00873                         tree->stop_axis = 7;
00874                 }
00875                 else if(axis == 8) // AABB
00876                 {
00877                         tree->start_axis = 0;
00878                         tree->stop_axis = 4;
00879                 }
00880                 else if(axis == 6) // OBB
00881                 {
00882                         tree->start_axis = 0;
00883                         tree->stop_axis = 3;
00884                 }
00885                 else
00886                 {
00887                         MEM_freeN(tree);
00888                         return NULL;
00889                 }
00890 
00891 
00892                 //Allocate arrays
00893                 numnodes = maxsize + implicit_needed_branches(tree_type, maxsize) + tree_type;
00894 
00895                 tree->nodes = (BVHNode **)MEM_callocN(sizeof(BVHNode *)*numnodes, "BVHNodes");
00896                 
00897                 if(!tree->nodes)
00898                 {
00899                         MEM_freeN(tree);
00900                         return NULL;
00901                 }
00902                 
00903                 tree->nodebv = (float*)MEM_callocN(sizeof(float)* axis * numnodes, "BVHNodeBV");
00904                 if(!tree->nodebv)
00905                 {
00906                         MEM_freeN(tree->nodes);
00907                         MEM_freeN(tree);
00908                 }
00909 
00910                 tree->nodechild = (BVHNode**)MEM_callocN(sizeof(BVHNode*) * tree_type * numnodes, "BVHNodeBV");
00911                 if(!tree->nodechild)
00912                 {
00913                         MEM_freeN(tree->nodebv);
00914                         MEM_freeN(tree->nodes);
00915                         MEM_freeN(tree);
00916                 }
00917 
00918                 tree->nodearray = (BVHNode *)MEM_callocN(sizeof(BVHNode)* numnodes, "BVHNodeArray");
00919                 
00920                 if(!tree->nodearray)
00921                 {
00922                         MEM_freeN(tree->nodechild);
00923                         MEM_freeN(tree->nodebv);
00924                         MEM_freeN(tree->nodes);
00925                         MEM_freeN(tree);
00926                         return NULL;
00927                 }
00928 
00929                 //link the dynamic bv and child links
00930                 for(i=0; i< numnodes; i++)
00931                 {
00932                         tree->nodearray[i].bv = tree->nodebv + i * axis;
00933                         tree->nodearray[i].children = tree->nodechild + i * tree_type;
00934                 }
00935                 
00936         }
00937 
00938         return tree;
00939 }
00940 
00941 void BLI_bvhtree_free(BVHTree *tree)
00942 {       
00943         if(tree)
00944         {
00945                 MEM_freeN(tree->nodes);
00946                 MEM_freeN(tree->nodearray);
00947                 MEM_freeN(tree->nodebv);
00948                 MEM_freeN(tree->nodechild);
00949                 MEM_freeN(tree);
00950         }
00951 }
00952 
00953 void BLI_bvhtree_balance(BVHTree *tree)
00954 {
00955         int i;
00956 
00957         BVHNode*  branches_array = tree->nodearray + tree->totleaf;
00958         BVHNode** leafs_array    = tree->nodes;
00959 
00960         //This function should only be called once (some big bug goes here if its being called more than once per tree)
00961         assert(tree->totbranch == 0);
00962 
00963         //Build the implicit tree
00964         non_recursive_bvh_div_nodes(tree, branches_array, leafs_array, tree->totleaf);
00965 
00966         //current code expects the branches to be linked to the nodes array
00967         //we perform that linkage here
00968         tree->totbranch = implicit_needed_branches(tree->tree_type, tree->totleaf);
00969         for(i = 0; i < tree->totbranch; i++)
00970                 tree->nodes[tree->totleaf + i] = branches_array + i;
00971 
00972         build_skip_links(tree, tree->nodes[tree->totleaf], NULL, NULL);
00973         //bvhtree_info(tree);
00974 }
00975 
00976 int BLI_bvhtree_insert(BVHTree *tree, int index, float *co, int numpoints)
00977 {
00978         int i;
00979         BVHNode *node = NULL;
00980         
00981         // insert should only possible as long as tree->totbranch is 0
00982         if(tree->totbranch > 0)
00983                 return 0;
00984         
00985         if(tree->totleaf+1 >= MEM_allocN_len(tree->nodes)/sizeof(*(tree->nodes)))
00986                 return 0;
00987         
00988         // TODO check if have enough nodes in array
00989         
00990         node = tree->nodes[tree->totleaf] = &(tree->nodearray[tree->totleaf]);
00991         tree->totleaf++;
00992         
00993         create_kdop_hull(tree, node, co, numpoints, 0);
00994         node->index= index;
00995         
00996         // inflate the bv with some epsilon
00997         for (i = tree->start_axis; i < tree->stop_axis; i++)
00998         {
00999                 node->bv[(2 * i)] -= tree->epsilon; // minimum 
01000                 node->bv[(2 * i) + 1] += tree->epsilon; // maximum 
01001         }
01002 
01003         return 1;
01004 }
01005 
01006 
01007 // call before BLI_bvhtree_update_tree()
01008 int BLI_bvhtree_update_node(BVHTree *tree, int index, float *co, float *co_moving, int numpoints)
01009 {
01010         int i;
01011         BVHNode *node= NULL;
01012         
01013         // check if index exists
01014         if(index > tree->totleaf)
01015                 return 0;
01016         
01017         node = tree->nodearray + index;
01018         
01019         create_kdop_hull(tree, node, co, numpoints, 0);
01020         
01021         if(co_moving)
01022                 create_kdop_hull(tree, node, co_moving, numpoints, 1);
01023         
01024         // inflate the bv with some epsilon
01025         for (i = tree->start_axis; i < tree->stop_axis; i++)
01026         {
01027                 node->bv[(2 * i)] -= tree->epsilon; // minimum 
01028                 node->bv[(2 * i) + 1] += tree->epsilon; // maximum 
01029         }
01030 
01031         return 1;
01032 }
01033 
01034 // call BLI_bvhtree_update_node() first for every node/point/triangle
01035 void BLI_bvhtree_update_tree(BVHTree *tree)
01036 {
01037         //Update bottom=>top
01038         //TRICKY: the way we build the tree all the childs have an index greater than the parent
01039         //This allows us todo a bottom up update by starting on the biger numbered branch
01040 
01041         BVHNode** root  = tree->nodes + tree->totleaf;
01042         BVHNode** index = tree->nodes + tree->totleaf + tree->totbranch-1;
01043 
01044         for (; index >= root; index--)
01045                 node_join(tree, *index);
01046 }
01047 
01048 float BLI_bvhtree_getepsilon(BVHTree *tree)
01049 {
01050         return tree->epsilon;
01051 }
01052 
01053 
01054 /*
01055  * BLI_bvhtree_overlap
01056  */
01057 // overlap - is it possbile for 2 bv's to collide ?
01058 static int tree_overlap(BVHNode *node1, BVHNode *node2, int start_axis, int stop_axis)
01059 {
01060         float *bv1 = node1->bv;
01061         float *bv2 = node2->bv;
01062 
01063         float *bv1_end = bv1 + (stop_axis<<1);
01064                 
01065         bv1 += start_axis<<1;
01066         bv2 += start_axis<<1;
01067         
01068         // test all axis if min + max overlap
01069         for (; bv1 != bv1_end; bv1+=2, bv2+=2)
01070         {
01071                 if ((*(bv1) > *(bv2 + 1)) || (*(bv2) > *(bv1 + 1))) 
01072                         return 0;
01073         }
01074         
01075         return 1;
01076 }
01077 
01078 static void traverse(BVHOverlapData *data, BVHNode *node1, BVHNode *node2)
01079 {
01080         int j;
01081         
01082         if(tree_overlap(node1, node2, data->start_axis, data->stop_axis))
01083         {
01084                 // check if node1 is a leaf
01085                 if(!node1->totnode)
01086                 {
01087                         // check if node2 is a leaf
01088                         if(!node2->totnode)
01089                         {
01090                                 
01091                                 if(node1 == node2)
01092                                 {
01093                                         return;
01094                                 }
01095                                         
01096                                 if(data->i >= data->max_overlap)
01097                                 {       
01098                                         // try to make alloc'ed memory bigger
01099                                         data->overlap = realloc(data->overlap, sizeof(BVHTreeOverlap)*data->max_overlap*2);
01100                                         
01101                                         if(!data->overlap)
01102                                         {
01103                                                 printf("Out of Memory in traverse\n");
01104                                                 return;
01105                                         }
01106                                         data->max_overlap *= 2;
01107                                 }
01108                                 
01109                                 // both leafs, insert overlap!
01110                                 data->overlap[data->i].indexA = node1->index;
01111                                 data->overlap[data->i].indexB = node2->index;
01112 
01113                                 data->i++;
01114                         }
01115                         else
01116                         {
01117                                 for(j = 0; j < data->tree2->tree_type; j++)
01118                                 {
01119                                         if(node2->children[j])
01120                                                 traverse(data, node1, node2->children[j]);
01121                                 }
01122                         }
01123                 }
01124                 else
01125                 {
01126                         
01127                         for(j = 0; j < data->tree2->tree_type; j++)
01128                         {
01129                                 if(node1->children[j])
01130                                         traverse(data, node1->children[j], node2);
01131                         }
01132                 }
01133         }
01134         return;
01135 }
01136 
01137 BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, unsigned int *result)
01138 {
01139         int j;
01140         unsigned int total = 0;
01141         BVHTreeOverlap *overlap = NULL, *to = NULL;
01142         BVHOverlapData **data;
01143         
01144         // check for compatibility of both trees (can't compare 14-DOP with 18-DOP)
01145         if((tree1->axis != tree2->axis) && (tree1->axis == 14 || tree2->axis == 14) && (tree1->axis == 18 || tree2->axis == 18))
01146                 return NULL;
01147         
01148         // fast check root nodes for collision before doing big splitting + traversal
01149         if(!tree_overlap(tree1->nodes[tree1->totleaf], tree2->nodes[tree2->totleaf], MIN2(tree1->start_axis, tree2->start_axis), MIN2(tree1->stop_axis, tree2->stop_axis)))
01150                 return NULL;
01151 
01152         data = MEM_callocN(sizeof(BVHOverlapData *)* tree1->tree_type, "BVHOverlapData_star");
01153         
01154         for(j = 0; j < tree1->tree_type; j++)
01155         {
01156                 data[j] = (BVHOverlapData *)MEM_callocN(sizeof(BVHOverlapData), "BVHOverlapData");
01157                 
01158                 // init BVHOverlapData
01159                 data[j]->overlap = (BVHTreeOverlap *)malloc(sizeof(BVHTreeOverlap)*MAX2(tree1->totleaf, tree2->totleaf));
01160                 data[j]->tree1 = tree1;
01161                 data[j]->tree2 = tree2;
01162                 data[j]->max_overlap = MAX2(tree1->totleaf, tree2->totleaf);
01163                 data[j]->i = 0;
01164                 data[j]->start_axis = MIN2(tree1->start_axis, tree2->start_axis);
01165                 data[j]->stop_axis  = MIN2(tree1->stop_axis,  tree2->stop_axis );
01166         }
01167 
01168 #pragma omp parallel for private(j) schedule(static)
01169         for(j = 0; j < MIN2(tree1->tree_type, tree1->nodes[tree1->totleaf]->totnode); j++)
01170         {
01171                 traverse(data[j], tree1->nodes[tree1->totleaf]->children[j], tree2->nodes[tree2->totleaf]);
01172         }
01173         
01174         for(j = 0; j < tree1->tree_type; j++)
01175                 total += data[j]->i;
01176         
01177         to = overlap = (BVHTreeOverlap *)MEM_callocN(sizeof(BVHTreeOverlap)*total, "BVHTreeOverlap");
01178         
01179         for(j = 0; j < tree1->tree_type; j++)
01180         {
01181                 memcpy(to, data[j]->overlap, data[j]->i*sizeof(BVHTreeOverlap));
01182                 to+=data[j]->i;
01183         }
01184         
01185         for(j = 0; j < tree1->tree_type; j++)
01186         {
01187                 free(data[j]->overlap);
01188                 MEM_freeN(data[j]);
01189         }
01190         MEM_freeN(data);
01191         
01192         (*result) = total;
01193         return overlap;
01194 }
01195 
01196 
01197 /*
01198  * Nearest neighbour - BLI_bvhtree_find_nearest
01199  */
01200 static float squared_dist(const float *a, const float *b)
01201 {
01202         float tmp[3];
01203         VECSUB(tmp, a, b);
01204         return INPR(tmp, tmp);
01205 }
01206 
01207 //Determines the nearest point of the given node BV. Returns the squared distance to that point.
01208 static float calc_nearest_point(const float *proj, BVHNode *node, float *nearest)
01209 {
01210         int i;
01211         const float *bv = node->bv;
01212 
01213         //nearest on AABB hull
01214         for(i=0; i != 3; i++, bv += 2)
01215         {
01216                 if(bv[0] > proj[i])
01217                         nearest[i] = bv[0];
01218                 else if(bv[1] < proj[i])
01219                         nearest[i] = bv[1];
01220                 else
01221                         nearest[i] = proj[i]; 
01222         }
01223 
01224 /*
01225         //nearest on a general hull
01226         VECCOPY(nearest, data->co);
01227         for(i = data->tree->start_axis; i != data->tree->stop_axis; i++, bv+=2)
01228         {
01229                 float proj = INPR( nearest, KDOP_AXES[i]);
01230                 float dl = bv[0] - proj;
01231                 float du = bv[1] - proj;
01232 
01233                 if(dl > 0)
01234                 {
01235                         VECADDFAC(nearest, nearest, KDOP_AXES[i], dl);
01236                 }
01237                 else if(du < 0)
01238                 {
01239                         VECADDFAC(nearest, nearest, KDOP_AXES[i], du);
01240                 }
01241         }
01242 */
01243         return squared_dist(proj, nearest);
01244 }
01245 
01246 
01247 typedef struct NodeDistance
01248 {
01249         BVHNode *node;
01250         float dist;
01251 
01252 } NodeDistance;
01253 
01254 #define NodeDistance_priority(a,b)      ( (a).dist < (b).dist )
01255 
01256 // TODO: use a priority queue to reduce the number of nodes looked on
01257 static void dfs_find_nearest_dfs(BVHNearestData *data, BVHNode *node)
01258 {
01259         if(node->totnode == 0)
01260         {
01261                 if(data->callback)
01262                         data->callback(data->userdata , node->index, data->co, &data->nearest);
01263                 else
01264                 {
01265                         data->nearest.index     = node->index;
01266                         data->nearest.dist      = calc_nearest_point(data->proj, node, data->nearest.co);
01267                 }
01268         }
01269         else
01270         {
01271                 //Better heuristic to pick the closest node to dive on
01272                 int i;
01273                 float nearest[3];
01274 
01275                 if(data->proj[ node->main_axis ] <= node->children[0]->bv[node->main_axis*2+1])
01276                 {
01277 
01278                         for(i=0; i != node->totnode; i++)
01279                         {
01280                                 if( calc_nearest_point(data->proj, node->children[i], nearest) >= data->nearest.dist) continue;
01281                                 dfs_find_nearest_dfs(data, node->children[i]);
01282                         }
01283                 }
01284                 else
01285                 {
01286                         for(i=node->totnode-1; i >= 0 ; i--)
01287                         {
01288                                 if( calc_nearest_point(data->proj, node->children[i], nearest) >= data->nearest.dist) continue;
01289                                 dfs_find_nearest_dfs(data, node->children[i]);
01290                         }
01291                 }
01292         }
01293 }
01294 
01295 static void dfs_find_nearest_begin(BVHNearestData *data, BVHNode *node)
01296 {
01297         float nearest[3], sdist;
01298         sdist = calc_nearest_point(data->proj, node, nearest);
01299         if(sdist >= data->nearest.dist) return;
01300         dfs_find_nearest_dfs(data, node);
01301 }
01302 
01303 
01304 #if 0
01305 static void NodeDistance_push_heap(NodeDistance *heap, int heap_size)
01306 PUSH_HEAP_BODY(NodeDistance, NodeDistance_priority, heap, heap_size)
01307 
01308 static void NodeDistance_pop_heap(NodeDistance *heap, int heap_size)
01309 POP_HEAP_BODY(NodeDistance, NodeDistance_priority, heap, heap_size)
01310 
01311 //NN function that uses an heap.. this functions leads to an optimal number of min-distance
01312 //but for normal tri-faces and BV 6-dop.. a simple dfs with local heuristics (as implemented
01313 //in source/blender/blenkernel/intern/shrinkwrap.c) works faster.
01314 //
01315 //It may make sense to use this function if the callback queries are very slow.. or if its impossible
01316 //to get a nice heuristic
01317 //
01318 //this function uses "malloc/free" instead of the MEM_* because it intends to be openmp safe
01319 static void bfs_find_nearest(BVHNearestData *data, BVHNode *node)
01320 {
01321         int i;
01322         NodeDistance default_heap[DEFAULT_FIND_NEAREST_HEAP_SIZE];
01323         NodeDistance *heap=default_heap, current;
01324         int heap_size = 0, max_heap_size = sizeof(default_heap)/sizeof(default_heap[0]);
01325         float nearest[3];
01326 
01327         int callbacks = 0, push_heaps = 0;
01328 
01329         if(node->totnode == 0)
01330         {
01331                 dfs_find_nearest_dfs(data, node);
01332                 return;
01333         }
01334 
01335         current.node = node;
01336         current.dist = calc_nearest_point(data->proj, node, nearest);
01337 
01338         while(current.dist < data->nearest.dist)
01339         {
01340 //              printf("%f : %f\n", current.dist, data->nearest.dist);
01341                 for(i=0; i< current.node->totnode; i++)
01342                 {
01343                         BVHNode *child = current.node->children[i];
01344                         if(child->totnode == 0)
01345                         {
01346                                 callbacks++;
01347                                 dfs_find_nearest_dfs(data, child);
01348                         }
01349                         else
01350                         {
01351                                 //adjust heap size
01352                                 if(heap_size >= max_heap_size
01353                                 && ADJUST_MEMORY(default_heap, (void**)&heap, heap_size+1, &max_heap_size, sizeof(heap[0])) == FALSE)
01354                                 {
01355                                         printf("WARNING: bvh_find_nearest got out of memory\n");
01356 
01357                                         if(heap != default_heap)
01358                                                 free(heap);
01359 
01360                                         return;
01361                                 }
01362 
01363                                 heap[heap_size].node = current.node->children[i];
01364                                 heap[heap_size].dist = calc_nearest_point(data->proj, current.node->children[i], nearest);
01365 
01366                                 if(heap[heap_size].dist >= data->nearest.dist) continue;
01367                                 heap_size++;
01368 
01369                                 NodeDistance_push_heap(heap, heap_size);
01370         //                      PUSH_HEAP_BODY(NodeDistance, NodeDistance_priority, heap, heap_size);
01371                                 push_heaps++;
01372                         }
01373                 }
01374                 
01375                 if(heap_size == 0) break;
01376 
01377                 current = heap[0];
01378                 NodeDistance_pop_heap(heap, heap_size);
01379 //              POP_HEAP_BODY(NodeDistance, NodeDistance_priority, heap, heap_size);
01380                 heap_size--;
01381         }
01382 
01383 //      printf("hsize=%d, callbacks=%d, pushs=%d\n", heap_size, callbacks, push_heaps);
01384 
01385         if(heap != default_heap)
01386                 free(heap);
01387 }
01388 #endif
01389 
01390 
01391 int BLI_bvhtree_find_nearest(BVHTree *tree, const float *co, BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata)
01392 {
01393         int i;
01394 
01395         BVHNearestData data;
01396         BVHNode* root = tree->nodes[tree->totleaf];
01397 
01398         //init data to search
01399         data.tree = tree;
01400         data.co = co;
01401 
01402         data.callback = callback;
01403         data.userdata = userdata;
01404 
01405         for(i = data.tree->start_axis; i != data.tree->stop_axis; i++)
01406         {
01407                 data.proj[i] = INPR(data.co, KDOP_AXES[i]);
01408         }
01409 
01410         if(nearest)
01411         {
01412                 memcpy( &data.nearest , nearest, sizeof(*nearest) );
01413         }
01414         else
01415         {
01416                 data.nearest.index = -1;
01417                 data.nearest.dist = FLT_MAX;
01418         }
01419 
01420         //dfs search
01421         if(root)
01422                 dfs_find_nearest_begin(&data, root);
01423 
01424         //copy back results
01425         if(nearest)
01426         {
01427                 memcpy(nearest, &data.nearest, sizeof(*nearest));
01428         }
01429 
01430         return data.nearest.index;
01431 }
01432 
01433 
01434 /*
01435  * Raycast - BLI_bvhtree_ray_cast
01436  *
01437  * raycast is done by performing a DFS on the BVHTree and saving the closest hit
01438  */
01439 
01440 
01441 //Determines the distance that the ray must travel to hit the bounding volume of the given node
01442 static float ray_nearest_hit(BVHRayCastData *data, float *bv)
01443 {
01444         int i;
01445 
01446         float low = 0, upper = data->hit.dist;
01447 
01448         for(i=0; i != 3; i++, bv += 2)
01449         {
01450                 if(data->ray_dot_axis[i] == 0.0f)
01451                 {
01452                         //axis aligned ray
01453                         if(data->ray.origin[i] < bv[0] - data->ray.radius
01454                         || data->ray.origin[i] > bv[1] + data->ray.radius)
01455                                 return FLT_MAX;
01456                 }
01457                 else
01458                 {
01459                         float ll = (bv[0] - data->ray.radius - data->ray.origin[i]) / data->ray_dot_axis[i];
01460                         float lu = (bv[1] + data->ray.radius - data->ray.origin[i]) / data->ray_dot_axis[i];
01461 
01462                         if(data->ray_dot_axis[i] > 0.0f)
01463                         {
01464                                 if(ll > low)   low = ll;
01465                                 if(lu < upper) upper = lu;
01466                         }
01467                         else
01468                         {
01469                                 if(lu > low)   low = lu;
01470                                 if(ll < upper) upper = ll;
01471                         }
01472         
01473                         if(low > upper) return FLT_MAX;
01474                 }
01475         }
01476         return low;
01477 }
01478 
01479 //Determines the distance that the ray must travel to hit the bounding volume of the given node
01480 //Based on Tactical Optimization of Ray/Box Intersection, by Graham Fyffe
01481 //[http://tog.acm.org/resources/RTNews/html/rtnv21n1.html#art9]
01482 //
01483 //TODO this doens't has data->ray.radius in consideration
01484 static float fast_ray_nearest_hit(const BVHRayCastData *data, const BVHNode *node)
01485 {
01486         const float *bv = node->bv;
01487         float dist;
01488         
01489         float t1x = (bv[data->index[0]] - data->ray.origin[0]) * data->idot_axis[0];
01490         float t2x = (bv[data->index[1]] - data->ray.origin[0]) * data->idot_axis[0];
01491         float t1y = (bv[data->index[2]] - data->ray.origin[1]) * data->idot_axis[1];
01492         float t2y = (bv[data->index[3]] - data->ray.origin[1]) * data->idot_axis[1];
01493         float t1z = (bv[data->index[4]] - data->ray.origin[2]) * data->idot_axis[2];
01494         float t2z = (bv[data->index[5]] - data->ray.origin[2]) * data->idot_axis[2];
01495 
01496         if(t1x > t2y || t2x < t1y || t1x > t2z || t2x < t1z || t1y > t2z || t2y < t1z) return FLT_MAX;
01497         if(t2x < 0.0 || t2y < 0.0 || t2z < 0.0) return FLT_MAX;
01498         if(t1x > data->hit.dist || t1y > data->hit.dist || t1z > data->hit.dist) return FLT_MAX;
01499 
01500         dist = t1x;
01501         if (t1y > dist) dist = t1y;
01502         if (t1z > dist) dist = t1z;
01503         return dist;
01504 }
01505 
01506 static void dfs_raycast(BVHRayCastData *data, BVHNode *node)
01507 {
01508         int i;
01509 
01510         //ray-bv is really fast.. and simple tests revealed its worth to test it
01511         //before calling the ray-primitive functions
01512         /* XXX: temporary solution for particles untill fast_ray_nearest_hit supports ray.radius */
01513         float dist = (data->ray.radius > 0.0f) ? ray_nearest_hit(data, node->bv) : fast_ray_nearest_hit(data, node);
01514         if(dist >= data->hit.dist) return;
01515 
01516         if(node->totnode == 0)
01517         {
01518                 if(data->callback)
01519                         data->callback(data->userdata, node->index, &data->ray, &data->hit);
01520                 else
01521                 {
01522                         data->hit.index = node->index;
01523                         data->hit.dist  = dist;
01524                         VECADDFAC(data->hit.co, data->ray.origin, data->ray.direction, dist);
01525                 }
01526         }
01527         else
01528         {
01529                 //pick loop direction to dive into the tree (based on ray direction and split axis)
01530                 if(data->ray_dot_axis[ (int)node->main_axis ] > 0.0f)
01531                 {
01532                         for(i=0; i != node->totnode; i++)
01533                         {
01534                                 dfs_raycast(data, node->children[i]);
01535                         }
01536                 }
01537                 else
01538                 {
01539                         for(i=node->totnode-1; i >= 0; i--)
01540                         {
01541                                 dfs_raycast(data, node->children[i]);
01542                         }
01543                 }
01544         }
01545 }
01546 
01547 #if 0
01548 static void iterative_raycast(BVHRayCastData *data, BVHNode *node)
01549 {
01550         while(node)
01551         {
01552                 float dist = fast_ray_nearest_hit(data, node);
01553                 if(dist >= data->hit.dist)
01554                 {
01555                         node = node->skip[1];
01556                         continue;
01557                 }
01558 
01559                 if(node->totnode == 0)
01560                 {
01561                         if(data->callback)
01562                                 data->callback(data->userdata, node->index, &data->ray, &data->hit);
01563                         else
01564                         {
01565                                 data->hit.index = node->index;
01566                                 data->hit.dist  = dist;
01567                                 VECADDFAC(data->hit.co, data->ray.origin, data->ray.direction, dist);
01568                         }
01569                         
01570                         node = node->skip[1];
01571                 }
01572                 else
01573                 {
01574                         node = node->children[0];
01575                 }       
01576         }
01577 }
01578 #endif
01579 
01580 int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata)
01581 {
01582         int i;
01583         BVHRayCastData data;
01584         BVHNode * root = tree->nodes[tree->totleaf];
01585 
01586         data.tree = tree;
01587 
01588         data.callback = callback;
01589         data.userdata = userdata;
01590 
01591         VECCOPY(data.ray.origin,    co);
01592         VECCOPY(data.ray.direction, dir);
01593         data.ray.radius = radius;
01594 
01595         normalize_v3(data.ray.direction);
01596 
01597         for(i=0; i<3; i++)
01598         {
01599                 data.ray_dot_axis[i] = INPR( data.ray.direction, KDOP_AXES[i]);
01600                 data.idot_axis[i] = 1.0f / data.ray_dot_axis[i];
01601 
01602                 if(fabs(data.ray_dot_axis[i]) < FLT_EPSILON)
01603                 {
01604                         data.ray_dot_axis[i] = 0.0;
01605                 }
01606                 data.index[2*i] = data.idot_axis[i] < 0.0 ? 1 : 0;
01607                 data.index[2*i+1] = 1 - data.index[2*i];
01608                 data.index[2*i]   += 2*i;
01609                 data.index[2*i+1] += 2*i;
01610         }
01611 
01612 
01613         if(hit)
01614                 memcpy( &data.hit, hit, sizeof(*hit) );
01615         else
01616         {
01617                 data.hit.index = -1;
01618                 data.hit.dist = FLT_MAX;
01619         }
01620 
01621         if(root)
01622         {
01623                 dfs_raycast(&data, root);
01624 //              iterative_raycast(&data, root);
01625          }
01626 
01627 
01628         if(hit)
01629                 memcpy( hit, &data.hit, sizeof(*hit) );
01630 
01631         return data.hit.index;
01632 }
01633 
01634 float BLI_bvhtree_bb_raycast(float *bv, float *light_start, float *light_end, float *pos)
01635 {
01636         BVHRayCastData data;
01637         float dist = 0.0;
01638 
01639         data.hit.dist = FLT_MAX;
01640         
01641         // get light direction
01642         data.ray.direction[0] = light_end[0] - light_start[0];
01643         data.ray.direction[1] = light_end[1] - light_start[1];
01644         data.ray.direction[2] = light_end[2] - light_start[2];
01645         
01646         data.ray.radius = 0.0;
01647         
01648         data.ray.origin[0] = light_start[0];
01649         data.ray.origin[1] = light_start[1];
01650         data.ray.origin[2] = light_start[2];
01651         
01652         normalize_v3(data.ray.direction);
01653         VECCOPY(data.ray_dot_axis, data.ray.direction);
01654         
01655         dist = ray_nearest_hit(&data, bv);
01656         
01657         if(dist > 0.0)
01658         {
01659                 VECADDFAC(pos, light_start, data.ray.direction, dist);
01660         }
01661         return dist;
01662         
01663 }
01664 
01665 /*
01666  * Range Query - as request by broken :P
01667  *
01668  * Allocs and fills an array with the indexs of node that are on the given spherical range (center, radius) 
01669  * Returns the size of the array.
01670  */
01671 typedef struct RangeQueryData
01672 {
01673         BVHTree *tree;
01674         const float *center;
01675         float radius;                   //squared radius
01676 
01677         int hits;
01678 
01679         BVHTree_RangeQuery callback;
01680         void *userdata;
01681 
01682 
01683 } RangeQueryData;
01684 
01685 
01686 static void dfs_range_query(RangeQueryData *data, BVHNode *node)
01687 {
01688         if(node->totnode == 0)
01689         {
01690 #if 0   /*UNUSED*/
01691                 //Calculate the node min-coords (if the node was a point then this is the point coordinates)
01692                 float co[3];
01693                 co[0] = node->bv[0];
01694                 co[1] = node->bv[2];
01695                 co[2] = node->bv[4];
01696 #endif
01697         }
01698         else
01699         {
01700                 int i;
01701                 for(i=0; i != node->totnode; i++)
01702                 {
01703                         float nearest[3];
01704                         float dist = calc_nearest_point(data->center, node->children[i], nearest);
01705                         if(dist < data->radius)
01706                         {
01707                                 //Its a leaf.. call the callback
01708                                 if(node->children[i]->totnode == 0)
01709                                 {
01710                                         data->hits++;
01711                                         data->callback( data->userdata, node->children[i]->index, dist );
01712                                 }
01713                                 else
01714                                         dfs_range_query( data, node->children[i] );
01715                         }
01716                 }
01717         }
01718 }
01719 
01720 int BLI_bvhtree_range_query(BVHTree *tree, const float *co, float radius, BVHTree_RangeQuery callback, void *userdata)
01721 {
01722         BVHNode * root = tree->nodes[tree->totleaf];
01723 
01724         RangeQueryData data;
01725         data.tree = tree;
01726         data.center = co;
01727         data.radius = radius*radius;
01728         data.hits = 0;
01729 
01730         data.callback = callback;
01731         data.userdata = userdata;
01732 
01733         if(root != NULL)
01734         {
01735                 float nearest[3];
01736                 float dist = calc_nearest_point(data.center, root, nearest);
01737                 if(dist < data.radius)
01738                 {
01739                         //Its a leaf.. call the callback
01740                         if(root->totnode == 0)
01741                         {
01742                                 data.hits++;
01743                                 data.callback( data.userdata, root->index, dist );
01744                         }
01745                         else
01746                                 dfs_range_query( &data, root );
01747                 }
01748         }
01749 
01750         return data.hits;
01751 }