*Added initial code of rayobject_rtbuild
An helper class to build trees
This commit is contained in:
+7
-2
@@ -47,7 +47,7 @@ void RE_rayobject_free(RayObject *r);
|
||||
|
||||
/* RayObject constructors */
|
||||
RayObject* RE_rayobject_octree_create(int ocres, int size);
|
||||
RayObject* RE_rayobject_bvh_create(int size);
|
||||
RayObject* RE_rayobject_blibvh_create(int size);
|
||||
RayObject* RE_rayobject_instance_create(RayObject *target, float transform[][4], void *ob, void *target_ob);
|
||||
|
||||
//RayObject* RayObject_derivedmesh_create(struct DerivedMesh*, void *ob);
|
||||
@@ -59,8 +59,13 @@ struct Isect
|
||||
float start[3];
|
||||
float vec[3];
|
||||
float labda;
|
||||
|
||||
/* length of vec, configured by RE_rayobject_raycast */
|
||||
int bv_index[6];
|
||||
float idot_axis[3];
|
||||
float dist;
|
||||
|
||||
float dist; /* length of vec, configured by RE_rayobject_raycast */
|
||||
|
||||
/* float end[3]; - not used */
|
||||
|
||||
float u, v;
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* $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 *****
|
||||
*/
|
||||
#ifndef RE_RAYOBJECT_RTBUILD_H
|
||||
#define RE_RAYOBJECT_RTBUILD_H
|
||||
|
||||
#include "rayobject.h"
|
||||
|
||||
/*
|
||||
* Ray Tree Builder
|
||||
* this structs helps building any type of tree
|
||||
* it contains several methods to organiza/split nodes
|
||||
* allowing to create a given tree on the fly.
|
||||
*
|
||||
* Idea is that other trees BVH, BIH can use this code to
|
||||
* generate with simple calls, and then convert to the theirs
|
||||
* specific structure on the fly.
|
||||
*/
|
||||
#define MAX_CHILDS 32
|
||||
typedef struct RTBuilder
|
||||
{
|
||||
/* list to all primitives in this tree */
|
||||
RayObject **begin, **end;
|
||||
|
||||
/* axis used (if any) on the split method */
|
||||
int split_axis;
|
||||
|
||||
/* links to child partitions calculated during splitting */
|
||||
RayObject **child[MAX_CHILDS+1];
|
||||
|
||||
} RTBuilder;
|
||||
|
||||
/* used during creation */
|
||||
RTBuilder* rtbuild_create(int size);
|
||||
void rtbuild_free(RTBuilder *b);
|
||||
void rtbuild_add(RTBuilder *b, RayObject *o);
|
||||
int rtbuild_size(RTBuilder *b);
|
||||
|
||||
/* used during tree reorganization */
|
||||
RTBuilder* rtbuild_get_child(RTBuilder *b, int child, RTBuilder *tmp);
|
||||
void rtbuild_mean_split(RTBuilder *b, int nchilds, int axis);
|
||||
void rtbuild_mean_split_largest_axis(RTBuilder *b, int nchilds);
|
||||
|
||||
/*
|
||||
static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *b)
|
||||
{
|
||||
int i;
|
||||
int nc = rtbuild_mean_split_largest_axis(b, BVH_NCHILDS);
|
||||
RTBuilder tmp;
|
||||
|
||||
BVHNode *bvh = tree->next_node++;
|
||||
|
||||
bvh->split_axis = tmp->split_axis;
|
||||
for(i=0; i<nc; i++)
|
||||
bvh->child[i] = bvh_rearrange( rtbuild_get_child(b, i, &tmp) );
|
||||
}
|
||||
*/
|
||||
|
||||
#endif
|
||||
+16
-16
@@ -36,19 +36,19 @@
|
||||
#include "render_types.h"
|
||||
#include "rayobject.h"
|
||||
|
||||
static int RayObject_bvh_intersect(RayObject *o, Isect *isec);
|
||||
static void RayObject_bvh_add(RayObject *o, RayObject *ob);
|
||||
static void RayObject_bvh_done(RayObject *o);
|
||||
static void RayObject_bvh_free(RayObject *o);
|
||||
static void RayObject_bvh_bb(RayObject *o, float *min, float *max);
|
||||
static int RayObject_blibvh_intersect(RayObject *o, Isect *isec);
|
||||
static void RayObject_blibvh_add(RayObject *o, RayObject *ob);
|
||||
static void RayObject_blibvh_done(RayObject *o);
|
||||
static void RayObject_blibvh_free(RayObject *o);
|
||||
static void RayObject_blibvh_bb(RayObject *o, float *min, float *max);
|
||||
|
||||
static RayObjectAPI bvh_api =
|
||||
{
|
||||
RayObject_bvh_intersect,
|
||||
RayObject_bvh_add,
|
||||
RayObject_bvh_done,
|
||||
RayObject_bvh_free,
|
||||
RayObject_bvh_bb
|
||||
RayObject_blibvh_intersect,
|
||||
RayObject_blibvh_add,
|
||||
RayObject_blibvh_done,
|
||||
RayObject_blibvh_free,
|
||||
RayObject_blibvh_bb
|
||||
};
|
||||
|
||||
typedef struct BVHObject
|
||||
@@ -60,7 +60,7 @@ typedef struct BVHObject
|
||||
} BVHObject;
|
||||
|
||||
|
||||
RayObject *RE_rayobject_bvh_create(int size)
|
||||
RayObject *RE_rayobject_blibvh_create(int size)
|
||||
{
|
||||
BVHObject *obj= (BVHObject*)MEM_callocN(sizeof(BVHObject), "BVHObject");
|
||||
assert( RayObject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */
|
||||
@@ -88,7 +88,7 @@ static void bvh_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTr
|
||||
}
|
||||
}
|
||||
|
||||
static int RayObject_bvh_intersect(RayObject *o, Isect *isec)
|
||||
static int RayObject_blibvh_intersect(RayObject *o, Isect *isec)
|
||||
{
|
||||
BVHObject *obj = (BVHObject*)o;
|
||||
BVHTreeRayHit hit;
|
||||
@@ -103,7 +103,7 @@ static int RayObject_bvh_intersect(RayObject *o, Isect *isec)
|
||||
return BLI_bvhtree_ray_cast(obj->bvh, isec->start, dir, 0.0, &hit, bvh_callback, isec);
|
||||
}
|
||||
|
||||
static void RayObject_bvh_add(RayObject *o, RayObject *ob)
|
||||
static void RayObject_blibvh_add(RayObject *o, RayObject *ob)
|
||||
{
|
||||
BVHObject *obj = (BVHObject*)o;
|
||||
float min_max[6];
|
||||
@@ -116,13 +116,13 @@ static void RayObject_bvh_add(RayObject *o, RayObject *ob)
|
||||
BLI_bvhtree_insert(obj->bvh, (int)ob, min_max, 2 );
|
||||
}
|
||||
|
||||
static void RayObject_bvh_done(RayObject *o)
|
||||
static void RayObject_blibvh_done(RayObject *o)
|
||||
{
|
||||
BVHObject *obj = (BVHObject*)o;
|
||||
BLI_bvhtree_balance(obj->bvh);
|
||||
}
|
||||
|
||||
static void RayObject_bvh_free(RayObject *o)
|
||||
static void RayObject_blibvh_free(RayObject *o)
|
||||
{
|
||||
BVHObject *obj = (BVHObject*)o;
|
||||
|
||||
@@ -132,7 +132,7 @@ static void RayObject_bvh_free(RayObject *o)
|
||||
MEM_freeN(obj);
|
||||
}
|
||||
|
||||
static void RayObject_bvh_bb(RayObject *o, float *min, float *max)
|
||||
static void RayObject_blibvh_bb(RayObject *o, float *min, float *max)
|
||||
{
|
||||
BVHObject *obj = (BVHObject*)o;
|
||||
DO_MINMAX( obj->bb[0], min, max );
|
||||
@@ -0,0 +1,222 @@
|
||||
#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);
|
||||
|
||||
|
||||
static void RayObject_rtbuild_init(RTBuilder *b, RayObject **begin, RayObject **end)
|
||||
{
|
||||
int i;
|
||||
|
||||
b->begin = begin;
|
||||
b->end = end;
|
||||
b->split_axis = 0;
|
||||
|
||||
for(i=0; i<MAX_CHILDS; i++)
|
||||
b->child[i] = 0;
|
||||
}
|
||||
|
||||
RTBuilder* RayObject_rtbuild_create(int size)
|
||||
{
|
||||
RTBuilder *builder = (RTBuilder*) MEM_mallocN( sizeof(RTBuilder), "RTBuilder" );
|
||||
RayObject **memblock= (RayObject**)MEM_mallocN( sizeof(RayObject*),"RTBuilder.objects");
|
||||
RayObject_rtbuild_init(builder, memblock, memblock);
|
||||
return builder;
|
||||
}
|
||||
|
||||
void RayObject_rtbuild_free(RTBuilder *b)
|
||||
{
|
||||
MEM_freeN(b->begin);
|
||||
MEM_freeN(b);
|
||||
}
|
||||
|
||||
void RayObject_rtbuild_add(RTBuilder *b, RayObject *o)
|
||||
{
|
||||
*(b->end++) = o;
|
||||
}
|
||||
|
||||
RTBuilder* rtbuild_get_child(RTBuilder *b, int child, RTBuilder *tmp)
|
||||
{
|
||||
RayObject_rtbuild_init( tmp, b->child[child], b->child[child+1] );
|
||||
return tmp;
|
||||
}
|
||||
|
||||
int RayObject_rtbuild_size(RTBuilder *b)
|
||||
{
|
||||
return b->end - b->begin;
|
||||
}
|
||||
|
||||
/* Split methods */
|
||||
static void merge_bb(RTBuilder *b, float *min, float *max)
|
||||
{
|
||||
RayObject **index = b->begin;
|
||||
|
||||
for(; index != b->end; index++)
|
||||
RE_rayobject_merge_bb(*index, min, max);
|
||||
}
|
||||
|
||||
static int calc_largest_axis(RTBuilder *b)
|
||||
{
|
||||
float min[3], max[3], sub[3];
|
||||
|
||||
INIT_MINMAX(min, max);
|
||||
merge_bb( b, min, max);
|
||||
|
||||
VECSUB(sub, max, min);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Unballanced mean
|
||||
//TODO better balance nodes
|
||||
//TODO suport for variable number of partitions (its hardcoded in 2)
|
||||
void rtbuild_mean_split(RTBuilder *b, int nchilds, int axis)
|
||||
{
|
||||
int nth[3] = {0, (b->end - b->begin)/2, b->end-b->begin};
|
||||
split_leafs(b, nth, 2, axis);
|
||||
}
|
||||
|
||||
|
||||
void rtbuild_mean_split_largest_axis(RTBuilder *b, int nchilds)
|
||||
{
|
||||
int axis = calc_largest_axis(b);
|
||||
rtbuild_mean_split(b, nchilds, axis);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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]);
|
||||
}
|
||||
|
||||
static int sort_get_value(RTBuilder *b, int i)
|
||||
{
|
||||
float min[3], max[3];
|
||||
RE_rayobject_merge_bb(b->begin[i], min, max);
|
||||
return max[i];
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
if(fc > fb)
|
||||
return b;
|
||||
else
|
||||
{
|
||||
if(fc > fa)
|
||||
return c;
|
||||
else
|
||||
return a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
while (sort_get_value(b,i) < x) i++;
|
||||
j--;
|
||||
while (x < sort_get_value(b,j)) j--;
|
||||
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
|
||||
static int partition_nth_element(RTBuilder *b, int _begin, int _end, int n)
|
||||
{
|
||||
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;
|
||||
for(i=0; i < partitions-1; i++)
|
||||
{
|
||||
if(nth[i] >= nth[partitions])
|
||||
break;
|
||||
|
||||
partition_nth_element(b, nth[i], nth[i+1], nth[partitions] );
|
||||
}
|
||||
}
|
||||
@@ -180,7 +180,7 @@ RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi)
|
||||
if(re->r.raystructure == R_RAYSTRUCTURE_HIER_BVH_OCTREE)
|
||||
raytree = obr->raytree = RE_rayobject_octree_create( re->r.ocres, faces );
|
||||
else //if(re->r.raystructure == R_RAYSTRUCTURE_HIER_BVH_BVH)
|
||||
raytree = obr->raytree = RE_rayobject_bvh_create( faces );
|
||||
raytree = obr->raytree = RE_rayobject_blibvh_create( faces );
|
||||
|
||||
face = obr->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "ObjectRen faces");
|
||||
obr->rayobi = obi;
|
||||
@@ -240,7 +240,7 @@ static void makeraytree_hier(Render *re)
|
||||
num_objects++;
|
||||
|
||||
//Create raytree
|
||||
re->raytree = RE_rayobject_bvh_create( num_objects );
|
||||
re->raytree = RE_rayobject_blibvh_create( num_objects );
|
||||
|
||||
for(obi=re->instancetable.first; obi; obi=obi->next)
|
||||
if(is_raytraceable(re, obi))
|
||||
@@ -292,7 +292,7 @@ static void makeraytree_single(Render *re)
|
||||
if(re->r.raystructure == R_RAYSTRUCTURE_SINGLE_OCTREE)
|
||||
raytree = re->raytree = RE_rayobject_octree_create( re->r.ocres, faces );
|
||||
else //if(re->r.raystructure == R_RAYSTRUCTURE_SINGLE_BVH)
|
||||
raytree = re->raytree = RE_rayobject_bvh_create( faces );
|
||||
raytree = re->raytree = RE_rayobject_blibvh_create( faces );
|
||||
|
||||
face = re->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "Render ray faces");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user