Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/kdop.c')
-rw-r--r--source/blender/blenkernel/intern/kdop.c810
1 files changed, 810 insertions, 0 deletions
diff --git a/source/blender/blenkernel/intern/kdop.c b/source/blender/blenkernel/intern/kdop.c
new file mode 100644
index 00000000000..8d2b48144be
--- /dev/null
+++ b/source/blender/blenkernel/intern/kdop.c
@@ -0,0 +1,810 @@
+/* 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): none yet.
+*
+* ***** END GPL/BL DUAL LICENSE BLOCK *****
+*/
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include "MEM_guardedalloc.h"
+/* types */
+#include "DNA_curve_types.h"
+#include "DNA_object_types.h"
+#include "DNA_object_force.h"
+#include "DNA_cloth_types.h"
+#include "DNA_key_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_modifier_types.h"
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_edgehash.h"
+#include "BLI_linklist.h"
+#include "BKE_curve.h"
+#include "BKE_deform.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_effect.h"
+#include "BKE_global.h"
+#include "BKE_key.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_cloth.h"
+#include "BKE_modifier.h"
+#include "BKE_utildefines.h"
+#include "BKE_DerivedMesh.h"
+#include "BIF_editdeform.h"
+#include "BIF_editkey.h"
+#include "DNA_screen_types.h"
+#include "BSE_headerbuttons.h"
+#include "BIF_screen.h"
+#include "BIF_space.h"
+#include "mydevice.h"
+
+
+////////////////////////////////////////////////////////////////////////
+// Additional fastened appending function
+// It uses the link to the last inserted node as start value
+// for searching the end of the list
+// NEW: in compare to the original function, this one returns
+// the reference to the last inserted node
+////////////////////////////////////////////////////////////////////////
+LinkNode *BLI_linklist_append_fast(LinkNode **listp, void *ptr) {
+ LinkNode *nlink= MEM_mallocN(sizeof(*nlink), "nlink");
+ LinkNode *node = *listp;
+
+ nlink->link = ptr;
+ nlink->next = NULL;
+
+ if(node == NULL){
+ *listp = nlink;
+ } else {
+ while(node->next != NULL){
+ node = node->next;
+ }
+ node->next = nlink;
+ }
+ return nlink;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+// 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, 1, 0}, {0, 0, 1}, {1, 1, 1}, {1, -1, 1}, {1, 1, -1},
+{1, -1, -1}, {1, 1, 0}, {1, 0, 1}, {0, 1, 1}, {1, -1, 0}, {1, 0, -1},
+{0, 1, -1}
+};
+
+///////////// choose bounding volume here! /////////////
+
+// #define KDOP_26
+
+// #define KDOP_14
+
+// AABB:
+// #define KDOP_8
+
+// OBB:
+#define KDOP_6
+
+
+
+#ifdef KDOP_26
+#define KDOP_END 13
+#define KDOP_START 0
+#endif
+
+// I didn't test this one!
+#ifdef KDOP_18
+#define KDOP_END 7
+#define KDOP_START 13
+#endif
+
+#ifdef KDOP_14
+#define KDOP_END 7
+#define KDOP_START 0
+#endif
+
+// this is basicly some AABB
+#ifdef KDOP_8
+#define KDOP_END 4
+#define KDOP_START 0
+#endif
+
+// this is basicly some OBB
+#ifdef KDOP_6
+#define KDOP_END 3
+#define KDOP_START 0
+#endif
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+// 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
+*/
+DO_INLINE void bvh_exchange(CollisionTree **a, int i, int j)
+{
+ CollisionTree *t=a[i];
+ a[i]=a[j];
+ a[j]=t;
+}
+DO_INLINE int floor_lg(int a)
+{
+ return (int)(floor(log(a)/log(2)));
+}
+
+/*
+* Insertion sort algorithm
+*/
+static void bvh_insertionsort(CollisionTree **a, int lo, int hi, int axis)
+{
+ int i,j;
+ CollisionTree *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(CollisionTree **a, int lo, int hi, CollisionTree * x, int axis)
+{
+ int i=lo, j=hi;
+ while (1)
+ {
+ while ((a[i])->bv[axis] < x->bv[axis]) i++;
+ j=j-1;
+ while (x->bv[axis] < (a[j])->bv[axis]) j=j-1;
+ if(!(i < j))
+ return i;
+ bvh_exchange(a, i,j);
+ i++;
+ }
+}
+
+/*
+* Heapsort algorithm
+*/
+static void bvh_downheap(CollisionTree **a, int i, int n, int lo, int axis)
+{
+ CollisionTree * 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(CollisionTree **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)
+ {
+ bvh_exchange(a, lo,lo+i-1);
+ bvh_downheap(a, 1,i-1,lo, axis);
+ }
+}
+
+static CollisionTree *bvh_medianof3(CollisionTree **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 (CollisionTree **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;
+ }
+}
+
+DO_INLINE void bvh_sort(CollisionTree **a0, int begin, int end, int axis)
+{
+ if (begin < end)
+ {
+ CollisionTree **a=a0;
+ bvh_introsort_loop(a, begin, end, 2*floor_lg(end-begin), axis);
+ bvh_insertionsort(a, begin, end, axis);
+ }
+}
+DO_INLINE void bvh_sort_along_axis(CollisionTree **face_list, int start, int end, int axis)
+{
+ bvh_sort(face_list, start, end, axis);
+}
+////////////////////////////////////////////////////////////////////////////////////////////////
+void bvh_free(BVH * bvh)
+{
+ LinkNode *search = NULL;
+ CollisionTree *tree = NULL;
+
+ if (bvh)
+ {
+
+ search = bvh->tree;
+
+ while(search)
+ {
+ LinkNode *next= search->next;
+ tree = search->link;
+
+ MEM_freeN(tree);
+
+ search = next;
+ }
+
+ BLI_linklist_free(bvh->tree,NULL);
+ bvh->tree = NULL;
+
+ if(bvh->current_x)
+ MEM_freeN(bvh->current_x);
+ if(bvh->current_xold)
+ MEM_freeN(bvh->current_xold);
+
+ MEM_freeN(bvh);
+ bvh = NULL;
+ }
+}
+
+// only supports x,y,z axis in the moment
+// but we should use a plain and simple function here for speed sake
+DO_INLINE int bvh_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
+ }
+}
+
+// depends on the fact that the BVH's for each face is already build
+DO_INLINE void bvh_calc_DOP_hull_from_faces(BVH * bvh, CollisionTree **tri, int numfaces, float *bv)
+{
+ float newmin,newmax;
+ int i, j;
+ for (j = 0; j < numfaces; j++)
+ {
+ // for all Axes.
+ for (i = KDOP_START; i < KDOP_END; i++)
+ {
+ newmin = (tri [j])->bv[(2 * i)];
+ if ((newmin < bv[(2 * i)]) || (j == 0))
+ {
+ bv[(2 * i)] = newmin;
+ }
+
+ newmax = (tri [j])->bv[(2 * i) + 1];
+ if ((newmax > bv[(2 * i) + 1]) || (j == 0))
+ {
+ bv[(2 * i) + 1] = newmax;
+ }
+ }
+ }
+}
+
+DO_INLINE void bvh_calc_DOP_hull_static(BVH * bvh, CollisionTree **tri, int numfaces, float *bv)
+{
+ MFace *tempMFace = bvh->mfaces;
+ float *tempBV = bv;
+ float newminmax;
+ int i, j, k;
+ for (j = 0; j < numfaces; j++)
+ {
+ tempMFace = bvh->mfaces + (tri [j])->tri_index;
+ // 3 or 4 vertices per face.
+ for (k = 0; k < 4; k++)
+ {
+ int temp = 0;
+ // If this is a triangle.
+ if (k == 3 && !tempMFace->v4)
+ continue;
+ // TODO: other name for "temp" this gets all vertices of a face
+ if (k == 0)
+ temp = tempMFace->v1;
+ else if (k == 1)
+ temp = tempMFace->v2;
+ else if (k == 2)
+ temp = tempMFace->v3;
+ else if (k == 3)
+ temp = tempMFace->v4;
+ // for all Axes.
+ for (i = KDOP_START; i < KDOP_END; i++)
+ {
+ newminmax = INPR(bvh->current_xold[temp].co, KDOP_AXES[i]);
+ if ((newminmax < tempBV[(2 * i)]) || (k == 0 && j == 0))
+ tempBV[(2 * i)] = newminmax;
+ if ((newminmax > tempBV[(2 * i) + 1])|| (k == 0 && j == 0))
+ tempBV[(2 * i) + 1] = newminmax;
+ }
+ }
+ }
+}
+
+DO_INLINE void bvh_calc_DOP_hull_moving(BVH * bvh, CollisionTree **tri, int numfaces, float *bv)
+{
+ MFace *tempMFace = bvh->mfaces;
+ float *tempBV = bv;
+ float newminmax;
+ int i, j, k;
+ for (j = 0; j < numfaces; j++)
+ {
+ tempMFace = bvh->mfaces + (tri [j])->tri_index;
+ // 3 or 4 vertices per face.
+ for (k = 0; k < 4; k++)
+ {
+ int temp = 0;
+ // If this is a triangle.
+ if (k == 3 && !tempMFace->v4)
+ continue;
+ // TODO: other name for "temp" this gets all vertices of a face
+ if (k == 0)
+ temp = tempMFace->v1;
+ else if (k == 1)
+ temp = tempMFace->v2;
+ else if (k == 2)
+ temp = tempMFace->v3;
+ else if (k == 3)
+ temp = tempMFace->v4;
+ // for all Axes.
+ for (i = KDOP_START; i < KDOP_END; i++)
+ {
+ newminmax = INPR(bvh->current_xold[temp].co, KDOP_AXES[i]);
+ if ((newminmax < tempBV[(2 * i)]) || (k == 0 && j == 0))
+ tempBV[(2 * i)] = newminmax;
+ if ((newminmax > tempBV[(2 * i) + 1])|| (k == 0 && j == 0))
+ tempBV[(2 * i) + 1] = newminmax;
+
+ newminmax = INPR(bvh->current_x[temp].co, KDOP_AXES[i]);
+ if ((newminmax < tempBV[(2 * i)]) || (k == 0 && j == 0))
+ tempBV[(2 * i)] = newminmax;
+ if ((newminmax > tempBV[(2 * i) + 1])|| (k == 0 && j == 0))
+ tempBV[(2 * i) + 1] = newminmax;
+ }
+ }
+ }
+}
+
+static void bvh_div_env_node(BVH *bvh, CollisionTree *tree, CollisionTree **face_list, unsigned int start, unsigned int end, int lastaxis, LinkNode *nlink)
+{
+ int i = 0;
+ CollisionTree *newtree = NULL;
+ int laxis = 0, max_nodes=4;
+ unsigned int tstart, tend;
+ LinkNode *nlink1 = nlink;
+ LinkNode *tnlink;
+ tree->traversed = 0;
+ // Determine which axis to split along
+ laxis = bvh_largest_axis(tree->bv);
+
+ // Sort along longest axis
+ if(laxis!=lastaxis)
+ bvh_sort_along_axis(face_list, start, end, laxis);
+
+ max_nodes = MIN2((end-start + 1 ),4);
+
+ for (i = 0; i < max_nodes; i++)
+ {
+ tree->count_nodes++;
+
+ if(end-start > 4)
+ {
+ int quarter = ((float)((float)(end - start + 1) / 4.0f));
+ tstart = start + i * quarter;
+ tend = tstart + quarter - 1;
+
+ // be sure that we get all faces
+ if(i==3)
+ {
+ tend = end;
+ }
+ }
+ else
+ {
+ tend = tstart = start + i;
+ }
+
+ // Build tree until 4 node left.
+ if ((tend-tstart + 1 ) > 1)
+ {
+ newtree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree");
+ tnlink = BLI_linklist_append_fast(&nlink1->next, newtree);
+
+ newtree->nodes[0] = newtree->nodes[1] = newtree->nodes[2] = newtree->nodes[3] = NULL;
+ newtree->count_nodes = 0;
+ newtree->parent = tree;
+ newtree->isleaf = 0;
+
+ tree->nodes[i] = newtree;
+
+ nlink1 = tnlink;
+
+ bvh_calc_DOP_hull_from_faces(bvh, &face_list[tstart], tend-tstart + 1, tree->nodes[i]->bv);
+
+ bvh_div_env_node(bvh, tree->nodes[i], face_list, tstart, tend, laxis, nlink1);
+ }
+ else // ok, we have 1 left for this node
+ {
+ CollisionTree *tnode = face_list[tstart];
+ tree->nodes[i] = tnode;
+ tree->nodes[i]->parent = tree;
+ }
+ }
+ return;
+}
+
+/* function cannot be directly called - needs alloced bvh */
+void bvh_build (BVH *bvh)
+{
+ unsigned int i = 0, j = 0, k = 0;
+ CollisionTree **face_list=NULL;
+ CollisionTree *tree=NULL;
+ LinkNode *nlink = NULL;
+
+ tree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree");
+ // TODO: check succesfull alloc
+ BLI_linklist_append(&bvh->tree, tree);
+
+ nlink = bvh->tree;
+
+ if (tree == NULL)
+ {
+ printf("bvh_build: Out of memory for nodes.\n");
+ bvh_free(bvh);
+ return;
+ }
+ bvh->root = bvh->tree->link;
+ bvh->root->isleaf = 0;
+ bvh->root->parent = NULL;
+ bvh->root->nodes[0] = bvh->root->nodes[1] = bvh->root->nodes[1] = bvh->root->nodes[3] = NULL;
+
+ if(bvh->numfaces<=1)
+ {
+ bvh->root->tri_index = 0; // Why that? --> only one face there
+ bvh->root->isleaf = 1;
+ bvh->root->traversed = 0;
+ bvh->root->count_nodes = 0;
+ bvh->leaf_root = bvh->root;
+ bvh->leaf_tree = bvh->root;
+ bvh->root->nextLeaf = NULL;
+ bvh->root->prevLeaf = NULL;
+ }
+ else
+ {
+ // create face boxes
+ face_list = MEM_callocN (bvh->numfaces * sizeof (CollisionTree *), "CollisionTree");
+ if (face_list == NULL)
+ {
+ printf("bvh_build: Out of memory for face_list.\n");
+ bvh_free(bvh);
+ return;
+ }
+
+ // create face boxes
+ for(i = 0, k = 0; i < bvh->numfaces; i++)
+ {
+ LinkNode *tnlink;
+
+ tree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree");
+ // TODO: check succesfull alloc
+
+ tnlink = BLI_linklist_append_fast(&nlink->next, tree);
+
+ face_list[i] = tree;
+ tree->tri_index = i;
+ tree->isleaf = 1;
+ tree->nextLeaf = NULL;
+ tree->prevLeaf = bvh->leaf_tree;
+ tree->parent = NULL;
+ tree->count_nodes = 0;
+
+ if(i==0)
+ {
+ bvh->leaf_tree = bvh->leaf_root = tree;
+ }
+ else
+ {
+ bvh->leaf_tree->nextLeaf = tree;
+ bvh->leaf_tree = bvh->leaf_tree->nextLeaf;
+ }
+
+ tree->nodes[0] = tree->nodes[1] = tree->nodes[2] = tree->nodes[3] = NULL;
+
+ bvh_calc_DOP_hull_static(bvh, &face_list[i], 1, tree->bv);
+
+ // inflate the bv with some epsilon
+ for (j = KDOP_START; j < KDOP_END; j++)
+ {
+ tree->bv[(2 * j)] -= bvh->epsilon; // minimum
+ tree->bv[(2 * j) + 1] += bvh->epsilon; // maximum
+ }
+
+ nlink = tnlink;
+ }
+
+ // build root bvh
+ bvh_calc_DOP_hull_from_faces(bvh, face_list, bvh->numfaces, bvh->root->bv);
+
+ // This is the traversal function.
+ bvh_div_env_node(bvh, bvh->root, face_list, 0, bvh->numfaces-1, 0, nlink);
+ if (face_list)
+ MEM_freeN(face_list);
+
+ }
+
+}
+
+// bvh_overlap - is it possbile for 2 bv's to collide ?
+DO_INLINE int bvh_overlap(float *bv1, float *bv2)
+{
+ int i = 0;
+ for (i = KDOP_START; i < KDOP_END; i++)
+ {
+ // Minimum test.
+ if (bv1[(2 * i)] > bv2[(2 * i) + 1])
+ {
+ return 0;
+ }
+ // Maxiumum test.
+ if (bv2[(2 * i)] > bv1[(2 * i) + 1])
+ {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+/**
+ * bvh_traverse - traverse two bvh trees looking for potential collisions.
+ *
+ * max collisions are n*n collisions --> every triangle collide with
+ * every other triangle that doesn't require any realloc, but uses
+ * much memory
+ */
+int bvh_traverse ( ClothModifierData * clmd, CollisionModifierData * collmd, CollisionTree * tree1, CollisionTree * tree2, float step, CM_COLLISION_RESPONSE collision_response)
+{
+ int i = 0, ret=0;
+
+ /*
+ // Shouldn't be possible
+ if(!tree1 || !tree2)
+ {
+ printf("Error: no tree there\n");
+ return 0;
+}
+ */
+ if (bvh_overlap(tree1->bv, tree2->bv))
+ {
+ // Check if this node in the first tree is a leaf
+ if (tree1->isleaf)
+ {
+ // Check if this node in the second tree a leaf
+ if (tree2->isleaf)
+ {
+ // Provide the collision response.
+
+ if(collision_response)
+ collision_response (clmd, collmd, tree1, tree2);
+ return 1;
+ }
+ else
+ {
+ // Process the quad tree.
+ for (i = 0; i < 4; i++)
+ {
+ // Only traverse nodes that exist.
+ if (tree2->nodes[i] && bvh_traverse (clmd, collmd, tree1, tree2->nodes[i], step, collision_response))
+ ret = 1;
+ }
+ }
+ }
+ else
+ {
+ // Process the quad tree.
+ for (i = 0; i < 4; i++)
+ {
+ // Only traverse nodes that exist.
+ if (tree1->nodes [i] && bvh_traverse (clmd, collmd, tree1->nodes[i], tree2, step, collision_response))
+ ret = 1;
+ }
+ }
+ }
+
+ return ret;
+}
+
+// bottom up update of bvh tree:
+// join the 4 children here
+void bvh_join(CollisionTree * tree)
+{
+ int i = 0, j = 0;
+ if (!tree)
+ return;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (tree->nodes[i])
+ {
+ for (j = KDOP_START; j < KDOP_END; j++)
+ {
+ // update minimum
+ if ((tree->nodes[i]->bv[(2 * j)] < tree->bv[(2 * j)]) || (i == 0))
+ {
+ tree->bv[(2 * j)] = tree->nodes[i]->bv[(2 * j)];
+ }
+ // update maximum
+ if ((tree->nodes[i]->bv[(2 * j) + 1] > tree->bv[(2 * j) + 1])|| (i == 0))
+ {
+ tree->bv[(2 * j) + 1] = tree->nodes[i]->bv[(2 * j) + 1];
+ }
+ }
+ }
+ else
+ break;
+ }
+}
+
+// update static bvh
+/* you have to update the bvh position before calling this function */
+void bvh_update(BVH * bvh, int moving)
+{
+ CollisionTree *leaf, *parent;
+ int traversecheck = 1; // if this is zero we don't go further
+ unsigned int j = 0;
+
+ for (leaf = bvh->leaf_root; leaf; leaf = leaf->nextLeaf)
+ {
+ traversecheck = 1;
+ if ((leaf->parent) && (leaf->parent->traversed == leaf->parent->count_nodes))
+ {
+ leaf->parent->traversed = 0;
+ }
+ if(!moving)
+ bvh_calc_DOP_hull_static(bvh, &leaf, 1, leaf->bv);
+ else
+ bvh_calc_DOP_hull_moving(bvh, &leaf, 1, leaf->bv);
+
+ // inflate the bv with some epsilon
+ for (j = KDOP_START; j < KDOP_END; j++)
+ {
+ leaf->bv[(2 * j)] -= bvh->epsilon; // minimum
+ leaf->bv[(2 * j) + 1] += bvh->epsilon; // maximum
+ }
+
+ for (parent = leaf->parent; parent; parent = parent->parent)
+ {
+ if (traversecheck)
+ {
+ parent->traversed++; // we tried to go up in hierarchy
+ if (parent->traversed < parent->count_nodes)
+ {
+ traversecheck = 0;
+
+ if (parent->parent)
+ {
+ if (parent->parent->traversed == parent->parent->count_nodes)
+ {
+ parent->parent->traversed = 0;
+ }
+ }
+ break; // we do not need to check further
+ }
+ else
+ {
+ bvh_join(parent);
+ }
+ }
+
+ }
+ }
+}
+