MERGING TRUNK

This commit is contained in:
2008-06-23 16:37:51 +00:00
354 changed files with 52714 additions and 9653 deletions

View File

@@ -0,0 +1,810 @@
/**
*
* ***** 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 *****
*/
#include "math.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MEM_guardedalloc.h"
#include "BKE_utildefines.h"
#include "BLI_kdopbvh.h"
#include "BLI_arithb.h"
#ifdef _OPENMP
#include <omp.h>
#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;
} BVHNode;
struct BVHTree
{
BVHNode **nodes;
BVHNode *nodearray; /* pre-alloc branch nodes */
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
};
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 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) // 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;
int i, k;
// don't init boudings for the moving case
if(!moving)
{
for (i = tree->start_axis; i < tree->stop_axis; i++)
{
node->bv[2*i] = FLT_MAX;
node->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 < node->bv[2 * i])
node->bv[2 * i] = newminmax;
if (newminmax > node->bv[(2 * i) + 1])
node->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->bv;
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;
}
}
}
int BLI_bvhtree_insert(BVHTree *tree, int index, float *co, int numpoints)
{
BVHNode *node= NULL;
int i;
// 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_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;
}
// 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)
{
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
}
}
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 = get_largest_axis(node->bv);
// 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
{
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(float *bv1, float *bv2, int start_axis, int stop_axis)
{
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->bv, node2->bv, 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)
{
// check if node2 is a leaf
if(!node2->totnode)
{
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]->bv, tree2->nodes[tree2->totleaf]->bv, 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 < MIN2(tree1->tree_type, tree1->nodes[tree1->totleaf]->totnode); 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;
int i = 0;
// 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 *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;
}

View File

@@ -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)
@@ -3965,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]<max2[0] && min1[1]<max2[1] && min1[2]<max2[2] &&

View File

@@ -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)) {

View File

@@ -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,21 @@ void BLI_cleanup_file(const char *relabase, char *dir)
if (dir[a] == '\\') break;
a--;
}
strcpy(dir+a,eind);
if (a<0) {
break;
} else {
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 +942,21 @@ void BLI_cleanup_file(const char *relabase, char *dir)
if (dir[a] == '/') break;
a--;
}
strcpy(dir+a,eind);
if (a<0) {
break;
} else {
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 */
@@ -1114,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
@@ -1150,23 +1171,32 @@ int BLI_convertstringcode(char *path, const char *basepath)
BLI_char_switch(tmp, '\\', '/');
BLI_char_switch(base, '\\', '/');
if (tmp[0] == '/' && tmp[1] == '/') {
char *filepart= BLI_strdup(tmp+2); /* skip code */
/* 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 (wasrelative) {
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);
}
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