Revision: 15934 http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=15934 Author: jaguarandi Date: 2008-08-03 17:37:24 +0200 (Sun, 03 Aug 2008)
Log Message: ----------- added openmp support for bvhtree build (max processes = tree_type) Modified Paths: -------------- branches/soc-2008-jaguarandi/source/blender/blenkernel/intern/shrinkwrap.c branches/soc-2008-jaguarandi/source/blender/blenlib/intern/BLI_kdopbvh.c branches/soc-2008-jaguarandi/source/blender/makesdna/DNA_constraint_types.h Modified: branches/soc-2008-jaguarandi/source/blender/blenkernel/intern/shrinkwrap.c =================================================================== --- branches/soc-2008-jaguarandi/source/blender/blenkernel/intern/shrinkwrap.c 2008-08-03 15:35:56 UTC (rev 15933) +++ branches/soc-2008-jaguarandi/source/blender/blenkernel/intern/shrinkwrap.c 2008-08-03 15:37:24 UTC (rev 15934) @@ -1024,7 +1024,7 @@ break; case MOD_SHRINKWRAP_NORMAL: - shrinkwrap_calc_normal_projection(&calc); + BENCH(shrinkwrap_calc_normal_projection(&calc)); break; case MOD_SHRINKWRAP_NEAREST_VERTEX: Modified: branches/soc-2008-jaguarandi/source/blender/blenlib/intern/BLI_kdopbvh.c =================================================================== --- branches/soc-2008-jaguarandi/source/blender/blenlib/intern/BLI_kdopbvh.c 2008-08-03 15:35:56 UTC (rev 15933) +++ branches/soc-2008-jaguarandi/source/blender/blenlib/intern/BLI_kdopbvh.c 2008-08-03 15:37:24 UTC (rev 15934) @@ -28,8 +28,9 @@ #include "math.h" #include <stdio.h> -#include <stdlib.h> +#include <stdlib.h> #include <string.h> +#include <assert.h> #include "MEM_guardedalloc.h" @@ -294,10 +295,32 @@ } } +// calculate max number of branches +int needed_branches(int tree_type, int leafs) +{ +#if 1 + //Worst case scenary ( return max(0, leafs-tree_type)+1 ) + if(leafs <= tree_type) + return 1; + else + return leafs-tree_type+1; + +#else + //If our bvh kdop is "almost perfect" + //TODO i dont trust the float arithmetic in here (and I am not sure this formula is according to our splitting method) + int i, numbranches = 0; + for(i = 1; i <= (int)ceil((float)((float)log(leafs)/(float)log(tree_type))); i++) + numbranches += (pow(tree_type, i) / tree_type); + + return numbranches; +#endif +} + + BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis) { BVHTree *tree; - int numbranches=0, i; + int numnodes, i; // theres not support for trees below binary-trees :P if(tree_type < 2) @@ -343,26 +366,25 @@ } - // calculate max number of branches, our bvh kdop is "almost perfect" - for(i = 1; i <= (int)ceil((float)((float)log(maxsize)/(float)log(tree_type))); i++) - numbranches += (pow(tree_type, i) / tree_type); + //Allocate arrays + numnodes = maxsize + needed_branches(tree_type, maxsize) + tree_type; + + tree->nodes = (BVHNode **)MEM_callocN(sizeof(BVHNode *)*numnodes, "BVHNodes"); - tree->nodes = (BVHNode **)MEM_callocN(sizeof(BVHNode *)*(numbranches+maxsize + tree_type), "BVHNodes"); - if(!tree->nodes) { MEM_freeN(tree); return NULL; } - tree->nodebv = (float*)MEM_callocN(sizeof(float)* axis * (numbranches+maxsize + tree_type), "BVHNodeBV"); + tree->nodebv = (float*)MEM_callocN(sizeof(float)* axis * numnodes, "BVHNodeBV"); if(!tree->nodebv) { MEM_freeN(tree->nodes); MEM_freeN(tree); } - tree->nodechild = (BVHNode**)MEM_callocN(sizeof(BVHNode*) * tree_type * (numbranches+maxsize + tree_type), "BVHNodeBV"); + tree->nodechild = (BVHNode**)MEM_callocN(sizeof(BVHNode*) * tree_type * numnodes, "BVHNodeBV"); if(!tree->nodechild) { MEM_freeN(tree->nodebv); @@ -370,7 +392,7 @@ MEM_freeN(tree); } - tree->nodearray = (BVHNode *)MEM_callocN(sizeof(BVHNode)*(numbranches+maxsize + tree_type), "BVHNodeArray"); + tree->nodearray = (BVHNode *)MEM_callocN(sizeof(BVHNode)* numnodes, "BVHNodeArray"); if(!tree->nodearray) { @@ -382,7 +404,7 @@ } //link the dynamic bv and child links - for(i=0; i< numbranches+maxsize + tree_type; i++) + for(i=0; i< numnodes; i++) { tree->nodearray[i].bv = tree->nodebv + i * axis; tree->nodearray[i].children = tree->nodechild + i * tree_type; @@ -422,6 +444,13 @@ bv[(2 * i) + 1] = newminmax; } } + + // inflate the bv with some epsilon + for (i = tree->start_axis; i < tree->stop_axis; i++) + { + bv[(2 * i)] -= tree->epsilon; // minimum + bv[(2 * i) + 1] += tree->epsilon; // maximum + } } // depends on the fact that the BVH's for each face is already build @@ -457,14 +486,13 @@ int BLI_bvhtree_insert(BVHTree *tree, int index, float *co, int numpoints) { - BVHNode *node= NULL; - int i; + BVHNode *node = NULL; // insert should only possible as long as tree->totbranch is 0 if(tree->totbranch > 0) return 0; - if(tree->totleaf+1 >= MEM_allocN_len(tree->nodes)) + if(tree->totleaf+1 >= MEM_allocN_len(tree->nodes)/sizeof(*(tree->nodes))) return 0; // TODO check if have enough nodes in array @@ -473,14 +501,6 @@ tree->totleaf++; create_kdop_hull(tree, node, co, numpoints, 0); - - // inflate the bv with some epsilon - for (i = tree->start_axis; i < tree->stop_axis; i++) - { - node->bv[(2 * i)] -= tree->epsilon; // minimum - node->bv[(2 * i) + 1] += tree->epsilon; // maximum - } - node->index= index; return 1; @@ -511,25 +531,24 @@ } } -static void bvh_div_nodes(BVHTree *tree, BVHNode *node, int start, int end, char lastaxis) +static void bvh_div_nodes(BVHTree *tree, BVHNode *node, int start, int end, int free_node_index) { - char laxis; - int i, tend; - BVHNode *tnode; - int slice = (end-start+tree->tree_type-1)/tree->tree_type; //division rounded up + int i; + + const char laxis = get_largest_axis(node->bv); //determine longest axis to split along + const int slice = (end-start)/tree->tree_type; //division rounded down + const int rest = (end-start)%tree->tree_type; //remainder of division - // Determine which axis to split along - laxis = get_largest_axis(node->bv); - //laxis = (lastaxis + 2) % tree->axis; // XYZ split + assert( node->totnode == 0 ); node->main_axis = laxis/2; // split nodes along longest axis - for (i=0; start < end; start += slice, i++) //i counts the current child + for (i=0; start < end; node->totnode = ++i) //i counts the current child { - tend = start + slice; + int tend = start + slice + (i < rest ? 1 : 0); - if(tend > end) tend = end; + assert( tend <= end); if(tend-start == 1) // ok, we have 1 left for this node { @@ -538,21 +557,86 @@ } else { - tnode = node->children[i] = tree->nodes[tree->totleaf + tree->totbranch] = &(tree->nodearray[tree->totbranch + tree->totleaf]); - tree->totbranch++; + BVHNode *tnode = node->children[i] = tree->nodes[free_node_index] = &(tree->nodearray[free_node_index]); +// printf("Used %d (%d)\n", free_node_index, tend-start); tnode->parent = node; if(tend != end) partition_nth_element(tree->nodes, start, end, tend, laxis); + refit_kdop_hull(tree, tnode, start, tend); - bvh_div_nodes(tree, tnode, start, tend, laxis); // not called on XYZ split + + bvh_div_nodes(tree, tnode, start, tend, free_node_index+1); + free_node_index += needed_branches(tree->tree_type, tend-start); } - node->totnode++; + start = tend; } return; } +static void omp_bvh_div_nodes(BVHTree *tree, BVHNode *node, int start, int end, int free_node_index) +{ + int i; + + const char laxis = get_largest_axis(node->bv); //determine longest axis to split along + const int slice = (end-start)/tree->tree_type; //division rounded down + const int rest = (end-start)%tree->tree_type; //remainder of division + + int omp_data_start[tree->tree_type]; + int omp_data_end [tree->tree_type]; + int omp_data_index[tree->tree_type]; + + assert( node->totnode == 0 ); + + node->main_axis = laxis/2; + + // split nodes along longest axis + for (i=0; start < end; node->totnode = ++i) //i counts the current child + { + //Split the rest from left to right (TODO: this doenst makes an optimal tree) + int tend = start + slice + (i < rest ? 1 : 0); + + assert( tend <= end); + + //save data for later OMP + omp_data_start[i] = start; + omp_data_end [i] = tend; + omp_data_index[i] = free_node_index; + + if(tend-start == 1) + { + node->children[i] = tree->nodes[start]; + node->children[i]->parent = node; + } + else + { + node->children[i] = tree->nodes[free_node_index] = &(tree->nodearray[free_node_index]); + + if(tend != end) + partition_nth_element(tree->nodes, start, end, tend, laxis); + + free_node_index += needed_branches(tree->tree_type, tend-start); + } + + start = tend; + } + +#pragma omp parallel for private(i) schedule(static) + for( i = 0; i < node->totnode; i++) + { + if(omp_data_end[i]-omp_data_start[i] > 1) + { + BVHNode *tnode = node->children[i]; + refit_kdop_hull(tree, tnode, omp_data_start[i], omp_data_end[i]); + bvh_div_nodes (tree, tnode, omp_data_start[i], omp_data_end[i], omp_data_index[i]+1); + } + } + + return; +} + + #if 0 static void verify_tree(BVHTree *tree) { @@ -604,23 +688,21 @@ void BLI_bvhtree_balance(BVHTree *tree) { - int i; - BVHNode *node; + assert(tree->totbranch == 0); + if(tree->totleaf != 0) + { + // create root node + BVHNode *node = tree->nodes[tree->totleaf] = &(tree->nodearray[tree->totleaf]); + tree->totbranch++; - if(tree->totleaf == 0) - return; - - // create root node - node = tree->nodes[tree->totleaf] = &(tree->nodearray[tree->totleaf]); - tree->totbranch++; - - // refit root bvh node - refit_kdop_hull(tree, tree->nodes[tree->totleaf], 0, tree->totleaf); // not called on XYZ split - // create + balance tree - bvh_div_nodes(tree, tree->nodes[tree->totleaf], 0, tree->totleaf, 0); - //BLI_bvhtree_update_tree(tree); // XYZ split - - // verify_tree(tree); + // refit root bvh node + refit_kdop_hull(tree, node, 0, tree->totleaf); + + // create + balance tree + omp_bvh_div_nodes(tree, node, 0, tree->totleaf, tree->totleaf+1); + tree->totbranch = needed_branches( tree->tree_type, tree->totleaf ); + // verify_tree(tree); + } } // overlap - is it possbile for 2 bv's to collide ? @@ -796,7 +878,6 @@ int BLI_bvhtree_update_node(BVHTree *tree, int index, float *co, float *co_moving, int numpoints) { BVHNode *node= NULL; - int i = 0; // check if index exists if(index > tree->totleaf) @@ -809,13 +890,6 @@ if(co_moving) create_kdop_hull(tree, node, co_moving, numpoints, 1); - // inflate the bv with some epsilon - for (i = tree->start_axis; i < tree->stop_axis; i++) - { - node->bv[(2 * i)] -= tree->epsilon; // minimum - node->bv[(2 * i) + 1] += tree->epsilon; // maximum - } - return 1; } Modified: branches/soc-2008-jaguarandi/source/blender/makesdna/DNA_constraint_types.h =================================================================== --- branches/soc-2008-jaguarandi/source/blender/makesdna/DNA_constraint_types.h 2008-08-03 15:35:56 UTC (rev 15933) @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org http://lists.blender.org/mailman/listinfo/bf-blender-cvs