Merge bvh tree from cloth branch

This commit is contained in:
Andre Susano Pinto
2008-05-25 13:44:55 +00:00
parent c4937891ea
commit fd53876faf

View File

@@ -49,6 +49,38 @@
#define node_get_bv(tree, node) ((node)->bv)
#define node_get_child(tree,node,i) ((node)->children[i])
/* Util macros */
#define TO_STR(a) #a
#define JOIN(a,b) a##b
/* Benchmark macros */
#if 1
#define BENCH(a) \
do { \
clock_t _clock_init = clock(); \
(a); \
printf("%s: %fms\n", #a, (float)(clock()-_clock_init)*1000/CLOCKS_PER_SEC); \
} while(0)
#define BENCH_VAR(name) clock_t JOIN(_bench_step,name) = 0, JOIN(_bench_total,name) = 0
#define BENCH_BEGIN(name) JOIN(_bench_step, name) = clock()
#define BENCH_END(name) JOIN(_bench_total,name) += clock() - JOIN(_bench_step,name)
#define BENCH_RESET(name) JOIN(_bench_total, name) = 0
#define BENCH_REPORT(name) printf("%s: %fms\n", TO_STR(name), JOIN(_bench_total,name)*1000.0f/CLOCKS_PER_SEC)
#else
#define BENCH(a) (a)
#define BENCH_VAR(name)
#define BENCH_BEGIN(name)
#define BENCH_END(name)
#define BENCH_RESET(name)
#define BENCH_REPORT(name)
#endif
typedef struct BVHNode
{
struct BVHNode **children;// max 8 children
@@ -63,15 +95,15 @@ typedef struct BVHNode
struct BVHTree
{
BVHNode **nodes;
float *nodebv; // pre-alloc bounding-volumes for nodes
BVHNode **nodechild; // pre-alloc childs for nodes
BVHNode *nodearray; // pre-alloc branchs
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;
char tree_type; // type of tree (4 => quadtree)
char axis; // kdop type (6 => OBB, 7 => AABB, ...)
char start_axis, stop_axis; // KDOP_AXES array indices according to axis
char start_axis, stop_axis; // KDOP_AXES array indices according to axis char start_axis, stop_axis; // KDOP_AXES array indices according to axis
};
typedef struct BVHOverlapData
@@ -103,6 +135,34 @@ static float KDOP_AXES[13][3] =
// http://ralphunden.net/content/tutorials/a-guide-to-introsort/
// and he derived it from the SUN STL
//////////////////////////////////////////////////////////////////////////////////////////////////////
static int size_threshold = 16;
/*
* Common methods for all algorithms
*/
static int floor_lg(int a)
{
return (int)(floor(log(a)/log(2)));
}
/*
* Insertion sort algorithm
*/
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;
}
}
static int bvh_partition(BVHNode **a, int lo, int hi, BVHNode * x, int axis)
{
@@ -119,6 +179,41 @@ static int bvh_partition(BVHNode **a, int lo, int hi, BVHNode * x, int axis)
}
}
/*
* Heapsort algorithm
*/
static void bvh_downheap(BVHNode **a, int i, int n, int lo, int axis)
{
BVHNode * d = a[lo+i-1];
int child;
while (i<=n/2)
{
child = 2*i;
if ((child < n) && ((a[lo+child-1])->bv[axis] < (a[lo+child])->bv[axis]))
{
child++;
}
if (!(d->bv[axis] < (a[lo+child-1])->bv[axis])) break;
a[lo+i-1] = a[lo+child-1];
i = child;
}
a[lo+i-1] = d;
}
static void bvh_heapsort(BVHNode **a, int lo, int hi, int axis)
{
int n = hi-lo, i;
for (i=n/2; i>=1; i=i-1)
{
bvh_downheap(a, i,n,lo, axis);
}
for (i=n; i>1; i=i-1)
{
SWAP(BVHNode*, a[lo],a[lo+i-1]);
bvh_downheap(a, 1,i-1,lo, axis);
}
}
static BVHNode *bvh_medianof3(BVHNode **a, int lo, int mid, int hi, int axis) // returns Sortable
{
if ((a[mid])->bv[axis] < (a[lo])->bv[axis])
@@ -146,23 +241,57 @@ static BVHNode *bvh_medianof3(BVHNode **a, int lo, int mid, int hi, int axis) //
return a[mid];
}
}
/*
* Quicksort algorithm modified for Introsort
*/
static void bvh_introsort_loop (BVHNode **a, int lo, int hi, int depth_limit, int axis)
{
int p;
while (hi-lo > size_threshold)
{
if (depth_limit == 0)
{
bvh_heapsort(a, lo, hi, axis);
return;
}
depth_limit=depth_limit-1;
p=bvh_partition(a, lo, hi, bvh_medianof3(a, lo, lo+((hi-lo)/2)+1, hi-1, axis), axis);
bvh_introsort_loop(a, p, hi, depth_limit, axis);
hi=p;
}
}
static void sort(BVHNode **a0, int begin, int end, int axis)
{
if (begin < end)
{
BVHNode **a=a0;
bvh_introsort_loop(a, begin, end, 2*floor_lg(end-begin), axis);
bvh_insertionsort(a, begin, end, axis);
}
}
void sort_along_axis(BVHTree *tree, int start, int end, int axis)
{
sort(tree->nodes, start, end, axis);
}
//after a call to this function you can expect one of:
// every node to left of a[n] are smaller than it
// every node to the right of a[n-1] are greater than it
void partition_nth_element(BVHNode **a, int _begin, int _end, int n, int axis)
{
int begin = _begin, end = _end;
while(begin < n && end >= n)
{
int mid = bvh_partition(a, begin, end, bvh_medianof3(a, begin, (begin+end-1)/2, end-1, axis), axis );
if(mid >= n)
end = n-1;
else
begin = n+1;
}
// every node to left of a[n] are smaller or equal to it
// every node to the right of a[n] are greater or equal to it
int partition_nth_element(BVHNode **a, int _begin, int _end, int n, int axis){
int begin = _begin, end = _end, cut;
while(end-begin > 3)
{
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);
return n;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -278,6 +407,7 @@ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis)
return tree;
}
static void create_kdop_hull(BVHTree *tree, BVHNode *node, float *co, int numpoints, int moving)
{
float newminmax;
@@ -417,7 +547,6 @@ static void bvh_div_nodes(BVHTree *tree, BVHNode *node, int start, int end, char
{
tend = start + slice;
if(tend > end) tend = end;
if(tend-start == 1) // ok, we have 1 left for this node
@@ -432,7 +561,9 @@ static void bvh_div_nodes(BVHTree *tree, BVHNode *node, int start, int end, char
tnode = node->children[i] = tree->nodes[tree->totleaf + tree->totbranch] = &(tree->nodearray[tree->totbranch + tree->totleaf]);
tree->totbranch++;
tnode->parent = node;
if(tend != end)
partition_nth_element(tree->nodes, start, end, tend, laxis);
refit_kdop_hull(tree, tnode, start, tend);
bvh_div_nodes(tree, tnode, start, tend, laxis);
}
@@ -592,7 +723,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result)
{
int j, total = 0;
BVHTreeOverlap *overlap = NULL, *to = NULL;
BVHOverlapData *data[tree1->tree_type];
BVHOverlapData **data;
// check for compatibility of both trees (can't compare 14-DOP with 18-DOP)
if((tree1->axis != tree2->axis) && ((tree1->axis == 14) || tree2->axis == 14))
@@ -601,6 +732,8 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result)
// fast check root nodes for collision before doing big splitting + traversal
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)))
return 0;
*data = MEM_callocN(sizeof(BVHOverlapData *)* tree1->tree_type, "BVHOverlapData_star");
for(j = 0; j < tree1->tree_type; j++)
{
@@ -636,6 +769,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result)
free(data[j]->overlap);
MEM_freeN(data[j]);
}
MEM_freeN(*data);
(*result) = total;
return overlap;