2009-07-02 15:45:15 +00:00
|
|
|
#include <assert.h>
|
|
|
|
|
#include <math.h>
|
2009-07-06 19:45:00 +00:00
|
|
|
#include <stdlib.h>
|
2009-08-02 12:11:14 +00:00
|
|
|
#include <algorithm>
|
2009-07-02 15:45:15 +00:00
|
|
|
|
2009-06-30 22:07:42 +00:00
|
|
|
#include "rayobject_rtbuild.h"
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
#include "BLI_arithb.h"
|
|
|
|
|
#include "BKE_utildefines.h"
|
|
|
|
|
|
|
|
|
|
static int partition_nth_element(RTBuilder *b, int _begin, int _end, int n);
|
|
|
|
|
static void split_leafs(RTBuilder *b, int *nth, int partitions, int split_axis);
|
2009-07-06 19:45:00 +00:00
|
|
|
static int split_leafs_by_plane(RTBuilder *b, int begin, int end, float plane);
|
2009-06-30 22:07:42 +00:00
|
|
|
|
2009-07-01 11:27:43 +00:00
|
|
|
static void rtbuild_init(RTBuilder *b, RayObject **begin, RayObject **end)
|
2009-06-30 22:07:42 +00:00
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
b->begin = begin;
|
|
|
|
|
b->end = end;
|
|
|
|
|
b->split_axis = 0;
|
2009-07-07 19:07:53 +00:00
|
|
|
b->child_sorted_axis = -1;
|
2009-06-30 22:07:42 +00:00
|
|
|
|
2009-07-02 15:45:15 +00:00
|
|
|
for(i=0; i<RTBUILD_MAX_CHILDS; i++)
|
2009-07-01 11:27:43 +00:00
|
|
|
b->child_offset[i] = 0;
|
2009-07-10 16:42:51 +00:00
|
|
|
|
|
|
|
|
INIT_MINMAX(b->bb, b->bb+3);
|
2009-06-30 22:07:42 +00:00
|
|
|
}
|
|
|
|
|
|
2009-07-01 11:27:43 +00:00
|
|
|
RTBuilder* rtbuild_create(int size)
|
2009-06-30 22:07:42 +00:00
|
|
|
{
|
|
|
|
|
RTBuilder *builder = (RTBuilder*) MEM_mallocN( sizeof(RTBuilder), "RTBuilder" );
|
2009-07-01 11:27:43 +00:00
|
|
|
RayObject **memblock= (RayObject**)MEM_mallocN( sizeof(RayObject*)*size,"RTBuilder.objects");
|
|
|
|
|
rtbuild_init(builder, memblock, memblock);
|
2009-06-30 22:07:42 +00:00
|
|
|
return builder;
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-01 11:27:43 +00:00
|
|
|
void rtbuild_free(RTBuilder *b)
|
2009-06-30 22:07:42 +00:00
|
|
|
{
|
|
|
|
|
MEM_freeN(b->begin);
|
|
|
|
|
MEM_freeN(b);
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-01 11:27:43 +00:00
|
|
|
void rtbuild_add(RTBuilder *b, RayObject *o)
|
2009-06-30 22:07:42 +00:00
|
|
|
{
|
|
|
|
|
*(b->end++) = o;
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-10 16:42:51 +00:00
|
|
|
void rtbuild_calc_bb(RTBuilder *b)
|
2009-06-30 22:07:42 +00:00
|
|
|
{
|
2009-07-10 16:42:51 +00:00
|
|
|
if(b->bb[0] == 1.0e30f)
|
|
|
|
|
{
|
|
|
|
|
RayObject **index = b->begin;
|
|
|
|
|
for(; index != b->end; index++)
|
|
|
|
|
RE_rayobject_merge_bb(*index, b->bb, b->bb+3);
|
|
|
|
|
}
|
2009-06-30 22:07:42 +00:00
|
|
|
}
|
|
|
|
|
|
2009-07-10 16:42:51 +00:00
|
|
|
void rtbuild_merge_bb(RTBuilder *b, float *min, float *max)
|
2009-06-30 22:07:42 +00:00
|
|
|
{
|
2009-07-10 16:42:51 +00:00
|
|
|
rtbuild_calc_bb(b);
|
|
|
|
|
DO_MIN(b->bb, min);
|
|
|
|
|
DO_MAX(b->bb+3, max);
|
2009-06-30 22:07:42 +00:00
|
|
|
}
|
|
|
|
|
|
2009-07-10 16:42:51 +00:00
|
|
|
int rtbuild_get_largest_axis(RTBuilder *b)
|
2009-06-30 22:07:42 +00:00
|
|
|
{
|
2009-07-10 16:42:51 +00:00
|
|
|
rtbuild_calc_bb(b);
|
|
|
|
|
return bb_largest_axis(b->bb, b->bb+3);
|
2009-06-30 22:07:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2009-07-10 16:42:51 +00:00
|
|
|
int rtbuild_size(RTBuilder *b)
|
2009-07-06 19:45:00 +00:00
|
|
|
{
|
2009-07-10 16:42:51 +00:00
|
|
|
return b->end - b->begin;
|
2009-07-06 19:45:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2009-07-10 16:42:51 +00:00
|
|
|
RTBuilder* rtbuild_get_child(RTBuilder *b, int child, RTBuilder *tmp)
|
2009-07-06 19:45:00 +00:00
|
|
|
{
|
2009-07-10 16:42:51 +00:00
|
|
|
rtbuild_init( tmp, b->begin + b->child_offset[child], b->begin + b->child_offset[child+1] );
|
|
|
|
|
tmp->child_sorted_axis = b->child_sorted_axis;
|
|
|
|
|
return tmp;
|
2009-07-06 19:45:00 +00:00
|
|
|
}
|
2009-07-10 16:42:51 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-07-02 15:45:15 +00:00
|
|
|
//Left balanced tree
|
2009-07-01 11:27:43 +00:00
|
|
|
int rtbuild_mean_split(RTBuilder *b, int nchilds, int axis)
|
2009-06-30 22:07:42 +00:00
|
|
|
{
|
2009-07-02 15:45:15 +00:00
|
|
|
int i;
|
2009-07-02 21:57:50 +00:00
|
|
|
int mleafs_per_child, Mleafs_per_child;
|
2009-07-02 15:45:15 +00:00
|
|
|
int tot_leafs = rtbuild_size(b);
|
2009-07-02 21:57:50 +00:00
|
|
|
int missing_leafs;
|
2009-07-02 15:45:15 +00:00
|
|
|
|
|
|
|
|
long long s;
|
2009-07-01 11:27:43 +00:00
|
|
|
|
2009-07-02 15:45:15 +00:00
|
|
|
assert(nchilds <= RTBUILD_MAX_CHILDS);
|
|
|
|
|
|
|
|
|
|
//TODO optimize calc of leafs_per_child
|
|
|
|
|
for(s=nchilds; s<tot_leafs; s*=nchilds);
|
2009-07-02 21:57:50 +00:00
|
|
|
Mleafs_per_child = s/nchilds;
|
|
|
|
|
mleafs_per_child = Mleafs_per_child/nchilds;
|
2009-07-02 15:45:15 +00:00
|
|
|
|
2009-07-02 21:57:50 +00:00
|
|
|
//split min leafs per child
|
2009-07-02 15:45:15 +00:00
|
|
|
b->child_offset[0] = 0;
|
2009-07-02 21:57:50 +00:00
|
|
|
for(i=1; i<=nchilds; i++)
|
|
|
|
|
b->child_offset[i] = mleafs_per_child;
|
|
|
|
|
|
|
|
|
|
//split remaining leafs
|
|
|
|
|
missing_leafs = tot_leafs - mleafs_per_child*nchilds;
|
|
|
|
|
for(i=1; i<=nchilds; i++)
|
2009-07-02 15:45:15 +00:00
|
|
|
{
|
2009-07-02 21:57:50 +00:00
|
|
|
if(missing_leafs > Mleafs_per_child - mleafs_per_child)
|
2009-07-02 15:45:15 +00:00
|
|
|
{
|
2009-07-02 21:57:50 +00:00
|
|
|
b->child_offset[i] += Mleafs_per_child - mleafs_per_child;
|
|
|
|
|
missing_leafs -= Mleafs_per_child - mleafs_per_child;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
b->child_offset[i] += missing_leafs;
|
|
|
|
|
missing_leafs = 0;
|
|
|
|
|
break;
|
2009-07-02 15:45:15 +00:00
|
|
|
}
|
|
|
|
|
}
|
2009-07-02 21:57:50 +00:00
|
|
|
|
|
|
|
|
//adjust for accumulative offsets
|
|
|
|
|
for(i=1; i<=nchilds; i++)
|
|
|
|
|
b->child_offset[i] += b->child_offset[i-1];
|
|
|
|
|
|
|
|
|
|
//Count created childs
|
|
|
|
|
for(i=nchilds; b->child_offset[i] == b->child_offset[i-1]; i--);
|
|
|
|
|
split_leafs(b, b->child_offset, i, axis);
|
|
|
|
|
|
|
|
|
|
assert( b->child_offset[0] == 0 && b->child_offset[i] == tot_leafs );
|
|
|
|
|
return i;
|
2009-06-30 22:07:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2009-07-01 11:27:43 +00:00
|
|
|
int rtbuild_mean_split_largest_axis(RTBuilder *b, int nchilds)
|
2009-06-30 22:07:42 +00:00
|
|
|
{
|
2009-07-02 15:45:15 +00:00
|
|
|
int axis = rtbuild_get_largest_axis(b);
|
2009-07-01 11:27:43 +00:00
|
|
|
return rtbuild_mean_split(b, nchilds, axis);
|
2009-06-30 22:07:42 +00:00
|
|
|
}
|
|
|
|
|
|
2009-07-06 19:45:00 +00:00
|
|
|
/*
|
|
|
|
|
* "separators" is an array of dim NCHILDS-1
|
|
|
|
|
* and indicates where to cut the childs
|
|
|
|
|
*/
|
|
|
|
|
int rtbuild_median_split(RTBuilder *b, float *separators, int nchilds, int axis)
|
|
|
|
|
{
|
|
|
|
|
int size = rtbuild_size(b);
|
|
|
|
|
|
|
|
|
|
assert(nchilds <= RTBUILD_MAX_CHILDS);
|
|
|
|
|
if(size <= nchilds)
|
|
|
|
|
{
|
|
|
|
|
return rtbuild_mean_split(b, nchilds, axis);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
b->split_axis = axis;
|
|
|
|
|
|
|
|
|
|
//Calculate child offsets
|
|
|
|
|
b->child_offset[0] = 0;
|
|
|
|
|
for(i=0; i<nchilds-1; i++)
|
|
|
|
|
b->child_offset[i+1] = split_leafs_by_plane(b, b->child_offset[i], size, separators[i]);
|
|
|
|
|
b->child_offset[nchilds] = size;
|
|
|
|
|
|
|
|
|
|
for(i=0; i<nchilds; i++)
|
|
|
|
|
if(b->child_offset[i+1] - b->child_offset[i] == size)
|
|
|
|
|
return rtbuild_mean_split(b, nchilds, axis);
|
|
|
|
|
|
|
|
|
|
return nchilds;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int rtbuild_median_split_largest_axis(RTBuilder *b, int nchilds)
|
|
|
|
|
{
|
|
|
|
|
int la, i;
|
|
|
|
|
float separators[RTBUILD_MAX_CHILDS];
|
2009-07-10 16:42:51 +00:00
|
|
|
|
|
|
|
|
rtbuild_calc_bb(b);
|
2009-07-06 19:45:00 +00:00
|
|
|
|
2009-07-10 16:42:51 +00:00
|
|
|
la = bb_largest_axis(b->bb,b->bb+3);
|
2009-07-06 19:45:00 +00:00
|
|
|
for(i=1; i<nchilds; i++)
|
2009-07-10 16:42:51 +00:00
|
|
|
separators[i-1] = (b->bb[la+3]-b->bb[la])*i / nchilds;
|
2009-07-06 19:45:00 +00:00
|
|
|
|
|
|
|
|
return rtbuild_median_split(b, separators, nchilds, la);
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-07 15:42:08 +00:00
|
|
|
//Heuristics Object Splitter
|
|
|
|
|
typedef struct CostObject CostObject;
|
|
|
|
|
struct CostObject
|
|
|
|
|
{
|
|
|
|
|
RayObject *obj;
|
2009-07-08 20:04:40 +00:00
|
|
|
float cost;
|
2009-07-07 15:42:08 +00:00
|
|
|
float bb[6];
|
|
|
|
|
};
|
|
|
|
|
|
2009-08-02 12:11:14 +00:00
|
|
|
template<class Obj,int Axis>
|
|
|
|
|
bool obj_bb_compare(const Obj &a, const Obj &b)
|
|
|
|
|
{
|
|
|
|
|
if(a.bb[Axis] != b.bb[Axis])
|
|
|
|
|
return a.bb[Axis] < b.bb[Axis];
|
|
|
|
|
return a.obj < b.obj;
|
|
|
|
|
}
|
2009-07-07 15:42:08 +00:00
|
|
|
|
|
|
|
|
void costobject_sort(CostObject *begin, CostObject *end, int axis)
|
|
|
|
|
{
|
2009-08-02 12:11:14 +00:00
|
|
|
if(axis == 0) return std::sort(begin, end, obj_bb_compare<CostObject,0> );
|
|
|
|
|
if(axis == 1) return std::sort(begin, end, obj_bb_compare<CostObject,1> );
|
|
|
|
|
if(axis == 2) return std::sort(begin, end, obj_bb_compare<CostObject,2> );
|
|
|
|
|
assert(false);
|
2009-07-07 15:42:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-07-10 16:42:51 +00:00
|
|
|
/* Object Surface Area Heuristic splitter */
|
2009-07-07 15:42:08 +00:00
|
|
|
int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds)
|
|
|
|
|
{
|
|
|
|
|
int size = rtbuild_size(b);
|
|
|
|
|
assert(nchilds == 2);
|
|
|
|
|
|
|
|
|
|
if(size <= nchilds)
|
|
|
|
|
{
|
|
|
|
|
return rtbuild_mean_split_largest_axis(b, nchilds);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
float bcost = FLT_MAX;
|
2009-07-08 20:04:40 +00:00
|
|
|
float childrens_cost = 0;
|
2009-07-08 21:56:24 +00:00
|
|
|
int i, axis, baxis = -1, boffset = size/2, k, try_axis[3];
|
2009-07-12 18:04:10 +00:00
|
|
|
CostObject *cost = (CostObject*)MEM_mallocN( sizeof(CostObject)*size, "RTBuilder.HeuristicObjectSplitter" );
|
|
|
|
|
float *acc_bb = (float*)MEM_mallocN( sizeof(float)*6*size, "RTBuilder.HeuristicObjectSplitterBB" );
|
2009-07-07 15:42:08 +00:00
|
|
|
|
|
|
|
|
for(i=0; i<size; i++)
|
|
|
|
|
{
|
|
|
|
|
cost[i].obj = b->begin[i];
|
|
|
|
|
INIT_MINMAX(cost[i].bb, cost[i].bb+3);
|
2009-07-08 20:04:40 +00:00
|
|
|
RE_rayobject_merge_bb(cost[i].obj, cost[i].bb, cost[i].bb+3);
|
|
|
|
|
cost[i].cost = RE_rayobject_cost(cost[i].obj);
|
|
|
|
|
childrens_cost += cost[i].cost;
|
2009-07-07 15:42:08 +00:00
|
|
|
}
|
|
|
|
|
|
2009-07-07 19:07:53 +00:00
|
|
|
if(b->child_sorted_axis >= 0 && b->child_sorted_axis < 3)
|
|
|
|
|
{
|
2009-07-08 20:04:40 +00:00
|
|
|
try_axis[0] = b->child_sorted_axis;
|
2009-07-07 19:07:53 +00:00
|
|
|
try_axis[1] = (b->child_sorted_axis+1)%3;
|
|
|
|
|
try_axis[2] = (b->child_sorted_axis+2)%3;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
try_axis[0] = 0;
|
|
|
|
|
try_axis[1] = 1;
|
|
|
|
|
try_axis[2] = 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(axis=try_axis[k=0]; k<3; axis=try_axis[++k])
|
2009-07-07 15:42:08 +00:00
|
|
|
{
|
2009-07-08 20:04:40 +00:00
|
|
|
float left_cost, right_cost;
|
2009-07-07 15:42:08 +00:00
|
|
|
float other_bb[6];
|
|
|
|
|
|
2009-07-08 20:04:40 +00:00
|
|
|
|
|
|
|
|
|
2009-07-07 15:42:08 +00:00
|
|
|
costobject_sort(cost, cost+size, axis);
|
|
|
|
|
for(i=size-1; i>=0; i--)
|
|
|
|
|
{
|
|
|
|
|
float *bb = acc_bb+i*6;
|
|
|
|
|
if(i == size-1)
|
|
|
|
|
{
|
2009-07-07 19:07:53 +00:00
|
|
|
VECCOPY(bb, cost[i].bb);
|
|
|
|
|
VECCOPY(bb+3, cost[i].bb+3);
|
2009-07-07 15:42:08 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2009-07-07 19:07:53 +00:00
|
|
|
bb[0] = MIN2(cost[i].bb[0], bb[6+0]);
|
|
|
|
|
bb[1] = MIN2(cost[i].bb[1], bb[6+1]);
|
|
|
|
|
bb[2] = MIN2(cost[i].bb[2], bb[6+2]);
|
|
|
|
|
|
|
|
|
|
bb[3] = MAX2(cost[i].bb[3], bb[6+3]);
|
|
|
|
|
bb[4] = MAX2(cost[i].bb[4], bb[6+4]);
|
|
|
|
|
bb[5] = MAX2(cost[i].bb[5], bb[6+5]);
|
2009-07-07 15:42:08 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
INIT_MINMAX(other_bb, other_bb+3);
|
2009-07-07 19:07:53 +00:00
|
|
|
DO_MIN( cost[0].bb, other_bb );
|
|
|
|
|
DO_MAX( cost[0].bb+3, other_bb+3 );
|
2009-07-08 20:04:40 +00:00
|
|
|
left_cost = cost[0].cost;
|
|
|
|
|
right_cost = childrens_cost-cost[0].cost;
|
|
|
|
|
if(right_cost < 0) right_cost = 0;
|
2009-07-07 15:42:08 +00:00
|
|
|
|
|
|
|
|
for(i=1; i<size; i++)
|
|
|
|
|
{
|
|
|
|
|
//Worst case heuristic (cost of each child is linear)
|
2009-07-07 19:07:53 +00:00
|
|
|
float hcost, left_side, right_side;
|
|
|
|
|
|
2009-07-08 21:56:24 +00:00
|
|
|
left_side = bb_area(other_bb, other_bb+3)*(left_cost+logf(i));
|
|
|
|
|
right_side= bb_area(acc_bb+i*6, acc_bb+i*6+3)*(right_cost+logf(i));
|
2009-07-07 19:07:53 +00:00
|
|
|
|
|
|
|
|
if(left_side > bcost) break; //No way we can find a better heuristic in this axis
|
|
|
|
|
|
|
|
|
|
hcost = left_side+right_side;
|
2009-07-08 20:04:40 +00:00
|
|
|
assert(hcost >= 0);
|
2009-07-07 19:07:53 +00:00
|
|
|
if( hcost < bcost
|
|
|
|
|
|| (hcost == bcost && axis < baxis)) //this makes sure the tree built is the same whatever is the order of the sorting axis
|
2009-07-07 15:42:08 +00:00
|
|
|
{
|
|
|
|
|
bcost = hcost;
|
|
|
|
|
baxis = axis;
|
|
|
|
|
boffset = i;
|
|
|
|
|
}
|
2009-07-07 19:07:53 +00:00
|
|
|
DO_MIN( cost[i].bb, other_bb );
|
|
|
|
|
DO_MAX( cost[i].bb+3, other_bb+3 );
|
2009-07-08 20:04:40 +00:00
|
|
|
left_cost += cost[i].cost;
|
|
|
|
|
right_cost -= cost[i].cost;
|
|
|
|
|
if(right_cost < 0.0f) right_cost = 0.0;
|
2009-07-07 19:07:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(baxis == axis)
|
|
|
|
|
{
|
|
|
|
|
for(i=0; i<size; i++)
|
|
|
|
|
b->begin[i] = cost[i].obj;
|
|
|
|
|
b->child_sorted_axis = axis;
|
2009-07-07 15:42:08 +00:00
|
|
|
}
|
2009-07-08 21:56:24 +00:00
|
|
|
|
|
|
|
|
assert(baxis >= 0 && baxis < 3);
|
2009-07-07 15:42:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
b->child_offset[0] = 0;
|
|
|
|
|
b->child_offset[1] = boffset;
|
|
|
|
|
b->child_offset[2] = size;
|
|
|
|
|
|
|
|
|
|
MEM_freeN(acc_bb);
|
|
|
|
|
MEM_freeN(cost);
|
|
|
|
|
return nchilds;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-06-30 22:07:42 +00:00
|
|
|
/*
|
|
|
|
|
* Helper code
|
|
|
|
|
* PARTITION code / used on mean-split
|
|
|
|
|
* basicly this a std::nth_element (like on C++ STL algorithm)
|
|
|
|
|
*/
|
|
|
|
|
static void sort_swap(RTBuilder *b, int i, int j)
|
|
|
|
|
{
|
|
|
|
|
SWAP(RayObject*, b->begin[i], b->begin[j]);
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-01 11:27:43 +00:00
|
|
|
static float sort_get_value(RTBuilder *b, int i)
|
2009-06-30 22:07:42 +00:00
|
|
|
{
|
|
|
|
|
float min[3], max[3];
|
2009-07-01 11:27:43 +00:00
|
|
|
INIT_MINMAX(min, max);
|
2009-06-30 22:07:42 +00:00
|
|
|
RE_rayobject_merge_bb(b->begin[i], min, max);
|
2009-07-01 11:27:43 +00:00
|
|
|
return max[b->split_axis];
|
2009-06-30 22:07:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int medianof3(RTBuilder *d, int a, int b, int c)
|
|
|
|
|
{
|
|
|
|
|
float fa = sort_get_value( d, a );
|
|
|
|
|
float fb = sort_get_value( d, b );
|
|
|
|
|
float fc = sort_get_value( d, c );
|
|
|
|
|
|
|
|
|
|
if(fb < fa)
|
|
|
|
|
{
|
|
|
|
|
if(fc < fb)
|
|
|
|
|
return b;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if(fc < fa)
|
|
|
|
|
return c;
|
|
|
|
|
else
|
|
|
|
|
return a;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2009-07-02 21:57:50 +00:00
|
|
|
if(fc < fb)
|
2009-06-30 22:07:42 +00:00
|
|
|
{
|
2009-07-02 21:57:50 +00:00
|
|
|
if(fc < fa)
|
2009-06-30 22:07:42 +00:00
|
|
|
return a;
|
2009-07-02 21:57:50 +00:00
|
|
|
else
|
|
|
|
|
return c;
|
2009-06-30 22:07:42 +00:00
|
|
|
}
|
2009-07-02 21:57:50 +00:00
|
|
|
else
|
|
|
|
|
return b;
|
2009-06-30 22:07:42 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void insertionsort(RTBuilder *b, int lo, int hi)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
for(i=lo; i<hi; i++)
|
|
|
|
|
{
|
|
|
|
|
RayObject *t = b->begin[i];
|
|
|
|
|
float tv= sort_get_value(b, i);
|
|
|
|
|
int j=i;
|
|
|
|
|
|
|
|
|
|
while( j != lo && tv < sort_get_value(b, j-1))
|
|
|
|
|
{
|
|
|
|
|
b->begin[j] = b->begin[j-1];
|
|
|
|
|
j--;
|
|
|
|
|
}
|
|
|
|
|
b->begin[j] = t;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int partition(RTBuilder *b, int lo, int mid, int hi)
|
|
|
|
|
{
|
|
|
|
|
float x = sort_get_value( b, mid );
|
|
|
|
|
|
|
|
|
|
int i=lo, j=hi;
|
|
|
|
|
while (1)
|
|
|
|
|
{
|
2009-07-02 21:57:50 +00:00
|
|
|
while(sort_get_value(b,i) < x) i++;
|
2009-06-30 22:07:42 +00:00
|
|
|
j--;
|
2009-07-02 21:57:50 +00:00
|
|
|
while(x < sort_get_value(b,j)) j--;
|
2009-06-30 22:07:42 +00:00
|
|
|
if(!(i < j))
|
|
|
|
|
return i;
|
|
|
|
|
|
|
|
|
|
sort_swap(b, i, j);
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// PARTITION code / used on mean-split
|
|
|
|
|
// basicly this is an adapted std::nth_element (C++ STL <algorithm>)
|
|
|
|
|
//
|
|
|
|
|
// after a call to this function you can expect one of:
|
|
|
|
|
// 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
|
2009-07-02 21:57:50 +00:00
|
|
|
static int partition_nth_element(RTBuilder *b, int _begin, int n, int _end)
|
2009-06-30 22:07:42 +00:00
|
|
|
{
|
|
|
|
|
int begin = _begin, end = _end, cut;
|
|
|
|
|
while(end-begin > 3)
|
|
|
|
|
{
|
|
|
|
|
cut = partition(b, begin, medianof3(b, begin, begin+(end-begin)/2, end-1), end);
|
|
|
|
|
if(cut <= n)
|
|
|
|
|
begin = cut;
|
|
|
|
|
else
|
|
|
|
|
end = cut;
|
|
|
|
|
}
|
|
|
|
|
insertionsort(b, begin, end);
|
|
|
|
|
|
|
|
|
|
return n;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void split_leafs(RTBuilder *b, int *nth, int partitions, int split_axis)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
b->split_axis = split_axis;
|
2009-07-02 21:57:50 +00:00
|
|
|
|
2009-06-30 22:07:42 +00:00
|
|
|
for(i=0; i < partitions-1; i++)
|
|
|
|
|
{
|
2009-07-02 21:57:50 +00:00
|
|
|
assert(nth[i] < nth[i+1] && nth[i+1] < nth[partitions]);
|
2009-06-30 22:07:42 +00:00
|
|
|
|
|
|
|
|
partition_nth_element(b, nth[i], nth[i+1], nth[partitions] );
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-07-06 19:45:00 +00:00
|
|
|
|
|
|
|
|
static int split_leafs_by_plane(RTBuilder *b, int begin, int end, float plane)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
for(i = begin; i != end; i++)
|
|
|
|
|
{
|
|
|
|
|
if(sort_get_value(b, i) < plane)
|
|
|
|
|
{
|
|
|
|
|
sort_swap(b, i, begin);
|
|
|
|
|
begin++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return begin;
|
|
|
|
|
}
|
2009-07-10 16:42:51 +00:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Bounding Box utils
|
|
|
|
|
*/
|
|
|
|
|
float bb_volume(float *min, float *max)
|
|
|
|
|
{
|
|
|
|
|
return (max[0]-min[0])*(max[1]-min[1])*(max[2]-min[2]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float bb_area(float *min, float *max)
|
|
|
|
|
{
|
|
|
|
|
float sub[3], a;
|
|
|
|
|
sub[0] = max[0]-min[0];
|
|
|
|
|
sub[1] = max[1]-min[1];
|
|
|
|
|
sub[2] = max[2]-min[2];
|
|
|
|
|
|
|
|
|
|
a = (sub[0]*sub[1] + sub[0]*sub[2] + sub[1]*sub[2])*2;
|
|
|
|
|
assert(a >= 0.0);
|
|
|
|
|
return a;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int bb_largest_axis(float *min, float *max)
|
|
|
|
|
{
|
|
|
|
|
float sub[3];
|
|
|
|
|
|
|
|
|
|
sub[0] = max[0]-min[0];
|
|
|
|
|
sub[1] = max[1]-min[1];
|
|
|
|
|
sub[2] = max[2]-min[2];
|
|
|
|
|
if(sub[0] > sub[1])
|
|
|
|
|
{
|
|
|
|
|
if(sub[0] > sub[2])
|
|
|
|
|
return 0;
|
|
|
|
|
else
|
|
|
|
|
return 2;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if(sub[1] > sub[2])
|
|
|
|
|
return 1;
|
|
|
|
|
else
|
|
|
|
|
return 2;
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-07-14 23:08:55 +00:00
|
|
|
|
|
|
|
|
int bb_fits_inside(float *outer_min, float *outer_max, float *inner_min, float *inner_max)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
for(i=0; i<3; i++)
|
|
|
|
|
if(outer_min[i] > inner_min[i]) return 0;
|
|
|
|
|
|
|
|
|
|
for(i=0; i<3; i++)
|
|
|
|
|
if(outer_max[i] < inner_max[i]) return 0;
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|