2009-09-06 19:14:06 +00:00
|
|
|
/**
|
|
|
|
|
* $Id$
|
|
|
|
|
*
|
|
|
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
|
|
|
*
|
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
|
|
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
|
*
|
|
|
|
|
* The Original Code is Copyright (C) 2009 Blender Foundation.
|
|
|
|
|
* All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* The Original Code is: all of this file.
|
|
|
|
|
*
|
|
|
|
|
* Contributor(s): André Pinto.
|
|
|
|
|
*
|
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
|
|
|
*/
|
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"
|
|
|
|
|
|
2009-08-03 17:56:38 +00:00
|
|
|
static bool selected_node(RTBuilder::Object *node)
|
2009-06-30 22:07:42 +00:00
|
|
|
{
|
2009-08-03 17:56:38 +00:00
|
|
|
return node->selected;
|
|
|
|
|
}
|
2009-06-30 22:07:42 +00:00
|
|
|
|
2009-08-03 17:56:38 +00:00
|
|
|
static void rtbuild_init(RTBuilder *b)
|
|
|
|
|
{
|
|
|
|
|
b->split_axis = -1;
|
|
|
|
|
b->primitives.begin = 0;
|
|
|
|
|
b->primitives.end = 0;
|
|
|
|
|
b->primitives.maxsize = 0;
|
2009-06-30 22:07:42 +00:00
|
|
|
|
2009-08-03 17:56:38 +00:00
|
|
|
for(int i=0; i<RTBUILD_MAX_CHILDS; i++)
|
2009-07-01 11:27:43 +00:00
|
|
|
b->child_offset[i] = 0;
|
2009-08-03 17:56:38 +00:00
|
|
|
|
|
|
|
|
for(int i=0; i<3; i++)
|
|
|
|
|
b->sorted_begin[i] = b->sorted_end[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-08-03 17:56:38 +00:00
|
|
|
RTBuilder::Object *memblock= (RTBuilder::Object*)MEM_mallocN( sizeof(RTBuilder::Object)*size,"RTBuilder.objects");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rtbuild_init(builder);
|
|
|
|
|
|
|
|
|
|
builder->primitives.begin = builder->primitives.end = memblock;
|
|
|
|
|
builder->primitives.maxsize = size;
|
|
|
|
|
|
|
|
|
|
for(int i=0; i<3; i++)
|
|
|
|
|
{
|
|
|
|
|
builder->sorted_begin[i] = (RTBuilder::Object**)MEM_mallocN( sizeof(RTBuilder::Object*)*size,"RTBuilder.sorted_objects");
|
|
|
|
|
builder->sorted_end[i] = builder->sorted_begin[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
{
|
2009-08-03 17:56:38 +00:00
|
|
|
if(b->primitives.begin) MEM_freeN(b->primitives.begin);
|
|
|
|
|
|
|
|
|
|
for(int i=0; i<3; i++)
|
|
|
|
|
if(b->sorted_begin[i])
|
|
|
|
|
MEM_freeN(b->sorted_begin[i]);
|
|
|
|
|
|
2009-06-30 22:07:42 +00:00
|
|
|
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
|
|
|
{
|
2009-08-03 17:56:38 +00:00
|
|
|
assert( b->primitives.begin + b->primitives.maxsize != b->primitives.end );
|
|
|
|
|
|
|
|
|
|
b->primitives.end->obj = o;
|
|
|
|
|
b->primitives.end->cost = RE_rayobject_cost(o);
|
2009-06-30 22:07:42 +00:00
|
|
|
|
2009-08-03 17:56:38 +00:00
|
|
|
INIT_MINMAX(b->primitives.end->bb, b->primitives.end->bb+3);
|
|
|
|
|
RE_rayobject_merge_bb(o, b->primitives.end->bb, b->primitives.end->bb+3);
|
|
|
|
|
|
|
|
|
|
for(int i=0; i<3; i++)
|
2009-07-10 16:42:51 +00:00
|
|
|
{
|
2009-08-03 17:56:38 +00:00
|
|
|
*(b->sorted_end[i]) = b->primitives.end;
|
|
|
|
|
b->sorted_end[i]++;
|
2009-07-10 16:42:51 +00:00
|
|
|
}
|
2009-08-03 17:56:38 +00:00
|
|
|
b->primitives.end++;
|
2009-06-30 22:07:42 +00:00
|
|
|
}
|
|
|
|
|
|
2009-08-03 17:56:38 +00:00
|
|
|
int rtbuild_size(RTBuilder *b)
|
2009-06-30 22:07:42 +00:00
|
|
|
{
|
2009-08-03 17:56:38 +00:00
|
|
|
return b->sorted_end[0] - b->sorted_begin[0];
|
2009-06-30 22:07:42 +00:00
|
|
|
}
|
|
|
|
|
|
2009-08-03 17:56:38 +00:00
|
|
|
|
|
|
|
|
template<class Obj,int Axis>
|
|
|
|
|
static bool obj_bb_compare(const Obj &a, const Obj &b)
|
2009-06-30 22:07:42 +00:00
|
|
|
{
|
2009-08-03 17:56:38 +00:00
|
|
|
if(a->bb[Axis] != b->bb[Axis])
|
|
|
|
|
return a->bb[Axis] < b->bb[Axis];
|
|
|
|
|
return a->obj < b->obj;
|
2009-06-30 22:07:42 +00:00
|
|
|
}
|
|
|
|
|
|
2009-08-03 17:56:38 +00:00
|
|
|
template<class Item>
|
|
|
|
|
static void object_sort(Item *begin, Item *end, int axis)
|
|
|
|
|
{
|
|
|
|
|
if(axis == 0) return std::sort(begin, end, obj_bb_compare<Item,0> );
|
|
|
|
|
if(axis == 1) return std::sort(begin, end, obj_bb_compare<Item,1> );
|
|
|
|
|
if(axis == 2) return std::sort(begin, end, obj_bb_compare<Item,2> );
|
|
|
|
|
assert(false);
|
|
|
|
|
}
|
2009-06-30 22:07:42 +00:00
|
|
|
|
2009-08-03 17:56:38 +00:00
|
|
|
void rtbuild_done(RTBuilder *b)
|
2009-07-06 19:45:00 +00:00
|
|
|
{
|
2009-08-03 17:56:38 +00:00
|
|
|
for(int i=0; i<3; i++)
|
|
|
|
|
if(b->sorted_begin[i])
|
|
|
|
|
object_sort( b->sorted_begin[i], b->sorted_end[i], i );
|
2009-07-06 19:45:00 +00:00
|
|
|
}
|
|
|
|
|
|
2009-08-03 17:56:38 +00:00
|
|
|
RayObject* rtbuild_get_primitive(RTBuilder *b, int index)
|
|
|
|
|
{
|
|
|
|
|
return b->sorted_begin[0][index]->obj;
|
|
|
|
|
}
|
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-08-03 17:56:38 +00:00
|
|
|
rtbuild_init( tmp );
|
|
|
|
|
|
|
|
|
|
for(int i=0; i<3; i++)
|
|
|
|
|
if(b->sorted_begin[i])
|
|
|
|
|
{
|
|
|
|
|
tmp->sorted_begin[i] = b->sorted_begin[i] + b->child_offset[child ];
|
|
|
|
|
tmp->sorted_end [i] = b->sorted_begin[i] + b->child_offset[child+1];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
tmp->sorted_begin[i] = 0;
|
|
|
|
|
tmp->sorted_end [i] = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-10 16:42:51 +00:00
|
|
|
return tmp;
|
2009-07-06 19:45:00 +00:00
|
|
|
}
|
2009-07-10 16:42:51 +00:00
|
|
|
|
2009-08-03 17:56:38 +00:00
|
|
|
void rtbuild_calc_bb(RTBuilder *b)
|
|
|
|
|
{
|
|
|
|
|
if(b->bb[0] == 1.0e30f)
|
|
|
|
|
{
|
|
|
|
|
for(RTBuilder::Object **index = b->sorted_begin[0]; index != b->sorted_end[0]; index++)
|
|
|
|
|
RE_rayobject_merge_bb( (*index)->obj , b->bb, b->bb+3);
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-07-10 16:42:51 +00:00
|
|
|
|
2009-08-03 17:56:38 +00:00
|
|
|
void rtbuild_merge_bb(RTBuilder *b, float *min, float *max)
|
|
|
|
|
{
|
|
|
|
|
rtbuild_calc_bb(b);
|
|
|
|
|
DO_MIN(b->bb, min);
|
|
|
|
|
DO_MAX(b->bb+3, max);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
int rtbuild_get_largest_axis(RTBuilder *b)
|
|
|
|
|
{
|
|
|
|
|
rtbuild_calc_bb(b);
|
|
|
|
|
return bb_largest_axis(b->bb, b->bb+3);
|
|
|
|
|
}
|
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-08-03 17:56:38 +00:00
|
|
|
*/
|
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
|
|
|
|
|
*/
|
2009-08-03 17:56:38 +00:00
|
|
|
/*
|
2009-07-06 19:45:00 +00:00
|
|
|
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-08-03 17:56:38 +00:00
|
|
|
*/
|
2009-07-06 19:45:00 +00:00
|
|
|
|
2009-07-07 15:42:08 +00:00
|
|
|
//Heuristics Object Splitter
|
|
|
|
|
|
|
|
|
|
|
2009-08-03 17:56:38 +00:00
|
|
|
struct SweepCost
|
2009-07-07 15:42:08 +00:00
|
|
|
{
|
2009-08-03 17:56:38 +00:00
|
|
|
float bb[6];
|
|
|
|
|
float cost;
|
|
|
|
|
};
|
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);
|
2009-08-03 17:56:38 +00:00
|
|
|
assert(size > 1);
|
|
|
|
|
int baxis = -1, boffset = 0;
|
2009-07-07 15:42:08 +00:00
|
|
|
|
2009-08-03 17:56:38 +00:00
|
|
|
if(size > nchilds)
|
2009-07-07 15:42:08 +00:00
|
|
|
{
|
|
|
|
|
float bcost = FLT_MAX;
|
2009-08-03 17:56:38 +00:00
|
|
|
baxis = -1, boffset = size/2;
|
2009-07-07 15:42:08 +00:00
|
|
|
|
2009-08-03 17:56:38 +00:00
|
|
|
SweepCost *sweep = (SweepCost*)MEM_mallocN( sizeof(SweepCost)*size, "RTBuilder.HeuristicSweep" );
|
2009-07-07 19:07:53 +00:00
|
|
|
|
2009-08-03 17:56:38 +00:00
|
|
|
for(int axis=0; axis<3; axis++)
|
2009-07-07 15:42:08 +00:00
|
|
|
{
|
2009-08-03 17:56:38 +00:00
|
|
|
SweepCost sweep_left;
|
2009-07-07 15:42:08 +00:00
|
|
|
|
2009-08-03 17:56:38 +00:00
|
|
|
RTBuilder::Object **obj = b->sorted_begin[axis];
|
|
|
|
|
|
|
|
|
|
// float right_cost = 0;
|
|
|
|
|
for(int i=size-1; i>=0; i--)
|
2009-07-07 15:42:08 +00:00
|
|
|
{
|
|
|
|
|
if(i == size-1)
|
|
|
|
|
{
|
2009-08-03 17:56:38 +00:00
|
|
|
VECCOPY(sweep[i].bb, obj[i]->bb);
|
|
|
|
|
VECCOPY(sweep[i].bb+3, obj[i]->bb+3);
|
|
|
|
|
sweep[i].cost = obj[i]->cost;
|
2009-07-07 15:42:08 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2009-08-03 17:56:38 +00:00
|
|
|
sweep[i].bb[0] = MIN2(obj[i]->bb[0], sweep[i+1].bb[0]);
|
|
|
|
|
sweep[i].bb[1] = MIN2(obj[i]->bb[1], sweep[i+1].bb[1]);
|
|
|
|
|
sweep[i].bb[2] = MIN2(obj[i]->bb[2], sweep[i+1].bb[2]);
|
|
|
|
|
sweep[i].bb[3] = MAX2(obj[i]->bb[3], sweep[i+1].bb[3]);
|
|
|
|
|
sweep[i].bb[4] = MAX2(obj[i]->bb[4], sweep[i+1].bb[4]);
|
|
|
|
|
sweep[i].bb[5] = MAX2(obj[i]->bb[5], sweep[i+1].bb[5]);
|
|
|
|
|
sweep[i].cost = obj[i]->cost + sweep[i+1].cost;
|
2009-07-07 15:42:08 +00:00
|
|
|
}
|
2009-08-03 17:56:38 +00:00
|
|
|
// right_cost += obj[i]->cost;
|
2009-07-07 15:42:08 +00:00
|
|
|
}
|
|
|
|
|
|
2009-08-03 17:56:38 +00:00
|
|
|
sweep_left.bb[0] = obj[0]->bb[0];
|
|
|
|
|
sweep_left.bb[1] = obj[0]->bb[1];
|
|
|
|
|
sweep_left.bb[2] = obj[0]->bb[2];
|
|
|
|
|
sweep_left.bb[3] = obj[0]->bb[3];
|
|
|
|
|
sweep_left.bb[4] = obj[0]->bb[4];
|
|
|
|
|
sweep_left.bb[5] = obj[0]->bb[5];
|
|
|
|
|
sweep_left.cost = obj[0]->cost;
|
|
|
|
|
|
|
|
|
|
// right_cost -= obj[0]->cost; if(right_cost < 0) right_cost = 0;
|
|
|
|
|
|
|
|
|
|
for(int i=1; i<size; i++)
|
2009-07-07 15:42:08 +00:00
|
|
|
{
|
|
|
|
|
//Worst case heuristic (cost of each child is linear)
|
2009-07-07 19:07:53 +00:00
|
|
|
float hcost, left_side, right_side;
|
|
|
|
|
|
2009-08-03 17:56:38 +00:00
|
|
|
left_side = bb_area(sweep_left.bb, sweep_left.bb+3)*(sweep_left.cost+logf(i));
|
|
|
|
|
right_side= bb_area(sweep[i].bb, sweep[i].bb+3)*(sweep[i].cost+logf(size-i));
|
|
|
|
|
hcost = left_side+right_side;
|
|
|
|
|
|
2009-08-03 23:25:38 +00:00
|
|
|
assert(left_side >= 0);
|
|
|
|
|
assert(right_side >= 0);
|
2009-07-07 19:07:53 +00:00
|
|
|
|
|
|
|
|
if(left_side > bcost) break; //No way we can find a better heuristic in this axis
|
|
|
|
|
|
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-08-03 17:56:38 +00:00
|
|
|
DO_MIN( obj[i]->bb, sweep_left.bb );
|
|
|
|
|
DO_MAX( obj[i]->bb+3, sweep_left.bb+3 );
|
|
|
|
|
|
|
|
|
|
sweep_left.cost += obj[i]->cost;
|
|
|
|
|
// right_cost -= obj[i]->cost; if(right_cost < 0) right_cost = 0;
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2009-08-03 17:56:38 +00:00
|
|
|
MEM_freeN(sweep);
|
2009-07-07 15:42:08 +00:00
|
|
|
}
|
2009-08-03 17:56:38 +00:00
|
|
|
else if(size == 2)
|
2009-06-30 22:07:42 +00:00
|
|
|
{
|
2009-08-03 17:56:38 +00:00
|
|
|
baxis = 0;
|
|
|
|
|
boffset = 1;
|
2009-06-30 22:07:42 +00:00
|
|
|
}
|
2009-08-03 17:56:38 +00:00
|
|
|
else if(size == 1)
|
2009-06-30 22:07:42 +00:00
|
|
|
{
|
2009-08-03 17:56:38 +00:00
|
|
|
b->child_offset[0] = 0;
|
|
|
|
|
b->child_offset[1] = 1;
|
|
|
|
|
return 1;
|
2009-06-30 22:07:42 +00:00
|
|
|
}
|
|
|
|
|
|
2009-08-03 17:56:38 +00:00
|
|
|
b->child_offset[0] = 0;
|
|
|
|
|
b->child_offset[1] = boffset;
|
|
|
|
|
b->child_offset[2] = size;
|
2009-06-30 22:07:42 +00:00
|
|
|
|
|
|
|
|
|
2009-08-03 17:56:38 +00:00
|
|
|
/* Adjust sorted arrays for childs */
|
|
|
|
|
for(int i=0; i<boffset; i++) b->sorted_begin[baxis][i]->selected = true;
|
|
|
|
|
for(int i=boffset; i<size; i++) b->sorted_begin[baxis][i]->selected = false;
|
|
|
|
|
for(int i=0; i<3; i++)
|
|
|
|
|
std::stable_partition( b->sorted_begin[i], b->sorted_end[i], selected_node );
|
2009-06-30 22:07:42 +00:00
|
|
|
|
2009-08-03 17:56:38 +00:00
|
|
|
return nchilds;
|
2009-06-30 22:07:42 +00:00
|
|
|
}
|
|
|
|
|
|
2009-08-03 17:56:38 +00:00
|
|
|
/*
|
|
|
|
|
* Helper code
|
|
|
|
|
* PARTITION code / used on mean-split
|
|
|
|
|
* basicly this a std::nth_element (like on C++ STL algorithm)
|
|
|
|
|
*/
|
|
|
|
|
/*
|
2009-06-30 22:07:42 +00:00
|
|
|
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
|
|
|
|
2009-08-03 17:56:38 +00:00
|
|
|
if(split_axis == 0) std::nth_element(b, nth[i], nth[i+1], nth[partitions], obj_bb_compare<RTBuilder::Object,0>);
|
|
|
|
|
if(split_axis == 1) std::nth_element(b, nth[i], nth[i+1], nth[partitions], obj_bb_compare<RTBuilder::Object,1>);
|
|
|
|
|
if(split_axis == 2) std::nth_element(b, nth[i], nth[i+1], nth[partitions], obj_bb_compare<RTBuilder::Object,2>);
|
2009-07-06 19:45:00 +00:00
|
|
|
}
|
|
|
|
|
}
|
2009-08-03 17:56:38 +00:00
|
|
|
*/
|
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;
|
|
|
|
|
}
|