From 0b7ab2f8ec1405b60262a13cf5d1ed671579dd69 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Mon, 5 May 2008 17:30:33 +0000 Subject: Merge from trunk svn merge -r 14626:14692 https://svn.blender.org/svnroot/bf-blender/trunk/blender --- source/blender/blenlib/BLI_blenlib.h | 3 +- source/blender/blenlib/intern/bpath.c | 4 +- source/blender/blenlib/intern/util.c | 122 ++++++++++++++++++++-------------- 3 files changed, 76 insertions(+), 53 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/BLI_blenlib.h b/source/blender/blenlib/BLI_blenlib.h index 33567d92c99..e24ccad12fb 100644 --- a/source/blender/blenlib/BLI_blenlib.h +++ b/source/blender/blenlib/BLI_blenlib.h @@ -150,7 +150,8 @@ void BLI_cleanup_dir(const char *relabase, char *dir); /* same as above but adds * @a framenum The framenumber to replace the frame code with. * @retval Returns true if the path was relative (started with "//"). */ -int BLI_convertstringcode(char *path, const char *basepath, int framenum); +int BLI_convertstringcode(char *path, const char *basepath); +int BLI_convertstringframe(char *path, int frame); void BLI_makestringcode(const char *relfile, char *file); diff --git a/source/blender/blenlib/intern/bpath.c b/source/blender/blenlib/intern/bpath.c index 66eb63c8dfd..79d3e487712 100644 --- a/source/blender/blenlib/intern/bpath.c +++ b/source/blender/blenlib/intern/bpath.c @@ -130,9 +130,9 @@ void BLI_bpathIterator_getPathExpanded( struct BPathIterator *bpi, char *path_ex libpath = BLI_bpathIterator_getLib(bpi); if (libpath) { /* check the files location relative to its library path */ - BLI_convertstringcode(path_expanded, libpath, G.scene->r.cfra); + BLI_convertstringcode(path_expanded, libpath); } else { /* local data, use the blend files path */ - BLI_convertstringcode(path_expanded, G.sce, G.scene->r.cfra); + BLI_convertstringcode(path_expanded, G.sce); } } char* BLI_bpathIterator_getLib( struct BPathIterator *bpi) { diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c index cdac1ba7061..c85849b5ed4 100644 --- a/source/blender/blenlib/intern/util.c +++ b/source/blender/blenlib/intern/util.c @@ -877,7 +877,7 @@ void BLI_cleanup_file(const char *relabase, char *dir) short a; char *start, *eind; if (relabase) { - BLI_convertstringcode(dir, relabase, 0); + BLI_convertstringcode(dir, relabase); } #ifdef WIN32 if(dir[0]=='.') { /* happens for example in FILE_MAIN */ @@ -1037,10 +1037,78 @@ void BLI_makestringcode(const char *relfile, char *file) } } -int BLI_convertstringcode(char *path, const char *basepath, int framenum) + +int BLI_convertstringframe(char *path, int frame) +{ + int ch_sta, ch_end, i; + /* Insert current frame: file### -> file001 */ + ch_sta = ch_end = 0; + for (i = 0; path[i] != '\0'; i++) { + if (path[i] == '\\' || path[i] == '/') { + ch_end = 0; /* this is a directory name, dont use any hashes we found */ + } else if (path[i] == '#') { + ch_sta = i; + ch_end = ch_sta+1; + while (path[ch_end] == '#') { + ch_end++; + } + i = ch_end-1; /* keep searching */ + + /* dont break, there may be a slash after this that invalidates the previous #'s */ + } + } + if (ch_end) { /* warning, ch_end is the last # +1 */ + /* Add the frame number? */ + short numlen, hashlen; + char tmp[FILE_MAX]; + + char format[16]; /* 6 is realistically the maxframe (300000), so 8 should be enough, but 16 to be safe. */ + if (((ch_end-1)-ch_sta) >= 16) { + ch_end = ch_sta+15; /* disallow values longer then 'format' can hold */ + } + + strcpy(tmp, path); + + numlen = 1 + (int)log10((double)frame); /* this is the number of chars in the number */ + hashlen = ch_end - ch_sta; + + sprintf(format, "%d", frame); + + if (numlen==hashlen) { /* simple case */ + memcpy(tmp+ch_sta, format, numlen); + } else if (numlen < hashlen) { + memcpy(tmp+ch_sta + (hashlen-numlen), format, numlen); /*dont copy the string terminator */ + memset(tmp+ch_sta, '0', hashlen-numlen); + } else { + /* number is longer then number of #'s */ + if (tmp[ch_end] == '\0') { /* hashes are last, no need to move any string*/ + /* bad juju - not testing string length here :/ */ + memcpy(tmp+ch_sta, format, numlen+1); /* add 1 to get the string terminator \0 */ + } else { + /* we need to move the end characters, reuse i */ + int j; + + i = strlen(tmp); /* +1 to copy the string terminator */ + j = i + (numlen-hashlen); /* from/to */ + + while (i >= ch_end) { + tmp[j] = tmp[i]; + i--; + j--; + } + memcpy(tmp + ch_sta, format, numlen); + } + } + strcpy(path, tmp); + return 1; + } + return 0; +} + + +int BLI_convertstringcode(char *path, const char *basepath) { int wasrelative; - int ch_sta, ch_end; char tmp[FILE_MAX]; char base[FILE_MAX]; char vol[3] = {'\0', '\0', '\0'}; @@ -1098,54 +1166,8 @@ int BLI_convertstringcode(char *path, const char *basepath, int framenum) MEM_freeN(filepart); } - - /* Insert current frame: file### -> file001 */ - ch_end = 0; - for (ch_sta = 0; tmp[ch_sta] != '\0'; ch_sta++) { - if (tmp[ch_sta] == '#') { - ch_end = ch_sta+1; - while (tmp[ch_end] == '#') { - ch_end++; - } - break; - } - } - if (ch_end) { /* warning, ch_end is the last # +1 */ - /* Add the frame number? */ - short numlen, hashlen; - char format[16]; /* 6 is realistically the maxframe (300000), so 8 should be enough, but 16 to be safe. */ - - numlen = 1 + (int)log10((double)framenum); /* this is the number of chars in the number */ - hashlen = ch_end - ch_sta; - - sprintf(format, "%d", framenum); - - if (numlen==hashlen) { /* simple case */ - memcpy(tmp+ch_sta, format, numlen); - } else if (numlen < hashlen) { - memcpy(tmp+ch_sta + (hashlen-numlen), format, numlen); /*dont copy the string terminator */ - memset(tmp+ch_sta, '0', hashlen-numlen); - } else { - /* number is longer then number of #'s */ - if (tmp[ch_end] == '\0') { /* hashes are last, no need to move any string*/ - /* bad juju - not testing string length here :/ */ - memcpy(tmp+ch_sta, format, numlen+1); /* add 1 to get the string terminator \0 */ - } else { - /* we need to move the end characters */ - int i = strlen(tmp); /* +1 to copy the string terminator */ - int j = i + (numlen-hashlen); /* from/to */ - while (i >= ch_end) { - tmp[j] = tmp[i]; - i--; - j--; - } - memcpy(tmp + ch_sta, format, numlen); - } - } - } - /* done with file### stuff */ - strcpy(path, tmp); + #ifdef WIN32 /* skip first two chars, which in case of absolute path will be drive:/blabla and -- cgit v1.2.3 From 859a05864cb1c16130175bc304ed1beb1589eb4e Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Wed, 14 May 2008 18:25:23 +0000 Subject: I'm considering using bvhtree for shrinkwrap but the build was considerable slower than kdtree as so i've made some improvements So basicly theres no shrinkwrap improvements for now... --- source/blender/blenlib/BLI_kdopbvh.h | 63 +++ source/blender/blenlib/intern/BLI_kdopbvh.c | 725 ++++++++++++++++++++++++++++ 2 files changed, 788 insertions(+) create mode 100644 source/blender/blenlib/BLI_kdopbvh.h create mode 100644 source/blender/blenlib/intern/BLI_kdopbvh.c (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h new file mode 100644 index 00000000000..c1240da6c3a --- /dev/null +++ b/source/blender/blenlib/BLI_kdopbvh.h @@ -0,0 +1,63 @@ +/** + * + * ***** 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) 2006 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Daniel Genrich, Andre Pinto + * + * ***** END GPL LICENSE BLOCK ***** + */ + + +#ifndef BLI_KDOPBVH_H +#define BLI_KDOPBVH_H + +#include + +struct BVHTree; +typedef struct BVHTree BVHTree; + +typedef struct BVHTreeOverlap { + int indexA; + int indexB; +} BVHTreeOverlap; + +BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis); +void BLI_bvhtree_free(BVHTree *tree); + +/* construct: first insert points, then call balance */ +int BLI_bvhtree_insert(BVHTree *tree, int index, float *co, int numpoints); +void BLI_bvhtree_balance(BVHTree *tree); + +/* update: first update points/nodes, then call update_tree to refit the bounding volumes */ +int BLI_bvhtree_update_node(BVHTree *tree, int index, float *co, float *co_moving, int numpoints); +void BLI_bvhtree_update_tree(BVHTree *tree); + +/* collision/overlap: check two trees if they overlap, alloc's *overlap with length of the int return value */ +BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result); + +float BLI_bvhtree_getepsilon(BVHTree *tree); + +#endif // BLI_KDOPBVH_H + + + + diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c new file mode 100644 index 00000000000..6a16efc060f --- /dev/null +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -0,0 +1,725 @@ +/* kdop.c +* +* +* ***** BEGIN GPL/BL DUAL 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. The Blender +* Foundation also sells licenses for use in proprietary software under +* the Blender License. See http://www.blender.org/BL/ for information +* about this. +* +* 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) Blender Foundation +* All rights reserved. +* +* The Original Code is: all of this file. +* +* Contributor(s): Daniel Genrich, Andre Pinto +* +* ***** END GPL/BL DUAL LICENSE BLOCK ***** +*/ + +#include "math.h" +#include +#include +#include + +#include "MEM_guardedalloc.h" + +#include "BKE_utildefines.h" + +#include "BLI_kdopbvh.h" +#include "BLI_arithb.h" + +#ifdef _OPENMP +#include +#endif + +#define node_get_bv(tree, node) ((node)->bv) +#define node_get_child(tree,node,i) ((node)->children[i]) + +typedef struct BVHNode +{ + struct BVHNode **children;// max 8 children + struct BVHNode *parent; // needed for bottom - top update + float *bv; // Bounding volume of all nodes, max 13 axis + int index; // face, edge, vertex index + char totnode; // how many nodes are used, used for speedup + char traversed; // how many nodes already traversed until this level? + char main_axis; // axis that was used to split childs +} BVHNode; + +struct BVHTree +{ + BVHNode **nodes; + float *nodebv; // pre-alloc bounding-volumes for nodes + BVHNode **nodechild; // pre-alloc childs for nodes + BVHNode *nodearray; // pre-alloc branchs + float epsilon; // epslion is used for inflation of the k-dop + int totleaf; // leafs + int totbranch; + char tree_type; // type of tree (4 => quadtree) + char axis; // kdop type (6 => OBB, 7 => AABB, ...) + char start_axis, stop_axis; // KDOP_AXES array indices according to axis +}; + +typedef struct BVHOverlapData +{ + BVHTree *tree1, *tree2; + BVHTreeOverlap *overlap; + int i, max_overlap; /* i is number of overlaps */ +} BVHOverlapData; +//////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////// +// Bounding Volume Hierarchy Definition +// +// Notes: From OBB until 26-DOP --> all bounding volumes possible, just choose type below +// Notes: You have to choose the type at compile time ITM +// Notes: You can choose the tree type --> binary, quad, octree, choose below +//////////////////////////////////////////////////////////////////////// + +static float KDOP_AXES[13][3] = +{ {1.0, 0, 0}, {0, 1.0, 0}, {0, 0, 1.0}, {1.0, 1.0, 1.0}, {1.0, -1.0, 1.0}, {1.0, 1.0, -1.0}, +{1.0, -1.0, -1.0}, {1.0, 1.0, 0}, {1.0, 0, 1.0}, {0, 1.0, 1.0}, {1.0, -1.0, 0}, {1.0, 0, -1.0}, +{0, 1.0, -1.0} +}; + +////////////////////////////////////////////////////////////////////////////////////////////////////// +// Introsort +// with permission deriven from the following Java code: +// http://ralphunden.net/content/tutorials/a-guide-to-introsort/ +// and he derived it from the SUN STL +////////////////////////////////////////////////////////////////////////////////////////////////////// + +static int bvh_partition(BVHNode **a, int lo, int hi, BVHNode * x, int axis) +{ + int i=lo, j=hi; + while (1) + { + while ((a[i])->bv[axis] < x->bv[axis]) i++; + j--; + while (x->bv[axis] < (a[j])->bv[axis]) j--; + if(!(i < j)) + return i; + SWAP( BVHNode* , a[i], a[j]); + i++; + } +} + +static BVHNode *bvh_medianof3(BVHNode **a, int lo, int mid, int hi, int axis) // returns Sortable +{ + if ((a[mid])->bv[axis] < (a[lo])->bv[axis]) + { + if ((a[hi])->bv[axis] < (a[mid])->bv[axis]) + return a[mid]; + else + { + if ((a[hi])->bv[axis] < (a[lo])->bv[axis]) + return a[hi]; + else + return a[lo]; + } + } + else + { + if ((a[hi])->bv[axis] < (a[mid])->bv[axis]) + { + if ((a[hi])->bv[axis] < (a[lo])->bv[axis]) + return a[lo]; + else + return a[hi]; + } + else + return a[mid]; + } +} + +//after a call to this function you can expect one of: +// every node to left of a[n] are smaller than it +// every node to the right of a[n-1] are greater than it +void partition_nth_element(BVHNode **a, int _begin, int _end, int n, int axis) +{ + int begin = _begin, end = _end; + while(begin < n && end >= n) + { + int mid = bvh_partition(a, begin, end, bvh_medianof3(a, begin, (begin+end-1)/2, end-1, axis), axis ); + + if(mid >= n) + end = n-1; + else + begin = n+1; + } + +} + +////////////////////////////////////////////////////////////////////////////////////////////////////// + +void BLI_bvhtree_free(BVHTree *tree) +{ + if(tree) + { + MEM_freeN(tree->nodes); + MEM_freeN(tree->nodearray); + MEM_freeN(tree->nodebv); + MEM_freeN(tree->nodechild); + MEM_freeN(tree); + } +} + +BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis) +{ + BVHTree *tree; + int numbranches=0, i; + + // only support up to octree + if(tree_type > 8) + return NULL; + + tree = (BVHTree *)MEM_callocN(sizeof(BVHTree), "BVHTree"); + + if(tree) + { + tree->epsilon = epsilon; + tree->tree_type = tree_type; + tree->axis = axis; + + if(axis == 26) + { + tree->start_axis = 0; + tree->stop_axis = 13; + } + else if(axis == 18) + { + tree->start_axis = 7; + tree->stop_axis = 13; + } + else if(axis == 14) + { + tree->start_axis = 0; + tree->stop_axis = 7; + } + else if(axis == 8) // AABB + { + tree->start_axis = 0; + tree->stop_axis = 4; + } + else if(axis == 6) // OBB + { + tree->start_axis = 0; + tree->stop_axis = 3; + } + else + { + MEM_freeN(tree); + return NULL; + } + + + // 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); + + 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"); + if(!tree->nodebv) + { + MEM_freeN(tree->nodes); + MEM_freeN(tree); + } + + tree->nodechild = (BVHNode**)MEM_callocN(sizeof(BVHNode*) * tree_type * (numbranches+maxsize + tree_type), "BVHNodeBV"); + if(!tree->nodechild) + { + MEM_freeN(tree->nodebv); + MEM_freeN(tree->nodes); + MEM_freeN(tree); + } + + tree->nodearray = (BVHNode *)MEM_callocN(sizeof(BVHNode)*(numbranches+maxsize + tree_type), "BVHNodeArray"); + + if(!tree->nodearray) + { + MEM_freeN(tree->nodechild); + MEM_freeN(tree->nodebv); + MEM_freeN(tree->nodes); + MEM_freeN(tree); + return NULL; + } + + //link the dynamic bv and child links + for(i=0; i< numbranches+maxsize + tree_type; i++) + { + tree->nodearray[i].bv = tree->nodebv + i * axis; + tree->nodearray[i].children = tree->nodechild + i * tree_type; + } + + } + + return tree; +} + +static void create_kdop_hull(BVHTree *tree, BVHNode *node, float *co, int numpoints, int moving) +{ + float newminmax; + float *bv = node_get_bv(tree, node); + int i, k; + + // don't init boudings for the moving case + if(!moving) + { + for (i = tree->start_axis; i < tree->stop_axis; i++) + { + bv[2*i] = FLT_MAX; + bv[2*i + 1] = -FLT_MAX; + } + } + + for(k = 0; k < numpoints; k++) + { + // for all Axes. + for (i = tree->start_axis; i < tree->stop_axis; i++) + { + newminmax = INPR(&co[k * 3], KDOP_AXES[i]); + if (newminmax < bv[2 * i]) + bv[2 * i] = newminmax; + if (newminmax > bv[(2 * i) + 1]) + bv[(2 * i) + 1] = newminmax; + } + } +} + +// depends on the fact that the BVH's for each face is already build +static void refit_kdop_hull(BVHTree *tree, BVHNode *node, int start, int end) +{ + float newmin,newmax; + int i, j; + float *bv = node_get_bv(tree, node); + + for (i = tree->start_axis; i < tree->stop_axis; i++) + { + bv[2*i] = FLT_MAX; + bv[2*i + 1] = -FLT_MAX; + } + + for (j = start; j < end; j++) + { + // for all Axes. + for (i = tree->start_axis; i < tree->stop_axis; i++) + { + newmin = tree->nodes[j]->bv[(2 * i)]; + if ((newmin < bv[(2 * i)])) + bv[(2 * i)] = newmin; + + newmax = tree->nodes[j]->bv[(2 * i) + 1]; + if ((newmax > bv[(2 * i) + 1])) + bv[(2 * i) + 1] = newmax; + } + } +} + +static inline void inflate_kdop_hull(BVHTree *tree, BVHNode *node) +{ + int i; + float *bv = node_get_bv(tree, node); + + for(i= tree->axis; i; i--) + { + *bv++ -= tree->epsilon; // minimum + *bv++ += tree->epsilon; // maximum + } +} + +// only supports x,y,z axis in the moment +// but we should use a plain and simple function here for speed sake +static char kdop_hull_get_largest_axis(BVHTree *tree, BVHNode *node) +{ + float *bv = node_get_bv(tree, node); + float middle_point[3]; + + middle_point[0] = (bv[1]) - (bv[0]); // x axis + middle_point[1] = (bv[3]) - (bv[2]); // y axis + middle_point[2] = (bv[5]) - (bv[4]); // z axis + if (middle_point[0] > middle_point[1]) + { + if (middle_point[0] > middle_point[2]) + return 1; // max x axis + else + return 5; // max z axis + } + else + { + if (middle_point[1] > middle_point[2]) + return 3; // max y axis + else + return 5; // max z axis + } +} + + +int BLI_bvhtree_insert(BVHTree *tree, int index, float *co, int numpoints) +{ + 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)) + return 0; + + // TODO check if have enough nodes in array + + node = tree->nodes[tree->totleaf] = &(tree->nodearray[tree->totleaf]); + tree->totleaf++; + + //create and inflate hull + create_kdop_hull(tree, node, co, numpoints, 0); + inflate_kdop_hull(tree, node); + + node->index= index; + + return 1; +} + + +static void bvh_div_nodes(BVHTree *tree, BVHNode *node, int start, int end, char lastaxis) +{ + char laxis; + int i, tend; + BVHNode *tnode; + int slice = (end-start+tree->tree_type-1)/tree->tree_type; //division rounded up + + // Determine which axis to split along + laxis = kdop_hull_get_largest_axis(tree, node); + + // split nodes along longest axis + for (i=0; start < end; start += slice, i++) //i counts the current child + { + tend = start + slice; + + + if(tend > end) tend = end; + + if(tend-start == 1) // ok, we have 1 left for this node + { + node->children[i] = tree->nodes[start]; + node->children[i]->parent = node; + } + else + { + partition_nth_element(tree->nodes, start, end, tend, laxis); + + tnode = node->children[i] = tree->nodes[tree->totleaf + tree->totbranch] = &(tree->nodearray[tree->totbranch + tree->totleaf]); + tree->totbranch++; + tnode->parent = node; + + refit_kdop_hull(tree, tnode, start, tend); + bvh_div_nodes(tree, tnode, start, tend, laxis); + } + node->totnode++; + } + + return; +} + +static void verify_tree(BVHTree *tree) +{ + int i, j, check = 0; + + // check the pointer list + for(i = 0; i < tree->totleaf; i++) + { + if(tree->nodes[i]->parent == NULL) + printf("Leaf has no parent: %d\n", i); + else + { + for(j = 0; j < tree->tree_type; j++) + { + if(tree->nodes[i]->parent->children[j] == tree->nodes[i]) + check = 1; + } + if(!check) + { + printf("Parent child relationship doesn't match: %d\n", i); + } + check = 0; + } + } + + // check the leaf list + for(i = 0; i < tree->totleaf; i++) + { + if(tree->nodearray[i].parent == NULL) + printf("Leaf has no parent: %d\n", i); + else + { + for(j = 0; j < tree->tree_type; j++) + { + if(tree->nodearray[i].parent->children[j] == &tree->nodearray[i]) + check = 1; + } + if(!check) + { + printf("Parent child relationship doesn't match: %d\n", i); + } + check = 0; + } + } + + printf("branches: %d, leafs: %d, total: %d\n", tree->totbranch, tree->totleaf, tree->totbranch + tree->totleaf); +} + +void BLI_bvhtree_balance(BVHTree *tree) +{ + BVHNode *node; + + 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); + // create + balance tree + bvh_div_nodes(tree, tree->nodes[tree->totleaf], 0, tree->totleaf, 0); + + // verify_tree(tree); +} + +// overlap - is it possbile for 2 bv's to collide ? +static int tree_overlap(BVHNode *node1, BVHNode *node2, int start_axis, int stop_axis) +{ + float *bv1 = node1->bv; + float *bv2 = node2->bv; + + float *bv1_end = bv1 + (stop_axis<<1); + + bv1 += start_axis<<1; + bv2 += start_axis<<1; + + // test all axis if min + max overlap + for (; bv1 != bv1_end; bv1+=2, bv2+=2) + { + if ((*(bv1) > *(bv2 + 1)) || (*(bv2) > *(bv1 + 1))) + return 0; + } + + return 1; +} + +static void traverse(BVHOverlapData *data, BVHNode *node1, BVHNode *node2) +{ + int j; + + if(tree_overlap(node1, node2, MIN2(data->tree1->start_axis, data->tree2->start_axis), MIN2(data->tree1->stop_axis, data->tree2->stop_axis))) + { + // check if node1 is a leaf + if(node1->index) + { + // check if node2 is a leaf + if(node2->index) + { + + if(node1 == node2) + { + return; + } + + if(data->i >= data->max_overlap) + { + // try to make alloc'ed memory bigger + data->overlap = realloc(data->overlap, sizeof(BVHTreeOverlap)*data->max_overlap*2); + + if(!data->overlap) + { + printf("Out of Memory in traverse\n"); + return; + } + data->max_overlap *= 2; + } + + // both leafs, insert overlap! + data->overlap[data->i].indexA = node1->index; + data->overlap[data->i].indexB = node2->index; + + data->i++; + } + else + { + for(j = 0; j < data->tree2->tree_type; j++) + { + if(node2->children[j]) + traverse(data, node1, node2->children[j]); + } + } + } + else + { + + for(j = 0; j < data->tree2->tree_type; j++) + { + if(node1->children[j]) + traverse(data, node1->children[j], node2); + } + } + } + return; +} + +BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result) +{ + int j, total = 0; + BVHTreeOverlap *overlap = NULL, *to = NULL; + BVHOverlapData *data[tree1->tree_type]; + + // check for compatibility of both trees (can't compare 14-DOP with 18-DOP) + if((tree1->axis != tree2->axis) && ((tree1->axis == 14) || tree2->axis == 14)) + return 0; + + // fast check root nodes for collision before doing big splitting + traversal + if(!tree_overlap(tree1->nodes[tree1->totleaf], tree2->nodes[tree2->totleaf], MIN2(tree1->start_axis, tree2->start_axis), MIN2(tree1->stop_axis, tree2->stop_axis))) + return 0; + + for(j = 0; j < tree1->tree_type; j++) + { + data[j] = (BVHOverlapData *)MEM_callocN(sizeof(BVHOverlapData), "BVHOverlapData"); + + // init BVHOverlapData + data[j]->overlap = (BVHTreeOverlap *)malloc(sizeof(BVHTreeOverlap)*MAX2(tree1->totleaf, tree2->totleaf)); + data[j]->tree1 = tree1; + data[j]->tree2 = tree2; + data[j]->max_overlap = MAX2(tree1->totleaf, tree2->totleaf); + data[j]->i = 0; + } + +#pragma omp parallel for private(j) schedule(static) + for(j = 0; j < tree1->tree_type; j++) + { + traverse(data[j], tree1->nodes[tree1->totleaf]->children[j], tree2->nodes[tree2->totleaf]); + } + + for(j = 0; j < tree1->tree_type; j++) + total += data[j]->i; + + to = overlap = (BVHTreeOverlap *)MEM_callocN(sizeof(BVHTreeOverlap)*total, "BVHTreeOverlap"); + + for(j = 0; j < tree1->tree_type; j++) + { + memcpy(to, data[j]->overlap, data[j]->i*sizeof(BVHTreeOverlap)); + to+=data[j]->i; + } + + for(j = 0; j < tree1->tree_type; j++) + { + free(data[j]->overlap); + MEM_freeN(data[j]); + } + + (*result) = total; + return overlap; +} + + +// bottom up update of bvh tree: +// join the 4 children here +static void node_join(BVHTree *tree, BVHNode *node) +{ + int i, j; + + for (i = tree->start_axis; i < tree->stop_axis; i++) + { + node->bv[2*i] = FLT_MAX; + node->bv[2*i + 1] = -FLT_MAX; + } + + for (i = 0; i < tree->tree_type; i++) + { + if (node->children[i]) + { + for (j = tree->start_axis; j < tree->stop_axis; j++) + { + // update minimum + if (node->children[i]->bv[(2 * j)] < node->bv[(2 * j)]) + node->bv[(2 * j)] = node->children[i]->bv[(2 * j)]; + + // update maximum + if (node->children[i]->bv[(2 * j) + 1] > node->bv[(2 * j) + 1]) + node->bv[(2 * j) + 1] = node->children[i]->bv[(2 * j) + 1]; + } + } + else + break; + } +} + +// call before BLI_bvhtree_update_tree() +int BLI_bvhtree_update_node(BVHTree *tree, int index, float *co, float *co_moving, int numpoints) +{ + BVHNode *node= NULL; + + // check if index exists + if(index > tree->totleaf) + return 0; + + node = tree->nodearray + index; + + create_kdop_hull(tree, node, co, numpoints, 0); + + if(co_moving) + create_kdop_hull(tree, node, co_moving, numpoints, 1); + + // inflate the bv with some epsilon + inflate_kdop_hull(tree, node); + + return 1; +} + +// call BLI_bvhtree_update_node() first for every node/point/triangle +void BLI_bvhtree_update_tree(BVHTree *tree) +{ + BVHNode *leaf, *parent; + + // reset tree traversing flag + for (leaf = tree->nodearray + tree->totleaf; leaf != tree->nodearray + tree->totleaf + tree->totbranch; leaf++) + leaf->traversed = 0; + + for (leaf = tree->nodearray; leaf != tree->nodearray + tree->totleaf; leaf++) + { + for (parent = leaf->parent; parent; parent = parent->parent) + { + parent->traversed++; // we tried to go up in hierarchy + if (parent->traversed < parent->totnode) + break; // we do not need to check further + else + node_join(tree, parent); + } + } +} + +float BLI_bvhtree_getepsilon(BVHTree *tree) +{ + return tree->epsilon; +} + -- cgit v1.2.3 From fd53876faf4dbf50946729deef20c5e6264b5d20 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Sun, 25 May 2008 13:44:55 +0000 Subject: Merge bvh tree from cloth branch --- source/blender/blenlib/intern/BLI_kdopbvh.c | 170 +++++++++++++++++++++++++--- 1 file changed, 152 insertions(+), 18 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 6a16efc060f..4b72085a2b1 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -49,6 +49,38 @@ #define node_get_bv(tree, node) ((node)->bv) #define node_get_child(tree,node,i) ((node)->children[i]) +/* Util macros */ +#define TO_STR(a) #a +#define JOIN(a,b) a##b + +/* Benchmark macros */ +#if 1 + +#define BENCH(a) \ + do { \ + clock_t _clock_init = clock(); \ + (a); \ + printf("%s: %fms\n", #a, (float)(clock()-_clock_init)*1000/CLOCKS_PER_SEC); \ +} while(0) + +#define BENCH_VAR(name) clock_t JOIN(_bench_step,name) = 0, JOIN(_bench_total,name) = 0 +#define BENCH_BEGIN(name) JOIN(_bench_step, name) = clock() +#define BENCH_END(name) JOIN(_bench_total,name) += clock() - JOIN(_bench_step,name) +#define BENCH_RESET(name) JOIN(_bench_total, name) = 0 +#define BENCH_REPORT(name) printf("%s: %fms\n", TO_STR(name), JOIN(_bench_total,name)*1000.0f/CLOCKS_PER_SEC) + +#else + +#define BENCH(a) (a) +#define BENCH_VAR(name) +#define BENCH_BEGIN(name) +#define BENCH_END(name) +#define BENCH_RESET(name) +#define BENCH_REPORT(name) + +#endif + + typedef struct BVHNode { struct BVHNode **children;// max 8 children @@ -63,15 +95,15 @@ typedef struct BVHNode struct BVHTree { BVHNode **nodes; - float *nodebv; // pre-alloc bounding-volumes for nodes - BVHNode **nodechild; // pre-alloc childs for nodes BVHNode *nodearray; // pre-alloc branchs + BVHNode **nodechild; // pre-alloc childs for nodes + float *nodebv; // pre-alloc bounding-volumes for nodes float epsilon; // epslion is used for inflation of the k-dop int totleaf; // leafs int totbranch; char tree_type; // type of tree (4 => quadtree) char axis; // kdop type (6 => OBB, 7 => AABB, ...) - char start_axis, stop_axis; // KDOP_AXES array indices according to axis + char start_axis, stop_axis; // KDOP_AXES array indices according to axis char start_axis, stop_axis; // KDOP_AXES array indices according to axis }; typedef struct BVHOverlapData @@ -103,6 +135,34 @@ static float KDOP_AXES[13][3] = // http://ralphunden.net/content/tutorials/a-guide-to-introsort/ // and he derived it from the SUN STL ////////////////////////////////////////////////////////////////////////////////////////////////////// +static int size_threshold = 16; +/* +* Common methods for all algorithms +*/ +static int floor_lg(int a) +{ + return (int)(floor(log(a)/log(2))); +} + +/* +* Insertion sort algorithm +*/ +static void bvh_insertionsort(BVHNode **a, int lo, int hi, int axis) +{ + int i,j; + BVHNode *t; + for (i=lo; i < hi; i++) + { + j=i; + t = a[i]; + while((j!=lo) && (t->bv[axis] < (a[j-1])->bv[axis])) + { + a[j] = a[j-1]; + j--; + } + a[j] = t; + } +} static int bvh_partition(BVHNode **a, int lo, int hi, BVHNode * x, int axis) { @@ -119,6 +179,41 @@ static int bvh_partition(BVHNode **a, int lo, int hi, BVHNode * x, int axis) } } +/* +* Heapsort algorithm +*/ +static void bvh_downheap(BVHNode **a, int i, int n, int lo, int axis) +{ + BVHNode * d = a[lo+i-1]; + int child; + while (i<=n/2) + { + child = 2*i; + if ((child < n) && ((a[lo+child-1])->bv[axis] < (a[lo+child])->bv[axis])) + { + child++; + } + if (!(d->bv[axis] < (a[lo+child-1])->bv[axis])) break; + a[lo+i-1] = a[lo+child-1]; + i = child; + } + a[lo+i-1] = d; +} + +static void bvh_heapsort(BVHNode **a, int lo, int hi, int axis) +{ + int n = hi-lo, i; + for (i=n/2; i>=1; i=i-1) + { + bvh_downheap(a, i,n,lo, axis); + } + for (i=n; i>1; i=i-1) + { + SWAP(BVHNode*, a[lo],a[lo+i-1]); + bvh_downheap(a, 1,i-1,lo, axis); + } +} + static BVHNode *bvh_medianof3(BVHNode **a, int lo, int mid, int hi, int axis) // returns Sortable { if ((a[mid])->bv[axis] < (a[lo])->bv[axis]) @@ -146,23 +241,57 @@ static BVHNode *bvh_medianof3(BVHNode **a, int lo, int mid, int hi, int axis) // return a[mid]; } } - -//after a call to this function you can expect one of: -// every node to left of a[n] are smaller than it -// every node to the right of a[n-1] are greater than it -void partition_nth_element(BVHNode **a, int _begin, int _end, int n, int axis) +/* +* Quicksort algorithm modified for Introsort +*/ +static void bvh_introsort_loop (BVHNode **a, int lo, int hi, int depth_limit, int axis) { - int begin = _begin, end = _end; - while(begin < n && end >= n) + int p; + + while (hi-lo > size_threshold) { - int mid = bvh_partition(a, begin, end, bvh_medianof3(a, begin, (begin+end-1)/2, end-1, axis), axis ); + if (depth_limit == 0) + { + bvh_heapsort(a, lo, hi, axis); + return; + } + depth_limit=depth_limit-1; + p=bvh_partition(a, lo, hi, bvh_medianof3(a, lo, lo+((hi-lo)/2)+1, hi-1, axis), axis); + bvh_introsort_loop(a, p, hi, depth_limit, axis); + hi=p; + } +} - if(mid >= n) - end = n-1; - else - begin = n+1; +static void sort(BVHNode **a0, int begin, int end, int axis) +{ + if (begin < end) + { + BVHNode **a=a0; + bvh_introsort_loop(a, begin, end, 2*floor_lg(end-begin), axis); + bvh_insertionsort(a, begin, end, axis); } +} +void sort_along_axis(BVHTree *tree, int start, int end, int axis) +{ + sort(tree->nodes, start, end, axis); +} +//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 +int partition_nth_element(BVHNode **a, int _begin, int _end, int n, int axis){ + int begin = _begin, end = _end, cut; + while(end-begin > 3) + { + cut = bvh_partition(a, begin, end, bvh_medianof3(a, begin, (begin+end)/2, end-1, axis), axis ); + if(cut <= n) + begin = cut; + else + end = cut; + } + bvh_insertionsort(a, begin, end, axis); + + return n; } ////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -278,6 +407,7 @@ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis) return tree; } + static void create_kdop_hull(BVHTree *tree, BVHNode *node, float *co, int numpoints, int moving) { float newminmax; @@ -417,7 +547,6 @@ static void bvh_div_nodes(BVHTree *tree, BVHNode *node, int start, int end, char { tend = start + slice; - if(tend > end) tend = end; if(tend-start == 1) // ok, we have 1 left for this node @@ -432,7 +561,9 @@ static void bvh_div_nodes(BVHTree *tree, BVHNode *node, int start, int end, char tnode = node->children[i] = tree->nodes[tree->totleaf + tree->totbranch] = &(tree->nodearray[tree->totbranch + tree->totleaf]); tree->totbranch++; 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); } @@ -592,7 +723,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result) { int j, total = 0; BVHTreeOverlap *overlap = NULL, *to = NULL; - BVHOverlapData *data[tree1->tree_type]; + BVHOverlapData **data; // check for compatibility of both trees (can't compare 14-DOP with 18-DOP) if((tree1->axis != tree2->axis) && ((tree1->axis == 14) || tree2->axis == 14)) @@ -601,6 +732,8 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result) // fast check root nodes for collision before doing big splitting + traversal if(!tree_overlap(tree1->nodes[tree1->totleaf], tree2->nodes[tree2->totleaf], MIN2(tree1->start_axis, tree2->start_axis), MIN2(tree1->stop_axis, tree2->stop_axis))) return 0; + + *data = MEM_callocN(sizeof(BVHOverlapData *)* tree1->tree_type, "BVHOverlapData_star"); for(j = 0; j < tree1->tree_type; j++) { @@ -636,6 +769,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result) free(data[j]->overlap); MEM_freeN(data[j]); } + MEM_freeN(*data); (*result) = total; return overlap; -- cgit v1.2.3 From ad2fecf2660e9da7748ab6cce37569e1bc2a11e1 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Sun, 25 May 2008 15:43:18 +0000 Subject: Added BVH nearest neighbour code, for now only works in 6-dop and finds the node with the nearest bounding volume. I'll work on making it more generic. So far it querys faster than kdtree, but building the tree is slower. And bvhtree NN uses an heuristic based on the last match. Shrinkwrap (OBCube)24578 over (OBSuzanne)31658 kdtree build: 30.000000ms query: 1360.000000ms bvhtree build: 140.000000ms query: 490.000000ms Shrinkwrap now uses bvhtree (binary tree, 6dop) for nearest vertex. --- source/blender/blenlib/BLI_kdopbvh.h | 9 +++ source/blender/blenlib/intern/BLI_kdopbvh.c | 120 +++++++++++++++++++++++++++- 2 files changed, 127 insertions(+), 2 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h index c1240da6c3a..18ecfe7a2e9 100644 --- a/source/blender/blenlib/BLI_kdopbvh.h +++ b/source/blender/blenlib/BLI_kdopbvh.h @@ -40,6 +40,12 @@ typedef struct BVHTreeOverlap { int indexB; } BVHTreeOverlap; +typedef struct BVHTreeNearest +{ + int index; /* the index of the nearest found (untouched if none is found within a dist radius from the given coordinates) */ + float dist; /* squared distance to search arround */ +} BVHTreeNearest; + BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis); void BLI_bvhtree_free(BVHTree *tree); @@ -56,6 +62,9 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result) float BLI_bvhtree_getepsilon(BVHTree *tree); +/* find nearest node to the given coordinates (if nearest is given it will only search nodes where square distance is smaller than nearest->dist) */ +int BLI_bvhtree_find_nearest(BVHTree *tree, float *co, BVHTreeNearest *nearest); + #endif // BLI_KDOPBVH_H diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 4b72085a2b1..c510f9afb00 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -112,6 +112,14 @@ typedef struct BVHOverlapData BVHTreeOverlap *overlap; int i, max_overlap; /* i is number of overlaps */ } BVHOverlapData; + +typedef struct BVHNearestData +{ + BVHTree *tree; + float *co; + float proj[13]; //coordinates projection over axis + BVHTreeNearest nearest; +} BVHNearestData; //////////////////////////////////////// @@ -340,12 +348,12 @@ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis) tree->start_axis = 0; tree->stop_axis = 7; } - else if(axis == 8) // AABB + else if(axis == 8) { tree->start_axis = 0; tree->stop_axis = 4; } - else if(axis == 6) // OBB + else if(axis == 6) // AABB { tree->start_axis = 0; tree->stop_axis = 3; @@ -857,3 +865,111 @@ float BLI_bvhtree_getepsilon(BVHTree *tree) return tree->epsilon; } + +//Nearest neighbour +static float squared_dist(const float *a, const float *b) +{ + float tmp[3]; + VECSUB(tmp, a, b); + return INPR(tmp, tmp); +} + +static float calc_nearest_point(BVHNearestData *data, BVHNode *node, float *nearest) +{ + int i; + const float *bv = node_get_bv(data->tree, node); + + //nearest on AABB hull + for(i=0; i != 3; i++, bv += 2) + { + if(bv[0] > data->proj[i]) + nearest[i] = bv[0]; + else if(bv[1] < data->proj[i]) + nearest[i] = bv[1]; + else + nearest[i] = data->proj[i]; + } + +/* + //nearest on a general hull + VECCOPY(nearest, data->co); + for(i = data->tree->start_axis; i != data->tree->stop_axis; i++, bv+=2) + { + float proj = INPR( nearest, KDOP_AXES[i]); + float dl = bv[0] - proj; + float du = bv[1] - proj; + + if(dl > 0) + { + VECADDFAC(nearest, nearest, KDOP_AXES[i], dl); + } + else if(du < 0) + { + VECADDFAC(nearest, nearest, KDOP_AXES[i], du); + } + } +*/ + return squared_dist(data->co, nearest); +} + + +static void dfs_find_nearest(BVHNearestData *data, BVHNode *node) +{ + int i; + float nearest[3], sdist; + + sdist = calc_nearest_point(data, node, nearest); + + if(sdist >= data->nearest.dist) return; + + if(node->totnode == 0) + { + data->nearest.dist = sdist; + data->nearest.index = node->index; + } + else + { + for(i=0; i != node->totnode; i++) + { + dfs_find_nearest(data, node->children[i]); + } + } +} + +int BLI_bvhtree_find_nearest(BVHTree *tree, float *co, BVHTreeNearest *nearest) +{ + int i; + + BVHNearestData data; + + //init data to search + data.tree = tree; + data.co = co; + + for(i = data.tree->start_axis; i != data.tree->stop_axis; i++) + { + data.proj[i] = INPR(data.co, KDOP_AXES[i]); + } + + if(nearest) + { + memcpy( &data.nearest , nearest, sizeof(*nearest) ); + } + else + { + data.nearest.index = -1; + data.nearest.dist = FLT_MAX; + } + + //dfs search + dfs_find_nearest(&data, tree->nodes[tree->totleaf] ); + + //copy back results + if(nearest) + { + memcpy(nearest, &data.nearest, sizeof(*nearest)); + } + + return data.nearest.index; +} + -- cgit v1.2.3 From ad3f4c89aa3386f7be71444f882ba7e68711459e Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Sun, 25 May 2008 15:47:54 +0000 Subject: Merge BVH tree fixes from cloth branch svn merge -r 14954:14963 https://svn.blender.org/svnroot/bf-blender/branches/cloth/blender/source/blender/blenlib/BLI_kdopbvh.h svn merge -r 14954:14963 https://svn.blender.org/svnroot/bf-blender/branches/cloth/blender/source/blender/blenlib/intern/BLI_kdopbvh.c --- source/blender/blenlib/intern/BLI_kdopbvh.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index c510f9afb00..97a0e305e89 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -741,7 +741,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result) if(!tree_overlap(tree1->nodes[tree1->totleaf], tree2->nodes[tree2->totleaf], MIN2(tree1->start_axis, tree2->start_axis), MIN2(tree1->stop_axis, tree2->stop_axis))) return 0; - *data = MEM_callocN(sizeof(BVHOverlapData *)* tree1->tree_type, "BVHOverlapData_star"); + data = MEM_callocN(sizeof(BVHOverlapData *)* tree1->tree_type, "BVHOverlapData_star"); for(j = 0; j < tree1->tree_type; j++) { @@ -777,7 +777,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result) free(data[j]->overlap); MEM_freeN(data[j]); } - MEM_freeN(*data); + MEM_freeN(data); (*result) = total; return overlap; -- cgit v1.2.3 From 4383743acea4d30625b3a4a8cb9e77ad883fd79e Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Mon, 26 May 2008 21:57:53 +0000 Subject: Fixed some compile erros under msvc (thanks lguillaume) Fixed object dependency (thanks ZanQdo for pointing it out) Make some code cleaner (preparing for adding bvh trees on nearest surface) --- source/blender/blenlib/BLI_kdopbvh.h | 5 +++-- source/blender/blenlib/intern/BLI_kdopbvh.c | 7 ++++--- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h index 18ecfe7a2e9..6a91e0e283b 100644 --- a/source/blender/blenlib/BLI_kdopbvh.h +++ b/source/blender/blenlib/BLI_kdopbvh.h @@ -42,8 +42,9 @@ typedef struct BVHTreeOverlap { typedef struct BVHTreeNearest { - int index; /* the index of the nearest found (untouched if none is found within a dist radius from the given coordinates) */ - float dist; /* squared distance to search arround */ + int index; /* the index of the nearest found (untouched if none is found within a dist radius from the given coordinates) */ + float nearest[3]; /* nearest coordinates (untouched it none is found within a dist radius from the given coordinates) */ + float dist; /* squared distance to search arround */ } BVHTreeNearest; BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis); diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 97a0e305e89..b3cd00c0042 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -7,7 +7,7 @@ * 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. The Blender -* Foundation also sells licenses for use in proprietary software under +* Foundation also sells licenses for usinle in proprietary software under * the Blender License. See http://www.blender.org/BL/ for information * about this. * @@ -475,7 +475,7 @@ static void refit_kdop_hull(BVHTree *tree, BVHNode *node, int start, int end) } } -static inline void inflate_kdop_hull(BVHTree *tree, BVHNode *node) +static void inflate_kdop_hull(BVHTree *tree, BVHNode *node) { int i; float *bv = node_get_bv(tree, node); @@ -924,8 +924,9 @@ static void dfs_find_nearest(BVHNearestData *data, BVHNode *node) if(node->totnode == 0) { - data->nearest.dist = sdist; data->nearest.index = node->index; + VECCOPY(data->nearest.nearest, nearest); + data->nearest.dist = sdist; } else { -- cgit v1.2.3 From 2a0a999a7146ff2a3a2726e62b976f5e49da1872 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Tue, 27 May 2008 18:32:23 +0000 Subject: Added bvh nearest neighbour for nearest surface shrinkwrap --- source/blender/blenlib/BLI_kdopbvh.h | 6 +++++- source/blender/blenlib/intern/BLI_kdopbvh.c | 20 ++++++++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h index 6a91e0e283b..055c2754a21 100644 --- a/source/blender/blenlib/BLI_kdopbvh.h +++ b/source/blender/blenlib/BLI_kdopbvh.h @@ -47,6 +47,10 @@ typedef struct BVHTreeNearest float dist; /* squared distance to search arround */ } BVHTreeNearest; +/* returns square of the minimum distance from given co to the node, nearest point is stored on nearest */ +typedef float (*BVHTree_NearestPointCallback) (void *userdata, int index, const float *co, float *nearest); + + BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis); void BLI_bvhtree_free(BVHTree *tree); @@ -64,7 +68,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result) float BLI_bvhtree_getepsilon(BVHTree *tree); /* find nearest node to the given coordinates (if nearest is given it will only search nodes where square distance is smaller than nearest->dist) */ -int BLI_bvhtree_find_nearest(BVHTree *tree, float *co, BVHTreeNearest *nearest); +int BLI_bvhtree_find_nearest(BVHTree *tree, float *co, BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata); #endif // BLI_KDOPBVH_H diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index b3cd00c0042..ef7c13a8918 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -117,6 +117,8 @@ typedef struct BVHNearestData { BVHTree *tree; float *co; + BVHTree_NearestPointCallback callback; + void *userdata; float proj[13]; //coordinates projection over axis BVHTreeNearest nearest; } BVHNearestData; @@ -919,25 +921,32 @@ static void dfs_find_nearest(BVHNearestData *data, BVHNode *node) float nearest[3], sdist; sdist = calc_nearest_point(data, node, nearest); - if(sdist >= data->nearest.dist) return; if(node->totnode == 0) { + if(data->callback) + sdist = data->callback(data->userdata , node->index, data->co, nearest); + + if(sdist >= data->nearest.dist) return; + data->nearest.index = node->index; VECCOPY(data->nearest.nearest, nearest); data->nearest.dist = sdist; } else { - for(i=0; i != node->totnode; i++) + if(sdist < data->nearest.dist) { - dfs_find_nearest(data, node->children[i]); + for(i=0; i != node->totnode; i++) + { + dfs_find_nearest(data, node->children[i]); + } } } } -int BLI_bvhtree_find_nearest(BVHTree *tree, float *co, BVHTreeNearest *nearest) +int BLI_bvhtree_find_nearest(BVHTree *tree, float *co, BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata) { int i; @@ -947,6 +956,9 @@ int BLI_bvhtree_find_nearest(BVHTree *tree, float *co, BVHTreeNearest *nearest) data.tree = tree; data.co = co; + data.callback = callback; + data.userdata = userdata; + for(i = data.tree->start_axis; i != data.tree->stop_axis; i++) { data.proj[i] = INPR(data.co, KDOP_AXES[i]); -- cgit v1.2.3 From db650f1be9d73b9c4d2e200a91a87fd5b2bb24d8 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Tue, 3 Jun 2008 19:20:57 +0000 Subject: Removed BLI_kdopbvh --- source/blender/blenlib/BLI_kdopbvh.h | 77 --- source/blender/blenlib/intern/BLI_kdopbvh.c | 988 ---------------------------- 2 files changed, 1065 deletions(-) delete mode 100644 source/blender/blenlib/BLI_kdopbvh.h delete mode 100644 source/blender/blenlib/intern/BLI_kdopbvh.c (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h deleted file mode 100644 index 055c2754a21..00000000000 --- a/source/blender/blenlib/BLI_kdopbvh.h +++ /dev/null @@ -1,77 +0,0 @@ -/** - * - * ***** 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) 2006 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): Daniel Genrich, Andre Pinto - * - * ***** END GPL LICENSE BLOCK ***** - */ - - -#ifndef BLI_KDOPBVH_H -#define BLI_KDOPBVH_H - -#include - -struct BVHTree; -typedef struct BVHTree BVHTree; - -typedef struct BVHTreeOverlap { - int indexA; - int indexB; -} BVHTreeOverlap; - -typedef struct BVHTreeNearest -{ - int index; /* the index of the nearest found (untouched if none is found within a dist radius from the given coordinates) */ - float nearest[3]; /* nearest coordinates (untouched it none is found within a dist radius from the given coordinates) */ - float dist; /* squared distance to search arround */ -} BVHTreeNearest; - -/* returns square of the minimum distance from given co to the node, nearest point is stored on nearest */ -typedef float (*BVHTree_NearestPointCallback) (void *userdata, int index, const float *co, float *nearest); - - -BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis); -void BLI_bvhtree_free(BVHTree *tree); - -/* construct: first insert points, then call balance */ -int BLI_bvhtree_insert(BVHTree *tree, int index, float *co, int numpoints); -void BLI_bvhtree_balance(BVHTree *tree); - -/* update: first update points/nodes, then call update_tree to refit the bounding volumes */ -int BLI_bvhtree_update_node(BVHTree *tree, int index, float *co, float *co_moving, int numpoints); -void BLI_bvhtree_update_tree(BVHTree *tree); - -/* collision/overlap: check two trees if they overlap, alloc's *overlap with length of the int return value */ -BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result); - -float BLI_bvhtree_getepsilon(BVHTree *tree); - -/* find nearest node to the given coordinates (if nearest is given it will only search nodes where square distance is smaller than nearest->dist) */ -int BLI_bvhtree_find_nearest(BVHTree *tree, float *co, BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata); - -#endif // BLI_KDOPBVH_H - - - - diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c deleted file mode 100644 index ef7c13a8918..00000000000 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ /dev/null @@ -1,988 +0,0 @@ -/* kdop.c -* -* -* ***** BEGIN GPL/BL DUAL 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. The Blender -* Foundation also sells licenses for usinle in proprietary software under -* the Blender License. See http://www.blender.org/BL/ for information -* about this. -* -* 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) Blender Foundation -* All rights reserved. -* -* The Original Code is: all of this file. -* -* Contributor(s): Daniel Genrich, Andre Pinto -* -* ***** END GPL/BL DUAL LICENSE BLOCK ***** -*/ - -#include "math.h" -#include -#include -#include - -#include "MEM_guardedalloc.h" - -#include "BKE_utildefines.h" - -#include "BLI_kdopbvh.h" -#include "BLI_arithb.h" - -#ifdef _OPENMP -#include -#endif - -#define node_get_bv(tree, node) ((node)->bv) -#define node_get_child(tree,node,i) ((node)->children[i]) - -/* Util macros */ -#define TO_STR(a) #a -#define JOIN(a,b) a##b - -/* Benchmark macros */ -#if 1 - -#define BENCH(a) \ - do { \ - clock_t _clock_init = clock(); \ - (a); \ - printf("%s: %fms\n", #a, (float)(clock()-_clock_init)*1000/CLOCKS_PER_SEC); \ -} while(0) - -#define BENCH_VAR(name) clock_t JOIN(_bench_step,name) = 0, JOIN(_bench_total,name) = 0 -#define BENCH_BEGIN(name) JOIN(_bench_step, name) = clock() -#define BENCH_END(name) JOIN(_bench_total,name) += clock() - JOIN(_bench_step,name) -#define BENCH_RESET(name) JOIN(_bench_total, name) = 0 -#define BENCH_REPORT(name) printf("%s: %fms\n", TO_STR(name), JOIN(_bench_total,name)*1000.0f/CLOCKS_PER_SEC) - -#else - -#define BENCH(a) (a) -#define BENCH_VAR(name) -#define BENCH_BEGIN(name) -#define BENCH_END(name) -#define BENCH_RESET(name) -#define BENCH_REPORT(name) - -#endif - - -typedef struct BVHNode -{ - struct BVHNode **children;// max 8 children - struct BVHNode *parent; // needed for bottom - top update - float *bv; // Bounding volume of all nodes, max 13 axis - int index; // face, edge, vertex index - char totnode; // how many nodes are used, used for speedup - char traversed; // how many nodes already traversed until this level? - char main_axis; // axis that was used to split childs -} BVHNode; - -struct BVHTree -{ - BVHNode **nodes; - BVHNode *nodearray; // pre-alloc branchs - BVHNode **nodechild; // pre-alloc childs for nodes - float *nodebv; // pre-alloc bounding-volumes for nodes - float epsilon; // epslion is used for inflation of the k-dop - int totleaf; // leafs - int totbranch; - char tree_type; // type of tree (4 => quadtree) - char axis; // kdop type (6 => OBB, 7 => AABB, ...) - char start_axis, stop_axis; // KDOP_AXES array indices according to axis char start_axis, stop_axis; // KDOP_AXES array indices according to axis -}; - -typedef struct BVHOverlapData -{ - BVHTree *tree1, *tree2; - BVHTreeOverlap *overlap; - int i, max_overlap; /* i is number of overlaps */ -} BVHOverlapData; - -typedef struct BVHNearestData -{ - BVHTree *tree; - float *co; - BVHTree_NearestPointCallback callback; - void *userdata; - float proj[13]; //coordinates projection over axis - BVHTreeNearest nearest; -} BVHNearestData; -//////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////////// -// Bounding Volume Hierarchy Definition -// -// Notes: From OBB until 26-DOP --> all bounding volumes possible, just choose type below -// Notes: You have to choose the type at compile time ITM -// Notes: You can choose the tree type --> binary, quad, octree, choose below -//////////////////////////////////////////////////////////////////////// - -static float KDOP_AXES[13][3] = -{ {1.0, 0, 0}, {0, 1.0, 0}, {0, 0, 1.0}, {1.0, 1.0, 1.0}, {1.0, -1.0, 1.0}, {1.0, 1.0, -1.0}, -{1.0, -1.0, -1.0}, {1.0, 1.0, 0}, {1.0, 0, 1.0}, {0, 1.0, 1.0}, {1.0, -1.0, 0}, {1.0, 0, -1.0}, -{0, 1.0, -1.0} -}; - -////////////////////////////////////////////////////////////////////////////////////////////////////// -// Introsort -// with permission deriven from the following Java code: -// http://ralphunden.net/content/tutorials/a-guide-to-introsort/ -// and he derived it from the SUN STL -////////////////////////////////////////////////////////////////////////////////////////////////////// -static int size_threshold = 16; -/* -* Common methods for all algorithms -*/ -static int floor_lg(int a) -{ - return (int)(floor(log(a)/log(2))); -} - -/* -* Insertion sort algorithm -*/ -static void bvh_insertionsort(BVHNode **a, int lo, int hi, int axis) -{ - int i,j; - BVHNode *t; - for (i=lo; i < hi; i++) - { - j=i; - t = a[i]; - while((j!=lo) && (t->bv[axis] < (a[j-1])->bv[axis])) - { - a[j] = a[j-1]; - j--; - } - a[j] = t; - } -} - -static int bvh_partition(BVHNode **a, int lo, int hi, BVHNode * x, int axis) -{ - int i=lo, j=hi; - while (1) - { - while ((a[i])->bv[axis] < x->bv[axis]) i++; - j--; - while (x->bv[axis] < (a[j])->bv[axis]) j--; - if(!(i < j)) - return i; - SWAP( BVHNode* , a[i], a[j]); - i++; - } -} - -/* -* Heapsort algorithm -*/ -static void bvh_downheap(BVHNode **a, int i, int n, int lo, int axis) -{ - BVHNode * d = a[lo+i-1]; - int child; - while (i<=n/2) - { - child = 2*i; - if ((child < n) && ((a[lo+child-1])->bv[axis] < (a[lo+child])->bv[axis])) - { - child++; - } - if (!(d->bv[axis] < (a[lo+child-1])->bv[axis])) break; - a[lo+i-1] = a[lo+child-1]; - i = child; - } - a[lo+i-1] = d; -} - -static void bvh_heapsort(BVHNode **a, int lo, int hi, int axis) -{ - int n = hi-lo, i; - for (i=n/2; i>=1; i=i-1) - { - bvh_downheap(a, i,n,lo, axis); - } - for (i=n; i>1; i=i-1) - { - SWAP(BVHNode*, a[lo],a[lo+i-1]); - bvh_downheap(a, 1,i-1,lo, axis); - } -} - -static BVHNode *bvh_medianof3(BVHNode **a, int lo, int mid, int hi, int axis) // returns Sortable -{ - if ((a[mid])->bv[axis] < (a[lo])->bv[axis]) - { - if ((a[hi])->bv[axis] < (a[mid])->bv[axis]) - return a[mid]; - else - { - if ((a[hi])->bv[axis] < (a[lo])->bv[axis]) - return a[hi]; - else - return a[lo]; - } - } - else - { - if ((a[hi])->bv[axis] < (a[mid])->bv[axis]) - { - if ((a[hi])->bv[axis] < (a[lo])->bv[axis]) - return a[lo]; - else - return a[hi]; - } - else - return a[mid]; - } -} -/* -* Quicksort algorithm modified for Introsort -*/ -static void bvh_introsort_loop (BVHNode **a, int lo, int hi, int depth_limit, int axis) -{ - int p; - - while (hi-lo > size_threshold) - { - if (depth_limit == 0) - { - bvh_heapsort(a, lo, hi, axis); - return; - } - depth_limit=depth_limit-1; - p=bvh_partition(a, lo, hi, bvh_medianof3(a, lo, lo+((hi-lo)/2)+1, hi-1, axis), axis); - bvh_introsort_loop(a, p, hi, depth_limit, axis); - hi=p; - } -} - -static void sort(BVHNode **a0, int begin, int end, int axis) -{ - if (begin < end) - { - BVHNode **a=a0; - bvh_introsort_loop(a, begin, end, 2*floor_lg(end-begin), axis); - bvh_insertionsort(a, begin, end, axis); - } -} -void sort_along_axis(BVHTree *tree, int start, int end, int axis) -{ - sort(tree->nodes, start, end, axis); -} - -//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 -int partition_nth_element(BVHNode **a, int _begin, int _end, int n, int axis){ - int begin = _begin, end = _end, cut; - while(end-begin > 3) - { - cut = bvh_partition(a, begin, end, bvh_medianof3(a, begin, (begin+end)/2, end-1, axis), axis ); - if(cut <= n) - begin = cut; - else - end = cut; - } - bvh_insertionsort(a, begin, end, axis); - - return n; -} - -////////////////////////////////////////////////////////////////////////////////////////////////////// - -void BLI_bvhtree_free(BVHTree *tree) -{ - if(tree) - { - MEM_freeN(tree->nodes); - MEM_freeN(tree->nodearray); - MEM_freeN(tree->nodebv); - MEM_freeN(tree->nodechild); - MEM_freeN(tree); - } -} - -BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis) -{ - BVHTree *tree; - int numbranches=0, i; - - // only support up to octree - if(tree_type > 8) - return NULL; - - tree = (BVHTree *)MEM_callocN(sizeof(BVHTree), "BVHTree"); - - if(tree) - { - tree->epsilon = epsilon; - tree->tree_type = tree_type; - tree->axis = axis; - - if(axis == 26) - { - tree->start_axis = 0; - tree->stop_axis = 13; - } - else if(axis == 18) - { - tree->start_axis = 7; - tree->stop_axis = 13; - } - else if(axis == 14) - { - tree->start_axis = 0; - tree->stop_axis = 7; - } - else if(axis == 8) - { - tree->start_axis = 0; - tree->stop_axis = 4; - } - else if(axis == 6) // AABB - { - tree->start_axis = 0; - tree->stop_axis = 3; - } - else - { - MEM_freeN(tree); - return NULL; - } - - - // 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); - - 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"); - if(!tree->nodebv) - { - MEM_freeN(tree->nodes); - MEM_freeN(tree); - } - - tree->nodechild = (BVHNode**)MEM_callocN(sizeof(BVHNode*) * tree_type * (numbranches+maxsize + tree_type), "BVHNodeBV"); - if(!tree->nodechild) - { - MEM_freeN(tree->nodebv); - MEM_freeN(tree->nodes); - MEM_freeN(tree); - } - - tree->nodearray = (BVHNode *)MEM_callocN(sizeof(BVHNode)*(numbranches+maxsize + tree_type), "BVHNodeArray"); - - if(!tree->nodearray) - { - MEM_freeN(tree->nodechild); - MEM_freeN(tree->nodebv); - MEM_freeN(tree->nodes); - MEM_freeN(tree); - return NULL; - } - - //link the dynamic bv and child links - for(i=0; i< numbranches+maxsize + tree_type; i++) - { - tree->nodearray[i].bv = tree->nodebv + i * axis; - tree->nodearray[i].children = tree->nodechild + i * tree_type; - } - - } - - return tree; -} - - -static void create_kdop_hull(BVHTree *tree, BVHNode *node, float *co, int numpoints, int moving) -{ - float newminmax; - float *bv = node_get_bv(tree, node); - int i, k; - - // don't init boudings for the moving case - if(!moving) - { - for (i = tree->start_axis; i < tree->stop_axis; i++) - { - bv[2*i] = FLT_MAX; - bv[2*i + 1] = -FLT_MAX; - } - } - - for(k = 0; k < numpoints; k++) - { - // for all Axes. - for (i = tree->start_axis; i < tree->stop_axis; i++) - { - newminmax = INPR(&co[k * 3], KDOP_AXES[i]); - if (newminmax < bv[2 * i]) - bv[2 * i] = newminmax; - if (newminmax > bv[(2 * i) + 1]) - bv[(2 * i) + 1] = newminmax; - } - } -} - -// depends on the fact that the BVH's for each face is already build -static void refit_kdop_hull(BVHTree *tree, BVHNode *node, int start, int end) -{ - float newmin,newmax; - int i, j; - float *bv = node_get_bv(tree, node); - - for (i = tree->start_axis; i < tree->stop_axis; i++) - { - bv[2*i] = FLT_MAX; - bv[2*i + 1] = -FLT_MAX; - } - - for (j = start; j < end; j++) - { - // for all Axes. - for (i = tree->start_axis; i < tree->stop_axis; i++) - { - newmin = tree->nodes[j]->bv[(2 * i)]; - if ((newmin < bv[(2 * i)])) - bv[(2 * i)] = newmin; - - newmax = tree->nodes[j]->bv[(2 * i) + 1]; - if ((newmax > bv[(2 * i) + 1])) - bv[(2 * i) + 1] = newmax; - } - } -} - -static void inflate_kdop_hull(BVHTree *tree, BVHNode *node) -{ - int i; - float *bv = node_get_bv(tree, node); - - for(i= tree->axis; i; i--) - { - *bv++ -= tree->epsilon; // minimum - *bv++ += tree->epsilon; // maximum - } -} - -// only supports x,y,z axis in the moment -// but we should use a plain and simple function here for speed sake -static char kdop_hull_get_largest_axis(BVHTree *tree, BVHNode *node) -{ - float *bv = node_get_bv(tree, node); - float middle_point[3]; - - middle_point[0] = (bv[1]) - (bv[0]); // x axis - middle_point[1] = (bv[3]) - (bv[2]); // y axis - middle_point[2] = (bv[5]) - (bv[4]); // z axis - if (middle_point[0] > middle_point[1]) - { - if (middle_point[0] > middle_point[2]) - return 1; // max x axis - else - return 5; // max z axis - } - else - { - if (middle_point[1] > middle_point[2]) - return 3; // max y axis - else - return 5; // max z axis - } -} - - -int BLI_bvhtree_insert(BVHTree *tree, int index, float *co, int numpoints) -{ - 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)) - return 0; - - // TODO check if have enough nodes in array - - node = tree->nodes[tree->totleaf] = &(tree->nodearray[tree->totleaf]); - tree->totleaf++; - - //create and inflate hull - create_kdop_hull(tree, node, co, numpoints, 0); - inflate_kdop_hull(tree, node); - - node->index= index; - - return 1; -} - - -static void bvh_div_nodes(BVHTree *tree, BVHNode *node, int start, int end, char lastaxis) -{ - char laxis; - int i, tend; - BVHNode *tnode; - int slice = (end-start+tree->tree_type-1)/tree->tree_type; //division rounded up - - // Determine which axis to split along - laxis = kdop_hull_get_largest_axis(tree, node); - - // split nodes along longest axis - for (i=0; start < end; start += slice, i++) //i counts the current child - { - tend = start + slice; - - if(tend > end) tend = end; - - if(tend-start == 1) // ok, we have 1 left for this node - { - node->children[i] = tree->nodes[start]; - node->children[i]->parent = node; - } - else - { - partition_nth_element(tree->nodes, start, end, tend, laxis); - - tnode = node->children[i] = tree->nodes[tree->totleaf + tree->totbranch] = &(tree->nodearray[tree->totbranch + tree->totleaf]); - tree->totbranch++; - 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); - } - node->totnode++; - } - - return; -} - -static void verify_tree(BVHTree *tree) -{ - int i, j, check = 0; - - // check the pointer list - for(i = 0; i < tree->totleaf; i++) - { - if(tree->nodes[i]->parent == NULL) - printf("Leaf has no parent: %d\n", i); - else - { - for(j = 0; j < tree->tree_type; j++) - { - if(tree->nodes[i]->parent->children[j] == tree->nodes[i]) - check = 1; - } - if(!check) - { - printf("Parent child relationship doesn't match: %d\n", i); - } - check = 0; - } - } - - // check the leaf list - for(i = 0; i < tree->totleaf; i++) - { - if(tree->nodearray[i].parent == NULL) - printf("Leaf has no parent: %d\n", i); - else - { - for(j = 0; j < tree->tree_type; j++) - { - if(tree->nodearray[i].parent->children[j] == &tree->nodearray[i]) - check = 1; - } - if(!check) - { - printf("Parent child relationship doesn't match: %d\n", i); - } - check = 0; - } - } - - printf("branches: %d, leafs: %d, total: %d\n", tree->totbranch, tree->totleaf, tree->totbranch + tree->totleaf); -} - -void BLI_bvhtree_balance(BVHTree *tree) -{ - BVHNode *node; - - 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); - // create + balance tree - bvh_div_nodes(tree, tree->nodes[tree->totleaf], 0, tree->totleaf, 0); - - // verify_tree(tree); -} - -// overlap - is it possbile for 2 bv's to collide ? -static int tree_overlap(BVHNode *node1, BVHNode *node2, int start_axis, int stop_axis) -{ - float *bv1 = node1->bv; - float *bv2 = node2->bv; - - float *bv1_end = bv1 + (stop_axis<<1); - - bv1 += start_axis<<1; - bv2 += start_axis<<1; - - // test all axis if min + max overlap - for (; bv1 != bv1_end; bv1+=2, bv2+=2) - { - if ((*(bv1) > *(bv2 + 1)) || (*(bv2) > *(bv1 + 1))) - return 0; - } - - return 1; -} - -static void traverse(BVHOverlapData *data, BVHNode *node1, BVHNode *node2) -{ - int j; - - if(tree_overlap(node1, node2, MIN2(data->tree1->start_axis, data->tree2->start_axis), MIN2(data->tree1->stop_axis, data->tree2->stop_axis))) - { - // check if node1 is a leaf - if(node1->index) - { - // check if node2 is a leaf - if(node2->index) - { - - if(node1 == node2) - { - return; - } - - if(data->i >= data->max_overlap) - { - // try to make alloc'ed memory bigger - data->overlap = realloc(data->overlap, sizeof(BVHTreeOverlap)*data->max_overlap*2); - - if(!data->overlap) - { - printf("Out of Memory in traverse\n"); - return; - } - data->max_overlap *= 2; - } - - // both leafs, insert overlap! - data->overlap[data->i].indexA = node1->index; - data->overlap[data->i].indexB = node2->index; - - data->i++; - } - else - { - for(j = 0; j < data->tree2->tree_type; j++) - { - if(node2->children[j]) - traverse(data, node1, node2->children[j]); - } - } - } - else - { - - for(j = 0; j < data->tree2->tree_type; j++) - { - if(node1->children[j]) - traverse(data, node1->children[j], node2); - } - } - } - return; -} - -BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result) -{ - int j, total = 0; - BVHTreeOverlap *overlap = NULL, *to = NULL; - BVHOverlapData **data; - - // check for compatibility of both trees (can't compare 14-DOP with 18-DOP) - if((tree1->axis != tree2->axis) && ((tree1->axis == 14) || tree2->axis == 14)) - return 0; - - // fast check root nodes for collision before doing big splitting + traversal - if(!tree_overlap(tree1->nodes[tree1->totleaf], tree2->nodes[tree2->totleaf], MIN2(tree1->start_axis, tree2->start_axis), MIN2(tree1->stop_axis, tree2->stop_axis))) - return 0; - - data = MEM_callocN(sizeof(BVHOverlapData *)* tree1->tree_type, "BVHOverlapData_star"); - - for(j = 0; j < tree1->tree_type; j++) - { - data[j] = (BVHOverlapData *)MEM_callocN(sizeof(BVHOverlapData), "BVHOverlapData"); - - // init BVHOverlapData - data[j]->overlap = (BVHTreeOverlap *)malloc(sizeof(BVHTreeOverlap)*MAX2(tree1->totleaf, tree2->totleaf)); - data[j]->tree1 = tree1; - data[j]->tree2 = tree2; - data[j]->max_overlap = MAX2(tree1->totleaf, tree2->totleaf); - data[j]->i = 0; - } - -#pragma omp parallel for private(j) schedule(static) - for(j = 0; j < tree1->tree_type; j++) - { - traverse(data[j], tree1->nodes[tree1->totleaf]->children[j], tree2->nodes[tree2->totleaf]); - } - - for(j = 0; j < tree1->tree_type; j++) - total += data[j]->i; - - to = overlap = (BVHTreeOverlap *)MEM_callocN(sizeof(BVHTreeOverlap)*total, "BVHTreeOverlap"); - - for(j = 0; j < tree1->tree_type; j++) - { - memcpy(to, data[j]->overlap, data[j]->i*sizeof(BVHTreeOverlap)); - to+=data[j]->i; - } - - for(j = 0; j < tree1->tree_type; j++) - { - free(data[j]->overlap); - MEM_freeN(data[j]); - } - MEM_freeN(data); - - (*result) = total; - return overlap; -} - - -// bottom up update of bvh tree: -// join the 4 children here -static void node_join(BVHTree *tree, BVHNode *node) -{ - int i, j; - - for (i = tree->start_axis; i < tree->stop_axis; i++) - { - node->bv[2*i] = FLT_MAX; - node->bv[2*i + 1] = -FLT_MAX; - } - - for (i = 0; i < tree->tree_type; i++) - { - if (node->children[i]) - { - for (j = tree->start_axis; j < tree->stop_axis; j++) - { - // update minimum - if (node->children[i]->bv[(2 * j)] < node->bv[(2 * j)]) - node->bv[(2 * j)] = node->children[i]->bv[(2 * j)]; - - // update maximum - if (node->children[i]->bv[(2 * j) + 1] > node->bv[(2 * j) + 1]) - node->bv[(2 * j) + 1] = node->children[i]->bv[(2 * j) + 1]; - } - } - else - break; - } -} - -// call before BLI_bvhtree_update_tree() -int BLI_bvhtree_update_node(BVHTree *tree, int index, float *co, float *co_moving, int numpoints) -{ - BVHNode *node= NULL; - - // check if index exists - if(index > tree->totleaf) - return 0; - - node = tree->nodearray + index; - - create_kdop_hull(tree, node, co, numpoints, 0); - - if(co_moving) - create_kdop_hull(tree, node, co_moving, numpoints, 1); - - // inflate the bv with some epsilon - inflate_kdop_hull(tree, node); - - return 1; -} - -// call BLI_bvhtree_update_node() first for every node/point/triangle -void BLI_bvhtree_update_tree(BVHTree *tree) -{ - BVHNode *leaf, *parent; - - // reset tree traversing flag - for (leaf = tree->nodearray + tree->totleaf; leaf != tree->nodearray + tree->totleaf + tree->totbranch; leaf++) - leaf->traversed = 0; - - for (leaf = tree->nodearray; leaf != tree->nodearray + tree->totleaf; leaf++) - { - for (parent = leaf->parent; parent; parent = parent->parent) - { - parent->traversed++; // we tried to go up in hierarchy - if (parent->traversed < parent->totnode) - break; // we do not need to check further - else - node_join(tree, parent); - } - } -} - -float BLI_bvhtree_getepsilon(BVHTree *tree) -{ - return tree->epsilon; -} - - -//Nearest neighbour -static float squared_dist(const float *a, const float *b) -{ - float tmp[3]; - VECSUB(tmp, a, b); - return INPR(tmp, tmp); -} - -static float calc_nearest_point(BVHNearestData *data, BVHNode *node, float *nearest) -{ - int i; - const float *bv = node_get_bv(data->tree, node); - - //nearest on AABB hull - for(i=0; i != 3; i++, bv += 2) - { - if(bv[0] > data->proj[i]) - nearest[i] = bv[0]; - else if(bv[1] < data->proj[i]) - nearest[i] = bv[1]; - else - nearest[i] = data->proj[i]; - } - -/* - //nearest on a general hull - VECCOPY(nearest, data->co); - for(i = data->tree->start_axis; i != data->tree->stop_axis; i++, bv+=2) - { - float proj = INPR( nearest, KDOP_AXES[i]); - float dl = bv[0] - proj; - float du = bv[1] - proj; - - if(dl > 0) - { - VECADDFAC(nearest, nearest, KDOP_AXES[i], dl); - } - else if(du < 0) - { - VECADDFAC(nearest, nearest, KDOP_AXES[i], du); - } - } -*/ - return squared_dist(data->co, nearest); -} - - -static void dfs_find_nearest(BVHNearestData *data, BVHNode *node) -{ - int i; - float nearest[3], sdist; - - sdist = calc_nearest_point(data, node, nearest); - if(sdist >= data->nearest.dist) return; - - if(node->totnode == 0) - { - if(data->callback) - sdist = data->callback(data->userdata , node->index, data->co, nearest); - - if(sdist >= data->nearest.dist) return; - - data->nearest.index = node->index; - VECCOPY(data->nearest.nearest, nearest); - data->nearest.dist = sdist; - } - else - { - if(sdist < data->nearest.dist) - { - for(i=0; i != node->totnode; i++) - { - dfs_find_nearest(data, node->children[i]); - } - } - } -} - -int BLI_bvhtree_find_nearest(BVHTree *tree, float *co, BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata) -{ - int i; - - BVHNearestData data; - - //init data to search - data.tree = tree; - data.co = co; - - data.callback = callback; - data.userdata = userdata; - - for(i = data.tree->start_axis; i != data.tree->stop_axis; i++) - { - data.proj[i] = INPR(data.co, KDOP_AXES[i]); - } - - if(nearest) - { - memcpy( &data.nearest , nearest, sizeof(*nearest) ); - } - else - { - data.nearest.index = -1; - data.nearest.dist = FLT_MAX; - } - - //dfs search - dfs_find_nearest(&data, tree->nodes[tree->totleaf] ); - - //copy back results - if(nearest) - { - memcpy(nearest, &data.nearest, sizeof(*nearest)); - } - - return data.nearest.index; -} - -- cgit v1.2.3 From a39c8de24be8511f121f61ab2c8bd424901a0e5c Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Tue, 3 Jun 2008 19:56:19 +0000 Subject: Reason of last commits kdopbvh tree is now on trunk. Added those files to the branch and added code for NearestNeighbour, needed for shrinkwrap --- source/blender/blenlib/BLI_kdopbvh.h | 14 +++ source/blender/blenlib/intern/BLI_kdopbvh.c | 154 ++++++++++++++++++++++++++-- 2 files changed, 157 insertions(+), 11 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h index b81ff0ee66f..41ff97d111d 100644 --- a/source/blender/blenlib/BLI_kdopbvh.h +++ b/source/blender/blenlib/BLI_kdopbvh.h @@ -40,6 +40,17 @@ typedef struct BVHTreeOverlap { int indexB; } BVHTreeOverlap; +typedef struct BVHTreeNearest +{ + int index; /* the index of the nearest found (untouched if none is found within a dist radius from the given coordinates) */ + float nearest[3]; /* nearest coordinates (untouched it none is found within a dist radius from the given coordinates) */ + float dist; /* squared distance to search arround */ +} BVHTreeNearest; + +/* returns square of the minimum distance from given co to the node, nearest point is stored on nearest */ +typedef float (*BVHTree_NearestPointCallback) (void *userdata, int index, const float *co, float *nearest); + + BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis); void BLI_bvhtree_free(BVHTree *tree); @@ -56,5 +67,8 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result) float BLI_bvhtree_getepsilon(BVHTree *tree); +/* find nearest node to the given coordinates (if nearest is given it will only search nodes where square distance is smaller than nearest->dist) */ +int BLI_bvhtree_find_nearest(BVHTree *tree, float *co, BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata); + #endif // BLI_KDOPBVH_H diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 9c4238431dc..2dc345e894e 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -73,6 +73,16 @@ typedef struct BVHOverlapData BVHTreeOverlap *overlap; int i, max_overlap; /* i is number of overlaps */ } BVHOverlapData; + +typedef struct BVHNearestData +{ + BVHTree *tree; + float *co; + BVHTree_NearestPointCallback callback; + void *userdata; + float proj[13]; //coordinates projection over axis + BVHTreeNearest nearest; +} BVHNearestData; //////////////////////////////////////// @@ -242,7 +252,6 @@ void sort_along_axis(BVHTree *tree, int start, int end, int axis) // every node to the right of a[n] are greater or equal to it int partition_nth_element(BVHNode **a, int _begin, int _end, int n, int axis){ int begin = _begin, end = _end, cut; - int i; while(end-begin > 3) { cut = bvh_partition(a, begin, end, bvh_medianof3(a, begin, (begin+end)/2, end-1, axis), axis ); @@ -256,7 +265,6 @@ int partition_nth_element(BVHNode **a, int _begin, int _end, int n, int axis){ return n; } - ////////////////////////////////////////////////////////////////////////////////////////////////////// void BLI_bvhtree_free(BVHTree *tree) @@ -374,6 +382,7 @@ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis) static void create_kdop_hull(BVHTree *tree, BVHNode *node, float *co, int numpoints, int moving) { float newminmax; + float *bv = node->bv; int i, k; // don't init boudings for the moving case @@ -381,8 +390,8 @@ static void create_kdop_hull(BVHTree *tree, BVHNode *node, float *co, int numpoi { for (i = tree->start_axis; i < tree->stop_axis; i++) { - node->bv[2*i] = FLT_MAX; - node->bv[2*i + 1] = -FLT_MAX; + bv[2*i] = FLT_MAX; + bv[2*i + 1] = -FLT_MAX; } } @@ -392,10 +401,10 @@ static void create_kdop_hull(BVHTree *tree, BVHNode *node, float *co, int numpoi for (i = tree->start_axis; i < tree->stop_axis; i++) { newminmax = INPR(&co[k * 3], KDOP_AXES[i]); - if (newminmax < node->bv[2 * i]) - node->bv[2 * i] = newminmax; - if (newminmax > node->bv[(2 * i) + 1]) - node->bv[(2 * i) + 1] = newminmax; + if (newminmax < bv[2 * i]) + bv[2 * i] = newminmax; + if (newminmax > bv[(2 * i) + 1]) + bv[(2 * i) + 1] = newminmax; } } } @@ -591,8 +600,11 @@ void BLI_bvhtree_balance(BVHTree *tree) } // overlap - is it possbile for 2 bv's to collide ? -static int tree_overlap(float *bv1, float *bv2, int start_axis, int stop_axis) +static int tree_overlap(BVHNode *node1, BVHNode *node2, int start_axis, int stop_axis) { + float *bv1 = node1->bv; + float *bv2 = node2->bv; + float *bv1_end = bv1 + (stop_axis<<1); bv1 += start_axis<<1; @@ -612,7 +624,7 @@ static void traverse(BVHOverlapData *data, BVHNode *node1, BVHNode *node2) { int j; - if(tree_overlap(node1->bv, node2->bv, MIN2(data->tree1->start_axis, data->tree2->start_axis), MIN2(data->tree1->stop_axis, data->tree2->stop_axis))) + if(tree_overlap(node1, node2, MIN2(data->tree1->start_axis, data->tree2->start_axis), MIN2(data->tree1->stop_axis, data->tree2->stop_axis))) { // check if node1 is a leaf if(!node1->totnode) @@ -678,7 +690,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result) return 0; // fast check root nodes for collision before doing big splitting + traversal - if(!tree_overlap(tree1->nodes[tree1->totleaf]->bv, tree2->nodes[tree2->totleaf]->bv, MIN2(tree1->start_axis, tree2->start_axis), MIN2(tree1->stop_axis, tree2->stop_axis))) + if(!tree_overlap(tree1->nodes[tree1->totleaf], tree2->nodes[tree2->totleaf], MIN2(tree1->start_axis, tree2->start_axis), MIN2(tree1->stop_axis, tree2->stop_axis))) return 0; data = MEM_callocN(sizeof(BVHOverlapData *)* tree1->tree_type, "BVHOverlapData_star"); @@ -809,3 +821,123 @@ float BLI_bvhtree_getepsilon(BVHTree *tree) { return tree->epsilon; } + + +//Nearest neighbour +static float squared_dist(const float *a, const float *b) +{ + float tmp[3]; + VECSUB(tmp, a, b); + return INPR(tmp, tmp); +} + +static float calc_nearest_point(BVHNearestData *data, BVHNode *node, float *nearest) +{ + int i; + const float *bv = node->bv; + + //nearest on AABB hull + for(i=0; i != 3; i++, bv += 2) + { + if(bv[0] > data->proj[i]) + nearest[i] = bv[0]; + else if(bv[1] < data->proj[i]) + nearest[i] = bv[1]; + else + nearest[i] = data->proj[i]; + } + +/* + //nearest on a general hull + VECCOPY(nearest, data->co); + for(i = data->tree->start_axis; i != data->tree->stop_axis; i++, bv+=2) + { + float proj = INPR( nearest, KDOP_AXES[i]); + float dl = bv[0] - proj; + float du = bv[1] - proj; + + if(dl > 0) + { + VECADDFAC(nearest, nearest, KDOP_AXES[i], dl); + } + else if(du < 0) + { + VECADDFAC(nearest, nearest, KDOP_AXES[i], du); + } + } +*/ + return squared_dist(data->co, nearest); +} + + +static void dfs_find_nearest(BVHNearestData *data, BVHNode *node) +{ + int i; + float nearest[3], sdist; + + sdist = calc_nearest_point(data, node, nearest); + if(sdist >= data->nearest.dist) return; + + if(node->totnode == 0) + { + if(data->callback) + sdist = data->callback(data->userdata , node->index, data->co, nearest); + + if(sdist >= data->nearest.dist) return; + + data->nearest.index = node->index; + VECCOPY(data->nearest.nearest, nearest); + data->nearest.dist = sdist; + } + else + { + if(sdist < data->nearest.dist) + { + for(i=0; i != node->totnode; i++) + { + dfs_find_nearest(data, node->children[i]); + } + } + } +} + +int BLI_bvhtree_find_nearest(BVHTree *tree, float *co, BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata) +{ + int i; + + BVHNearestData data; + + //init data to search + data.tree = tree; + data.co = co; + + data.callback = callback; + data.userdata = userdata; + + for(i = data.tree->start_axis; i != data.tree->stop_axis; i++) + { + data.proj[i] = INPR(data.co, KDOP_AXES[i]); + } + + if(nearest) + { + memcpy( &data.nearest , nearest, sizeof(*nearest) ); + } + else + { + data.nearest.index = -1; + data.nearest.dist = FLT_MAX; + } + + //dfs search + dfs_find_nearest(&data, tree->nodes[tree->totleaf] ); + + //copy back results + if(nearest) + { + memcpy(nearest, &data.nearest, sizeof(*nearest)); + } + + return data.nearest.index; +} + -- cgit v1.2.3 From 39d35edbe680424f88ddc2cff8ecd86fb77fae89 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Wed, 11 Jun 2008 22:53:52 +0000 Subject: Merge from trunk svn merge -r 15104:15202 https://svn.blender.org/svnroot/bf-blender/trunk/blender --- source/blender/blenlib/BLI_arithb.h | 4 ++ source/blender/blenlib/intern/BLI_kdopbvh.c | 24 +++++------ source/blender/blenlib/intern/arithb.c | 67 +++++++++++++++++++++++++++++ source/blender/blenlib/intern/bpath.c | 3 -- source/blender/blenlib/intern/util.c | 62 +++++++++++++++++--------- 5 files changed, 125 insertions(+), 35 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h index 9ed23bc32b6..4d277cf98e1 100644 --- a/source/blender/blenlib/BLI_arithb.h +++ b/source/blender/blenlib/BLI_arithb.h @@ -258,6 +258,7 @@ void Vec2Addf(float *v, float *v1, float *v2); void Vec2Subf(float *v, float *v1, float *v2); void Vec2Copyf(float *v1, float *v2); +void AxisAngleToQuat(float *q, float *axis, float angle); void vectoquat(float *vec, short axis, short upflag, float *q); float VecAngle2(float *v1, float *v2); @@ -269,6 +270,8 @@ float NormalizedVecAngle2_2D(float *v1, float *v2); void euler_rot(float *beul, float ang, char axis); +void NormalShortToFloat(float *out, short *in); +void NormalFloatToShort(short *out, float *in); float DistVL2Dfl(float *v1, float *v2, float *v3); float PdistVL2Dfl(float *v1, float *v2, float *v3); @@ -372,6 +375,7 @@ void tubemap(float x, float y, float z, float *u, float *v); void spheremap(float x, float y, float z, float *u, float *v); int LineIntersectsTriangle(float p1[3], float p2[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv); +int RayIntersectsTriangle(float p1[3], float d[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv); int SweepingSphereIntersectsTriangleUV(float p1[3], float p2[3], float radius, float v0[3], float v1[3], float v2[3], float *lambda, float *ipoint); int AxialLineIntersectsTriangle(int axis, float co1[3], float co2[3], float v0[3], float v1[3], float v2[3], float *lambda); int AabbIntersectAabb(float min1[3], float max1[3], float min2[3], float max2[3]); diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 2dc345e894e..e69332be295 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -250,16 +250,16 @@ void sort_along_axis(BVHTree *tree, int start, int end, int axis) //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 -int partition_nth_element(BVHNode **a, int _begin, int _end, int n, int axis){ - int begin = _begin, end = _end, cut; - while(end-begin > 3) - { - cut = bvh_partition(a, begin, end, bvh_medianof3(a, begin, (begin+end)/2, end-1, axis), axis ); - if(cut <= n) - begin = cut; - else - end = cut; - } +int partition_nth_element(BVHNode **a, int _begin, int _end, int n, int axis){ + int begin = _begin, end = _end, cut; + while(end-begin > 3) + { + cut = bvh_partition(a, begin, end, bvh_medianof3(a, begin, (begin+end)/2, end-1, axis), axis ); + if(cut <= n) + begin = cut; + else + end = cut; + } bvh_insertionsort(a, begin, end, axis); return n; @@ -424,7 +424,7 @@ static void refit_kdop_hull(BVHTree *tree, BVHNode *node, int start, int end) for (j = start; j < end; j++) { - // for all Axes. +// for all Axes. for (i = tree->start_axis; i < tree->stop_axis; i++) { newmin = tree->nodes[j]->bv[(2 * i)]; @@ -708,7 +708,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result) } #pragma omp parallel for private(j) schedule(static) - for(j = 0; j < tree1->tree_type; j++) + for(j = 0; j < MIN2(tree1->tree_type, tree1->nodes[tree1->totleaf]->totnode); j++) { traverse(data[j], tree1->nodes[tree1->totleaf]->children[j], tree2->nodes[tree2->totleaf]); } diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index 48a149f4b3a..322a9e6fd02 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -1335,6 +1335,22 @@ void NormalQuat(float *q) } } +void AxisAngleToQuat(float *q, float *axis, float angle) +{ + float nor[3]; + float si; + + VecCopyf(nor, axis); + Normalize(nor); + + angle /= 2; + si = (float)sin(angle); + q[0] = (float)cos(angle); + q[1] = nor[0] * si; + q[2] = nor[1] * si; + q[3] = nor[2] * si; +} + void vectoquat(float *vec, short axis, short upflag, float *q) { float q2[4], nor[3], *fp, mat[3][3], angle, si, co, x2, y2, z2, len1; @@ -2258,6 +2274,20 @@ double Sqrt3d(double d) else return exp(log(d)/3); } +void NormalShortToFloat(float *out, short *in) +{ + out[0] = in[0] / 32767.0; + out[1] = in[1] / 32767.0; + out[2] = in[2] / 32767.0; +} + +void NormalFloatToShort(short *out, float *in) +{ + out[0] = (short)(in[0] * 32767.0); + out[1] = (short)(in[1] * 32767.0); + out[2] = (short)(in[2] * 32767.0); +} + /* distance v1 to line v2-v3 */ /* using Hesse formula, NO LINE PIECE! */ float DistVL2Dfl( float *v1, float *v2, float *v3) { @@ -3671,6 +3701,43 @@ int LineIntersectsTriangle(float p1[3], float p2[3], float v0[3], float v1[3], f return 1; } +/* moved from effect.c + test if the ray starting at p1 going in d direction intersects the triangle v0..v2 + return non zero if it does +*/ +int RayIntersectsTriangle(float p1[3], float d[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv) +{ + float p[3], s[3], e1[3], e2[3], q[3]; + float a, f, u, v; + + VecSubf(e1, v1, v0); + VecSubf(e2, v2, v0); + + Crossf(p, d, e2); + a = Inpf(e1, p); + if ((a > -0.000001) && (a < 0.000001)) return 0; + f = 1.0f/a; + + VecSubf(s, p1, v0); + + Crossf(q, s, e1); + *lambda = f * Inpf(e2, q); + if ((*lambda < 0.0)) return 0; + + u = f * Inpf(s, p); + if ((u < 0.0)||(u > 1.0)) return 0; + + v = f * Inpf(d, q); + if ((v < 0.0)||((u + v) > 1.0)) return 0; + + if(uv) { + uv[0]= u; + uv[1]= v; + } + + return 1; +} + /* Adapted from the paper by Kasper Fauerby */ /* "Improved Collision detection and Response" */ int SweepingSphereIntersectsTriangleUV(float p1[3], float p2[3], float radius, float v0[3], float v1[3], float v2[3], float *lambda, float *ipoint) diff --git a/source/blender/blenlib/intern/bpath.c b/source/blender/blenlib/intern/bpath.c index 79d3e487712..898ad6ddd67 100644 --- a/source/blender/blenlib/intern/bpath.c +++ b/source/blender/blenlib/intern/bpath.c @@ -456,13 +456,10 @@ void checkMissingFiles( char *txtname ) { /* be sure there is low chance of the path being too short */ char filepath_expanded[FILE_MAXDIR*2]; - char *libpath; int files_missing = 0; BLI_bpathIterator_init(&bpi); while (!BLI_bpathIterator_isDone(&bpi)) { - libpath = BLI_bpathIterator_getLib(&bpi); - BLI_bpathIterator_getPathExpanded( &bpi, filepath_expanded ); if (!BLI_exists(filepath_expanded)) { diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c index 3610813f2da..a353015052c 100644 --- a/source/blender/blenlib/intern/util.c +++ b/source/blender/blenlib/intern/util.c @@ -865,11 +865,8 @@ int BLI_strcaseeq(char *a, char *b) { void BLI_cleanup_dir(const char *relabase, char *dir) { BLI_cleanup_file(relabase, dir); -#ifdef WIN32 - strcat(dir, "\\"); -#else - strcat(dir, "/"); -#endif + BLI_add_slash(dir); + } void BLI_cleanup_file(const char *relabase, char *dir) @@ -878,7 +875,23 @@ void BLI_cleanup_file(const char *relabase, char *dir) char *start, *eind; if (relabase) { BLI_convertstringcode(dir, relabase); + } else { + if (dir[0]=='/' && dir[1]=='/') { + if (dir[2]== '\0') { + return; /* path is "//" - cant clean it */ + } + dir = dir+2; /* skip the first // */ + } } + + /* Note + * memmove( start, eind, strlen(eind)+1 ); + * is the same as + * strcpy( start, eind ); + * except strcpy should not be used because there is overlap, + * so use memmove's slightly more obscure syntax - Campbell + */ + #ifdef WIN32 if(dir[0]=='.') { /* happens for example in FILE_MAIN */ get_default_root(dir); @@ -892,17 +905,18 @@ void BLI_cleanup_file(const char *relabase, char *dir) if (dir[a] == '\\') break; a--; } - strcpy(dir+a,eind); + memmove( dir+a, eind, strlen(eind)+1 ); + } while ( (start = strstr(dir,"\\.\\")) ){ eind = start + strlen("\\.\\") - 1; - strcpy(start,eind); + memmove( start, eind, strlen(eind)+1 ); } while ( (start = strstr(dir,"\\\\" )) ){ eind = start + strlen("\\\\") - 1; - strcpy(start,eind); + memmove( start, eind, strlen(eind)+1 ); } if((a = strlen(dir))){ /* remove the '\\' at the end */ @@ -925,17 +939,17 @@ void BLI_cleanup_file(const char *relabase, char *dir) if (dir[a] == '/') break; a--; } - strcpy(dir+a,eind); + memmove( dir+a, eind, strlen(eind)+1 ); } while ( (start = strstr(dir,"/./")) ){ eind = start + strlen("/./") - 1; - strcpy(start,eind); + memmove( start, eind, strlen(eind)+1 ); } while ( (start = strstr(dir,"//" )) ){ eind = start + strlen("//") - 1; - strcpy(start,eind); + memmove( start, eind, strlen(eind)+1 ); } if( (a = strlen(dir)) ){ /* remove all '/' at the end */ @@ -1150,24 +1164,32 @@ int BLI_convertstringcode(char *path, const char *basepath) BLI_char_switch(tmp, '\\', '/'); BLI_char_switch(base, '\\', '/'); + /* Paths starting with // will get the blend file as their base, + * this isnt standard in any os but is uesed in blender all over the place */ if (tmp[0] == '/' && tmp[1] == '/') { - char *filepart= BLI_strdup(tmp+2); /* skip code */ char *lslash= BLI_last_slash(base); - if (lslash) { int baselen= (int) (lslash-base) + 1; - + /* use path for for temp storage here, we copy back over it right away */ + BLI_strncpy(path, tmp+2, FILE_MAX); + memcpy(tmp, base, baselen); - strcpy(tmp+baselen, filepart); + strcpy(tmp+baselen, path); + strcpy(path, tmp); } else { - strcpy(tmp, filepart); + strcpy(path, tmp+2); } - - MEM_freeN(filepart); + } else { + strcpy(path, tmp); } - BLI_cleanup_file(NULL, tmp); - strcpy(path, tmp); + if (path[0]!='\0') { + if ( path[strlen(path)-1]=='/') { + BLI_cleanup_dir(NULL, path); + } else { + BLI_cleanup_file(NULL, path); + } + } #ifdef WIN32 /* skip first two chars, which in case of -- cgit v1.2.3 From ffbe42129e0d043214daf9b07125d9d8140d1c74 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Fri, 20 Jun 2008 21:36:15 +0000 Subject: svn merge -r 15202:15292 https://svn.blender.org/svnroot/bf-blender/trunk/blender --- source/blender/blenlib/intern/util.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c index a353015052c..5a85fbfc375 100644 --- a/source/blender/blenlib/intern/util.c +++ b/source/blender/blenlib/intern/util.c @@ -905,8 +905,11 @@ void BLI_cleanup_file(const char *relabase, char *dir) if (dir[a] == '\\') break; a--; } - memmove( dir+a, eind, strlen(eind)+1 ); - + if (a<0) { + break; + } else { + memmove( dir+a, eind, strlen(eind)+1 ); + } } while ( (start = strstr(dir,"\\.\\")) ){ @@ -939,7 +942,11 @@ void BLI_cleanup_file(const char *relabase, char *dir) if (dir[a] == '/') break; a--; } - memmove( dir+a, eind, strlen(eind)+1 ); + if (a<0) { + break; + } else { + memmove( dir+a, eind, strlen(eind)+1 ); + } } while ( (start = strstr(dir,"/./")) ){ @@ -1128,8 +1135,8 @@ int BLI_convertstringcode(char *path, const char *basepath) char vol[3] = {'\0', '\0', '\0'}; BLI_strncpy(vol, path, 3); - wasrelative= (strncmp(vol, "//", 2)==0); - + wasrelative= (vol[0]=='/' && vol[1]=='/'); + #ifdef WIN32 /* we are checking here if we have an absolute path that is not in the current blend file as a lib main - we are basically checking for the case that a @@ -1166,7 +1173,7 @@ int BLI_convertstringcode(char *path, const char *basepath) /* Paths starting with // will get the blend file as their base, * this isnt standard in any os but is uesed in blender all over the place */ - if (tmp[0] == '/' && tmp[1] == '/') { + if (wasrelative) { char *lslash= BLI_last_slash(base); if (lslash) { int baselen= (int) (lslash-base) + 1; -- cgit v1.2.3 From c7dbc6548811f37bfeda4013ab70e342d50707b7 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Mon, 30 Jun 2008 22:57:52 +0000 Subject: svn merge -r 15292:15392 https://svn.blender.org/svnroot/bf-blender/trunk/blender --- source/blender/blenlib/BLI_arithb.h | 1 + source/blender/blenlib/intern/arithb.c | 68 ++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h index 4d277cf98e1..4fa880c36d1 100644 --- a/source/blender/blenlib/BLI_arithb.h +++ b/source/blender/blenlib/BLI_arithb.h @@ -374,6 +374,7 @@ void LocQuatSizeToMat4(float mat[][4], float loc[3], float quat[4], float size[3 void tubemap(float x, float y, float z, float *u, float *v); void spheremap(float x, float y, float z, float *u, float *v); +int LineIntersectLine(float v1[3], float v2[3], float v3[3], float v4[3], float i1[3], float i2[3]); int LineIntersectsTriangle(float p1[3], float p2[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv); int RayIntersectsTriangle(float p1[3], float d[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv); int SweepingSphereIntersectsTriangleUV(float p1[3], float p2[3], float radius, float v0[3], float v1[3], float v2[3], float *lambda, float *ipoint); diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index 322a9e6fd02..2084ab3da5f 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -4032,6 +4032,74 @@ int AxialLineIntersectsTriangle(int axis, float p1[3], float p2[3], float v0[3], return 1; } +/* Returns the number of point of interests + * 0 - lines are colinear + * 1 - lines are coplanar, i1 is set to intersection + * 2 - i1 and i2 are the nearest points on line 1 (v1, v2) and line 2 (v3, v4) respectively + * */ +int LineIntersectLine(float v1[3], float v2[3], float v3[3], float v4[3], float i1[3], float i2[3]) +{ + float a[3], b[3], c[3], ab[3], cb[3], dir1[3], dir2[3]; + float d; + + VecSubf(c, v3, v1); + VecSubf(a, v2, v1); + VecSubf(b, v4, v3); + + VecCopyf(dir1, a); + Normalize(dir1); + VecCopyf(dir2, b); + Normalize(dir2); + d = Inpf(dir1, dir2); + if (d == 1.0f || d == -1.0f) { + /* colinear */ + return 0; + } + + Crossf(ab, a, b); + d = Inpf(c, ab); + + /* test if the two lines are coplanar */ + if (d > -0.000001f && d < 0.000001f) { + Crossf(cb, c, b); + + VecMulf(a, Inpf(cb, ab) / Inpf(ab, ab)); + VecAddf(i1, v1, a); + VecCopyf(i2, i1); + + return 1; /* one intersection only */ + } + /* if not */ + else { + float n[3], t[3]; + float v3t[3], v4t[3]; + VecSubf(t, v1, v3); + + /* offset between both plane where the lines lies */ + Crossf(n, a, b); + Projf(t, t, n); + + /* for the first line, offset the second line until it is coplanar */ + VecAddf(v3t, v3, t); + VecAddf(v4t, v4, t); + + VecSubf(c, v3t, v1); + VecSubf(a, v2, v1); + VecSubf(b, v4t, v3); + + Crossf(ab, a, b); + Crossf(cb, c, b); + + VecMulf(a, Inpf(cb, ab) / Inpf(ab, ab)); + VecAddf(i1, v1, a); + + /* for the second line, just substract the offset from the first intersection point */ + VecSubf(i2, i1, t); + + return 2; /* two nearest points */ + } +} + int AabbIntersectAabb(float min1[3], float max1[3], float min2[3], float max2[3]) { return (min1[0] Date: Wed, 9 Jul 2008 19:43:09 +0000 Subject: Add raycast ability for BLI_kdopbvh small bvh fixes: *allow to create any tree type >= 2 *save split axis changed shrinkwrap to perform normal cast with raytree and bvh tree and print both times: Shrinkwrap (OBCube)24578 over (OBSuzanne)504482 target = raytree_create_from_mesh(calc->target): 1260.000000ms shrinkwrap_calc_normal_projection_raytree(&calc): 1850.000000ms tree = bvhtree_from_mesh_tri(calc->target): 3330.000000ms shrinkwrap_calc_normal_projection(&calc): 3780.000000ms On general query time is bit smaller on bvh tree.. but the build time of bvh is pretty big. (build time can be removed from both if a cache system is added) But I am still trying to see how fast I can make the bvh build --- source/blender/blenlib/BLI_kdopbvh.h | 18 +++ source/blender/blenlib/intern/BLI_kdopbvh.c | 164 ++++++++++++++++++++++++++-- 2 files changed, 173 insertions(+), 9 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h index 41ff97d111d..1e56faaff55 100644 --- a/source/blender/blenlib/BLI_kdopbvh.h +++ b/source/blender/blenlib/BLI_kdopbvh.h @@ -47,9 +47,25 @@ typedef struct BVHTreeNearest float dist; /* squared distance to search arround */ } BVHTreeNearest; +typedef struct BVHTreeRay +{ + float origin[3]; /* ray origin */ + float direction[3]; /* ray direction */ +} BVHTreeRay; + +typedef struct BVHTreeRayHit +{ + int index; /* index of the tree node (untouched if no hit is found) */ + float co[3]; /* coordinates of the hit point */ + float dist; /* distance to the hit point */ +} BVHTreeRayHit; + /* returns square of the minimum distance from given co to the node, nearest point is stored on nearest */ typedef float (*BVHTree_NearestPointCallback) (void *userdata, int index, const float *co, float *nearest); +/* returns the ray distancence from given co to the node, nearest point is stored on nearest */ +typedef float (*BVHTree_RayCastCallback) (void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit); + BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis); void BLI_bvhtree_free(BVHTree *tree); @@ -70,5 +86,7 @@ float BLI_bvhtree_getepsilon(BVHTree *tree); /* find nearest node to the given coordinates (if nearest is given it will only search nodes where square distance is smaller than nearest->dist) */ int BLI_bvhtree_find_nearest(BVHTree *tree, float *co, BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata); +int BLI_bvhtree_ray_cast(BVHTree *tree, float *co, float *dir, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata); + #endif // BLI_KDOPBVH_H diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index e69332be295..e7b5ccd4d54 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -82,8 +82,23 @@ typedef struct BVHNearestData void *userdata; float proj[13]; //coordinates projection over axis BVHTreeNearest nearest; + } BVHNearestData; -//////////////////////////////////////// + +typedef struct BVHRayCastData +{ + BVHTree *tree; + + BVHTree_RayCastCallback callback; + void *userdata; + + + BVHTreeRay ray; + float ray_dot_axis[13]; + + BVHTreeRayHit hit; +} BVHRayCastData; +////////////////////////////////////////m //////////////////////////////////////////////////////////////////////// @@ -284,8 +299,8 @@ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis) BVHTree *tree; int numbranches=0, i; - // only support up to octree - if(tree_type > 8) + // theres not support for trees below binary-trees :P + if(tree_type < 2) return NULL; tree = (BVHTree *)MEM_callocN(sizeof(BVHTree), "BVHTree"); @@ -415,6 +430,7 @@ static void refit_kdop_hull(BVHTree *tree, BVHNode *node, int start, int end) float newmin,newmax; int i, j; float *bv = node->bv; + for (i = tree->start_axis; i < tree->stop_axis; i++) { @@ -436,6 +452,7 @@ static void refit_kdop_hull(BVHTree *tree, BVHNode *node, int start, int end) bv[(2 * i) + 1] = newmax; } } + } int BLI_bvhtree_insert(BVHTree *tree, int index, float *co, int numpoints) @@ -503,6 +520,7 @@ static void bvh_div_nodes(BVHTree *tree, BVHNode *node, int start, int end, char // Determine which axis to split along laxis = get_largest_axis(node->bv); + node->main_axis = laxis/2; // split nodes along longest axis for (i=0; start < end; start += slice, i++) //i counts the current child @@ -582,6 +600,7 @@ static void verify_tree(BVHTree *tree) void BLI_bvhtree_balance(BVHTree *tree) { + int i; BVHNode *node; if(tree->totleaf == 0) @@ -823,7 +842,10 @@ float BLI_bvhtree_getepsilon(BVHTree *tree) } -//Nearest neighbour + +/* + * Nearest neighbour + */ static float squared_dist(const float *a, const float *b) { float tmp[3]; @@ -891,12 +913,9 @@ static void dfs_find_nearest(BVHNearestData *data, BVHNode *node) } else { - if(sdist < data->nearest.dist) + for(i=0; i != node->totnode; i++) { - for(i=0; i != node->totnode; i++) - { - dfs_find_nearest(data, node->children[i]); - } + dfs_find_nearest(data, node->children[i]); } } } @@ -941,3 +960,130 @@ int BLI_bvhtree_find_nearest(BVHTree *tree, float *co, BVHTreeNearest *nearest, return data.nearest.index; } + + +/* + * Ray cast + */ + +static float ray_nearest_hit(BVHRayCastData *data, BVHNode *node) +{ + int i; + const float *bv = node->bv; + + float low = 0, upper = data->hit.dist; + + for(i=0; i != 3; i++, bv += 2) + { + if(data->ray_dot_axis[i] == 0.0f) + { + //axis aligned ray + if(data->ray.origin[i] < bv[0] + || data->ray.origin[i] > bv[1]) + return FLT_MAX; + } + else + { + float ll = (bv[0] - data->ray.origin[i]) / data->ray_dot_axis[i]; + float lu = (bv[1] - data->ray.origin[i]) / data->ray_dot_axis[i]; + + if(data->ray_dot_axis[i] > 0) + { + if(ll > low) low = ll; + if(lu < upper) upper = lu; + } + else + { + if(lu > low) low = lu; + if(ll < upper) upper = ll; + } + + if(low > upper) return FLT_MAX; + } + } + return low; +} + +static void dfs_raycast(BVHRayCastData *data, BVHNode *node) +{ + int i; + float dist; + + dist = ray_nearest_hit(data, node); + + if(dist >= data->hit.dist) return; + + if(node->totnode == 0) + { + if(data->callback) + dist = data->callback(data->userdata, node->index, &data->ray, &data->hit); + else + { + data->hit.index = node->index; + data->hit.dist = dist; + VECADDFAC(data->hit.co, data->ray.origin, data->ray.direction, dist); + } + } + else + { + //pick loop direction to dive into the tree (based on ray direction and split axis) + if(data->ray_dot_axis[ node->main_axis ] > 0) + { + for(i=0; i != node->totnode; i++) + { + dfs_raycast(data, node->children[i]); + } + } + else + { + for(i=node->totnode-1; i >= 0; i--) + { + dfs_raycast(data, node->children[i]); + } + } + } +} + + + +int BLI_bvhtree_ray_cast(BVHTree *tree, float *co, float *dir, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata) +{ + int i; + BVHRayCastData data; + + data.tree = tree; + + data.callback = callback; + data.userdata = userdata; + + VECCOPY(data.ray.origin, co); + VECCOPY(data.ray.direction, dir); + + Normalize(data.ray.direction); + + for(i=0; i<3; i++) + { + data.ray_dot_axis[i] = INPR( data.ray.direction, KDOP_AXES[i]); + + if(fabs(data.ray_dot_axis[i]) < 1e-7) + data.ray_dot_axis[i] = 0.0; + } + + + if(hit) + memcpy( &data.hit, hit, sizeof(*hit) ); + else + { + data.hit.index = -1; + data.hit.dist = FLT_MAX; + } + + dfs_raycast(&data, tree->nodes[tree->totleaf]); + + + if(hit) + memcpy( hit, &data.hit, sizeof(*hit) ); + + return data.hit.index; +} + -- cgit v1.2.3 From 21d032e919522a199ea8343b70925d1257aa8479 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Fri, 11 Jul 2008 19:46:35 +0000 Subject: Added sphere cast (tought it doenst seems to solve the intersection problem) Fixed SweepingSphereIntersectsTriangleUV --- source/blender/blenlib/intern/arithb.c | 254 ++++++++++++++++----------------- 1 file changed, 120 insertions(+), 134 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index 2084ab3da5f..a366862d064 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -55,11 +55,10 @@ #include #include "BLI_arithb.h" #include "BLI_memarena.h" +#include "BKE_utildefines.h" /* A few small defines. Keep'em local! */ #define SMALL_NUMBER 1.e-8 -#define ABS(x) ((x) < 0 ? -(x) : (x)) -#define SWAP(type, a, b) { type sw_ap; sw_ap=(a); (a)=(b); (b)=sw_ap; } #if defined(WIN32) || defined(__APPLE__) @@ -3740,12 +3739,50 @@ int RayIntersectsTriangle(float p1[3], float d[3], float v0[3], float v1[3], flo /* Adapted from the paper by Kasper Fauerby */ /* "Improved Collision detection and Response" */ +static int getLowestRoot(float a, float b, float c, float maxR, float* root) +{ + // Check if a solution exists + float determinant = b*b - 4.0f*a*c; + + // If determinant is negative it means no solutions. + if (determinant >= 0.0f) + { + // calculate the two roots: (if determinant == 0 then + // x1==x2 but let’s disregard that slight optimization) + float sqrtD = sqrt(determinant); + float r1 = (-b - sqrtD) / (2.0f*a); + float r2 = (-b + sqrtD) / (2.0f*a); + + // Sort so x1 <= x2 + if (r1 > r2) + SWAP( float, r1, r2); + + // Get lowest root: + if (r1 > 0.0f && r1 < maxR) + { + *root = r1; + return 1; + } + + // It is possible that we want x2 - this can happen + // if x1 < 0 + if (r2 > 0.0f && r2 < maxR) + { + *root = r2; + return 1; + } + } + // No (valid) solutions + return 0; +} + int SweepingSphereIntersectsTriangleUV(float p1[3], float p2[3], float radius, float v0[3], float v1[3], float v2[3], float *lambda, float *ipoint) { float e1[3], e2[3], e3[3], point[3], vel[3], /*dist[3],*/ nor[3], temp[3], bv[3]; - float a, b, c, d, e, x, y, z, t, t0, t1, radius2=radius*radius; + float a, b, c, d, e, x, y, z, radius2=radius*radius; float elen2,edotv,edotbv,nordotv,vel2; - int embedded_in_plane=0, found_by_sweep=0; + float newLambda; + int found_by_sweep=0; VecSubf(e1,v1,v0); VecSubf(e2,v2,v0); @@ -3754,44 +3791,41 @@ int SweepingSphereIntersectsTriangleUV(float p1[3], float p2[3], float radius, f /*---test plane of tri---*/ Crossf(nor,e1,e2); Normalize(nor); + /* flip normal */ if(Inpf(nor,vel)>0.0f) VecMulf(nor,-1.0f); a=Inpf(p1,nor)-Inpf(v0,nor); - nordotv=Inpf(nor,vel); - if ((nordotv > -0.000001) && (nordotv < 0.000001)) { - if(fabs(a)>=1.0f) + if (fabs(nordotv) < 0.000001) + { + if(fabs(a)>=radius) + { return 0; - else{ - embedded_in_plane=1; - t0=0.0f; - t1=1.0f; } } - else{ - t0=(radius-a)/nordotv; - t1=(-radius-a)/nordotv; - /* make t0t1){b=t1; t1=t0; t0=b;} + else + { + float t0=(-a+radius)/nordotv; + float t1=(-a-radius)/nordotv; + + if(t0>t1) + SWAP(float, t0, t1); if(t0>1.0f || t1<0.0f) return 0; /* clamp to [0,1] */ - t0=(t0<0.0f)?0.0f:((t0>1.0f)?1.0:t0); - t1=(t1<0.0f)?0.0f:((t1>1.0f)?1.0:t1); - } + CLAMP(t0, 0.0f, 1.0f); + CLAMP(t1, 0.0f, 1.0f); -/*---test inside of tri---*/ - if(embedded_in_plane==0){ + /*---test inside of tri---*/ /* plane intersection point */ - VecCopyf(point,vel); - VecMulf(point,t0); - VecAddf(point,point,p1); - VecCopyf(temp,nor); - VecMulf(temp,radius); - VecSubf(point,point,temp); + + point[0] = p1[0] + vel[0]*t0 - nor[0]*radius; + point[1] = p1[1] + vel[1]*t0 - nor[1]*radius; + point[2] = p1[2] + vel[2]*t0 - nor[2]*radius; + /* is the point in the tri? */ a=Inpf(e1,e1); @@ -3806,14 +3840,19 @@ int SweepingSphereIntersectsTriangleUV(float p1[3], float p2[3], float radius, f y=e*a-d*b; z=x+y-(a*c-b*b); - if(( ((unsigned int)z)& ~(((unsigned int)x)|((unsigned int)y)) ) & 0x80000000){ + + if( z <= 0.0f && (x >= 0.0f && y >= 0.0f)) + { + //( ((unsigned int)z)& ~(((unsigned int)x)|((unsigned int)y)) ) & 0x80000000){ *lambda=t0; VecCopyf(ipoint,point); return 1; } } + *lambda=1.0f; + /*---test points---*/ a=vel2=Inpf(vel,vel); @@ -3821,73 +3860,42 @@ int SweepingSphereIntersectsTriangleUV(float p1[3], float p2[3], float radius, f VecSubf(temp,p1,v0); b=2.0f*Inpf(vel,temp); c=Inpf(temp,temp)-radius2; - d=b*b-4*a*c; - - if(d>=0.0f){ - if(d==0.0f) - t=-b/2*a; - else{ - z=sqrt(d); - x=(-b-z)*0.5/a; - y=(-b+z)*0.5/a; - t=x0.0 && t < *lambda){ - *lambda=t; - VecCopyf(ipoint,v0); - found_by_sweep=1; - } + if(getLowestRoot(a, b, c, *lambda, lambda)) + { + VecCopyf(ipoint,v0); + found_by_sweep=1; } /*v1*/ VecSubf(temp,p1,v1); b=2.0f*Inpf(vel,temp); c=Inpf(temp,temp)-radius2; - d=b*b-4*a*c; - - if(d>=0.0f){ - if(d==0.0f) - t=-b/2*a; - else{ - z=sqrt(d); - x=(-b-z)*0.5/a; - y=(-b+z)*0.5/a; - t=x0.0 && t < *lambda){ - *lambda=t; - VecCopyf(ipoint,v1); - found_by_sweep=1; - } + if(getLowestRoot(a, b, c, *lambda, lambda)) + { + VecCopyf(ipoint,v1); + found_by_sweep=1; } + /*v2*/ VecSubf(temp,p1,v2); b=2.0f*Inpf(vel,temp); c=Inpf(temp,temp)-radius2; - d=b*b-4*a*c; - - if(d>=0.0f){ - if(d==0.0f) - t=-b/2*a; - else{ - z=sqrt(d); - x=(-b-z)*0.5/a; - y=(-b+z)*0.5/a; - t=x0.0 && t < *lambda){ - *lambda=t; - VecCopyf(ipoint,v2); - found_by_sweep=1; - } + if(getLowestRoot(a, b, c, *lambda, lambda)) + { + VecCopyf(ipoint,v2); + found_by_sweep=1; } /*---test edges---*/ + VecSubf(e3,v2,v1); //wasnt yet calculated + + /*e1*/ VecSubf(bv,v0,p1); + elen2 = Inpf(e1,e1); edotv = Inpf(e1,vel); edotbv = Inpf(e1,bv); @@ -3895,27 +3903,18 @@ int SweepingSphereIntersectsTriangleUV(float p1[3], float p2[3], float radius, f a=elen2*(-Inpf(vel,vel))+edotv*edotv; b=2.0f*(elen2*Inpf(vel,bv)-edotv*edotbv); c=elen2*(radius2-Inpf(bv,bv))+edotbv*edotbv; - d=b*b-4*a*c; - if(d>=0.0f){ - if(d==0.0f) - t=-b/2*a; - else{ - z=sqrt(d); - x=(-b-z)*0.5/a; - y=(-b+z)*0.5/a; - t=x=0.0f) && (e<=1.0f)){ - if(t>0.0 && t < *lambda){ - *lambda=t; - VecCopyf(ipoint,e1); - VecMulf(ipoint,e); - VecAddf(ipoint,ipoint,v0); - found_by_sweep=1; - } + if(e >= 0.0f && e <= 1.0f) + { + *lambda = newLambda; + VecCopyf(ipoint,e1); + VecMulf(ipoint,e); + VecAddf(ipoint,ipoint,v0); + found_by_sweep=1; } } @@ -3928,32 +3927,27 @@ int SweepingSphereIntersectsTriangleUV(float p1[3], float p2[3], float radius, f a=elen2*(-Inpf(vel,vel))+edotv*edotv; b=2.0f*(elen2*Inpf(vel,bv)-edotv*edotbv); c=elen2*(radius2-Inpf(bv,bv))+edotbv*edotbv; - d=b*b-4*a*c; - if(d>=0.0f){ - if(d==0.0f) - t=-b/2*a; - else{ - z=sqrt(d); - x=(-b-z)*0.5/a; - y=(-b+z)*0.5/a; - t=x=0.0f) && (e<=1.0f)){ - if(t>0.0 && t < *lambda){ - *lambda=t; - VecCopyf(ipoint,e2); - VecMulf(ipoint,e); - VecAddf(ipoint,ipoint,v0); - found_by_sweep=1; - } + if(e >= 0.0f && e <= 1.0f) + { + *lambda = newLambda; + VecCopyf(ipoint,e2); + VecMulf(ipoint,e); + VecAddf(ipoint,ipoint,v0); + found_by_sweep=1; } } /*e3*/ - VecSubf(e3,v2,v1); + VecSubf(bv,v0,p1); + elen2 = Inpf(e1,e1); + edotv = Inpf(e1,vel); + edotbv = Inpf(e1,bv); + VecSubf(bv,v1,p1); elen2 = Inpf(e3,e3); edotv = Inpf(e3,vel); @@ -3962,30 +3956,22 @@ int SweepingSphereIntersectsTriangleUV(float p1[3], float p2[3], float radius, f a=elen2*(-Inpf(vel,vel))+edotv*edotv; b=2.0f*(elen2*Inpf(vel,bv)-edotv*edotbv); c=elen2*(radius2-Inpf(bv,bv))+edotbv*edotbv; - d=b*b-4*a*c; - if(d>=0.0f){ - if(d==0.0f) - t=-b/2*a; - else{ - z=sqrt(d); - x=(-b-z)*0.5/a; - y=(-b+z)*0.5/a; - t=x=0.0f) && (e<=1.0f)){ - if(t>0.0 && t < *lambda){ - *lambda=t; - VecCopyf(ipoint,e3); - VecMulf(ipoint,e); - VecAddf(ipoint,ipoint,v1); - found_by_sweep=1; - } + if(e >= 0.0f && e <= 1.0f) + { + *lambda = newLambda; + VecCopyf(ipoint,e3); + VecMulf(ipoint,e); + VecAddf(ipoint,ipoint,v1); + found_by_sweep=1; } } + return found_by_sweep; } int AxialLineIntersectsTriangle(int axis, float p1[3], float p2[3], float v0[3], float v1[3], float v2[3], float *lambda) -- cgit v1.2.3 From 70730c722679653d6accbb0ce36840ed84baf739 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Sun, 13 Jul 2008 13:21:01 +0000 Subject: svn merge -r 15392:15551 https://svn.blender.org/svnroot/bf-blender/trunk/blender --- source/blender/blenlib/BLI_arithb.h | 6 +++ source/blender/blenlib/BLI_winstuff.h | 3 ++ source/blender/blenlib/intern/BLI_kdopbvh.c | 2 + source/blender/blenlib/intern/arithb.c | 60 +++++++++++++++++++++++++++++ source/blender/blenlib/intern/util.c | 1 + 5 files changed, 72 insertions(+) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h index 4fa880c36d1..c22b6f79e08 100644 --- a/source/blender/blenlib/BLI_arithb.h +++ b/source/blender/blenlib/BLI_arithb.h @@ -50,6 +50,9 @@ extern "C" { #ifndef M_SQRT1_2 #define M_SQRT1_2 0.70710678118654752440 #endif +#ifndef M_1_PI +#define M_1_PI 0.318309886183790671538 +#endif #ifdef WIN32 #ifndef FREE_WINDOWS @@ -323,6 +326,9 @@ void yuv_to_rgb(float y, float u, float v, float *lr, float *lg, float *lb); void ycc_to_rgb(float y, float cb, float cr, float *lr, float *lg, float *lb); void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr); void rgb_to_hsv(float r, float g, float b, float *lh, float *ls, float *lv); +void xyz_to_rgb(float x, float y, float z, float *r, float *g, float *b); +int constrain_rgb(float *r, float *g, float *b); +void gamma_correct_rgb(float *r, float *g, float *b); unsigned int hsv_to_cpack(float h, float s, float v); unsigned int rgb_to_cpack(float r, float g, float b); void cpack_to_rgb(unsigned int col, float *r, float *g, float *b); diff --git a/source/blender/blenlib/BLI_winstuff.h b/source/blender/blenlib/BLI_winstuff.h index 9c192ba8b09..11150075bac 100644 --- a/source/blender/blenlib/BLI_winstuff.h +++ b/source/blender/blenlib/BLI_winstuff.h @@ -73,6 +73,9 @@ #ifndef M_SQRT1_2 #define M_SQRT1_2 0.70710678118654752440 #endif +#ifndef M_1_PI +#define M_1_PI 0.318309886183790671538 +#endif #define MAXPATHLEN MAX_PATH diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index e7b5ccd4d54..d84a9d09d4b 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -551,6 +551,7 @@ static void bvh_div_nodes(BVHTree *tree, BVHNode *node, int start, int end, char return; } +#if 0 static void verify_tree(BVHTree *tree) { int i, j, check = 0; @@ -597,6 +598,7 @@ static void verify_tree(BVHTree *tree) printf("branches: %d, leafs: %d, total: %d\n", tree->totbranch, tree->totleaf, tree->totbranch + tree->totleaf); } +#endif void BLI_bvhtree_balance(BVHTree *tree) { diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index a366862d064..dd9c76d9172 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -3413,6 +3413,66 @@ void rgb_to_hsv(float r, float g, float b, float *lh, float *ls, float *lv) *lv = v; } +/*http://brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html + * SMPTE-C XYZ to RGB matrix*/ +void xyz_to_rgb(float xc, float yc, float zc, float *r, float *g, float *b) +{ + *r = (3.50570 * xc) + (-1.73964 * yc) + (-0.544011 * zc); + *g = (-1.06906 * xc) + (1.97781 * yc) + (0.0351720 * zc); + *b = (0.0563117 * xc) + (-0.196994 * yc) + (1.05005 * zc); +} + +/*If the requested RGB shade contains a negative weight for + one of the primaries, it lies outside the colour gamut + accessible from the given triple of primaries. Desaturate + it by adding white, equal quantities of R, G, and B, enough + to make RGB all positive. The function returns 1 if the + components were modified, zero otherwise.*/ +int constrain_rgb(float *r, float *g, float *b) +{ + float w; + + /* Amount of white needed is w = - min(0, *r, *g, *b) */ + + w = (0 < *r) ? 0 : *r; + w = (w < *g) ? w : *g; + w = (w < *b) ? w : *b; + w = -w; + + /* Add just enough white to make r, g, b all positive. */ + + if (w > 0) { + *r += w; *g += w; *b += w; + return 1; /* Colour modified to fit RGB gamut */ + } + + return 0; /* Colour within RGB gamut */ +} + +/*Transform linear RGB values to nonlinear RGB values. Rec. + 709 is ITU-R Recommendation BT. 709 (1990) ``Basic + Parameter Values for the HDTV Standard for the Studio and + for International Programme Exchange'', formerly CCIR Rec. + 709.*/ +void gamma_correct(float *c) +{ + /* Rec. 709 gamma correction. */ + float cc = 0.018; + + if (*c < cc) { + *c *= ((1.099 * pow(cc, 0.45)) - 0.099) / cc; + } else { + *c = (1.099 * pow(*c, 0.45)) - 0.099; + } +} + +void gamma_correct_rgb(float *r, float *g, float *b) +{ + gamma_correct(r); + gamma_correct(g); + gamma_correct(b); +} + /* we define a 'cpack' here as a (3 byte color code) number that can be expressed like 0xFFAA66 or so. for that reason it is sensitive for endianness... with this function it works correctly diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c index 5a85fbfc375..48ebf770e1b 100644 --- a/source/blender/blenlib/intern/util.c +++ b/source/blender/blenlib/intern/util.c @@ -1722,6 +1722,7 @@ void BLI_where_am_i(char *fullname, const char *name) path = br_find_exe( NULL ); if (path) { strcpy(fullname, path); + free(path); return; } #endif -- cgit v1.2.3 From 785123cc5ab2d9681817bee6ee6bd8c11ac476f0 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Mon, 14 Jul 2008 18:42:53 +0000 Subject: Improved build time on BLI_kdopbvh Its now faster than raytree (both on build and query) Things tryed: X=>Y=>Z=>X split (reduces build time.. but increases query time) bucket sorts (initial sorts for fast usage of bucket take a long time) (nth is linear.. so its quite fast already) Best times archieve with: *usage of 4-ary trees.. reduces build time and tree size but didnt decreased query time *quads are on the same node instead of splitting in 2 tris.. (this actually turned on speedup on query time.. since tree size is reduced by a factor of 2) *test ray-bb before ray-primitive gives better times on both tris and quads Notes: measures where made projecting a sphere from inside the head of suzanne. --- source/blender/blenlib/intern/BLI_kdopbvh.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index d84a9d09d4b..73bc3e6a9bc 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -520,6 +520,8 @@ static void bvh_div_nodes(BVHTree *tree, BVHNode *node, int start, int end, char // Determine which axis to split along laxis = get_largest_axis(node->bv); + //laxis = (lastaxis + 2) % tree->axis; // XYZ split + node->main_axis = laxis/2; // split nodes along longest axis @@ -543,7 +545,7 @@ static void bvh_div_nodes(BVHTree *tree, BVHNode *node, int start, int end, char 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); + bvh_div_nodes(tree, tnode, start, tend, laxis); // not called on XYZ split } node->totnode++; } @@ -613,9 +615,10 @@ void BLI_bvhtree_balance(BVHTree *tree) tree->totbranch++; // refit root bvh node - refit_kdop_hull(tree, tree->nodes[tree->totleaf], 0, tree->totleaf); + 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); } @@ -1009,16 +1012,16 @@ static float ray_nearest_hit(BVHRayCastData *data, BVHNode *node) static void dfs_raycast(BVHRayCastData *data, BVHNode *node) { int i; - float dist; - - dist = ray_nearest_hit(data, node); + //ray-bv is really fast.. and simple tests revealed its worth to test it + //before calling the ray-primitive functions + float dist = ray_nearest_hit(data, node); if(dist >= data->hit.dist) return; if(node->totnode == 0) { if(data->callback) - dist = data->callback(data->userdata, node->index, &data->ray, &data->hit); + data->callback(data->userdata, node->index, &data->ray, &data->hit); else { data->hit.index = node->index; -- cgit v1.2.3 From afc30d1a33506d8c0fb08f6b2df7856071383430 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Tue, 15 Jul 2008 12:54:57 +0000 Subject: There was a problem with the last merge :S Somehow it didnt finished and didnt added some files under the svn control (found thanks to lguillaume that reported some files were missing) Last merge fixed and also merged modifications up to revision 15584. I checked the diff svn diff --new . --old https://svn.blender.org/svnroot/bf-blender/trunk/blender And everything seems to be right now --- source/blender/blenlib/BLI_mempool.h | 44 +++++++++ source/blender/blenlib/intern/BLI_mempool.c | 140 ++++++++++++++++++++++++++++ 2 files changed, 184 insertions(+) create mode 100644 source/blender/blenlib/BLI_mempool.h create mode 100644 source/blender/blenlib/intern/BLI_mempool.c (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/BLI_mempool.h b/source/blender/blenlib/BLI_mempool.h new file mode 100644 index 00000000000..8b31459dd38 --- /dev/null +++ b/source/blender/blenlib/BLI_mempool.h @@ -0,0 +1,44 @@ +/** + * Simple fast memory allocator + * + * + * ***** 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) 2008 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Geoffrey Bantle. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef BLI_MEMPOOL_H +#define BLI_MEMPOOL_H + +struct BLI_mempool; +typedef struct BLI_mempool BLI_mempool; + +BLI_mempool *BLI_mempool_create(int esize, int tote, int pchunk); +void *BLI_mempool_alloc(BLI_mempool *pool); +void *BLI_mempool_calloc(BLI_mempool *pool); +void BLI_mempool_free(BLI_mempool *pool, void *addr); +void BLI_mempool_destroy(BLI_mempool *pool); + + +#endif diff --git a/source/blender/blenlib/intern/BLI_mempool.c b/source/blender/blenlib/intern/BLI_mempool.c new file mode 100644 index 00000000000..7ac7b8b1791 --- /dev/null +++ b/source/blender/blenlib/intern/BLI_mempool.c @@ -0,0 +1,140 @@ +/** + * + * ***** 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) 2008 by Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/* + Simple, fast memory allocator for allocating many elements of the same size. +*/ + +#include "MEM_guardedalloc.h" +#include "BLI_blenlib.h" +#include "DNA_listBase.h" +#include "BLI_linklist.h" +#include + +typedef struct BLI_freenode{ + struct BLI_freenode *next; +}BLI_freenode; + +typedef struct BLI_mempool_chunk{ + struct BLI_mempool_chunk *next, *prev; + void *data; +}BLI_mempool_chunk; + +typedef struct BLI_mempool{ + struct ListBase chunks; + int esize, csize, pchunk; /*size of elements and chunks in bytes and number of elements per chunk*/ + struct BLI_freenode *free; /*free element list. Interleaved into chunk datas.*/ +}BLI_mempool; + +BLI_mempool *BLI_mempool_create(int esize, int tote, int pchunk) +{ BLI_mempool *pool = NULL; + BLI_freenode *lasttail = NULL, *curnode = NULL; + int i,j, maxchunks; + char *addr; + + /*allocate the pool structure*/ + pool = MEM_mallocN(sizeof(BLI_mempool),"memory pool"); + pool->esize = esize; + pool->pchunk = pchunk; + pool->csize = esize * pchunk; + pool->chunks.first = pool->chunks.last = NULL; + + maxchunks = tote / pchunk; + + /*allocate the actual chunks*/ + for(i=0; i < maxchunks; i++){ + BLI_mempool_chunk *mpchunk = MEM_mallocN(sizeof(BLI_mempool_chunk), "BLI_Mempool Chunk"); + mpchunk->next = mpchunk->prev = NULL; + mpchunk->data = MEM_mallocN(pool->csize, "BLI Mempool Chunk Data"); + BLI_addtail(&(pool->chunks), mpchunk); + + if(i==0) pool->free = mpchunk->data; /*start of the list*/ + /*loop through the allocated data, building the pointer structures*/ + for(addr = mpchunk->data, j=0; j < pool->pchunk; j++){ + curnode = ((BLI_freenode*)addr); + addr += pool->esize; + curnode->next = (BLI_freenode*)addr; + } + /*final pointer in the previously allocated chunk is wrong.*/ + if(lasttail) lasttail->next = mpchunk->data; + /*set the end of this chunks memoryy to the new tail for next iteration*/ + lasttail = curnode; + } + /*terminate the list*/ + curnode->next = NULL; + return pool; +} +void *BLI_mempool_alloc(BLI_mempool *pool){ + void *retval=NULL; + BLI_freenode *curnode=NULL; + char *addr=NULL; + int j; + + if(!(pool->free)){ + /*need to allocate a new chunk*/ + BLI_mempool_chunk *mpchunk = MEM_mallocN(sizeof(BLI_mempool_chunk), "BLI_Mempool Chunk"); + mpchunk->next = mpchunk->prev = NULL; + mpchunk->data = MEM_mallocN(pool->csize, "BLI_Mempool Chunk Data"); + BLI_addtail(&(pool->chunks), mpchunk); + + pool->free = mpchunk->data; /*start of the list*/ + for(addr = mpchunk->data, j=0; j < pool->pchunk; j++){ + curnode = ((BLI_freenode*)addr); + addr += pool->esize; + curnode->next = (BLI_freenode*)addr; + } + curnode->next = NULL; /*terminate the list*/ + } + + retval = pool->free; + pool->free = pool->free->next; + //memset(retval, 0, pool->esize); + return retval; +} + +void *BLI_mempool_calloc(BLI_mempool *pool){ + void *retval=NULL; + retval = BLI_mempool_alloc(pool); + memset(retval, 0, pool->esize); + return retval; +} + + + +void BLI_mempool_free(BLI_mempool *pool, void *addr){ //doesnt protect against double frees, dont be stupid! + BLI_freenode *newhead = addr; + newhead->next = pool->free; + pool->free = newhead; +} +void BLI_mempool_destroy(BLI_mempool *pool) +{ + BLI_mempool_chunk *mpchunk=NULL; + for(mpchunk = pool->chunks.first; mpchunk; mpchunk = mpchunk->next) MEM_freeN(mpchunk->data); + BLI_freelistN(&(pool->chunks)); + MEM_freeN(pool); +} -- cgit v1.2.3 From 59a2b5017185369836678b14325666f62dba9311 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Fri, 18 Jul 2008 22:24:20 +0000 Subject: *Added "kept" mesh above surface option on shrinkwrap to nearest surface changed a few code relative to project over normal mode (to try to kept code generic and more independent of modifier itself) --- source/blender/blenlib/BLI_kdopbvh.h | 5 +++-- source/blender/blenlib/intern/BLI_kdopbvh.c | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h index 1e56faaff55..d090784e450 100644 --- a/source/blender/blenlib/BLI_kdopbvh.h +++ b/source/blender/blenlib/BLI_kdopbvh.h @@ -57,6 +57,7 @@ typedef struct BVHTreeRayHit { int index; /* index of the tree node (untouched if no hit is found) */ float co[3]; /* coordinates of the hit point */ + float no[3]; /* normal on hit point */ float dist; /* distance to the hit point */ } BVHTreeRayHit; @@ -84,9 +85,9 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result) float BLI_bvhtree_getepsilon(BVHTree *tree); /* find nearest node to the given coordinates (if nearest is given it will only search nodes where square distance is smaller than nearest->dist) */ -int BLI_bvhtree_find_nearest(BVHTree *tree, float *co, BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata); +int BLI_bvhtree_find_nearest(BVHTree *tree, const float *co, BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata); -int BLI_bvhtree_ray_cast(BVHTree *tree, float *co, float *dir, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata); +int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata); #endif // BLI_KDOPBVH_H diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 73bc3e6a9bc..58a8f9f845c 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -925,7 +925,7 @@ static void dfs_find_nearest(BVHNearestData *data, BVHNode *node) } } -int BLI_bvhtree_find_nearest(BVHTree *tree, float *co, BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata) +int BLI_bvhtree_find_nearest(BVHTree *tree, const float *co, BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata) { int i; @@ -1051,7 +1051,7 @@ static void dfs_raycast(BVHRayCastData *data, BVHNode *node) -int BLI_bvhtree_ray_cast(BVHTree *tree, float *co, float *dir, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata) +int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata) { int i; BVHRayCastData data; -- cgit v1.2.3 From 0703d9aad1aa3f1233389c462cdb90414fbe31ae Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Sat, 19 Jul 2008 15:22:38 +0000 Subject: Following the same optimization as bvh raycast: *Made nearest surface also use "quad" bvh tree (instead of splitting quads in 2 bvh nodes). Again that leaded to improvements in build and query time. *BLI_bvhtree_find_nearest api is now following the same concept as BLI_bvhtree_ray_cast removed code relative to bvhtree_from_mesh_tris. --- source/blender/blenlib/BLI_kdopbvh.h | 11 ++++++----- source/blender/blenlib/intern/BLI_kdopbvh.c | 17 ++++++++--------- 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h index d090784e450..6d9c82a9626 100644 --- a/source/blender/blenlib/BLI_kdopbvh.h +++ b/source/blender/blenlib/BLI_kdopbvh.h @@ -43,7 +43,8 @@ typedef struct BVHTreeOverlap { typedef struct BVHTreeNearest { int index; /* the index of the nearest found (untouched if none is found within a dist radius from the given coordinates) */ - float nearest[3]; /* nearest coordinates (untouched it none is found within a dist radius from the given coordinates) */ + float co[3]; /* nearest coordinates (untouched it none is found within a dist radius from the given coordinates) */ + float no[3]; /* normal at nearest coordinates (untouched it none is found within a dist radius from the given coordinates) */ float dist; /* squared distance to search arround */ } BVHTreeNearest; @@ -61,11 +62,11 @@ typedef struct BVHTreeRayHit float dist; /* distance to the hit point */ } BVHTreeRayHit; -/* returns square of the minimum distance from given co to the node, nearest point is stored on nearest */ -typedef float (*BVHTree_NearestPointCallback) (void *userdata, int index, const float *co, float *nearest); +/* callback must update nearest in case it finds a nearest result */ +typedef void (*BVHTree_NearestPointCallback) (void *userdata, int index, const float *co, BVHTreeNearest *nearest); -/* returns the ray distancence from given co to the node, nearest point is stored on nearest */ -typedef float (*BVHTree_RayCastCallback) (void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit); +/* callback must update hit in case it finds a nearest successful hit */ +typedef void (*BVHTree_RayCastCallback) (void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit); BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis); diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 58a8f9f845c..d9c24853236 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -897,6 +897,7 @@ static float calc_nearest_point(BVHNearestData *data, BVHNode *node, float *near } +// TODO: use a priority queue to reduce the number of nodes looked on static void dfs_find_nearest(BVHNearestData *data, BVHNode *node) { int i; @@ -908,20 +909,18 @@ static void dfs_find_nearest(BVHNearestData *data, BVHNode *node) if(node->totnode == 0) { if(data->callback) - sdist = data->callback(data->userdata , node->index, data->co, nearest); - - if(sdist >= data->nearest.dist) return; - - data->nearest.index = node->index; - VECCOPY(data->nearest.nearest, nearest); - data->nearest.dist = sdist; + data->callback(data->userdata , node->index, data->co, &data->nearest); + else + { + data->nearest.index = node->index; + VECCOPY(data->nearest.co, nearest); + data->nearest.dist = sdist; + } } else { for(i=0; i != node->totnode; i++) - { dfs_find_nearest(data, node->children[i]); - } } } -- cgit v1.2.3 From aec6b78deda32d7aa1631ec76efda5bcea83a8c9 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Tue, 22 Jul 2008 12:02:57 +0000 Subject: svn merge -r 15590:15688 https://svn.blender.org/svnroot/bf-blender/trunk/blender --- source/blender/blenlib/intern/arithb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index dd9c76d9172..a31c769a5b3 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -59,6 +59,7 @@ /* A few small defines. Keep'em local! */ #define SMALL_NUMBER 1.e-8 +#define CLAMP(a, b, c) if((a)<(b)) (a)=(b); else if((a)>(c)) (a)=(c) #if defined(WIN32) || defined(__APPLE__) -- cgit v1.2.3 From 289d875dfdd00165dacd92b554c472cc818dbd8f Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Fri, 1 Aug 2008 21:37:36 +0000 Subject: svn merge -r 15688:15908 https://svn.blender.org/svnroot/bf-blender/trunk/blender --- source/blender/blenlib/intern/arithb.c | 5 ----- source/blender/blenlib/intern/freetypefont.c | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index a31c769a5b3..c1edb7d3ac1 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -2535,11 +2535,6 @@ int IsectPQ2Df(float pt[2], float v1[2], float v2[2], float v3[2], float v4[2]) } - - /* copied from Geometry.c - todo - move to arithb.c or some other generic place we can reuse */ -#define SIDE_OF_LINE(pa,pb,pp) ((pa[0]-pp[0])*(pb[1]-pp[1]))-((pb[0]-pp[0])*(pa[1]-pp[1])) -#define POINT_IN_TRI(p0,p1,p2,p3) ((SIDE_OF_LINE(p1,p2,p0)>=0) && (SIDE_OF_LINE(p2,p3,p0)>=0) && (SIDE_OF_LINE(p3,p1,p0)>=0)) - /** * * @param min diff --git a/source/blender/blenlib/intern/freetypefont.c b/source/blender/blenlib/intern/freetypefont.c index 8b979f9ed23..74f152ac635 100644 --- a/source/blender/blenlib/intern/freetypefont.c +++ b/source/blender/blenlib/intern/freetypefont.c @@ -405,7 +405,7 @@ static VFontData *objfnt_to_ftvfontdata(PackedFile * pf) lcode = charcode; } - err = FT_Set_Charmap( face, (FT_CharMap) FT_ENCODING_UNICODE ); + err = FT_Select_Charmap( face, FT_ENCODING_UNICODE ); return vfd; } -- cgit v1.2.3 From c2cd6bebe609db6b8079b30ee90b3d9f9abb0e2d Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Sun, 3 Aug 2008 15:37:24 +0000 Subject: added openmp support for bvhtree build (max processes = tree_type) --- source/blender/blenlib/intern/BLI_kdopbvh.c | 196 +++++++++++++++++++--------- 1 file changed, 135 insertions(+), 61 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index d9c24853236..7c79381c5cd 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -28,8 +28,9 @@ #include "math.h" #include -#include +#include #include +#include #include "MEM_guardedalloc.h" @@ -294,10 +295,32 @@ void BLI_bvhtree_free(BVHTree *tree) } } +// 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,11 +366,10 @@ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis) } - // 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); - - tree->nodes = (BVHNode **)MEM_callocN(sizeof(BVHNode *)*(numbranches+maxsize + tree_type), "BVHNodes"); + //Allocate arrays + numnodes = maxsize + needed_branches(tree_type, maxsize) + tree_type; + + tree->nodes = (BVHNode **)MEM_callocN(sizeof(BVHNode *)*numnodes, "BVHNodes"); if(!tree->nodes) { @@ -355,14 +377,14 @@ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis) 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 @@ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis) 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 @@ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis) } //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 @@ static void create_kdop_hull(BVHTree *tree, BVHNode *node, float *co, int numpoi 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 @@ static void refit_kdop_hull(BVHTree *tree, BVHNode *node, int start, int end) 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 @@ int BLI_bvhtree_insert(BVHTree *tree, int index, float *co, int numpoints) 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 char get_largest_axis(float *bv) } } -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 @@ static void bvh_div_nodes(BVHTree *tree, BVHNode *node, int start, int end, char } 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 @@ static void verify_tree(BVHTree *tree) void BLI_bvhtree_balance(BVHTree *tree) { - int i; - BVHNode *node; - - 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 + assert(tree->totbranch == 0); + if(tree->totleaf != 0) + { + // create root node + BVHNode *node = tree->nodes[tree->totleaf] = &(tree->nodearray[tree->totleaf]); + tree->totbranch++; - // 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 @@ static void node_join(BVHTree *tree, BVHNode *node) 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 @@ int BLI_bvhtree_update_node(BVHTree *tree, int index, float *co, float *co_movin 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; } -- cgit v1.2.3 From d786fead104fc4ce1a42286631fb74a3b0dfd620 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Mon, 4 Aug 2008 11:50:36 +0000 Subject: Fixed double inflation in case of co_moving points --- source/blender/blenlib/intern/BLI_kdopbvh.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 7c79381c5cd..a65d2ca6ea0 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -444,13 +444,6 @@ static void create_kdop_hull(BVHTree *tree, BVHNode *node, float *co, int numpoi 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 @@ -486,6 +479,7 @@ static void refit_kdop_hull(BVHTree *tree, BVHNode *node, int start, int end) int BLI_bvhtree_insert(BVHTree *tree, int index, float *co, int numpoints) { + int i; BVHNode *node = NULL; // insert should only possible as long as tree->totbranch is 0 @@ -503,6 +497,13 @@ int BLI_bvhtree_insert(BVHTree *tree, int index, float *co, int numpoints) create_kdop_hull(tree, node, co, numpoints, 0); node->index= index; + // 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; } @@ -877,6 +878,7 @@ static void node_join(BVHTree *tree, BVHNode *node) // call before BLI_bvhtree_update_tree() int BLI_bvhtree_update_node(BVHTree *tree, int index, float *co, float *co_moving, int numpoints) { + int i; BVHNode *node= NULL; // check if index exists @@ -890,6 +892,13 @@ int BLI_bvhtree_update_node(BVHTree *tree, int index, float *co, float *co_movin 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; } -- cgit v1.2.3 From 0008b1d424647f7f174fa94c6309a7a4a00fb486 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Mon, 4 Aug 2008 20:30:57 +0000 Subject: Shrink BVHNode by 16bits --- source/blender/blenlib/intern/BLI_kdopbvh.c | 38 +++++++++-------------------- 1 file changed, 11 insertions(+), 27 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index a65d2ca6ea0..96eb42136fb 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -45,12 +45,10 @@ typedef struct BVHNode { - struct BVHNode **children; // max 8 children - struct BVHNode *parent; // needed for bottom - top update - float *bv; // Bounding volume of all nodes, max 13 axis - int index; /* face, edge, vertex index */ - char totnode; // how many nodes are used, used for speedup - char traversed; // how many nodes already traversed until this level? + struct BVHNode **children; // max 8 children + float *bv; // Bounding volume of all nodes, max 13 axis + int index; // face, edge, vertex index + char totnode; // how many nodes are used, used for speedup char main_axis; } BVHNode; @@ -554,13 +552,10 @@ static void bvh_div_nodes(BVHTree *tree, BVHNode *node, int start, int end, int if(tend-start == 1) // ok, we have 1 left for this node { node->children[i] = tree->nodes[start]; - node->children[i]->parent = node; } else { 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); @@ -608,7 +603,6 @@ static void omp_bvh_div_nodes(BVHTree *tree, BVHNode *node, int start, int end, if(tend-start == 1) { node->children[i] = tree->nodes[start]; - node->children[i]->parent = node; } else { @@ -905,23 +899,13 @@ int BLI_bvhtree_update_node(BVHTree *tree, int index, float *co, float *co_movin // call BLI_bvhtree_update_node() first for every node/point/triangle void BLI_bvhtree_update_tree(BVHTree *tree) { - BVHNode *leaf, *parent; - - // reset tree traversing flag - for (leaf = tree->nodearray + tree->totleaf; leaf != tree->nodearray + tree->totleaf + tree->totbranch; leaf++) - leaf->traversed = 0; - - for (leaf = tree->nodearray; leaf != tree->nodearray + tree->totleaf; leaf++) - { - for (parent = leaf->parent; parent; parent = parent->parent) - { - parent->traversed++; // we tried to go up in hierarchy - if (parent->traversed < parent->totnode) - break; // we do not need to check further - else - node_join(tree, parent); - } - } + BVHNode** root = tree->nodes + tree->totleaf; + BVHNode** index = tree->nodes + tree->totleaf + tree->totbranch-1; + + //Update bottom=>top + //TRICKY: the way we build the tree the parent of a child has an index < then the child index + for (; index != root; index--) + node_join(tree, *index); } float BLI_bvhtree_getepsilon(BVHTree *tree) -- cgit v1.2.3 From 2d04b641d4eb6d6e20a72067c1f55f2d4a6cdd9a Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Tue, 5 Aug 2008 18:49:51 +0000 Subject: Just a tmp commit about bvhtree build Theres something broken with BVHtree queries.. updates are not advised at all --- source/blender/blenlib/intern/BLI_kdopbvh.c | 139 +++++++++++++++++++++++++++- 1 file changed, 138 insertions(+), 1 deletion(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 96eb42136fb..9b36051e59f 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -680,10 +680,146 @@ static void verify_tree(BVHTree *tree) printf("branches: %d, leafs: %d, total: %d\n", tree->totbranch, tree->totleaf, tree->totbranch + tree->totleaf); } #endif - + +//Helper data and structures to build generalized implicit trees +//This code can be easily reduced +typedef struct BVHBuildHelper +{ + int tree_type; // + int totleafs; // + + int leafs_per_child [32]; //Min number of leafs that are archievable from a node at depth N + int branches_on_level[32]; //Number of nodes at depth N (tree_type^N) + + int remain_leafs; //Number of leafs that are placed on the level that is not 100% filled + +} BVHBuildHelper; + +static void build_implicit_tree_helper(BVHTree *tree, BVHBuildHelper *data) +{ + int depth = 0; + int remain; + int nnodes; + + data->totleafs = tree->totleaf; + data->tree_type= tree->tree_type; + + //Calculate the smallest tree_type^n such that tree_type^n >= num_leafs + for( + data->leafs_per_child[0] = 1; + data->leafs_per_child[0] < data->totleafs; + data->leafs_per_child[0] *= data->tree_type + ); + + + data->branches_on_level[0] = 1; + + + //We could stop the loop first (but I am lazy to find out when) + for(depth = 1; depth < 32; depth++) + { + data->branches_on_level[depth] = data->branches_on_level[depth-1] * data->tree_type; + data->leafs_per_child [depth] = data->leafs_per_child [depth-1] / data->tree_type; + } + + remain = data->totleafs - data->leafs_per_child[1]; + nnodes = (remain + data->tree_type - 2) / (data->tree_type - 1); + data->remain_leafs = remain + nnodes; +} + +// return the min index of all the leafs archivable with the given branch +static int implicit_leafs_index(BVHBuildHelper *data, int depth, int child_index) +{ + int min_leaf_index = child_index * data->leafs_per_child[depth-1]; + if(min_leaf_index < data->remain_leafs) + return min_leaf_index; + else + return data->totleafs - (data->branches_on_level[depth-1] - child_index) * data->leafs_per_child[depth]; +} + +//WARNING: Beautifull/tricky code starts here :P +//Generalized implicit trees +static void non_recursive_bvh_div_nodes(BVHTree *tree) +{ + int i; + + const int tree_type = tree->tree_type; + const int tree_offset = 2 - tree->tree_type; //this value is 0 (on binary trees) and negative on the others + const int num_leafs = tree->totleaf; + const int num_branches= MAX2(1, (num_leafs + tree_type - 3) / (tree_type-1) ); + + BVHNode* branches_array = tree->nodearray + tree->totleaf - 1; // This ocde uses 1 index arrays + BVHNode** leafs_array = tree->nodes; + + BVHBuildHelper data; + int depth = 0; + + build_implicit_tree_helper(tree, &data); + + //YAY this could be 1 loop.. but had to split in 2 to remove OMP dependencies + for(i=1; i <= num_branches; i = i*tree_type + tree_offset) + { + const int first_of_next_level = i*tree_type + tree_offset; + const int end_j = MIN2(first_of_next_level, num_branches + 1); //index of last branch on this level + int j; + + depth++; + +//#pragma omp parallel for private(j) schedule(static) + for(j = i; j < end_j; j++) + { + int k; + const int parent_level_index= j-i; + BVHNode* parent = branches_array + j; + char split_axis; + + int parent_leafs_begin = implicit_leafs_index(&data, depth, parent_level_index); + int parent_leafs_end = implicit_leafs_index(&data, depth, parent_level_index+1); + + refit_kdop_hull(tree, parent, parent_leafs_begin, parent_leafs_end); + split_axis = get_largest_axis(parent->bv); + parent->main_axis = split_axis / 2; + + for(k = 0; k < tree_type; k++) + { + int child_index = j * tree_type + tree_offset + k; + int child_level_index = child_index - first_of_next_level; //child level index + + int child_leafs_begin = implicit_leafs_index(&data, depth+1, child_level_index); + int child_leafs_end = implicit_leafs_index(&data, depth+1, child_level_index+1); + + assert( k != 0 || child_leafs_begin == parent_leafs_begin); + + if(child_leafs_end - child_leafs_begin > 1) + { + parent->children[k] = branches_array + child_index; + partition_nth_element(leafs_array, child_leafs_begin, parent_leafs_end, child_leafs_end, split_axis); + } + else if(child_leafs_end - child_leafs_begin == 1) + { + parent->children[k] = leafs_array[ child_leafs_begin ]; + } + else + { + parent->children[k] = NULL; + } + } + } + } + tree->nodes[tree->totleaf] = branches_array+0; + tree->totbranch = num_branches; + + +} + void BLI_bvhtree_balance(BVHTree *tree) { assert(tree->totbranch == 0); + assert(tree->totleaf != 0); + + non_recursive_bvh_div_nodes(tree); + printf("here\n"); +/* if(tree->totleaf != 0) { // create root node @@ -698,6 +834,7 @@ void BLI_bvhtree_balance(BVHTree *tree) tree->totbranch = needed_branches( tree->tree_type, tree->totleaf ); // verify_tree(tree); } +*/ } // overlap - is it possbile for 2 bv's to collide ? -- cgit v1.2.3 From e57c5ef56c306fe495346525fb9d1f9bcf8cfd2b Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Wed, 6 Aug 2008 15:46:38 +0000 Subject: Fixed non_recursive BVHbuild with openmp CHanged the BENCH functions to use: gettimeofday (wall time) instead of clock (cpu time) This was to test if the openmp was working right. --- source/blender/blenlib/intern/BLI_kdopbvh.c | 66 +++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 13 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 9b36051e59f..fcac5df934e 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -632,7 +632,22 @@ static void omp_bvh_div_nodes(BVHTree *tree, BVHNode *node, int start, int end, } +static void print_tree(BVHTree *tree, BVHNode *node, int depth) +{ + int i; + for(i=0; iindex, node - tree->nodearray); + for(i=2*tree->start_axis; i<2*tree->stop_axis; i++) + printf("%.3f ", node->bv[i]); + printf("\n"); + + for(i=0; itree_type; i++) + if(node->children[i]) + print_tree(tree, node->children[i], depth+1); +} + #if 0 + static void verify_tree(BVHTree *tree) { int i, j, check = 0; @@ -711,10 +726,8 @@ static void build_implicit_tree_helper(BVHTree *tree, BVHBuildHelper *data) data->leafs_per_child[0] *= data->tree_type ); - data->branches_on_level[0] = 1; - //We could stop the loop first (but I am lazy to find out when) for(depth = 1; depth < 32; depth++) { @@ -731,13 +744,15 @@ static void build_implicit_tree_helper(BVHTree *tree, BVHBuildHelper *data) static int implicit_leafs_index(BVHBuildHelper *data, int depth, int child_index) { int min_leaf_index = child_index * data->leafs_per_child[depth-1]; - if(min_leaf_index < data->remain_leafs) + if(min_leaf_index <= data->remain_leafs) return min_leaf_index; - else + else if(data->leafs_per_child[depth]) return data->totleafs - (data->branches_on_level[depth-1] - child_index) * data->leafs_per_child[depth]; + else + return data->remain_leafs; } -//WARNING: Beautifull/tricky code starts here :P +//WARNING: Beautiful/tricky code starts here :P //Generalized implicit trees static void non_recursive_bvh_div_nodes(BVHTree *tree) { @@ -748,7 +763,7 @@ static void non_recursive_bvh_div_nodes(BVHTree *tree) const int num_leafs = tree->totleaf; const int num_branches= MAX2(1, (num_leafs + tree_type - 3) / (tree_type-1) ); - BVHNode* branches_array = tree->nodearray + tree->totleaf - 1; // This ocde uses 1 index arrays + BVHNode* branches_array = tree->nodearray + tree->totleaf - 1; // This code uses 1 index arrays BVHNode** leafs_array = tree->nodes; BVHBuildHelper data; @@ -765,7 +780,7 @@ static void non_recursive_bvh_div_nodes(BVHTree *tree) depth++; -//#pragma omp parallel for private(j) schedule(static) +#pragma omp parallel for private(j) schedule(static) for(j = i; j < end_j; j++) { int k; @@ -776,8 +791,11 @@ static void non_recursive_bvh_div_nodes(BVHTree *tree) int parent_leafs_begin = implicit_leafs_index(&data, depth, parent_level_index); int parent_leafs_end = implicit_leafs_index(&data, depth, parent_level_index+1); + //split_axis = (depth*2 % 6); //use this instead of the 2 following lines for XYZ splitting + refit_kdop_hull(tree, parent, parent_leafs_begin, parent_leafs_end); split_axis = get_largest_axis(parent->bv); + parent->main_axis = split_axis / 2; for(k = 0; k < tree_type; k++) @@ -792,33 +810,55 @@ static void non_recursive_bvh_div_nodes(BVHTree *tree) if(child_leafs_end - child_leafs_begin > 1) { - parent->children[k] = branches_array + child_index; + parent->children[k] = branches_array + child_index; + +/* + printf("Add child %d (%d) to branch %d\n", + branches_array + child_index - tree->nodearray, + branches_array[ child_index ].index, + parent - tree->nodearray + ); +*/ + partition_nth_element(leafs_array, child_leafs_begin, parent_leafs_end, child_leafs_end, split_axis); } else if(child_leafs_end - child_leafs_begin == 1) { +/* + printf("Add child %d (%d) to branch %d\n", + leafs_array[ child_leafs_begin ] - tree->nodearray, + leafs_array[ child_leafs_begin ]->index, + parent - tree->nodearray + ); +*/ parent->children[k] = leafs_array[ child_leafs_begin ]; } else { parent->children[k] = NULL; + break; } + parent->totnode = k+1; } } } - tree->nodes[tree->totleaf] = branches_array+0; - tree->totbranch = num_branches; + for(i = 0; inodes[tree->totleaf + i] = branches_array + 1 + i; + + tree->totbranch = num_branches; + +// BLI_bvhtree_update_tree(tree); //Uncoment this for XYZ splitting } void BLI_bvhtree_balance(BVHTree *tree) { - assert(tree->totbranch == 0); - assert(tree->totleaf != 0); + if(tree->totleaf == 0) return; + assert(tree->totbranch == 0); non_recursive_bvh_div_nodes(tree); - printf("here\n"); + /* if(tree->totleaf != 0) { -- cgit v1.2.3 From 523634ca17a392a49e324244ee6f35ac2359544b Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Wed, 6 Aug 2008 16:50:07 +0000 Subject: svn merge -r 15908:15988 https://svn.blender.org/svnroot/bf-blender/trunk/blender --- source/blender/blenlib/intern/BLI_kdopbvh.c | 3 ++- source/blender/blenlib/intern/boxpack2d.c | 10 ++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index fcac5df934e..ebc0fb70863 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -865,7 +865,7 @@ void BLI_bvhtree_balance(BVHTree *tree) // create root node BVHNode *node = tree->nodes[tree->totleaf] = &(tree->nodearray[tree->totleaf]); tree->totbranch++; - +< // refit root bvh node refit_kdop_hull(tree, node, 0, tree->totleaf); @@ -875,6 +875,7 @@ void BLI_bvhtree_balance(BVHTree *tree) // verify_tree(tree); } */ + } // overlap - is it possbile for 2 bv's to collide ? diff --git a/source/blender/blenlib/intern/boxpack2d.c b/source/blender/blenlib/intern/boxpack2d.c index acd53e5d516..db7bae8a91d 100644 --- a/source/blender/blenlib/intern/boxpack2d.c +++ b/source/blender/blenlib/intern/boxpack2d.c @@ -42,6 +42,8 @@ #define TRF 2 #define TLF 4 #define BRF 8 +#define CORNERFLAGS (BLF|TRF|TLF|BRF) + #define BL 0 #define TR 1 #define TL 2 @@ -159,7 +161,7 @@ void boxPack2D(boxPack *boxarray, int len, float *tot_width, float *tot_height) vert->blb = vert->brb = vert->tlb =\ vert->isect_cache[0] = vert->isect_cache[1] =\ vert->isect_cache[2] = vert->isect_cache[3] = NULL; - vert->free = 15 &~ TRF; + vert->free = CORNERFLAGS &~ TRF; vert->trb = box; vert->index = i; i++; box->v[BL] = vert; vert++; @@ -167,7 +169,7 @@ void boxPack2D(boxPack *boxarray, int len, float *tot_width, float *tot_height) vert->trb= vert->brb = vert->tlb =\ vert->isect_cache[0] = vert->isect_cache[1] =\ vert->isect_cache[2] = vert->isect_cache[3] = NULL; - vert->free = 15 &~ BLF; + vert->free = CORNERFLAGS &~ BLF; vert->blb = box; vert->index = i; i++; box->v[TR] = vert; vert++; @@ -175,7 +177,7 @@ void boxPack2D(boxPack *boxarray, int len, float *tot_width, float *tot_height) vert->trb = vert->blb = vert->tlb =\ vert->isect_cache[0] = vert->isect_cache[1] =\ vert->isect_cache[2] = vert->isect_cache[3] = NULL; - vert->free = 15 &~ BRF; + vert->free = CORNERFLAGS &~ BRF; vert->brb = box; vert->index = i; i++; box->v[TL] = vert; vert++; @@ -183,7 +185,7 @@ void boxPack2D(boxPack *boxarray, int len, float *tot_width, float *tot_height) vert->trb = vert->blb = vert->brb =\ vert->isect_cache[0] = vert->isect_cache[1] =\ vert->isect_cache[2] = vert->isect_cache[3] = NULL; - vert->free = 15 &~ TLF; + vert->free = CORNERFLAGS &~ TLF; vert->tlb = box; vert->index = i; i++; box->v[BR] = vert; vert++; -- cgit v1.2.3 From 0b533d022d75063efa1e23f3cdad28a0ffa31513 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Thu, 7 Aug 2008 14:26:27 +0000 Subject: Added several comments to BLI_kdopbvh Changed BENCH to print both wall-clock/real time and cpu time --- source/blender/blenlib/intern/BLI_kdopbvh.c | 902 +++++++++++++--------------- 1 file changed, 434 insertions(+), 468 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index ebc0fb70863..7f634def386 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -45,11 +45,11 @@ typedef struct BVHNode { - struct BVHNode **children; // max 8 children + struct BVHNode **children; float *bv; // Bounding volume of all nodes, max 13 axis int index; // face, edge, vertex index char totnode; // how many nodes are used, used for speedup - char main_axis; + char main_axis; // Axis used to split this node } BVHNode; struct BVHTree @@ -281,139 +281,9 @@ int partition_nth_element(BVHNode **a, int _begin, int _end, int n, int axis){ ////////////////////////////////////////////////////////////////////////////////////////////////////// -void BLI_bvhtree_free(BVHTree *tree) -{ - if(tree) - { - MEM_freeN(tree->nodes); - MEM_freeN(tree->nodearray); - MEM_freeN(tree->nodebv); - MEM_freeN(tree->nodechild); - MEM_freeN(tree); - } -} - -// 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 numnodes, i; - - // theres not support for trees below binary-trees :P - if(tree_type < 2) - return NULL; - - tree = (BVHTree *)MEM_callocN(sizeof(BVHTree), "BVHTree"); - - if(tree) - { - tree->epsilon = epsilon; - tree->tree_type = tree_type; - tree->axis = axis; - - if(axis == 26) - { - tree->start_axis = 0; - tree->stop_axis = 13; - } - else if(axis == 18) - { - tree->start_axis = 7; - tree->stop_axis = 13; - } - else if(axis == 14) - { - tree->start_axis = 0; - tree->stop_axis = 7; - } - else if(axis == 8) // AABB - { - tree->start_axis = 0; - tree->stop_axis = 4; - } - else if(axis == 6) // OBB - { - tree->start_axis = 0; - tree->stop_axis = 3; - } - else - { - MEM_freeN(tree); - return NULL; - } - - - //Allocate arrays - numnodes = maxsize + needed_branches(tree_type, maxsize) + tree_type; - - tree->nodes = (BVHNode **)MEM_callocN(sizeof(BVHNode *)*numnodes, "BVHNodes"); - - if(!tree->nodes) - { - MEM_freeN(tree); - return NULL; - } - - 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 * numnodes, "BVHNodeBV"); - if(!tree->nodechild) - { - MEM_freeN(tree->nodebv); - MEM_freeN(tree->nodes); - MEM_freeN(tree); - } - - tree->nodearray = (BVHNode *)MEM_callocN(sizeof(BVHNode)* numnodes, "BVHNodeArray"); - - if(!tree->nodearray) - { - MEM_freeN(tree->nodechild); - MEM_freeN(tree->nodebv); - MEM_freeN(tree->nodes); - MEM_freeN(tree); - return NULL; - } - - //link the dynamic bv and child links - for(i=0; i< numnodes; i++) - { - tree->nodearray[i].bv = tree->nodebv + i * axis; - tree->nodearray[i].children = tree->nodechild + i * tree_type; - } - - } - - return tree; -} - - +/* + * BVHTree bounding volumes functions + */ static void create_kdop_hull(BVHTree *tree, BVHNode *node, float *co, int numpoints, int moving) { float newminmax; @@ -475,36 +345,6 @@ static void refit_kdop_hull(BVHTree *tree, BVHNode *node, int start, int end) } -int BLI_bvhtree_insert(BVHTree *tree, int index, float *co, int numpoints) -{ - 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)/sizeof(*(tree->nodes))) - return 0; - - // TODO check if have enough nodes in array - - node = tree->nodes[tree->totleaf] = &(tree->nodearray[tree->totleaf]); - tree->totleaf++; - - create_kdop_hull(tree, node, co, numpoints, 0); - node->index= index; - - // 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; -} - // only supports x,y,z axis in the moment // but we should use a plain and simple function here for speed sake static char get_largest_axis(float *bv) @@ -530,109 +370,42 @@ static char get_largest_axis(float *bv) } } -static void bvh_div_nodes(BVHTree *tree, BVHNode *node, int start, int end, int free_node_index) +// bottom-up update of bvh node BV +// join the children on the parent BV +static void node_join(BVHTree *tree, BVHNode *node) { - 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 - - assert( node->totnode == 0 ); - - node->main_axis = laxis/2; + int i, j; - // split nodes along longest axis - for (i=0; start < end; node->totnode = ++i) //i counts the current child - { - int tend = start + slice + (i < rest ? 1 : 0); - - assert( tend <= end); - - if(tend-start == 1) // ok, we have 1 left for this node - { - node->children[i] = tree->nodes[start]; - } - else - { - BVHNode *tnode = 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); - - refit_kdop_hull(tree, tnode, start, tend); - - bvh_div_nodes(tree, tnode, start, tend, free_node_index+1); - free_node_index += needed_branches(tree->tree_type, tend-start); - } - start = tend; + for (i = tree->start_axis; i < tree->stop_axis; i++) + { + node->bv[2*i] = FLT_MAX; + node->bv[2*i + 1] = -FLT_MAX; } - 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]; - } - 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++) + for (i = 0; i < tree->tree_type; i++) { - if(omp_data_end[i]-omp_data_start[i] > 1) + if (node->children[i]) { - 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); + for (j = tree->start_axis; j < tree->stop_axis; j++) + { + // update minimum + if (node->children[i]->bv[(2 * j)] < node->bv[(2 * j)]) + node->bv[(2 * j)] = node->children[i]->bv[(2 * j)]; + + // update maximum + if (node->children[i]->bv[(2 * j) + 1] > node->bv[(2 * j) + 1]) + node->bv[(2 * j) + 1] = node->children[i]->bv[(2 * j) + 1]; + } } + else + break; } - - return; } - -static void print_tree(BVHTree *tree, BVHNode *node, int depth) +/* + * Debug and information functions + */ +static void bvhtree_print_tree(BVHTree *tree, BVHNode *node, int depth) { int i; for(i=0; itree_type; i++) if(node->children[i]) - print_tree(tree, node->children[i], depth+1); + bvhtree_print_tree(tree, node->children[i], depth+1); +} + +static void bvhtree_info(BVHTree *tree) +{ + printf("BVHTree info\n"); + printf("tree_type = %d, axis = %d, epsilon = %f\n", tree->tree_type, tree->axis, tree->epsilon); + printf("nodes = %d, branches = %d, leafs = %d\n", tree->totbranch + tree->totleaf, tree->totbranch, tree->totleaf); + printf("Memory per node = %dbytes\n", sizeof(BVHNode) + sizeof(BVHNode*)*tree->tree_type + sizeof(float)*tree->axis); + printf("BV memory = %dbytes\n", MEM_allocN_len(tree->nodebv)); + + printf("Total memory = %dbytes\n", sizeof(BVHTree) + + MEM_allocN_len(tree->nodes) + + MEM_allocN_len(tree->nodearray) + + MEM_allocN_len(tree->nodechild) + + MEM_allocN_len(tree->nodebv) + ); + +// bvhtree_print_tree(tree, tree->nodes[tree->totleaf], 0); } #if 0 + static void verify_tree(BVHTree *tree) { int i, j, check = 0; @@ -696,8 +488,8 @@ static void verify_tree(BVHTree *tree) } #endif -//Helper data and structures to build generalized implicit trees -//This code can be easily reduced +//Helper data and structures to build a min-leaf generalized implicit tree +//This code can be easily reduced (basicly this is only method to calculate pow(k, n) in O(1).. and sutff like that) typedef struct BVHBuildHelper { int tree_type; // @@ -726,158 +518,405 @@ static void build_implicit_tree_helper(BVHTree *tree, BVHBuildHelper *data) data->leafs_per_child[0] *= data->tree_type ); - data->branches_on_level[0] = 1; + data->branches_on_level[0] = 1; + + //We could stop the loop first (but I am lazy to find out when) + for(depth = 1; depth < 32; depth++) + { + data->branches_on_level[depth] = data->branches_on_level[depth-1] * data->tree_type; + data->leafs_per_child [depth] = data->leafs_per_child [depth-1] / data->tree_type; + } + + remain = data->totleafs - data->leafs_per_child[1]; + nnodes = (remain + data->tree_type - 2) / (data->tree_type - 1); + data->remain_leafs = remain + nnodes; +} + +// return the min index of all the leafs archivable with the given branch +static int implicit_leafs_index(BVHBuildHelper *data, int depth, int child_index) +{ + int min_leaf_index = child_index * data->leafs_per_child[depth-1]; + if(min_leaf_index <= data->remain_leafs) + return min_leaf_index; + else if(data->leafs_per_child[depth]) + return data->totleafs - (data->branches_on_level[depth-1] - child_index) * data->leafs_per_child[depth]; + else + return data->remain_leafs; +} + +/** + * Generalized implicit tree build + * + * An implicit tree is a tree where its structure is implied, thus there is no need to store child pointers or indexs. + * Its possible to find the position of the child or the parent with simple maths (multiplication and adittion). This type + * of tree is for example used on heaps.. where node N has its childs at indexs N*2 and N*2+1. + * + * Altought in this case the tree type is general.. and not know until runtime. + * tree_type stands for the maximum number of childs that a tree node can have. + * All tree types >= 2 are supported. + * + * Advantages of the used trees include: + * - No need to store child/parent relations (they are implicit); + * - Any node child always has an index greater than the parent; + * - Brother nodes are sequencial in memory; + * + * + * Some math relations derived for general implicit trees: + * + * K = tree_type, ( 2 <= K ) + * ROOT = 1 + * N child of node A = A * K + (2 - K) + N, (0 <= N < K) + * + * Util methods: + * TODO... + * (looping elements, knowing if its a leaf or not.. etc...) + */ + +// This functions returns the number of branches needed to have the requested number of leafs. +static int implicit_needed_branches(int tree_type, int leafs) +{ + return MAX2(1, (leafs + tree_type - 3) / (tree_type-1) ); +} + +/* + * This function handles the problem of "sorting" the leafs (along the split_axis). + * + * It arranges the elements in the given partitions such that: + * - any element in partition N is less or equal to any element in partition N+1. + * - if all elements are diferent all partition will get the same subset of elements + * as if the array was sorted. + * + * partition P is described as the elements in the range ( nth[P] , nth[P+1] ] + * + * TODO: This can be optimized a bit by doing a specialized nth_element instead of K nth_elements + */ +static void split_leafs(BVHNode **leafs_array, int *nth, int partitions, int split_axis) +{ + int i; + for(i=0; i < partitions-1; i++) + { + if(nth[i] >= nth[partitions]) + break; + + partition_nth_element(leafs_array, nth[i], nth[partitions], nth[i+1], split_axis); + } +} + +/* + * This functions builds an optimal implicit tree from the given leafs. + * Where optimal stands for: + * - The resulting tree will have the smallest number of branches; + * - At most only one branch will have NULL childs; + * - All leafs will be stored at level N or N+1. + * + * This function creates an implicit tree on branches_array, the leafs are given on the leafs_array. + * + * The tree is built per depth levels. First branchs at depth 1.. then branches at depth 2.. etc.. + * The reason is that we can build level N+1 from level N witouth any data dependencies.. thus it allows + * to use multithread building. + * + * To archieve this is necessary to find how much leafs are accessible from a certain branch, BVHBuildHelper + * implicit_needed_branches and implicit_leafs_index are auxiliar functions to solve that "optimal-split". + */ +static void non_recursive_bvh_div_nodes(BVHTree *tree, BVHNode *branches_array, BVHNode **leafs_array, int num_leafs) +{ + int i; + + const int tree_type = tree->tree_type; + const int tree_offset = 2 - tree->tree_type; //this value is 0 (on binary trees) and negative on the others + const int num_branches= implicit_needed_branches(tree_type, num_leafs); + + BVHBuildHelper data; + int depth; + + branches_array--; //Implicit trees use 1-based indexs + + build_implicit_tree_helper(tree, &data); + + //Loop tree levels (log N) loops + for(i=1, depth = 1; i <= num_branches; i = i*tree_type + tree_offset, depth++) + { + const int first_of_next_level = i*tree_type + tree_offset; + const int end_j = MIN2(first_of_next_level, num_branches + 1); //index of last branch on this level + int j; + + //Loop all branches on this level +#pragma omp parallel for private(j) schedule(static) + for(j = i; j < end_j; j++) + { + int k; + const int parent_level_index= j-i; + BVHNode* parent = branches_array + j; + int nth_positions[ tree_type + 1 ]; + char split_axis; + + int parent_leafs_begin = implicit_leafs_index(&data, depth, parent_level_index); + int parent_leafs_end = implicit_leafs_index(&data, depth, parent_level_index+1); + + //This calculates the bounding box of this branch + //and chooses the largest axis as the axis to divide leafs + refit_kdop_hull(tree, parent, parent_leafs_begin, parent_leafs_end); + split_axis = get_largest_axis(parent->bv); + + //Save split axis (this can be used on raytracing to speedup the query time) + parent->main_axis = split_axis / 2; + + //Split the childs along the split_axis, note: its not needed to sort the whole leafs array + //Only to assure that the elements are partioned on a way that each child takes the elements + //it would take in case the whole array was sorted. + //Split_leafs takes care of that "sort" problem. + nth_positions[ 0] = parent_leafs_begin; + nth_positions[tree_type] = parent_leafs_end; + for(k = 1; k < tree_type; k++) + { + int child_index = j * tree_type + tree_offset + k; + int child_level_index = child_index - first_of_next_level; //child level index + nth_positions[k] = implicit_leafs_index(&data, depth+1, child_level_index); + } + + split_leafs(leafs_array, nth_positions, tree_type, split_axis); + + + //Setup children and totnode counters + //Not really needed but currently most of BVH code relies on having an explicit children structure + for(k = 0; k < tree_type; k++) + { + int child_index = j * tree_type + tree_offset + k; + int child_level_index = child_index - first_of_next_level; //child level index + + int child_leafs_begin = implicit_leafs_index(&data, depth+1, child_level_index); + int child_leafs_end = implicit_leafs_index(&data, depth+1, child_level_index+1); + + if(child_leafs_end - child_leafs_begin > 1) + parent->children[k] = branches_array + child_index; + else if(child_leafs_end - child_leafs_begin == 1) + parent->children[k] = leafs_array[ child_leafs_begin ]; + else + break; + + parent->totnode = k+1; + } + } + } +} + + +/* + * BLI_bvhtree api + */ +BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis) +{ + BVHTree *tree; + int numnodes, i; + + // theres not support for trees below binary-trees :P + if(tree_type < 2) + return NULL; + + tree = (BVHTree *)MEM_callocN(sizeof(BVHTree), "BVHTree"); + + if(tree) + { + tree->epsilon = epsilon; + tree->tree_type = tree_type; + tree->axis = axis; + + if(axis == 26) + { + tree->start_axis = 0; + tree->stop_axis = 13; + } + else if(axis == 18) + { + tree->start_axis = 7; + tree->stop_axis = 13; + } + else if(axis == 14) + { + tree->start_axis = 0; + tree->stop_axis = 7; + } + else if(axis == 8) // AABB + { + tree->start_axis = 0; + tree->stop_axis = 4; + } + else if(axis == 6) // OBB + { + tree->start_axis = 0; + tree->stop_axis = 3; + } + else + { + MEM_freeN(tree); + return NULL; + } + + + //Allocate arrays + numnodes = maxsize + implicit_needed_branches(tree_type, maxsize) + tree_type; + + tree->nodes = (BVHNode **)MEM_callocN(sizeof(BVHNode *)*numnodes, "BVHNodes"); + + if(!tree->nodes) + { + MEM_freeN(tree); + return NULL; + } + + 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 * numnodes, "BVHNodeBV"); + if(!tree->nodechild) + { + MEM_freeN(tree->nodebv); + MEM_freeN(tree->nodes); + MEM_freeN(tree); + } + + tree->nodearray = (BVHNode *)MEM_callocN(sizeof(BVHNode)* numnodes, "BVHNodeArray"); + + if(!tree->nodearray) + { + MEM_freeN(tree->nodechild); + MEM_freeN(tree->nodebv); + MEM_freeN(tree->nodes); + MEM_freeN(tree); + return NULL; + } - //We could stop the loop first (but I am lazy to find out when) - for(depth = 1; depth < 32; depth++) - { - data->branches_on_level[depth] = data->branches_on_level[depth-1] * data->tree_type; - data->leafs_per_child [depth] = data->leafs_per_child [depth-1] / data->tree_type; + //link the dynamic bv and child links + for(i=0; i< numnodes; i++) + { + tree->nodearray[i].bv = tree->nodebv + i * axis; + tree->nodearray[i].children = tree->nodechild + i * tree_type; + } + } - remain = data->totleafs - data->leafs_per_child[1]; - nnodes = (remain + data->tree_type - 2) / (data->tree_type - 1); - data->remain_leafs = remain + nnodes; + return tree; } -// return the min index of all the leafs archivable with the given branch -static int implicit_leafs_index(BVHBuildHelper *data, int depth, int child_index) -{ - int min_leaf_index = child_index * data->leafs_per_child[depth-1]; - if(min_leaf_index <= data->remain_leafs) - return min_leaf_index; - else if(data->leafs_per_child[depth]) - return data->totleafs - (data->branches_on_level[depth-1] - child_index) * data->leafs_per_child[depth]; - else - return data->remain_leafs; +void BLI_bvhtree_free(BVHTree *tree) +{ + if(tree) + { + MEM_freeN(tree->nodes); + MEM_freeN(tree->nodearray); + MEM_freeN(tree->nodebv); + MEM_freeN(tree->nodechild); + MEM_freeN(tree); + } } -//WARNING: Beautiful/tricky code starts here :P -//Generalized implicit trees -static void non_recursive_bvh_div_nodes(BVHTree *tree) +void BLI_bvhtree_balance(BVHTree *tree) { int i; - const int tree_type = tree->tree_type; - const int tree_offset = 2 - tree->tree_type; //this value is 0 (on binary trees) and negative on the others - const int num_leafs = tree->totleaf; - const int num_branches= MAX2(1, (num_leafs + tree_type - 3) / (tree_type-1) ); - - BVHNode* branches_array = tree->nodearray + tree->totleaf - 1; // This code uses 1 index arrays + BVHNode* branches_array = tree->nodearray + tree->totleaf; BVHNode** leafs_array = tree->nodes; - BVHBuildHelper data; - int depth = 0; - - build_implicit_tree_helper(tree, &data); - - //YAY this could be 1 loop.. but had to split in 2 to remove OMP dependencies - for(i=1; i <= num_branches; i = i*tree_type + tree_offset) - { - const int first_of_next_level = i*tree_type + tree_offset; - const int end_j = MIN2(first_of_next_level, num_branches + 1); //index of last branch on this level - int j; - - depth++; - -#pragma omp parallel for private(j) schedule(static) - for(j = i; j < end_j; j++) - { - int k; - const int parent_level_index= j-i; - BVHNode* parent = branches_array + j; - char split_axis; - - int parent_leafs_begin = implicit_leafs_index(&data, depth, parent_level_index); - int parent_leafs_end = implicit_leafs_index(&data, depth, parent_level_index+1); - - //split_axis = (depth*2 % 6); //use this instead of the 2 following lines for XYZ splitting - - refit_kdop_hull(tree, parent, parent_leafs_begin, parent_leafs_end); - split_axis = get_largest_axis(parent->bv); + //This function should only be called once (some big bug goes here if its being called more than once per tree) + assert(tree->totbranch == 0); - parent->main_axis = split_axis / 2; + //Build the implicit tree + non_recursive_bvh_div_nodes(tree, branches_array, leafs_array, tree->totleaf); - for(k = 0; k < tree_type; k++) - { - int child_index = j * tree_type + tree_offset + k; - int child_level_index = child_index - first_of_next_level; //child level index + //current code expects the branches to be linked to the nodes array + //we perform that linkage here + tree->totbranch = implicit_needed_branches(tree->tree_type, tree->totleaf); + for(i = 0; i < tree->totbranch; i++) + tree->nodes[tree->totleaf + i] = branches_array + i; - int child_leafs_begin = implicit_leafs_index(&data, depth+1, child_level_index); - int child_leafs_end = implicit_leafs_index(&data, depth+1, child_level_index+1); + //bvhtree_info(tree); +} - assert( k != 0 || child_leafs_begin == parent_leafs_begin); +int BLI_bvhtree_insert(BVHTree *tree, int index, float *co, int numpoints) +{ + 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)/sizeof(*(tree->nodes))) + return 0; + + // TODO check if have enough nodes in array + + node = tree->nodes[tree->totleaf] = &(tree->nodearray[tree->totleaf]); + tree->totleaf++; + + create_kdop_hull(tree, node, co, numpoints, 0); + node->index= index; + + // 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 + } - if(child_leafs_end - child_leafs_begin > 1) - { - parent->children[k] = branches_array + child_index; + return 1; +} -/* - printf("Add child %d (%d) to branch %d\n", - branches_array + child_index - tree->nodearray, - branches_array[ child_index ].index, - parent - tree->nodearray - ); -*/ - partition_nth_element(leafs_array, child_leafs_begin, parent_leafs_end, child_leafs_end, split_axis); - } - else if(child_leafs_end - child_leafs_begin == 1) - { -/* - printf("Add child %d (%d) to branch %d\n", - leafs_array[ child_leafs_begin ] - tree->nodearray, - leafs_array[ child_leafs_begin ]->index, - parent - tree->nodearray - ); -*/ - parent->children[k] = leafs_array[ child_leafs_begin ]; - } - else - { - parent->children[k] = NULL; - break; - } - parent->totnode = k+1; - } - } +// call before BLI_bvhtree_update_tree() +int BLI_bvhtree_update_node(BVHTree *tree, int index, float *co, float *co_moving, int numpoints) +{ + int i; + BVHNode *node= NULL; + + // check if index exists + if(index > tree->totleaf) + return 0; + + node = tree->nodearray + index; + + create_kdop_hull(tree, node, co, numpoints, 0); + + 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; +} - for(i = 0; inodes[tree->totleaf + i] = branches_array + 1 + i; +// call BLI_bvhtree_update_node() first for every node/point/triangle +void BLI_bvhtree_update_tree(BVHTree *tree) +{ + //Update bottom=>top + //TRICKY: the way we build the tree all the childs have an index greater than the parent + //This allows us todo a bottom up update by starting on the biger numbered branch - tree->totbranch = num_branches; + BVHNode** root = tree->nodes + tree->totleaf; + BVHNode** index = tree->nodes + tree->totleaf + tree->totbranch-1; -// BLI_bvhtree_update_tree(tree); //Uncoment this for XYZ splitting + for (; index != root; index--) + node_join(tree, *index); } -void BLI_bvhtree_balance(BVHTree *tree) +float BLI_bvhtree_getepsilon(BVHTree *tree) { - if(tree->totleaf == 0) return; + return tree->epsilon; +} - assert(tree->totbranch == 0); - non_recursive_bvh_div_nodes(tree); /* - if(tree->totleaf != 0) - { - // create root node - BVHNode *node = tree->nodes[tree->totleaf] = &(tree->nodearray[tree->totleaf]); - tree->totbranch++; -< - // 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); - } -*/ - -} - + * BLI_bvhtree_overlap + */ // overlap - is it possbile for 2 bv's to collide ? static int tree_overlap(BVHNode *node1, BVHNode *node2, int start_axis, int stop_axis) { @@ -1015,86 +1054,8 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result) } -// bottom up update of bvh tree: -// join the 4 children here -static void node_join(BVHTree *tree, BVHNode *node) -{ - int i, j; - - for (i = tree->start_axis; i < tree->stop_axis; i++) - { - node->bv[2*i] = FLT_MAX; - node->bv[2*i + 1] = -FLT_MAX; - } - - for (i = 0; i < tree->tree_type; i++) - { - if (node->children[i]) - { - for (j = tree->start_axis; j < tree->stop_axis; j++) - { - // update minimum - if (node->children[i]->bv[(2 * j)] < node->bv[(2 * j)]) - node->bv[(2 * j)] = node->children[i]->bv[(2 * j)]; - - // update maximum - if (node->children[i]->bv[(2 * j) + 1] > node->bv[(2 * j) + 1]) - node->bv[(2 * j) + 1] = node->children[i]->bv[(2 * j) + 1]; - } - } - else - break; - } -} - -// call before BLI_bvhtree_update_tree() -int BLI_bvhtree_update_node(BVHTree *tree, int index, float *co, float *co_moving, int numpoints) -{ - int i; - BVHNode *node= NULL; - - // check if index exists - if(index > tree->totleaf) - return 0; - - node = tree->nodearray + index; - - create_kdop_hull(tree, node, co, numpoints, 0); - - 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; -} - -// call BLI_bvhtree_update_node() first for every node/point/triangle -void BLI_bvhtree_update_tree(BVHTree *tree) -{ - BVHNode** root = tree->nodes + tree->totleaf; - BVHNode** index = tree->nodes + tree->totleaf + tree->totbranch-1; - - //Update bottom=>top - //TRICKY: the way we build the tree the parent of a child has an index < then the child index - for (; index != root; index--) - node_join(tree, *index); -} - -float BLI_bvhtree_getepsilon(BVHTree *tree) -{ - return tree->epsilon; -} - - - /* - * Nearest neighbour + * Nearest neighbour - BLI_bvhtree_find_nearest */ static float squared_dist(const float *a, const float *b) { @@ -1103,6 +1064,7 @@ static float squared_dist(const float *a, const float *b) return INPR(tmp, tmp); } +//Determines the nearest point of the given node BV. Returns the squared distance to that point. static float calc_nearest_point(BVHNearestData *data, BVHNode *node, float *nearest) { int i; @@ -1174,6 +1136,7 @@ int BLI_bvhtree_find_nearest(BVHTree *tree, const float *co, BVHTreeNearest *nea int i; BVHNearestData data; + BVHNode* root = tree->nodes[tree->totleaf]; //init data to search data.tree = tree; @@ -1198,7 +1161,8 @@ int BLI_bvhtree_find_nearest(BVHTree *tree, const float *co, BVHTreeNearest *nea } //dfs search - dfs_find_nearest(&data, tree->nodes[tree->totleaf] ); + if(root) + dfs_find_nearest(&data, root); //copy back results if(nearest) @@ -1210,11 +1174,13 @@ int BLI_bvhtree_find_nearest(BVHTree *tree, const float *co, BVHTreeNearest *nea } - /* - * Ray cast + * Raycast - BLI_bvhtree_ray_cast + * + * raycast is done by performing a DFS on the BVHTree and saving the closest hit */ +//Determines the distance that the ray must travel to hit the bounding volume of the given node static float ray_nearest_hit(BVHRayCastData *data, BVHNode *node) { int i; @@ -1293,12 +1259,11 @@ static void dfs_raycast(BVHRayCastData *data, BVHNode *node) } } - - int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata) { int i; BVHRayCastData data; + BVHNode * root = tree->nodes[tree->totleaf]; data.tree = tree; @@ -1327,7 +1292,8 @@ int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, BVHTr data.hit.dist = FLT_MAX; } - dfs_raycast(&data, tree->nodes[tree->totleaf]); + if(root) + dfs_raycast(&data, root); if(hit) -- cgit v1.2.3 From 7e7d416f4d4f7bdf4e31f7bf87eabbd9fe26c16d Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Mon, 11 Aug 2008 13:29:38 +0000 Subject: svn merge -r 15988:16055 https://svn.blender.org/svnroot/bf-blender/trunk/blender --- source/blender/blenlib/BLI_kdopbvh.h | 2 ++ source/blender/blenlib/intern/BLI_kdopbvh.c | 18 ++++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h index 6d9c82a9626..6d9a17efebf 100644 --- a/source/blender/blenlib/BLI_kdopbvh.h +++ b/source/blender/blenlib/BLI_kdopbvh.h @@ -1,4 +1,6 @@ /** + * + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 7f634def386..9671551a7f1 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -43,6 +43,10 @@ #include #endif + + +#define MAX_TREETYPE 32 + typedef struct BVHNode { struct BVHNode **children; @@ -71,6 +75,7 @@ typedef struct BVHOverlapData BVHTree *tree1, *tree2; BVHTreeOverlap *overlap; int i, max_overlap; /* i is number of overlaps */ + int start_axis, stop_axis; } BVHOverlapData; typedef struct BVHNearestData @@ -489,7 +494,7 @@ static void verify_tree(BVHTree *tree) #endif //Helper data and structures to build a min-leaf generalized implicit tree -//This code can be easily reduced (basicly this is only method to calculate pow(k, n) in O(1).. and sutff like that) +//This code can be easily reduced (basicly this is only method to calculate pow(k, n) in O(1).. and stuff like that) typedef struct BVHBuildHelper { int tree_type; // @@ -647,7 +652,7 @@ static void non_recursive_bvh_div_nodes(BVHTree *tree, BVHNode *branches_array, int k; const int parent_level_index= j-i; BVHNode* parent = branches_array + j; - int nth_positions[ tree_type + 1 ]; + int nth_positions[ MAX_TREETYPE + 1]; char split_axis; int parent_leafs_begin = implicit_leafs_index(&data, depth, parent_level_index); @@ -712,6 +717,9 @@ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis) // theres not support for trees below binary-trees :P if(tree_type < 2) return NULL; + + if(tree_type > MAX_TREETYPE) + return NULL; tree = (BVHTree *)MEM_callocN(sizeof(BVHTree), "BVHTree"); @@ -904,7 +912,7 @@ void BLI_bvhtree_update_tree(BVHTree *tree) BVHNode** root = tree->nodes + tree->totleaf; BVHNode** index = tree->nodes + tree->totleaf + tree->totbranch-1; - for (; index != root; index--) + for (; index >= root; index--) node_join(tree, *index); } @@ -942,7 +950,7 @@ static void traverse(BVHOverlapData *data, BVHNode *node1, BVHNode *node2) { int j; - if(tree_overlap(node1, node2, MIN2(data->tree1->start_axis, data->tree2->start_axis), MIN2(data->tree1->stop_axis, data->tree2->stop_axis))) + if(tree_overlap(node1, node2, data->start_axis, data->stop_axis)) { // check if node1 is a leaf if(!node1->totnode) @@ -1023,6 +1031,8 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result) data[j]->tree2 = tree2; data[j]->max_overlap = MAX2(tree1->totleaf, tree2->totleaf); data[j]->i = 0; + data[j]->start_axis = MIN2(tree1->start_axis, tree2->start_axis); + data[j]->stop_axis = MIN2(tree1->stop_axis, tree2->stop_axis ); } #pragma omp parallel for private(j) schedule(static) -- cgit v1.2.3 From c37923c7a386f8cdb8ad61e475821253e793da95 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Thu, 14 Aug 2008 15:37:47 +0000 Subject: Fixed bug related to some missed rays-hits.. just a lack of a FLT_EPSILON --- source/blender/blenlib/intern/BLI_kdopbvh.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 9671551a7f1..d0db13371b0 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -722,6 +722,11 @@ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis) return NULL; tree = (BVHTree *)MEM_callocN(sizeof(BVHTree), "BVHTree"); + + //tree epsilon must be >= FLT_EPSILON + //so that tangent rays can still hit a bounding volume.. + //this bug would show up when casting a ray aligned with a kdop-axis and with an edge of 2 faces + epsilon = MAX2(FLT_EPSILON, epsilon); if(tree) { @@ -1212,7 +1217,7 @@ static float ray_nearest_hit(BVHRayCastData *data, BVHNode *node) float ll = (bv[0] - data->ray.origin[i]) / data->ray_dot_axis[i]; float lu = (bv[1] - data->ray.origin[i]) / data->ray_dot_axis[i]; - if(data->ray_dot_axis[i] > 0) + if(data->ray_dot_axis[i] > 0.0f) { if(ll > low) low = ll; if(lu < upper) upper = lu; @@ -1252,7 +1257,7 @@ static void dfs_raycast(BVHRayCastData *data, BVHNode *node) else { //pick loop direction to dive into the tree (based on ray direction and split axis) - if(data->ray_dot_axis[ node->main_axis ] > 0) + if(data->ray_dot_axis[ node->main_axis ] > 0.0f) { for(i=0; i != node->totnode; i++) { @@ -1289,7 +1294,7 @@ int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, BVHTr { data.ray_dot_axis[i] = INPR( data.ray.direction, KDOP_AXES[i]); - if(fabs(data.ray_dot_axis[i]) < 1e-7) + if(fabs(data.ray_dot_axis[i]) < FLT_EPSILON) data.ray_dot_axis[i] = 0.0; } -- cgit v1.2.3 From fd0072e77cd28d52e00ea77542ba6d11018889b5 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Sun, 17 Aug 2008 17:08:00 +0000 Subject: Win64: please check my changes if you ran across them ;) But should be fine since no additional crashes were reported! --- source/blender/blenlib/BLI_editVert.h | 8 +++++--- source/blender/blenlib/intern/BLI_ghash.c | 6 +----- source/blender/blenlib/intern/fileops.c | 6 ++++-- source/blender/blenlib/intern/psfont.c | 2 +- source/blender/blenlib/intern/util.c | 8 ++++---- 5 files changed, 15 insertions(+), 15 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/BLI_editVert.h b/source/blender/blenlib/BLI_editVert.h index d42663e17c7..447f6a2a485 100644 --- a/source/blender/blenlib/BLI_editVert.h +++ b/source/blender/blenlib/BLI_editVert.h @@ -38,6 +38,8 @@ #include "DNA_customdata_types.h" #include "DNA_mesh_types.h" +#include "BLO_sys_types.h" // for intptr_t support + struct DerivedMesh; struct RetopoPaintData; @@ -53,7 +55,7 @@ typedef struct EditVert struct EditEdge *e; struct EditFace *f; void *p; - long l; + intptr_t l; float fp; } tmp; float no[3]; /*vertex normal */ @@ -95,7 +97,7 @@ typedef struct EditEdge struct EditEdge *e; struct EditFace *f; void *p; - long l; + intptr_t l; float fp; } tmp; short f1, f2; /* short, f1 is (ab)used in subdiv */ @@ -122,7 +124,7 @@ typedef struct EditFace struct EditEdge *e; struct EditFace *f; void *p; - long l; + intptr_t l; float fp; } tmp; float n[3], cent[3]; diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index 227cb8f5e9a..4a05285e504 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -256,11 +256,7 @@ int BLI_ghashutil_ptrcmp(void *a, void *b) { } unsigned int BLI_ghashutil_inthash(void *ptr) { -#if defined(_WIN64) - unsigned __int64 key = (unsigned __int64)ptr; -#else - unsigned long key = (unsigned long)ptr; -#endif + uintptr_t key = (uintptr_t)ptr; key += ~(key << 16); key ^= (key >> 5); diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c index 96de5e99f4f..2acbbbe6712 100644 --- a/source/blender/blenlib/intern/fileops.c +++ b/source/blender/blenlib/intern/fileops.c @@ -62,6 +62,8 @@ #include "BKE_utildefines.h" #include +#include "BLO_sys_types.h" // for intptr_t support + /* implementations: */ char *first_slash(char *string) { char *ffslash, *fbslash; @@ -72,7 +74,7 @@ char *first_slash(char *string) { if (!ffslash) return fbslash; else if (!fbslash) return ffslash; - if ((long)ffslash < (long)fbslash) return ffslash; + if ((intptr_t)ffslash < (intptr_t)fbslash) return ffslash; else return fbslash; } @@ -85,7 +87,7 @@ char *BLI_last_slash(const char *string) { if (!lfslash) return lbslash; else if (!lbslash) return lfslash; - if ((long)lfslash < (long)lbslash) return lbslash; + if ((intptr_t)lfslash < (intptr_t)lbslash) return lbslash; else return lfslash; } diff --git a/source/blender/blenlib/intern/psfont.c b/source/blender/blenlib/intern/psfont.c index 498c87cdef9..a31d0a4d8ec 100644 --- a/source/blender/blenlib/intern/psfont.c +++ b/source/blender/blenlib/intern/psfont.c @@ -54,7 +54,7 @@ typedef struct chardesc { short llx, lly; /* bounding box */ short urx, ury; short *data; /* char data */ - long datalen; + intptr_t datalen; } chardesc; typedef struct objfnt { diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c index 48ebf770e1b..a31121148e3 100644 --- a/source/blender/blenlib/intern/util.c +++ b/source/blender/blenlib/intern/util.c @@ -1970,7 +1970,7 @@ void BLI_timestr(double _time, char *str) int BLI_int_from_pointer(void *poin) { - long lval= (long)poin; + intptr_t lval= (intptr_t)poin; return (int)(lval>>3); } @@ -1978,17 +1978,17 @@ int BLI_int_from_pointer(void *poin) void *BLI_pointer_from_int(int val) { static int firsttime= 1; - static long basevalue= 0; + static intptr_t basevalue= 0; if(firsttime) { void *poin= malloc(10000); - basevalue= (long)poin; + basevalue= (intptr_t)poin; basevalue &= ~PMASK; printf("base: %d pointer %p\n", basevalue, poin); /* debug */ firsttime= 0; free(poin); } - return (void *)(basevalue | (((long)val)<<3)); + return (void *)(basevalue | (((intptr_t)val)<<3)); } #else -- cgit v1.2.3 From 62845c3d52b3d884352af18910a0478cb7443e52 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Sun, 17 Aug 2008 17:16:49 +0000 Subject: Win64: forget include => this compile errors never showed up on msvc (if anyone wonders) --- source/blender/blenlib/intern/BLI_ghash.c | 2 ++ source/blender/blenlib/intern/psfont.c | 2 ++ 2 files changed, 4 insertions(+) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index 4a05285e504..e9271ca3bb5 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -34,6 +34,8 @@ #include "MEM_guardedalloc.h" #include "BLI_ghash.h" +#include "BLO_sys_types.h" // for intptr_t support + #ifdef HAVE_CONFIG_H #include #endif diff --git a/source/blender/blenlib/intern/psfont.c b/source/blender/blenlib/intern/psfont.c index a31d0a4d8ec..216246dcdd7 100644 --- a/source/blender/blenlib/intern/psfont.c +++ b/source/blender/blenlib/intern/psfont.c @@ -43,6 +43,8 @@ #include "DNA_packedFile_types.h" #include "DNA_curve_types.h" +#include "BLO_sys_types.h" // for intptr_t support + #ifdef HAVE_CONFIG_H #include #endif -- cgit v1.2.3 From 89a735e4f80c59d8faeae04ff11d66572da107b4 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Sun, 17 Aug 2008 23:48:16 +0000 Subject: BVHTree fix (non 2.47) It was building incorrect trees when there was only 1 leaf. Code fixed to always generate a tree with at least 1 branch.. since most of bvh code relies on this. --- source/blender/blenlib/intern/BLI_kdopbvh.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 9671551a7f1..49f3c3cc9e6 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -634,6 +634,18 @@ static void non_recursive_bvh_div_nodes(BVHTree *tree, BVHNode *branches_array, BVHBuildHelper data; int depth; + //Most of bvhtree code relies on 1-leaf trees having at least one branch + //We handle that special case here + if(num_leafs == 1) + { + BVHNode *root = branches_array+0; + refit_kdop_hull(tree, root, 0, num_leafs); + root->main_axis = get_largest_axis(root->bv) / 2; + root->totnode = 1; + root->children[0] = leafs_array[0]; + return; + } + branches_array--; //Implicit trees use 1-based indexs build_implicit_tree_helper(tree, &data); -- cgit v1.2.3 From d5a890c078c770906e49239e3cbac89bf11ebd8d Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 18 Aug 2008 11:09:27 +0000 Subject: a) New unified effector system by Janne (jahka) + Me (genscher): particle and cloth/sb don't use different systems anymore. b) cloth wind corrected for new system c) Wind has noise option now d) @ Bjornmose: since the old factors are gone SB doesn't need to divide by 1000 etc. anymore. I didn't want to touch your code - you might like to take a look at it :) --- source/blender/blenlib/BLI_rand.h | 1 + source/blender/blenlib/intern/rand.c | 18 +++++++++++------- 2 files changed, 12 insertions(+), 7 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/BLI_rand.h b/source/blender/blenlib/BLI_rand.h index 0e534783c17..266aa347aff 100644 --- a/source/blender/blenlib/BLI_rand.h +++ b/source/blender/blenlib/BLI_rand.h @@ -44,6 +44,7 @@ struct RNG* rng_new (unsigned int seed); void rng_free (struct RNG* rng); void rng_seed (struct RNG* rng, unsigned int seed); +void rng_srandom(struct RNG *rng, unsigned int seed); int rng_getInt (struct RNG* rng); double rng_getDouble (struct RNG* rng); float rng_getFloat (struct RNG* rng); diff --git a/source/blender/blenlib/intern/rand.c b/source/blender/blenlib/intern/rand.c index ccc478203fe..c484a307393 100644 --- a/source/blender/blenlib/intern/rand.c +++ b/source/blender/blenlib/intern/rand.c @@ -81,6 +81,16 @@ void rng_seed(RNG *rng, unsigned int seed) { rng->X= (((r_uint64) seed)<<16) | LOWSEED; } +void rng_srandom(RNG *rng, unsigned int seed) { + extern unsigned char hash[]; // noise.c + + rng_seed(rng, seed + hash[seed & 255]); + seed= rng_getInt(rng); + rng_seed(rng, seed + hash[seed & 255]); + seed= rng_getInt(rng); + rng_seed(rng, seed + hash[seed & 255]); +} + int rng_getInt(RNG *rng) { rng->X= (MULTIPLIER*rng->X + ADDEND)&MASK; return (int) (rng->X>>17); @@ -132,13 +142,7 @@ void BLI_srand(unsigned int seed) { /* using hash table to create better seed */ void BLI_srandom(unsigned int seed) { - extern unsigned char hash[]; // noise.c - - rng_seed(&theBLI_rng, seed + hash[seed & 255]); - seed= rng_getInt(&theBLI_rng); - rng_seed(&theBLI_rng, seed + hash[seed & 255]); - seed= rng_getInt(&theBLI_rng); - rng_seed(&theBLI_rng, seed + hash[seed & 255]); + rng_srandom(&theBLI_rng, seed); } int BLI_rand(void) { -- cgit v1.2.3 From 2ce338f7e80094ad50cf1b30cc47ad6b85ae55b3 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Mon, 18 Aug 2008 14:33:26 +0000 Subject: svn merge -r 16077:16174 https://svn.blender.org/svnroot/bf-blender/trunk/blender --- source/blender/blenlib/BLI_editVert.h | 8 +++++--- source/blender/blenlib/BLI_rand.h | 1 + source/blender/blenlib/intern/BLI_ghash.c | 8 +++----- source/blender/blenlib/intern/BLI_kdopbvh.c | 12 ++++++++++++ source/blender/blenlib/intern/fileops.c | 6 ++++-- source/blender/blenlib/intern/psfont.c | 4 +++- source/blender/blenlib/intern/rand.c | 18 +++++++++++------- source/blender/blenlib/intern/util.c | 8 ++++---- 8 files changed, 43 insertions(+), 22 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/BLI_editVert.h b/source/blender/blenlib/BLI_editVert.h index d42663e17c7..447f6a2a485 100644 --- a/source/blender/blenlib/BLI_editVert.h +++ b/source/blender/blenlib/BLI_editVert.h @@ -38,6 +38,8 @@ #include "DNA_customdata_types.h" #include "DNA_mesh_types.h" +#include "BLO_sys_types.h" // for intptr_t support + struct DerivedMesh; struct RetopoPaintData; @@ -53,7 +55,7 @@ typedef struct EditVert struct EditEdge *e; struct EditFace *f; void *p; - long l; + intptr_t l; float fp; } tmp; float no[3]; /*vertex normal */ @@ -95,7 +97,7 @@ typedef struct EditEdge struct EditEdge *e; struct EditFace *f; void *p; - long l; + intptr_t l; float fp; } tmp; short f1, f2; /* short, f1 is (ab)used in subdiv */ @@ -122,7 +124,7 @@ typedef struct EditFace struct EditEdge *e; struct EditFace *f; void *p; - long l; + intptr_t l; float fp; } tmp; float n[3], cent[3]; diff --git a/source/blender/blenlib/BLI_rand.h b/source/blender/blenlib/BLI_rand.h index 0e534783c17..266aa347aff 100644 --- a/source/blender/blenlib/BLI_rand.h +++ b/source/blender/blenlib/BLI_rand.h @@ -44,6 +44,7 @@ struct RNG* rng_new (unsigned int seed); void rng_free (struct RNG* rng); void rng_seed (struct RNG* rng, unsigned int seed); +void rng_srandom(struct RNG *rng, unsigned int seed); int rng_getInt (struct RNG* rng); double rng_getDouble (struct RNG* rng); float rng_getFloat (struct RNG* rng); diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index 227cb8f5e9a..e9271ca3bb5 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -34,6 +34,8 @@ #include "MEM_guardedalloc.h" #include "BLI_ghash.h" +#include "BLO_sys_types.h" // for intptr_t support + #ifdef HAVE_CONFIG_H #include #endif @@ -256,11 +258,7 @@ int BLI_ghashutil_ptrcmp(void *a, void *b) { } unsigned int BLI_ghashutil_inthash(void *ptr) { -#if defined(_WIN64) - unsigned __int64 key = (unsigned __int64)ptr; -#else - unsigned long key = (unsigned long)ptr; -#endif + uintptr_t key = (uintptr_t)ptr; key += ~(key << 16); key ^= (key >> 5); diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index d0db13371b0..d20143f80e7 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -634,6 +634,18 @@ static void non_recursive_bvh_div_nodes(BVHTree *tree, BVHNode *branches_array, BVHBuildHelper data; int depth; + //Most of bvhtree code relies on 1-leaf trees having at least one branch + //We handle that special case here + if(num_leafs == 1) + { + BVHNode *root = branches_array+0; + refit_kdop_hull(tree, root, 0, num_leafs); + root->main_axis = get_largest_axis(root->bv) / 2; + root->totnode = 1; + root->children[0] = leafs_array[0]; + return; + } + branches_array--; //Implicit trees use 1-based indexs build_implicit_tree_helper(tree, &data); diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c index 96de5e99f4f..2acbbbe6712 100644 --- a/source/blender/blenlib/intern/fileops.c +++ b/source/blender/blenlib/intern/fileops.c @@ -62,6 +62,8 @@ #include "BKE_utildefines.h" #include +#include "BLO_sys_types.h" // for intptr_t support + /* implementations: */ char *first_slash(char *string) { char *ffslash, *fbslash; @@ -72,7 +74,7 @@ char *first_slash(char *string) { if (!ffslash) return fbslash; else if (!fbslash) return ffslash; - if ((long)ffslash < (long)fbslash) return ffslash; + if ((intptr_t)ffslash < (intptr_t)fbslash) return ffslash; else return fbslash; } @@ -85,7 +87,7 @@ char *BLI_last_slash(const char *string) { if (!lfslash) return lbslash; else if (!lbslash) return lfslash; - if ((long)lfslash < (long)lbslash) return lbslash; + if ((intptr_t)lfslash < (intptr_t)lbslash) return lbslash; else return lfslash; } diff --git a/source/blender/blenlib/intern/psfont.c b/source/blender/blenlib/intern/psfont.c index 498c87cdef9..216246dcdd7 100644 --- a/source/blender/blenlib/intern/psfont.c +++ b/source/blender/blenlib/intern/psfont.c @@ -43,6 +43,8 @@ #include "DNA_packedFile_types.h" #include "DNA_curve_types.h" +#include "BLO_sys_types.h" // for intptr_t support + #ifdef HAVE_CONFIG_H #include #endif @@ -54,7 +56,7 @@ typedef struct chardesc { short llx, lly; /* bounding box */ short urx, ury; short *data; /* char data */ - long datalen; + intptr_t datalen; } chardesc; typedef struct objfnt { diff --git a/source/blender/blenlib/intern/rand.c b/source/blender/blenlib/intern/rand.c index ccc478203fe..c484a307393 100644 --- a/source/blender/blenlib/intern/rand.c +++ b/source/blender/blenlib/intern/rand.c @@ -81,6 +81,16 @@ void rng_seed(RNG *rng, unsigned int seed) { rng->X= (((r_uint64) seed)<<16) | LOWSEED; } +void rng_srandom(RNG *rng, unsigned int seed) { + extern unsigned char hash[]; // noise.c + + rng_seed(rng, seed + hash[seed & 255]); + seed= rng_getInt(rng); + rng_seed(rng, seed + hash[seed & 255]); + seed= rng_getInt(rng); + rng_seed(rng, seed + hash[seed & 255]); +} + int rng_getInt(RNG *rng) { rng->X= (MULTIPLIER*rng->X + ADDEND)&MASK; return (int) (rng->X>>17); @@ -132,13 +142,7 @@ void BLI_srand(unsigned int seed) { /* using hash table to create better seed */ void BLI_srandom(unsigned int seed) { - extern unsigned char hash[]; // noise.c - - rng_seed(&theBLI_rng, seed + hash[seed & 255]); - seed= rng_getInt(&theBLI_rng); - rng_seed(&theBLI_rng, seed + hash[seed & 255]); - seed= rng_getInt(&theBLI_rng); - rng_seed(&theBLI_rng, seed + hash[seed & 255]); + rng_srandom(&theBLI_rng, seed); } int BLI_rand(void) { diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c index 48ebf770e1b..a31121148e3 100644 --- a/source/blender/blenlib/intern/util.c +++ b/source/blender/blenlib/intern/util.c @@ -1970,7 +1970,7 @@ void BLI_timestr(double _time, char *str) int BLI_int_from_pointer(void *poin) { - long lval= (long)poin; + intptr_t lval= (intptr_t)poin; return (int)(lval>>3); } @@ -1978,17 +1978,17 @@ int BLI_int_from_pointer(void *poin) void *BLI_pointer_from_int(int val) { static int firsttime= 1; - static long basevalue= 0; + static intptr_t basevalue= 0; if(firsttime) { void *poin= malloc(10000); - basevalue= (long)poin; + basevalue= (intptr_t)poin; basevalue &= ~PMASK; printf("base: %d pointer %p\n", basevalue, poin); /* debug */ firsttime= 0; free(poin); } - return (void *)(basevalue | (((long)val)<<3)); + return (void *)(basevalue | (((intptr_t)val)<<3)); } #else -- cgit v1.2.3 From a06321d55c2f25440120ac2fdead20639863a608 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Mon, 18 Aug 2008 19:31:40 +0000 Subject: Implemented a find_nearest with heaps. This reachs a minimal number of distance queries. But the cost of maintaining the heap seems to be very high. For now DFS with local heuristics gets better times.. so BVHTree still uses that. --- source/blender/blenlib/intern/BLI_kdopbvh.c | 205 ++++++++++++++++++++++++++-- 1 file changed, 194 insertions(+), 11 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index d20143f80e7..c41c3d8c3ab 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -46,6 +46,7 @@ #define MAX_TREETYPE 32 +#define DEFAULT_FIND_NEAREST_HEAP_SIZE 1024 typedef struct BVHNode { @@ -119,6 +120,72 @@ static float KDOP_AXES[13][3] = {0, 1.0, -1.0} }; +/* + * Generic push and pop heap + */ +#define PUSH_HEAP_BODY(HEAP_TYPE,PRIORITY,heap,heap_size) \ +{ \ + HEAP_TYPE element = heap[heap_size-1]; \ + int child = heap_size-1; \ + while(child != 0) \ + { \ + int parent = (child-1) / 2; \ + if(PRIORITY(element, heap[parent])) \ + { \ + heap[child] = heap[parent]; \ + child = parent; \ + } \ + else break; \ + } \ + heap[child] = element; \ +} + +#define POP_HEAP_BODY(HEAP_TYPE, PRIORITY,heap,heap_size) \ +{ \ + HEAP_TYPE element = heap[heap_size-1]; \ + int parent = 0; \ + while(parent < (heap_size-1)/2 ) \ + { \ + int child2 = (parent+1)*2; \ + if(PRIORITY(heap[child2-1], heap[child2])) \ + --child2; \ + \ + if(PRIORITY(element, heap[child2])) \ + break; \ + \ + heap[parent] = heap[child2]; \ + parent = child2; \ + } \ + heap[parent] = element; \ +} + +int ADJUST_MEMORY(void *local_memblock, void **memblock, int new_size, int *max_size, int size_per_item) +{ + int new_max_size = *max_size * 2; + void *new_memblock = NULL; + + if(new_size <= *max_size) + return TRUE; + + if(*memblock == local_memblock) + { + new_memblock = malloc( size_per_item * new_max_size ); + memcpy( new_memblock, *memblock, size_per_item * *max_size ); + } + else + new_memblock = realloc(*memblock, size_per_item * new_max_size ); + + if(new_memblock) + { + *memblock = new_memblock; + *max_size = new_max_size; + return TRUE; + } + else + return FALSE; +} + + ////////////////////////////////////////////////////////////////////////////////////////////////////// // Introsort // with permission deriven from the following Java code: @@ -1131,15 +1198,18 @@ static float calc_nearest_point(BVHNearestData *data, BVHNode *node, float *near } -// TODO: use a priority queue to reduce the number of nodes looked on -static void dfs_find_nearest(BVHNearestData *data, BVHNode *node) +typedef struct NodeDistance { - int i; - float nearest[3], sdist; + BVHNode *node; + float dist; - sdist = calc_nearest_point(data, node, nearest); - if(sdist >= data->nearest.dist) return; +} NodeDistance; +#define NodeDistance_priority(a,b) ( (a).dist < (b).dist ) + +// TODO: use a priority queue to reduce the number of nodes looked on +static void dfs_find_nearest_dfs(BVHNearestData *data, BVHNode *node) +{ if(node->totnode == 0) { if(data->callback) @@ -1147,17 +1217,130 @@ static void dfs_find_nearest(BVHNearestData *data, BVHNode *node) else { data->nearest.index = node->index; - VECCOPY(data->nearest.co, nearest); - data->nearest.dist = sdist; + data->nearest.dist = calc_nearest_point(data, node, data->nearest.co); } } else { - for(i=0; i != node->totnode; i++) - dfs_find_nearest(data, node->children[i]); + //Better heuristic to pick the closest node to dive on + int i; + float nearest[3]; + + if(data->proj[ node->main_axis ] <= node->children[0]->bv[node->main_axis*2+1]) + { + + for(i=0; i != node->totnode; i++) + { + if( calc_nearest_point(data, node->children[i], nearest) >= data->nearest.dist) continue; + dfs_find_nearest_dfs(data, node->children[i]); + } + } + else + { + for(i=node->totnode-1; i >= 0 ; i--) + { + if( calc_nearest_point(data, node->children[i], nearest) >= data->nearest.dist) continue; + dfs_find_nearest_dfs(data, node->children[i]); + } + } } } +static void dfs_find_nearest_begin(BVHNearestData *data, BVHNode *node) +{ + int i; + float nearest[3], sdist; + sdist = calc_nearest_point(data, node, nearest); + if(sdist >= data->nearest.dist) return; + dfs_find_nearest_dfs(data, node); +} + + +static void NodeDistance_push_heap(NodeDistance *heap, int heap_size) +PUSH_HEAP_BODY(NodeDistance, NodeDistance_priority, heap, heap_size) + +static void NodeDistance_pop_heap(NodeDistance *heap, int heap_size) +POP_HEAP_BODY(NodeDistance, NodeDistance_priority, heap, heap_size) + +//NN function that uses an heap.. this functions leads to an optimal number of min-distance +//but for normal tri-faces and BV 6-dop.. a simple dfs with local heuristics (as implemented +//in source/blender/blenkernel/intern/shrinkwrap.c) works faster. +// +//It may make sense to use this function if the callback queries are very slow.. or if its impossible +//to get a nice heuristic +// +//this function uses "malloc/free" instead of the MEM_* because it intends to be openmp safe +static void bfs_find_nearest(BVHNearestData *data, BVHNode *node) +{ + int i; + NodeDistance default_heap[DEFAULT_FIND_NEAREST_HEAP_SIZE]; + NodeDistance *heap=default_heap, current; + int heap_size = 0, max_heap_size = sizeof(default_heap)/sizeof(default_heap[0]); + float nearest[3]; + + int callbacks = 0, push_heaps = 0; + + if(node->totnode == 0) + { + dfs_find_nearest_dfs(data, node); + return; + } + + current.node = node; + current.dist = calc_nearest_point(data, node, nearest); + + while(current.dist < data->nearest.dist) + { +// printf("%f : %f\n", current.dist, data->nearest.dist); + for(i=0; i< current.node->totnode; i++) + { + BVHNode *child = current.node->children[i]; + if(child->totnode == 0) + { + callbacks++; + dfs_find_nearest_dfs(data, child); + } + else + { + //adjust heap size + if(heap_size >= max_heap_size + && ADJUST_MEMORY(default_heap, (void**)&heap, heap_size+1, &max_heap_size, sizeof(heap[0])) == FALSE) + { + printf("WARNING: bvh_find_nearest got out of memory\n"); + + if(heap != default_heap) + free(heap); + + return; + } + + heap[heap_size].node = current.node->children[i]; + heap[heap_size].dist = calc_nearest_point(data, current.node->children[i], nearest); + + if(heap[heap_size].dist >= data->nearest.dist) continue; + heap_size++; + + NodeDistance_push_heap(heap, heap_size); + // PUSH_HEAP_BODY(NodeDistance, NodeDistance_priority, heap, heap_size); + push_heaps++; + } + } + + if(heap_size == 0) break; + + current = heap[0]; + NodeDistance_pop_heap(heap, heap_size); +// POP_HEAP_BODY(NodeDistance, NodeDistance_priority, heap, heap_size); + heap_size--; + } + +// printf("hsize=%d, callbacks=%d, pushs=%d\n", heap_size, callbacks, push_heaps); + + if(heap != default_heap) + free(heap); +} + + int BLI_bvhtree_find_nearest(BVHTree *tree, const float *co, BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata) { int i; @@ -1189,7 +1372,7 @@ int BLI_bvhtree_find_nearest(BVHTree *tree, const float *co, BVHTreeNearest *nea //dfs search if(root) - dfs_find_nearest(&data, root); + dfs_find_nearest_begin(&data, root); //copy back results if(nearest) -- cgit v1.2.3 From 7630539fe88b3c0dc353ae194baea8d757b79cae Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Fri, 22 Aug 2008 15:00:30 +0000 Subject: Fix Windows compilation problem and update MSVC project files --- source/blender/blenlib/BLI_winstuff.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/BLI_winstuff.h b/source/blender/blenlib/BLI_winstuff.h index 11150075bac..3bb63506c95 100644 --- a/source/blender/blenlib/BLI_winstuff.h +++ b/source/blender/blenlib/BLI_winstuff.h @@ -61,6 +61,10 @@ // These definitions are also in arithb for simplicity +#ifdef __cplusplus +extern "C" { +#endif + #ifndef M_PI #define M_PI 3.14159265358979323846 #endif @@ -116,5 +120,9 @@ int closedir (DIR *dp); void get_default_root(char *root); int check_file_chars(char *filename); +#ifdef __cplusplus +} +#endif + #endif /* __WINSTUFF_H__ */ -- cgit v1.2.3 From 2076703a286a61b175441a0413f348b0596e1964 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Fri, 22 Aug 2008 18:28:34 +0000 Subject: Removed cast warnings from shrinkwrap.c and BLI_kdopbvh.c Only unused functions and openmp warnings left on those. --- source/blender/blenlib/intern/BLI_kdopbvh.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index c41c3d8c3ab..989e516d161 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -82,7 +82,7 @@ typedef struct BVHOverlapData typedef struct BVHNearestData { BVHTree *tree; - float *co; + const float *co; BVHTree_NearestPointCallback callback; void *userdata; float proj[13]; //coordinates projection over axis @@ -1248,7 +1248,6 @@ static void dfs_find_nearest_dfs(BVHNearestData *data, BVHNode *node) static void dfs_find_nearest_begin(BVHNearestData *data, BVHNode *node) { - int i; float nearest[3], sdist; sdist = calc_nearest_point(data, node, nearest); if(sdist >= data->nearest.dist) return; -- cgit v1.2.3 From cb89decfdcf5e6b2f26376d416633f4ccf0c532d Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 4 Sep 2008 20:51:28 +0000 Subject: Merge of first part of changes from the apricot branch, especially the features that are needed to run the game. Compile tested with scons, make, but not cmake, that seems to have an issue not related to these changes. The changes include: * GLSL support in the viewport and game engine, enable in the game menu in textured draw mode. * Synced and merged part of the duplicated blender and gameengine/ gameplayer drawing code. * Further refactoring of game engine drawing code, especially mesh storage changed a lot. * Optimizations in game engine armatures to avoid recomputations. * A python function to get the framerate estimate in game. * An option take object color into account in materials. * An option to restrict shadow casters to a lamp's layers. * Increase from 10 to 18 texture slots for materials, lamps, word. An extra texture slot shows up once the last slot is used. * Memory limit for undo, not enabled by default yet because it needs the .B.blend to be changed. * Multiple undo for image painting. * An offset for dupligroups, so not all objects in a group have to be at the origin. --- source/blender/blenlib/BLI_arithb.h | 1 + source/blender/blenlib/BLI_blenlib.h | 1 - source/blender/blenlib/intern/arithb.c | 8 ++++++++ 3 files changed, 9 insertions(+), 1 deletion(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h index c22b6f79e08..4448231b2b4 100644 --- a/source/blender/blenlib/BLI_arithb.h +++ b/source/blender/blenlib/BLI_arithb.h @@ -260,6 +260,7 @@ void Vec2Mulf(float *v1, float f); void Vec2Addf(float *v, float *v1, float *v2); void Vec2Subf(float *v, float *v1, float *v2); void Vec2Copyf(float *v1, float *v2); +void Vec2Lerpf(float *target, float *a, float *b, float t); void AxisAngleToQuat(float *q, float *axis, float angle); void vectoquat(float *vec, short axis, short upflag, float *q); diff --git a/source/blender/blenlib/BLI_blenlib.h b/source/blender/blenlib/BLI_blenlib.h index e24ccad12fb..c59cd2dab4e 100644 --- a/source/blender/blenlib/BLI_blenlib.h +++ b/source/blender/blenlib/BLI_blenlib.h @@ -73,7 +73,6 @@ extern ListBase fillvertbase; * @attention Defined in scanfill.c */ extern ListBase filledgebase; -extern int totblock; extern char btempdir[]; /* creator.c temp dir used instead of U.tempdir, set with BLI_where_is_temp( btempdir, 1 ); */ diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index 8bd7ad405af..50f8ba0fcde 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -2113,6 +2113,14 @@ void VecLerpf(float *target, float *a, float *b, float t) target[2]= s*a[2] + t*b[2]; } +void Vec2Lerpf(float *target, float *a, float *b, float t) +{ + float s = 1.0f-t; + + target[0]= s*a[0] + t*b[0]; + target[1]= s*a[1] + t*b[1]; +} + void VecMidf(float *v, float *v1, float *v2) { v[0]= 0.5f*(v1[0]+ v2[0]); -- cgit v1.2.3 From 18fe6c27ff2b4a76ec5c646a3dda0a7bd64d94b4 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 5 Sep 2008 06:05:25 +0000 Subject: Compiling/Warning Fixes (for scons/mingw + "split sources hack") Part 1: * Removed compiler warnings from texteditor work * Added round brackets around the new defines for IPO channels for extra texture layers * Tweaked priorities so that BLI_heap_* functions in blenlib can be found by linker (split-sources specific) TODO: * "monkey*" vars cannot be found still --- source/blender/blenlib/SConscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/SConscript b/source/blender/blenlib/SConscript index 649d3cb5659..65cebf02f62 100644 --- a/source/blender/blenlib/SConscript +++ b/source/blender/blenlib/SConscript @@ -24,4 +24,4 @@ if env['OURPLATFORM'] == 'linux2': if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw'): incs += ' ' + env['BF_PTHREADS_INC'] -env.BlenderLib ( 'bf_blenlib', sources, Split(incs), Split(defs), libtype=['core','player'], priority = [85,195], compileflags =cflags ) +env.BlenderLib ( 'bf_blenlib', sources, Split(incs), Split(defs), libtype=['core', 'intern', 'player'], priority = [85,150,195], compileflags =cflags ) -- cgit v1.2.3 From b32036f5d6b08233e30dc62ea0f5e84a0e75cc7c Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Fri, 5 Sep 2008 11:55:39 +0000 Subject: bvh nodes got parent node reference again --- source/blender/blenlib/intern/BLI_kdopbvh.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 989e516d161..341a27c4306 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -51,6 +51,7 @@ typedef struct BVHNode { struct BVHNode **children; + struct BVHNode *parent; // some user defined traversed need that float *bv; // Bounding volume of all nodes, max 13 axis int index; // face, edge, vertex index char totnode; // how many nodes are used, used for speedup @@ -700,6 +701,10 @@ static void non_recursive_bvh_div_nodes(BVHTree *tree, BVHNode *branches_array, BVHBuildHelper data; int depth; + + // set parent from root node to NULL + BVHNode *tmp = branches_array+0; + tmp->parent = NULL; //Most of bvhtree code relies on 1-leaf trees having at least one branch //We handle that special case here @@ -709,7 +714,8 @@ static void non_recursive_bvh_div_nodes(BVHTree *tree, BVHNode *branches_array, refit_kdop_hull(tree, root, 0, num_leafs); root->main_axis = get_largest_axis(root->bv) / 2; root->totnode = 1; - root->children[0] = leafs_array[0]; + root->children[0] = leafs_array[0]; + root->children[0]->parent = root; return; } @@ -772,9 +778,15 @@ static void non_recursive_bvh_div_nodes(BVHTree *tree, BVHNode *branches_array, int child_leafs_end = implicit_leafs_index(&data, depth+1, child_level_index+1); if(child_leafs_end - child_leafs_begin > 1) + { parent->children[k] = branches_array + child_index; + parent->children[k]->parent = parent; + } else if(child_leafs_end - child_leafs_begin == 1) + { parent->children[k] = leafs_array[ child_leafs_begin ]; + parent->children[k]->parent = parent; + } else break; -- cgit v1.2.3 From d88b4acc9bec144cb4a3155d68cc73274e035f55 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Fri, 5 Sep 2008 12:06:47 +0000 Subject: Fixing non-working check for incompatible trees --- source/blender/blenlib/intern/BLI_kdopbvh.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 341a27c4306..9f82a816147 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -482,7 +482,7 @@ static void bvhtree_print_tree(BVHTree *tree, BVHNode *node, int depth) { int i; for(i=0; iindex, node - tree->nodearray); + printf(" - %d (%ld): ", node->index, node - tree->nodearray); for(i=2*tree->start_axis; i<2*tree->stop_axis; i++) printf("%.3f ", node->bv[i]); printf("\n"); @@ -497,10 +497,10 @@ static void bvhtree_info(BVHTree *tree) printf("BVHTree info\n"); printf("tree_type = %d, axis = %d, epsilon = %f\n", tree->tree_type, tree->axis, tree->epsilon); printf("nodes = %d, branches = %d, leafs = %d\n", tree->totbranch + tree->totleaf, tree->totbranch, tree->totleaf); - printf("Memory per node = %dbytes\n", sizeof(BVHNode) + sizeof(BVHNode*)*tree->tree_type + sizeof(float)*tree->axis); + printf("Memory per node = %ldbytes\n", sizeof(BVHNode) + sizeof(BVHNode*)*tree->tree_type + sizeof(float)*tree->axis); printf("BV memory = %dbytes\n", MEM_allocN_len(tree->nodebv)); - printf("Total memory = %dbytes\n", sizeof(BVHTree) + printf("Total memory = %ldbytes\n", sizeof(BVHTree) + MEM_allocN_len(tree->nodes) + MEM_allocN_len(tree->nodearray) + MEM_allocN_len(tree->nodechild) @@ -1108,7 +1108,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result) BVHOverlapData **data; // check for compatibility of both trees (can't compare 14-DOP with 18-DOP) - if((tree1->axis != tree2->axis) && ((tree1->axis == 14) || tree2->axis == 14)) + if((tree1->axis != tree2->axis) && (tree1->axis == 14 || tree2->axis == 14) && (tree1->axis == 18 || tree2->axis == 18)) return 0; // fast check root nodes for collision before doing big splitting + traversal -- cgit v1.2.3 From e9b08b64fae2c8c5197f9c1e724f4017244a973c Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 9 Sep 2008 15:15:01 +0000 Subject: Fix for bug #17402: IK influence blending with pole targets didn't give smooth transition. Now it blends the result of IK solving in that case. --- source/blender/blenlib/BLI_arithb.h | 1 + source/blender/blenlib/intern/arithb.c | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h index 4448231b2b4..6e54fae58d0 100644 --- a/source/blender/blenlib/BLI_arithb.h +++ b/source/blender/blenlib/BLI_arithb.h @@ -164,6 +164,7 @@ void Mat3Inv(float m1[][3], float m2[][3]); void Mat3CpyMat4(float m1[][3],float m2[][4]); void Mat4CpyMat3(float m1[][4], float m2[][3]); +void Mat3BlendMat3(float out[][3], float dst[][3], float src[][3], float srcweight); void Mat4BlendMat4(float out[][4], float dst[][4], float src[][4], float srcweight); float Det2x2(float a,float b,float c, float d); diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index 50f8ba0fcde..f89f90f7045 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -759,6 +759,28 @@ void Mat4MulSerie(float answ[][4], float m1[][4], } } +void Mat3BlendMat3(float out[][3], float dst[][3], float src[][3], float srcweight) +{ + float squat[4], dquat[4], fquat[4]; + float ssize[3], dsize[3], fsize[4]; + float rmat[3][3], smat[3][3]; + + Mat3ToQuat(dst, dquat); + Mat3ToSize(dst, dsize); + + Mat3ToQuat(src, squat); + Mat3ToSize(src, ssize); + + /* do blending */ + QuatInterpol(fquat, dquat, squat, srcweight); + VecLerpf(fsize, dsize, ssize, srcweight); + + /* compose new matrix */ + QuatToMat3(fquat, rmat); + SizeToMat3(fsize, smat); + Mat3MulMat3(out, rmat, smat); +} + void Mat4BlendMat4(float out[][4], float dst[][4], float src[][4], float srcweight) { float squat[4], dquat[4], fquat[4]; -- cgit v1.2.3 From d2186508da224805db8d2fe299738a94e1a5e750 Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Sat, 13 Sep 2008 18:09:41 +0000 Subject: Particle collisions upgrade: - Particle now use the deflector objects collision modifier data to collide with deflectors and as a result can now use the velocity of the colliding object for more realistic collisions. - Dynamic rotations are also quite a bit more realistic and are related to the friction setting of the deflector (to get any dynamic rotations there has to be some friction). This is largely due to the separate handling of rolling friction (approximated to be 1% of normal sliding friction). - Collisions should be a bit faster on complex deflectors due to the tree structure used by the collision modifier. - Collision should also generally be a bit more accurate. To be noted: Only the average velocity of individual deflector faces is used, so collisions with rotating or deforming objects can't be handled accurately - this would require much more complex calculations. Subdividing the deflector object surface to smaller faces can help with this as the individual face velocities become more linear. --- source/blender/blenlib/BLI_kdopbvh.h | 3 ++- source/blender/blenlib/intern/BLI_kdopbvh.c | 11 ++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h index 6d9a17efebf..e3591a84e98 100644 --- a/source/blender/blenlib/BLI_kdopbvh.h +++ b/source/blender/blenlib/BLI_kdopbvh.h @@ -54,6 +54,7 @@ typedef struct BVHTreeRay { float origin[3]; /* ray origin */ float direction[3]; /* ray direction */ + float radius; /* radius around ray */ } BVHTreeRay; typedef struct BVHTreeRayHit @@ -90,7 +91,7 @@ float BLI_bvhtree_getepsilon(BVHTree *tree); /* find nearest node to the given coordinates (if nearest is given it will only search nodes where square distance is smaller than nearest->dist) */ int BLI_bvhtree_find_nearest(BVHTree *tree, const float *co, BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata); -int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata); +int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata); #endif // BLI_KDOPBVH_H diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 9f82a816147..30472beb3e6 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -1414,14 +1414,14 @@ static float ray_nearest_hit(BVHRayCastData *data, BVHNode *node) if(data->ray_dot_axis[i] == 0.0f) { //axis aligned ray - if(data->ray.origin[i] < bv[0] - || data->ray.origin[i] > bv[1]) + if(data->ray.origin[i] < bv[0] - data->ray.radius + || data->ray.origin[i] > bv[1] + data->ray.radius) return FLT_MAX; } else { - float ll = (bv[0] - data->ray.origin[i]) / data->ray_dot_axis[i]; - float lu = (bv[1] - data->ray.origin[i]) / data->ray_dot_axis[i]; + float ll = (bv[0] - data->ray.radius - data->ray.origin[i]) / data->ray_dot_axis[i]; + float lu = (bv[1] + data->ray.radius - data->ray.origin[i]) / data->ray_dot_axis[i]; if(data->ray_dot_axis[i] > 0.0f) { @@ -1480,7 +1480,7 @@ static void dfs_raycast(BVHRayCastData *data, BVHNode *node) } } -int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata) +int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata) { int i; BVHRayCastData data; @@ -1493,6 +1493,7 @@ int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, BVHTr VECCOPY(data.ray.origin, co); VECCOPY(data.ray.direction, dir); + data.ray.radius = radius; Normalize(data.ray.direction); -- cgit v1.2.3 From ac86c04401686a9d119ea84ad489ca3db7403e5c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 15 Sep 2008 01:32:53 +0000 Subject: added BLI_convertstringcwd, used so command line blendfiles and python scripts can be relative to the current path. - was alredy doing this for blendfiles, but better to have in its own function. header_text.c - renamed PATH_MAX, was defined by system includes. --- source/blender/blenlib/BLI_blenlib.h | 1 + source/blender/blenlib/intern/util.c | 43 ++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/BLI_blenlib.h b/source/blender/blenlib/BLI_blenlib.h index c59cd2dab4e..a1db7adf33d 100644 --- a/source/blender/blenlib/BLI_blenlib.h +++ b/source/blender/blenlib/BLI_blenlib.h @@ -151,6 +151,7 @@ void BLI_cleanup_dir(const char *relabase, char *dir); /* same as above but adds */ int BLI_convertstringcode(char *path, const char *basepath); int BLI_convertstringframe(char *path, int frame); +int BLI_convertstringcwd(char *path); void BLI_makestringcode(const char *relfile, char *file); diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c index a31121148e3..c27efcb7934 100644 --- a/source/blender/blenlib/intern/util.c +++ b/source/blender/blenlib/intern/util.c @@ -1211,6 +1211,49 @@ int BLI_convertstringcode(char *path, const char *basepath) return wasrelative; } + +/* + * Should only be done with command line paths. + * this is NOT somthing blenders internal paths support like the // prefix + */ +int BLI_convertstringcwd(char *path) +{ + int wasrelative = 1; + int filelen = strlen(path); + +#ifdef WIN32 + if (filelen >= 3 && path[1] == ':' && (path[2] == '\\' || path[2] == '/')) + wasrelative = 0; +#else + if (filelen >= 2 && path[0] == '/') + wasrelative = 0; +#endif + + if (wasrelative==1) { + char cwd[FILE_MAXDIR + FILE_MAXFILE]; + BLI_getwdN(cwd); /* incase the full path to the blend isnt used */ + + if (cwd[0] == '\0') { + printf( "Could not get the current working directory - $PWD for an unknown reason."); + } else { + /* uses the blend path relative to cwd important for loading relative linked files. + * + * cwd should contain c:\ etc on win32 so the relbase can be NULL + * relbase being NULL also prevents // being misunderstood as relative to the current + * blend file which isnt a feature we want to use in this case since were dealing + * with a path from the command line, rather then from inside Blender */ + + char origpath[FILE_MAXDIR + FILE_MAXFILE]; + BLI_strncpy(origpath, path, FILE_MAXDIR + FILE_MAXFILE); + + BLI_make_file_string(NULL, path, cwd, origpath); + } + } + + return wasrelative; +} + + /* copy di to fi, filename only */ void BLI_splitdirstring(char *di, char *fi) { -- cgit v1.2.3 From a0504ac922b314929e0028b8bcd0c6b1cd7eef91 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Fri, 19 Sep 2008 14:18:41 +0000 Subject: Patch #8213 by Shunichi Fuji Fixes crash with FT fonts in some cases, just removed unnused line of code. --- source/blender/blenlib/intern/freetypefont.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/intern/freetypefont.c b/source/blender/blenlib/intern/freetypefont.c index 74f152ac635..48a40db6a72 100644 --- a/source/blender/blenlib/intern/freetypefont.c +++ b/source/blender/blenlib/intern/freetypefont.c @@ -404,8 +404,6 @@ static VFontData *objfnt_to_ftvfontdata(PackedFile * pf) break; lcode = charcode; } - - err = FT_Select_Charmap( face, FT_ENCODING_UNICODE ); return vfd; } -- cgit v1.2.3 From 224607982ad664eaccfd703cff105eb6393b2d3e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 20 Sep 2008 10:11:42 +0000 Subject: Python api access to obcolor Option to copy obcolor in the copy menu Option to select same color in select grouped menu console.py - mistake in last commit caused a python error --- source/blender/blenlib/BLI_arithb.h | 1 + source/blender/blenlib/intern/arithb.c | 13 +++++++++++++ 2 files changed, 14 insertions(+) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h index 6e54fae58d0..4b858dcb503 100644 --- a/source/blender/blenlib/BLI_arithb.h +++ b/source/blender/blenlib/BLI_arithb.h @@ -91,6 +91,7 @@ float saasin(float fac); float sasqrt(float fac); int FloatCompare(float *v1, float *v2, float limit); +int FloatCompare4(float *v1, float *v2, float limit); float FloatLerpf(float target, float origin, float fac); float CalcNormFloat(float *v1, float *v2, float *v3, float *n); diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index f89f90f7045..c6634eb7707 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -1026,6 +1026,19 @@ int FloatCompare( float *v1, float *v2, float limit) return 0; } +int FloatCompare4( float *v1, float *v2, float limit) +{ + + if( fabs(v1[0]-v2[0]) Date: Sat, 20 Sep 2008 11:08:35 +0000 Subject: [#17600] char* -> const char* Thanks to Sean Bartell (wtachi), was causing many many warnings which distracted from the real problems. --- source/blender/blenlib/BLI_blenlib.h | 2 +- source/blender/blenlib/intern/util.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/BLI_blenlib.h b/source/blender/blenlib/BLI_blenlib.h index a1db7adf33d..6a50e2de0e5 100644 --- a/source/blender/blenlib/BLI_blenlib.h +++ b/source/blender/blenlib/BLI_blenlib.h @@ -224,7 +224,7 @@ int BLI_strcaseeq(char *a, char *b); /* in util.c */ #ifdef WITH_ICONV -void BLI_string_to_utf8(char *original, char *utf_8, char *code); +void BLI_string_to_utf8(char *original, char *utf_8, const char *code); #endif /** diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c index c27efcb7934..9dfe9557c1b 100644 --- a/source/blender/blenlib/intern/util.c +++ b/source/blender/blenlib/intern/util.c @@ -1955,7 +1955,7 @@ int BLI_strncasecmp(const char *s1, const char *s2, int n) { #include "iconv.h" #include "localcharset.h" -void BLI_string_to_utf8(char *original, char *utf_8, char *code) +void BLI_string_to_utf8(char *original, char *utf_8, const char *code) { size_t inbytesleft=strlen(original); size_t outbytesleft=512; -- cgit v1.2.3 From 9b9edad6b6fb4db3f393ef408921f8411b588814 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Sat, 20 Sep 2008 12:26:18 +0000 Subject: Patch 17403, small gcc warning fixes. --- source/blender/blenlib/intern/edgehash.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/intern/edgehash.c b/source/blender/blenlib/intern/edgehash.c index 3e1c8afb7a8..603c85655d7 100644 --- a/source/blender/blenlib/intern/edgehash.c +++ b/source/blender/blenlib/intern/edgehash.c @@ -77,8 +77,12 @@ void BLI_edgehash_insert(EdgeHash *eh, int v0, int v1, void *val) { unsigned int hash; Entry *e= malloc(sizeof(*e)); - if (v1nbuckets; + if (v1nbuckets; e->v0 = v0; e->v1 = v1; @@ -114,7 +118,11 @@ void** BLI_edgehash_lookup_p(EdgeHash *eh, int v0, int v1) { unsigned int hash; Entry *e; - if (v1nbuckets; for (e= eh->buckets[hash]; e; e= e->next) if (v0==e->v0 && v1==e->v1) -- cgit v1.2.3 From 768e12a064cf524a14a84203b100a33235bba30e Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Sat, 20 Sep 2008 14:43:59 +0000 Subject: Patch #17631 by Early Ehlinger His log: One of the calls to PIL_dynlib_get_error_as_string was assuming that it would return a valid string and not NULL (perhaps by converting to std::string). This patch simply changes it to always return a string, even when the error is not recognized. --- source/blender/blenlib/intern/dynlib.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/intern/dynlib.c b/source/blender/blenlib/intern/dynlib.c index c4692995f20..e7fa3332f43 100644 --- a/source/blender/blenlib/intern/dynlib.c +++ b/source/blender/blenlib/intern/dynlib.c @@ -77,12 +77,12 @@ char *PIL_dynlib_get_error_as_string(PILdynlib* lib) { int err; /* if lib is NULL reset the last error code */ + err= GetLastError(); if (!lib) { SetLastError(ERROR_SUCCESS); - return NULL; + err = ERROR_SUCCESS; } - err= GetLastError(); if (err) { static char buf[1024]; @@ -96,7 +96,7 @@ char *PIL_dynlib_get_error_as_string(PILdynlib* lib) { return buf; } - return NULL; + return "unrecognized error"; } void PIL_dynlib_close(PILdynlib *lib) { -- cgit v1.2.3 From d1dedb2cef4bf1dc2fd9b563dee7c1f45b79c173 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Mon, 22 Sep 2008 09:09:03 +0000 Subject: Added three XYZ color space options in code, will be activated later. Thanks matt for the typing work :) --- source/blender/blenlib/BLI_arithb.h | 6 +++++- source/blender/blenlib/intern/arithb.c | 28 +++++++++++++++++++++------- 2 files changed, 26 insertions(+), 8 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h index 4b858dcb503..e2e71a2fb1a 100644 --- a/source/blender/blenlib/BLI_arithb.h +++ b/source/blender/blenlib/BLI_arithb.h @@ -322,6 +322,10 @@ void i_window( float mat[][4] ); +#define BLI_CS_SMPTE 0 +#define BLI_CS_REC709 1 +#define BLI_CS_CIE 2 + void hsv_to_rgb(float h, float s, float v, float *r, float *g, float *b); void hex_to_rgb(char *hexcol, float *r, float *g, float *b); void rgb_to_yuv(float r, float g, float b, float *ly, float *lu, float *lv); @@ -329,7 +333,7 @@ void yuv_to_rgb(float y, float u, float v, float *lr, float *lg, float *lb); void ycc_to_rgb(float y, float cb, float cr, float *lr, float *lg, float *lb); void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr); void rgb_to_hsv(float r, float g, float b, float *lh, float *ls, float *lv); -void xyz_to_rgb(float x, float y, float z, float *r, float *g, float *b); +void xyz_to_rgb(float x, float y, float z, float *r, float *g, float *b, int colorspace); int constrain_rgb(float *r, float *g, float *b); void gamma_correct_rgb(float *r, float *g, float *b); unsigned int hsv_to_cpack(float h, float s, float v); diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index c6634eb7707..888a5ab2f64 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -3453,13 +3453,27 @@ void rgb_to_hsv(float r, float g, float b, float *lh, float *ls, float *lv) *lv = v; } -/*http://brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html - * SMPTE-C XYZ to RGB matrix*/ -void xyz_to_rgb(float xc, float yc, float zc, float *r, float *g, float *b) -{ - *r = (3.50570 * xc) + (-1.73964 * yc) + (-0.544011 * zc); - *g = (-1.06906 * xc) + (1.97781 * yc) + (0.0351720 * zc); - *b = (0.0563117 * xc) + (-0.196994 * yc) + (1.05005 * zc); +/*http://brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html */ + +void xyz_to_rgb(float xc, float yc, float zc, float *r, float *g, float *b, int colorspace) +{ + switch (colorspace) { + case BLI_CS_SMPTE: + *r = (3.50570 * xc) + (-1.73964 * yc) + (-0.544011 * zc); + *g = (-1.06906 * xc) + (1.97781 * yc) + (0.0351720 * zc); + *b = (0.0563117 * xc) + (-0.196994 * yc) + (1.05005 * zc); + break; + case BLI_CS_REC709: + *r = (3.240476 * xc) + (-1.537150 * yc) + (-0.498535 * zc); + *g = (-0.969256 * xc) + (1.875992 * yc) + (0.041556 * zc); + *b = (0.055648 * xc) + (-0.204043 * yc) + (1.057311 * zc); + break; + case BLI_CS_CIE: + *r = (2.28783848734076f * xc) + (-0.833367677835217f * yc) + (-0.454470795871421f * zc); + *g = (-0.511651380743862f * xc) + (1.42275837632178f * yc) + (0.0888930017552939f * zc); + *b = (0.00572040983140966f * xc) + (-0.0159068485104036f * yc) + (1.0101864083734f * zc); + break; + } } /*If the requested RGB shade contains a negative weight for -- cgit v1.2.3 From e4def00d5bc8c4b2947f74d2b5c3308ae07a4eee Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 22 Sep 2008 15:37:32 +0000 Subject: fix for [#15020] File browser: going back from the root of all directories introduces "../" ad libitum + harcoded path? bug was introduced when fixing BLI_cleanup_dir not to write to negative character indicies. added a BLI_parent_dir(char *path) --- source/blender/blenlib/BLI_blenlib.h | 3 +++ source/blender/blenlib/intern/util.c | 15 +++++++++++++++ 2 files changed, 18 insertions(+) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/BLI_blenlib.h b/source/blender/blenlib/BLI_blenlib.h index 6a50e2de0e5..4bbda9709d7 100644 --- a/source/blender/blenlib/BLI_blenlib.h +++ b/source/blender/blenlib/BLI_blenlib.h @@ -137,6 +137,9 @@ void BLI_dlist_reinit(struct DynamicList *dlist); void BLI_cleanup_file(const char *relabase, char *dir); void BLI_cleanup_dir(const char *relabase, char *dir); /* same as above but adds a trailing slash */ +/* go back one directory */ +int BLI_parent_dir(char *path); + /** * Blender's path code replacement function. * Bases @a path strings leading with "//" by the diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c index 9dfe9557c1b..1630842be05 100644 --- a/source/blender/blenlib/intern/util.c +++ b/source/blender/blenlib/intern/util.c @@ -1058,6 +1058,21 @@ void BLI_makestringcode(const char *relfile, char *file) } } +int BLI_parent_dir(char *path) +{ + char tmp[FILE_MAXDIR+FILE_MAXFILE+4]; + BLI_strncpy(tmp, path, sizeof(tmp)); + BLI_add_slash(tmp); + strcat(tmp, "../"); + BLI_cleanup_dir(NULL, tmp); + + if (!BLI_testextensie(tmp, "../")) { + BLI_strncpy(path, tmp, sizeof(tmp)); + return 1; + } else { + return 0; + } +} int BLI_convertstringframe(char *path, int frame) { -- cgit v1.2.3 From d438b466b75d44f1f80dbd1e0bcc6ae27d083461 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Mon, 22 Sep 2008 21:15:48 +0000 Subject: Fix file browser for Windows: going to the parent directory introduces ../\. Correct parent is ..\ under Windows. --- source/blender/blenlib/intern/util.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c index 1630842be05..d65fe8a476a 100644 --- a/source/blender/blenlib/intern/util.c +++ b/source/blender/blenlib/intern/util.c @@ -1060,13 +1060,18 @@ void BLI_makestringcode(const char *relfile, char *file) int BLI_parent_dir(char *path) { +#ifdef WIN32 + static char *parent_dir="..\\"; +#else + static char *parent_dir="../"; +#endif char tmp[FILE_MAXDIR+FILE_MAXFILE+4]; BLI_strncpy(tmp, path, sizeof(tmp)); BLI_add_slash(tmp); - strcat(tmp, "../"); + strcat(tmp, parent_dir); BLI_cleanup_dir(NULL, tmp); - if (!BLI_testextensie(tmp, "../")) { + if (!BLI_testextensie(tmp, parent_dir)) { BLI_strncpy(path, tmp, sizeof(tmp)); return 1; } else { -- cgit v1.2.3 From 25fc47aaf2a7898b81eb4617a1cd877832d675c2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 29 Sep 2008 02:16:18 +0000 Subject: tests for 2d triangle and quad intersection would only work if the points were ordered clockwise. now return 1 for clockwise, -1 for counter-clockwise and 0 for no intersection. --- source/blender/blenlib/intern/arithb.c | 48 +++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 15 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index 888a5ab2f64..0dda84b09fd 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -2553,29 +2553,47 @@ short IsectLLPt2Df(float x0,float y0,float x1,float y1, } // end Intersect_Lines #define SIDE_OF_LINE(pa,pb,pp) ((pa[0]-pp[0])*(pb[1]-pp[1]))-((pb[0]-pp[0])*(pa[1]-pp[1])) -#define ISECT_EPSILON 1e-6 - /* point in tri */ int IsectPT2Df(float pt[2], float v1[2], float v2[2], float v3[2]) { - if ((SIDE_OF_LINE(v1,v2,pt)>=-ISECT_EPSILON) && - (SIDE_OF_LINE(v2,v3,pt)>=-ISECT_EPSILON) && - (SIDE_OF_LINE(v3,v1,pt)>=-ISECT_EPSILON)) - return 1; - else { - return 0; + if (SIDE_OF_LINE(v1,v2,pt)>=0.0) { + if (SIDE_OF_LINE(v2,v3,pt)>=0.0) { + if (SIDE_OF_LINE(v3,v1,pt)>=0.0) { + return 1; + } + } + } else { + if (! (SIDE_OF_LINE(v2,v3,pt)>=0.0) ) { + if (! (SIDE_OF_LINE(v3,v1,pt)>=0.0)) { + return -1; + } + } } + + return 0; } /* point in quad - only convex quads */ int IsectPQ2Df(float pt[2], float v1[2], float v2[2], float v3[2], float v4[2]) { - if ((SIDE_OF_LINE(v1,v2,pt)>=-ISECT_EPSILON) && - (SIDE_OF_LINE(v2,v3,pt)>=-ISECT_EPSILON) && - (SIDE_OF_LINE(v3,v4,pt)>=-ISECT_EPSILON) && - (SIDE_OF_LINE(v4,v1,pt)>=-ISECT_EPSILON)) - return 1; - else - return 0; + if (SIDE_OF_LINE(v1,v2,pt)>=0.0) { + if (SIDE_OF_LINE(v2,v3,pt)>=0.0) { + if (SIDE_OF_LINE(v3,v4,pt)>=0.0) { + if (SIDE_OF_LINE(v4,v1,pt)>=0.0) { + return 1; + } + } + } + } else { + if (! (SIDE_OF_LINE(v2,v3,pt)>=0.0) ) { + if (! (SIDE_OF_LINE(v3,v4,pt)>=0.0)) { + if (! (SIDE_OF_LINE(v4,v1,pt)>=0.0)) { + return -1; + } + } + } + } + + return 0; } -- cgit v1.2.3 From 2a331067cc52693aa903a0487be29c93298c4b8b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 29 Sep 2008 17:08:11 +0000 Subject: resolve some compiler warnings with intel c/c++ compiler * subsurf code had a lot of unused variables, removed these where they are obviously not needed. commented if they could be useful later. * some variables declorations hide existing variables (many of these left), but fixed some that could cause confusion. * removed unused vars * obscure python memory leak with colorband. * make_sample_tables had a loop running wasnt used. * if 0'd functions in arithb.c that are not used yet. * made many functions static --- source/blender/blenlib/intern/arithb.c | 17 ++++++++++------- source/blender/blenlib/intern/bpath.c | 6 ++---- source/blender/blenlib/intern/psfont.c | 12 ++++++------ 3 files changed, 18 insertions(+), 17 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index 0dda84b09fd..79517c4fde4 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -2503,7 +2503,7 @@ short IsectLL2Df(float *v1, float *v2, float *v3, float *v4) 1: intersection */ -short IsectLLPt2Df(float x0,float y0,float x1,float y1, +static short IsectLLPt2Df(float x0,float y0,float x1,float y1, float x2,float y2,float x3,float y3, float *xi,float *yi) { @@ -3526,7 +3526,7 @@ int constrain_rgb(float *r, float *g, float *b) Parameter Values for the HDTV Standard for the Studio and for International Programme Exchange'', formerly CCIR Rec. 709.*/ -void gamma_correct(float *c) +static void gamma_correct(float *c) { /* Rec. 709 gamma correction. */ float cc = 0.018; @@ -3632,6 +3632,8 @@ void spheremap(float x, float y, float z, float *u, float *v) /* ------------------------------------------------------------------------- */ +/* proposed api by ton and zr, not used yet */ +#if 0 /* ***************** m1 = m2 ***************** */ void cpy_m3_m3(float m1[][3], float m2[][3]) { @@ -3655,7 +3657,6 @@ void ident_m4(float m[][4]) m[3][0]= m[3][1]= m[3][2]= 0.0; } - /* ***************** m1 = m2 (pre) * m3 (post) ***************** */ void mul_m3_m3m3(float m1[][3], float m2[][3], float m3[][3]) { @@ -3793,6 +3794,8 @@ void mul_v3_v3m4(float *v1, float *v2, float mat[][4]) } +#endif + /* moved from effect.c test if the line starting at p1 ending at p2 intersects the triangle v0..v2 return non zero if it does @@ -4240,7 +4243,7 @@ float lambda_cp_line_ex(float p[3], float l1[3], float l2[3], float cp[3]) } /* little sister we only need to know lambda */ -float lambda_cp_line(float p[3], float l1[3], float l2[3]) +static float lambda_cp_line(float p[3], float l1[3], float l2[3]) { float h[3],u[3]; VecSubf(u, l2, l1); @@ -4399,7 +4402,7 @@ void VecfCubicInterpol(float *x1, float *v1, float *x2, float *v2, float t, floa v[2]= 3*a[2]*t2 + 2*b[2]*t + v1[2]; } -int point_in_slice(float p[3], float v1[3], float l1[3], float l2[3]) +static int point_in_slice(float p[3], float v1[3], float l1[3], float l2[3]) { /* what is a slice ? @@ -4426,7 +4429,7 @@ but see a 'spat' which is a deformed cube with paired parallel planes needs only /*adult sister defining the slice planes by the origin and the normal NOTE |normal| may not be 1 but defining the thickness of the slice*/ -int point_in_slice_as(float p[3],float origin[3],float normal[3]) +static int point_in_slice_as(float p[3],float origin[3],float normal[3]) { float h,rp[3]; VecSubf(rp,p,origin); @@ -4436,7 +4439,7 @@ int point_in_slice_as(float p[3],float origin[3],float normal[3]) } /*mama (knowing the squared lenght of the normal)*/ -int point_in_slice_m(float p[3],float origin[3],float normal[3],float lns) +static int point_in_slice_m(float p[3],float origin[3],float normal[3],float lns) { float h,rp[3]; VecSubf(rp,p,origin); diff --git a/source/blender/blenlib/intern/bpath.c b/source/blender/blenlib/intern/bpath.c index 898ad6ddd67..e23c2658399 100644 --- a/source/blender/blenlib/intern/bpath.c +++ b/source/blender/blenlib/intern/bpath.c @@ -254,7 +254,7 @@ static struct Sequence *seq_stepdata__internal(struct BPathIterator *bpi, int st return NULL; } -void seq_getpath(struct BPathIterator *bpi, char *path) { +static void seq_getpath(struct BPathIterator *bpi, char *path) { Sequence *seq = (Sequence *)bpi->data; @@ -275,7 +275,7 @@ void seq_getpath(struct BPathIterator *bpi, char *path) { } } -void seq_setpath(struct BPathIterator *bpi, char *path) { +static void seq_setpath(struct BPathIterator *bpi, char *path) { Sequence *seq = (Sequence *)bpi->data; if (seq==NULL) return; @@ -456,7 +456,6 @@ void checkMissingFiles( char *txtname ) { /* be sure there is low chance of the path being too short */ char filepath_expanded[FILE_MAXDIR*2]; - int files_missing = 0; BLI_bpathIterator_init(&bpi); while (!BLI_bpathIterator_isDone(&bpi)) { @@ -470,7 +469,6 @@ void checkMissingFiles( char *txtname ) { } } bpathToText(btxt, &bpi); - files_missing = 1; } BLI_bpathIterator_step(&bpi); } diff --git a/source/blender/blenlib/intern/psfont.c b/source/blender/blenlib/intern/psfont.c index 216246dcdd7..54d7f8ec1af 100644 --- a/source/blender/blenlib/intern/psfont.c +++ b/source/blender/blenlib/intern/psfont.c @@ -977,7 +977,7 @@ static void applymat(float mat[][2], float *x, float *y) static void setcharlist(void) { - char *name, found; + char *name; /*found;*/ int i, j; for(i=0; i Date: Tue, 30 Sep 2008 04:08:00 +0000 Subject: modify BLI_convertstringcode so windows paths are converted from C:\foo.jpg to /c/foo.jpg since there is C:\ prefix cant exist on a unix system this wont break any files. --- source/blender/blenlib/intern/util.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c index d65fe8a476a..442a629b12d 100644 --- a/source/blender/blenlib/intern/util.c +++ b/source/blender/blenlib/intern/util.c @@ -1149,15 +1149,13 @@ int BLI_convertstringframe(char *path, int frame) int BLI_convertstringcode(char *path, const char *basepath) { - int wasrelative; + int wasrelative = (strncmp(path, "//", 2)==0); char tmp[FILE_MAX]; char base[FILE_MAX]; +#ifdef WIN32 char vol[3] = {'\0', '\0', '\0'}; BLI_strncpy(vol, path, 3); - wasrelative= (vol[0]=='/' && vol[1]=='/'); - -#ifdef WIN32 /* we are checking here if we have an absolute path that is not in the current blend file as a lib main - we are basically checking for the case that a UNIX root '/' is passed. @@ -1176,6 +1174,20 @@ int BLI_convertstringcode(char *path, const char *basepath) } #else BLI_strncpy(tmp, path, FILE_MAX); + + /* Check for loading a windows path on a posix system + * in this case, there is no use in trying C:/ since it + * will never exist on a unix os. + * + * Add a / prefix and lowercase the driveletter, remove the : + * C:\foo.JPG -> /c/foo.JPG */ + + if (tmp[1] == ':' && isalpha(tmp[0]) && (tmp[2]=='\\' || tmp[2]=='/') ) { + tmp[1] = tolower(tmp[0]); /* replace ':' with driveletter */ + tmp[0] = '/'; + /* '\' the slash will be converted later */ + } + #endif BLI_strncpy(base, basepath, FILE_MAX); -- cgit v1.2.3