*Added BLI_memarena on bvh

*Median split support on rtbuild
This commit is contained in:
2009-07-06 19:45:00 +00:00
parent aa12d2153f
commit c65a3e3166
3 changed files with 216 additions and 12 deletions

View File

@@ -65,8 +65,12 @@ int rtbuild_size(RTBuilder *b);
RTBuilder* rtbuild_get_child(RTBuilder *b, int child, RTBuilder *tmp);
/* Calculates child partitions and returns number of efectively needed partitions */
int rtbuild_mean_split(RTBuilder *b, int nchilds, int axis);
int rtbuild_mean_split_largest_axis(RTBuilder *b, int nchilds);
int rtbuild_get_largest_axis(RTBuilder *b);
int rtbuild_mean_split(RTBuilder *b, int nchilds, int axis);
int rtbuild_mean_split_largest_axis(RTBuilder *b, int nchilds);
int rtbuild_median_split(RTBuilder *b, float *separators, int nchilds, int axis);
int rtbuild_median_split_largest_axis(RTBuilder *b, int nchilds);
#endif

View File

@@ -32,10 +32,16 @@
#include "MEM_guardedalloc.h"
#include "BKE_utildefines.h"
#include "BLI_arithb.h"
#include "BLI_memarena.h"
#include "RE_raytrace.h"
#include "rayobject_rtbuild.h"
#include "rayobject.h"
#define DYNAMIC_ALLOC
#define SPLIT_OVERLAP_MEAN_LONGEST_AXIS /* objects mean split on the longest axis, childs BB are allowed to overlap */
//#define SPLIT_OVERLAP_MEDIAN_LONGEST_AXIS /* space median split on the longest axis, childs BB are allowed to overlap */
#define BVH_NCHILDS 4
typedef struct BVHTree BVHTree;
@@ -58,7 +64,11 @@ typedef struct BVHNode BVHNode;
struct BVHNode
{
BVHNode *child[BVH_NCHILDS];
#ifdef DYNAMIC_ALLOC
float bb[6];
#else
float *bb; //[6]; //[2][3];
#endif
int split_axis;
};
@@ -68,8 +78,12 @@ struct BVHTree
BVHNode *root;
#ifdef DYNAMIC_ALLOC
MemArena *node_arena;
#else
BVHNode *node_alloc, *node_next;
float *bb_alloc, *bb_next;
#endif
RTBuilder *builder;
};
@@ -83,8 +97,12 @@ RayObject *RE_rayobject_bvh_create(int size)
obj->rayobj.api = &bvh_api;
obj->root = NULL;
#ifdef DYNAMIC_ALLOC
obj->node_arena = NULL;
#else
obj->node_alloc = obj->node_next = NULL;
obj->bb_alloc = obj->bb_next = NULL;
#endif
obj->builder = rtbuild_create( size );
return RayObject_unalignRayAPI((RayObject*) obj);
@@ -95,11 +113,16 @@ static void bvh_free(BVHTree *obj)
if(obj->builder)
rtbuild_free(obj->builder);
#ifdef DYNAMIC_ALLOC
if(obj->node_arena)
BLI_memarena_free(obj->node_arena);
#else
if(obj->node_alloc)
MEM_freeN(obj->node_alloc);
if(obj->bb_alloc)
MEM_freeN(obj->bb_alloc);
#endif
MEM_freeN(obj);
}
@@ -190,6 +213,10 @@ static void bvh_add(BVHTree *obj, RayObject *ob)
static BVHNode *bvh_new_node(BVHTree *tree, int nid)
{
#ifdef DYNAMIC_ALLOC
BVHNode *node = BLI_memarena_alloc(tree->node_arena, sizeof(BVHNode));
return node;
#else
BVHNode *node = tree->node_alloc + nid - 1;
assert(RayObject_isAligned(node));
if(node+1 > tree->node_next)
@@ -199,6 +226,7 @@ static BVHNode *bvh_new_node(BVHTree *tree, int nid)
tree->bb_next += 6;
return node;
#endif
}
static int child_id(int pid, int nchild)
@@ -209,6 +237,9 @@ static int child_id(int pid, int nchild)
static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder, int nid)
{
if(rtbuild_size(builder) == 0)
return 0;
if(rtbuild_size(builder) == 1)
{
RayObject *child = builder->begin[0];
@@ -242,10 +273,17 @@ static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder, int nid)
else
{
int i;
int nc = rtbuild_mean_split_largest_axis(builder, BVH_NCHILDS);
RTBuilder tmp;
BVHNode *parent = bvh_new_node(tree, nid);
int nc;
#ifdef SPLIT_OVERLAP_MEAN_LONGEST_AXIS
nc = rtbuild_mean_split_largest_axis(builder, BVH_NCHILDS);
#elif defined(SPLIT_OVERLAP_MEDIAN_LONGEST_AXIS)
nc = rtbuild_median_split_largest_axis(builder, BVH_NCHILDS);
#else
assert(0);
#endif
INIT_MINMAX(parent->bb, parent->bb+3);
parent->split_axis = builder->split_axis;
@@ -261,31 +299,48 @@ static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder, int nid)
}
}
/*
static void bvh_info(BVHTree *obj)
{
printf("BVH: Used %d nodes\n", obj->node_next - obj->node_alloc);
}
*/
static void bvh_done(BVHTree *obj)
{
#ifdef DYNAMIC_ALLOC
int needed_nodes = (rtbuild_size(obj->builder)+1)*2;
if(needed_nodes > BLI_MEMARENA_STD_BUFSIZE)
needed_nodes = BLI_MEMARENA_STD_BUFSIZE;
obj->node_arena = BLI_memarena_new(needed_nodes);
BLI_memarena_use_malloc(obj->node_arena);
#else
int needed_nodes;
assert(obj->root == NULL && obj->node_alloc == NULL && obj->bb_alloc == NULL && obj->builder);
//TODO exact calculate needed nodes
needed_nodes = (rtbuild_size(obj->builder)+1)*2;
assert(needed_nodes > 0);
BVHNode *node = BLI_memarena_alloc(tree->node_arena, sizeof(BVHNode));
return node;
obj->node_alloc = (BVHNode*)MEM_mallocN( sizeof(BVHNode)*needed_nodes, "BVHTree.Nodes");
obj->node_next = obj->node_alloc;
obj->bb_alloc = (float*)MEM_mallocN( sizeof(float)*6*needed_nodes, "BVHTree.NodesBB");
obj->bb_next = obj->bb_alloc;
#endif
obj->root = bvh_rearrange( obj, obj->builder, 1 );
#ifndef DYNAMIC_ALLOC
assert(obj->node_alloc+needed_nodes >= obj->node_next);
#endif
rtbuild_free( obj->builder );
obj->builder = NULL;
assert(obj->node_alloc+needed_nodes >= obj->node_next);
}

