*Added BLI_memarena on bvh
*Median split support on rtbuild
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user