View File

@@ -1,5 +1,6 @@
#include <assert.h>
#include <math.h>
#include <stdlib.h>
#include "rayobject_rtbuild.h"
#include "MEM_guardedalloc.h"
@@ -8,6 +9,7 @@
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 int split_leafs_by_plane(RTBuilder *b, int begin, int end, float plane);
static void rtbuild_init(RTBuilder *b, RayObject **begin, RayObject **end)
@@ -61,12 +63,9 @@ static void merge_bb(RTBuilder *b, float *min, float *max)
RE_rayobject_merge_bb(*index, min, max);
}
int rtbuild_get_largest_axis(RTBuilder *b)
static int largest_axis(float *min, float *max)
{
float min[3], max[3], sub[3];
INIT_MINMAX(min, max);
merge_bb( b, min, max);
float sub[3];
sub[0] = max[0]-min[0];
sub[1] = max[1]-min[1];
@@ -87,7 +86,22 @@ int rtbuild_get_largest_axis(RTBuilder *b)
}
}
int rtbuild_get_largest_axis(RTBuilder *b)
{
float min[3], max[3];
INIT_MINMAX(min, max);
merge_bb( b, min, max);
return largest_axis(min,max);
}
/*
int rtbuild_median_split(RTBuilder *b, int nchilds, int axis)
{
}
*/
//Left balanced tree
int rtbuild_mean_split(RTBuilder *b, int nchilds, int axis)
{
@@ -146,6 +160,123 @@ int rtbuild_mean_split_largest_axis(RTBuilder *b, int nchilds)
return rtbuild_mean_split(b, nchilds, axis);
}
/*
* "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];
float min[3], max[3];
INIT_MINMAX(min, max);
merge_bb( b, min, max);
la = largest_axis(min,max);
for(i=1; i<nchilds; i++)
separators[i-1] = (max[la]-min[la])*i / nchilds;
return rtbuild_median_split(b, separators, nchilds, la);
}
//Heuristics Splitter
typedef struct CostEvent CostEvent;
struct CostEvent
{
float key;
float value;
};
int costevent_cmp(const CostEvent *a, const CostEvent *b)
{
if(a->key < b->key) return -1;
if(a->key > b->key) return 1;
if(a->value < b->value) return -1;
if(a->value > b->value) return 1;
return 0;
}
void costevent_sort(CostEvent *begin, CostEvent *end)
{
//TODO introsort
qsort(begin, sizeof(*begin), end-begin, (int(*)(const void *, const void *)) costevent_cmp);
}
/*
int rtbuild_heuristic_split(RTBuilder *b, int nchilds)
{
int size = rtbuild_size(b);
if(size <= nchilds)
{
return rtbuild_mean_split_largest_axis(b, nchilds);
}
else
{
CostEvent *events[3], *ev[3];
RayObject *index;
int a = 0;
for(a = 0; a<3; a++)
ev[a] = events[a] = MEM_malloc( sizeof(CostEvent)*2*size, "RTBuilder.SweepSplitCostEvent" );
for(index = b->begin; b != b->end; b++)
{
float min[3], max[3];
INIT_MINMAX(min, max);
RE_rayobject_merge_bb(index, min, max);
for(a = 0; a<3; a++)
{
ev[a]->key = min[a];
ev[a]->value = 1;
ev[a]++;
ev[a]->key = max[a];
ev[a]->value = -1;
ev[a]++;
}
}
for(a = 0; a<3; a++)
costevent_sort(events[a], ev[a]);
for(a = 0; a<3; a++)
MEM_freeN(ev[a]);
}
}
*/
/*
* Helper code
@@ -268,3 +399,17 @@ static void split_leafs(RTBuilder *b, int *nth, int partitions, int split_axis)
partition_nth_element(b, nth[i], nth[i+1], nth[partitions] );
}
}
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;
}