WIP commit, (just in case my HD breaks down). Don't expect anything to work. Code...
[blender.git] / source / blender / blenkernel / intern / implicit.c
index df5830f6a7721a26ac417155da23e9d540a237af..f61e2d22f1c1990097d90552ce8f04335a16e630 100644 (file)
@@ -49,6 +49,7 @@
 #include "BLI_blenlib.h"
 #include "BLI_arithb.h"
 #include "BLI_threads.h"
+#include "BKE_collisions.h"
 #include "BKE_curve.h"
 #include "BKE_displist.h"
 #include "BKE_effect.h"
@@ -570,7 +571,7 @@ DO_INLINE void mul_bfmatrix_S(fmatrix3x3 *matrix, float scalar)
 /* STATUS: verified */
 DO_INLINE void mul_bfmatrix_lfvector( float (*to)[3], fmatrix3x3 *from, float (*fLongVector)[3])
 {
-       unsigned int i = 0,j=0;
+       unsigned int i = 0;
        zero_lfvector(to, from[0].vcount);
        /* process diagonal elements */ 
        for(i = 0; i < from[0].vcount; i++)
@@ -579,7 +580,8 @@ DO_INLINE void mul_bfmatrix_lfvector( float (*to)[3], fmatrix3x3 *from, float (*
        }
 
        /* process off-diagonal entries (every off-diagonal entry needs to be symmetric) */
-#pragma parallel for shared(to,from, fLongVector) private(i) 
+       // TODO: pragma below is wrong, correct it!
+       // #pragma omp parallel for shared(to,from, fLongVector) private(i) 
        for(i = from[0].vcount; i < from[0].vcount+from[0].scount; i++)
        {
                // muladd_fmatrix_fvector(to[from[i].c], from[i].m, fLongVector[from[i].r]);
@@ -699,15 +701,15 @@ int implicit_init (Object *ob, ClothModifierData *clmd)
        unsigned int pinned = 0;
        Cloth *cloth = NULL;
        ClothVertex *verts = NULL;
-       ClothSpring *springs = NULL;
+       ClothSpring *spring = NULL;
        Implicit_Data *id = NULL;
+       LinkNode *search = NULL;
 
        // init memory guard
        // MEMORY_BASE.first = MEMORY_BASE.last = NULL;
 
        cloth = (Cloth *)clmd->clothObject;
        verts = cloth->verts;
-       springs = cloth->springs;
 
        // create implicit base
        id = (Implicit_Data *)MEM_callocN (sizeof(Implicit_Data), "implicit vecmat");
@@ -748,17 +750,22 @@ int implicit_init (Object *ob, ClothModifierData *clmd)
        id->S[0].vcount = pinned; id->S[0].scount = 0;
 
        // init springs */
+       search = cloth->springs;
        for(i=0;i<cloth->numsprings;i++) 
        {
+               spring = search->link;
+               
                // dFdV_start[i].r = big_I[i].r = big_zero[i].r = 
                id->A[i+cloth->numverts].r = id->dFdV[i+cloth->numverts].r = id->dFdX[i+cloth->numverts].r = 
-                       id->P[i+cloth->numverts].r = id->Pinv[i+cloth->numverts].r = id->bigI[i+cloth->numverts].r = springs[i].ij;
+                               id->P[i+cloth->numverts].r = id->Pinv[i+cloth->numverts].r = id->bigI[i+cloth->numverts].r = spring->ij;
 
                // dFdV_start[i].c = big_I[i].c = big_zero[i].c = 
                id->A[i+cloth->numverts].c = id->dFdV[i+cloth->numverts].c = id->dFdX[i+cloth->numverts].c = 
-                       id->P[i+cloth->numverts].c = id->Pinv[i+cloth->numverts].c = id->bigI[i+cloth->numverts].c = springs[i].kl;
+                       id->P[i+cloth->numverts].c = id->Pinv[i+cloth->numverts].c = id->bigI[i+cloth->numverts].c = spring->kl;
 
-               springs[i].matrix_index = i + cloth->numverts;
+               spring->matrix_index = i + cloth->numverts;
+               
+               search = search->next;
        }
 
        for(i = 0; i < cloth->numverts; i++)
@@ -804,11 +811,13 @@ int       implicit_free (ClothModifierData *clmd)
 
        return 1;
 }
+
 DO_INLINE float fb(float length, float L)
 {
        float x = length/L;
        return (-11.541f*pow(x,4)+34.193f*pow(x,3)-39.083f*pow(x,2)+23.116f*x-9.713f);
 }
+
 DO_INLINE float fbderiv(float length, float L)
 {
        float x = length/L;
@@ -827,6 +836,7 @@ DO_INLINE float fbstar(float length, float L, float kb, float cb)
        else
                return tempfb;          
 }
+
 DO_INLINE float fbstar_jacobi(float length, float L, float kb, float cb)
 {
        float tempfb = kb * fb(length, L);
@@ -841,6 +851,7 @@ DO_INLINE float fbstar_jacobi(float length, float L, float kb, float cb)
                return kb * fbderiv(length, L); 
        }       
 }
+
 DO_INLINE void filter(lfVector *V, fmatrix3x3 *S)
 {
        unsigned int i=0;
@@ -850,6 +861,7 @@ DO_INLINE void filter(lfVector *V, fmatrix3x3 *S)
                mul_fvector_fmatrix(V[S[i].r], V[S[i].r], S[i].m);
        }
 }
+
 // block diagonalizer
 void BuildPPinv(fmatrix3x3 *lA, fmatrix3x3 *P, fmatrix3x3 *Pinv, fmatrix3x3 *S, fmatrix3x3 *bigI)
 {
@@ -874,6 +886,7 @@ void BuildPPinv(fmatrix3x3 *lA, fmatrix3x3 *P, fmatrix3x3 *Pinv, fmatrix3x3 *S,
        }               
 
 }
+
 int  cg_filtered(lfVector *ldV, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S)
 {
        // Solves for unknown X in equation AX=B
@@ -940,7 +953,7 @@ int  cg_filtered(lfVector *ldV, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatr
        return conjgrad_loopcount<conjgrad_looplimit;  // true means we reached desired accuracy in given time - ie stable
 }
 /*
-int cg_filtered_pre(lfVector *ldV, fmatrix3x3 *lA, lfVector *lB, lfVector *z, lfVector *X0, float dt)
+int cg_filtered_pre(lfVector *ldV, fmatrix3x3 *lA, lfVector *lB, lfVector *z, lfVector *X0, fmatrix3x3 *P, fmatrix3x3 *Pinv, float dt)
 {
 // Solves for unknown X in equation AX=B
 unsigned int conjgrad_loopcount=0, conjgrad_looplimit=100;
@@ -1101,17 +1114,20 @@ DO_INLINE void dfdx_spring_type1(float to[3][3], float dir[3],float length,float
        mul_fmatrix_S(temp, k);
        add_fmatrix_fmatrix(to, temp, to);
 }
+
 DO_INLINE void dfdx_spring_type2(float to[3][3], float dir[3],float length,float L,float k, float cb)
 {
        // return  outerprod(dir,dir)*fbstar_jacobi(length, L, k, cb);
        mul_fvectorT_fvectorS(to, dir, dir, fbstar_jacobi(length, L, k, cb));
 }
+
 DO_INLINE void dfdv_damp(float to[3][3], float dir[3], float damping)
 {
        // derivative of force wrt velocity.  
        // return outerprod(dir,dir) * damping;
        mul_fvectorT_fvectorS(to, dir, dir, damping);
 }
+
 DO_INLINE void dfdx_spring(float to[3][3],  float dir[3],float length,float L,float k)
 {
        // dir is unit length direction, rest is spring's restlength, k is spring constant.
@@ -1122,6 +1138,7 @@ DO_INLINE void dfdx_spring(float to[3][3],  float dir[3],float length,float L,fl
        sub_fmatrix_fmatrix(to, to, I);
        mul_fmatrix_S(to, -k);
 }
+
 DO_INLINE void dfdx_damp(float to[3][3],  float dir[3],float length,const float vel[3],float rest,float damping)
 {
        // inner spring damping   vel is the relative velocity  of the endpoints.  
@@ -1132,7 +1149,7 @@ DO_INLINE void dfdx_damp(float to[3][3],  float dir[3],float length,const float
 
 }
 
-DO_INLINE void calc_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVector *lF, lfVector *X, lfVector *V, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX)
+DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVector *lF, lfVector *X, lfVector *V, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX)
 {
        float extent[3];
        float length = 0;
@@ -1142,25 +1159,28 @@ DO_INLINE void calc_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVect
        float L = s->restlen;
        float cb = clmd->sim_parms.structural;
 
-       float f[3] = {0,0,0};
+       float nullf[3] = {0,0,0};
        float stretch_force[3] = {0,0,0};
        float bending_force[3] = {0,0,0};
        float damping_force[3] = {0,0,0};
-       float dfdx[3][3]={ {0,0,0}, {0,0,0}, {0,0,0}};
-       float dfdv[3][3];
-       int needed = 0;
+       float nulldfdx[3][3]={ {0,0,0}, {0,0,0}, {0,0,0}};
        Cloth *cloth = clmd->clothObject;
        ClothVertex *verts = cloth->verts;
+       
+       VECCOPY(s->f, nullf);
+       cp_fmatrix(s->dfdx, nulldfdx);
+       cp_fmatrix(s->dfdv, nulldfdx);
 
        // calculate elonglation
        VECSUB(extent, X[s->kl], X[s->ij]);
        VECSUB(vel, V[s->kl], V[s->ij]);
        length = sqrt(INPR(extent, extent));
        
-       
+       s->flags &= ~CLOTH_SPRING_FLAG_NEEDED;
        
        if(length > ABS(ALMOST_ZERO))
        {
+               /*
                if(length>L)
                {
                        if((clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) 
@@ -1170,7 +1190,7 @@ DO_INLINE void calc_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVect
                                return;
                        }
                } 
-               
+               */
                mul_fvector_S(dir, extent, 1.0f/length);
        }
        else    
@@ -1179,60 +1199,63 @@ DO_INLINE void calc_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVect
        }
        
        
-       // calculate force of structural springs
-       if(s->type != BENDING)
+       // calculate force of structural + shear springs
+       if(s->type != CLOTH_SPRING_TYPE_BENDING)
        {
                if(length > L) // only on elonglation
                {
-                       needed++;
+                       s->flags |= CLOTH_SPRING_FLAG_NEEDED;
 
                        k = clmd->sim_parms.structural; 
 
                        mul_fvector_S(stretch_force, dir, (k*(length-L))); 
 
-                       VECADD(f, f, stretch_force);
+                       VECADD(s->f, s->f, stretch_force);
 
                        // Ascher & Boxman, p.21: Damping only during elonglation
                        mul_fvector_S(damping_force, extent, clmd->sim_parms.Cdis * ((INPR(vel,extent)/length))); 
-                       VECADD(f, f, damping_force);
+                       VECADD(s->f, s->f, damping_force);
 
-                       dfdx_spring_type1(dfdx, dir,length,L,k);
-
-                       dfdv_damp(dfdv, dir,clmd->sim_parms.Cdis);      
-                               
-                       sub_fmatrix_fmatrix(dFdV[s->ij].m, dFdV[s->ij].m, dfdv);
-                       
-                       sub_fmatrix_fmatrix(dFdV[s->kl].m, dFdV[s->kl].m, dfdv);
+                       dfdx_spring_type1(s->dfdx, dir,length,L,k);
 
-                       add_fmatrix_fmatrix(dFdV[s->matrix_index].m, dFdV[s->matrix_index].m, dfdv);    
-                       
+                       dfdv_damp(s->dfdv, dir,clmd->sim_parms.Cdis);
                }
        }
        else // calculate force of bending springs
        {
                if(length < L)
                {
-                       k = clmd->sim_parms.bending;
-
-                       needed++;       
+                       s->flags |= CLOTH_SPRING_FLAG_NEEDED;
+                       
+                       k = clmd->sim_parms.bending;    
 
                        mul_fvector_S(bending_force, dir, fbstar(length, L, k, cb));
-                       VECADD(f, f, bending_force);
+                       VECADD(s->f, s->f, bending_force);
 
-                       dfdx_spring_type2(dfdx, dir,length,L,k, cb);
+                       dfdx_spring_type2(s->dfdx, dir,length,L,k, cb);
                }
        }
+}
 
-       if(needed)
+DO_INLINE void cloth_apply_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVector *lF, lfVector *X, lfVector *V, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX)
+{
+       if(s->flags & CLOTH_SPRING_FLAG_NEEDED)
        {
-               VECADD(lF[s->ij], lF[s->ij], f);
-               VECSUB(lF[s->kl], lF[s->kl], f);
+               if(s->type != CLOTH_SPRING_TYPE_BENDING)
+               {
+                       sub_fmatrix_fmatrix(dFdV[s->ij].m, dFdV[s->ij].m, s->dfdv);
+                       sub_fmatrix_fmatrix(dFdV[s->kl].m, dFdV[s->kl].m, s->dfdv);
+                       add_fmatrix_fmatrix(dFdV[s->matrix_index].m, dFdV[s->matrix_index].m, s->dfdv); 
+               }
 
-               sub_fmatrix_fmatrix(dFdX[s->ij].m, dFdX[s->ij].m, dfdx);
-               sub_fmatrix_fmatrix(dFdX[s->kl].m, dFdX[s->kl].m, dfdx);
+               VECADD(lF[s->ij], lF[s->ij], s->f);
+               VECSUB(lF[s->kl], lF[s->kl], s->f);
 
-               add_fmatrix_fmatrix(dFdX[s->matrix_index].m, dFdX[s->matrix_index].m, dfdx);
-       }
+               sub_fmatrix_fmatrix(dFdX[s->ij].m, dFdX[s->ij].m, s->dfdx);
+               sub_fmatrix_fmatrix(dFdX[s->kl].m, dFdX[s->kl].m, s->dfdx);
+
+               add_fmatrix_fmatrix(dFdX[s->matrix_index].m, dFdX[s->matrix_index].m, s->dfdx);
+       }       
 }
 
 DO_INLINE void calculateTriangleNormal(float to[3], lfVector *X, MFace mface)
@@ -1243,6 +1266,7 @@ DO_INLINE void calculateTriangleNormal(float to[3], lfVector *X, MFace mface)
        VECSUB(v2, X[mface.v3], X[mface.v1]);
        cross_fvector(to, v1, v2);
 }
+
 DO_INLINE void calculatQuadNormal(float to[3], lfVector *X, MFace mface)
 {
        float temp = CalcNormFloat4(X[mface.v1],X[mface.v2],X[mface.v3],X[mface.v4],to);
@@ -1265,7 +1289,7 @@ void calculateWeightedVertexNormal(ClothModifierData *clmd, MFace *mfaces, float
                }
        }
 }
-float calculateVertexWindForce(int index, float wind[3], float vertexnormal[3])  
+float calculateVertexWindForce(float wind[3], float vertexnormal[3])  
 {
        return fabs(INPR(wind, vertexnormal) * 0.5f);
 }
@@ -1275,7 +1299,7 @@ DO_INLINE void calc_triangle_force(ClothModifierData *clmd, MFace mface, lfVecto
 
 }
 
-void calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVector *lV, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, ListBase *effectors, float time)
+void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVector *lV, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, ListBase *effectors, float time)
 {
        /* Collect forces and derivatives:  F,dFdX,dFdV */
        Cloth           *cloth          = clmd->clothObject;
@@ -1284,12 +1308,12 @@ void calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVector *l
        float           gravity[3];
        float           tm2[3][3]       = {{-spring_air,0,0}, {0,-spring_air,0},{0,0,-spring_air}};
        ClothVertex *verts = cloth->verts;
-       ClothSpring     *springs        = cloth->springs;
        MFace           *mfaces         = cloth->mfaces;
        float wind_normalized[3];
        unsigned int numverts = cloth->numverts;
        float auxvect[3], velgoal[3], tvect[3];
        float kd, ks;
+       LinkNode *search = cloth->springs;
 
 
        VECCOPY(gravity, clmd->sim_parms.gravity);
@@ -1305,7 +1329,7 @@ void calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVector *l
        submul_lfvectorS(lF, lV, spring_air, numverts);
 
        /* do goal stuff */
-       if(clmd->sim_parms.flags & CSIMSETT_FLAG_GOAL) 
+       if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) 
        {       
                for(i = 0; i < numverts; i++)
                {                       
@@ -1332,41 +1356,55 @@ void calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVector *l
        /* handle external forces like wind */
        if(effectors)
        {
-               float wind[3] = {0,1.0f,0};
+               float speed[3] = {0.0f, 0.0f,0.0f};
                float force[3]= {0.0f, 0.0f, 0.0f};
-
+               
+               #pragma omp parallel for private (i) shared(lF)
                for(i = 0; i < cloth->numverts; i++)
                {
                        float vertexnormal[3]={0,0,0};
+                       float fieldfactor = 1000.0f, windfactor  = 250.0f; // from sb
+                       
+                       pdDoEffectors(effectors, lX[i], force, speed, (float)G.scene->r.cfra, 0.0f, PE_WIND_AS_SPEED);          
+                       
+                       // TODO apply forcefields here
+                       VECADDS(lF[i], lF[i], force, fieldfactor*0.01f);
 
-                       pdDoEffectors(effectors, lX[i], force, wind, (float)G.scene->r.cfra, 0.0f, PE_WIND_AS_SPEED);           
-
-                       VECCOPY(wind_normalized, wind);
+                       VECCOPY(wind_normalized, speed);
                        Normalize(wind_normalized);
-
+                       
                        calculateWeightedVertexNormal(clmd, mfaces, vertexnormal, i, lX);
-                       VECADDS(lF[i], lF[i], wind_normalized, -calculateVertexWindForce(i, wind, vertexnormal));
+                       VECADDS(lF[i], lF[i], wind_normalized, -calculateVertexWindForce(speed, vertexnormal));
                }
        }
+       
+       // calculate spring forces
+       search = cloth->springs;
+       while(search)
+       {
+               // only handle active springs
+               // if(((clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED)){}
+               cloth_calc_spring_force(clmd, search->link, lF, lX, lV, dFdV, dFdX);
 
-       /* calculate and apply spring forces */
-       for(i = 0; i < cloth->numsprings; i++)
+               search = search->next;
+       }
+       
+       // apply spring forces
+       search = cloth->springs;
+       while(search)
        {
                // only handle active springs
-               if(((clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED))
-               {
-                       calc_spring_force(clmd, &springs[i], lF, lX, lV, dFdV, dFdX);
-               }
+               // if(((clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED))    
+               cloth_apply_spring_force(clmd, search->link, lF, lX, lV, dFdV, dFdX);
+               search = search->next;
        }
-
 }
 
-void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVector *lF, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float dt, fmatrix3x3 *A, lfVector *B, lfVector *dV, fmatrix3x3 *S, lfVector *z, lfVector *olddV)
+void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVector *lF, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float dt, fmatrix3x3 *A, lfVector *B, lfVector *dV, fmatrix3x3 *S, lfVector *z, lfVector *olddV, fmatrix3x3 *P, fmatrix3x3 *Pinv)
 {
        unsigned int numverts = dFdV[0].vcount;
 
        lfVector *dFdXmV = create_lfvector(numverts);
-
        initdiag_bfmatrix(A, I);
        zero_lfvector(dV, numverts);
 
@@ -1375,18 +1413,25 @@ void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVecto
        mul_bfmatrix_lfvector(dFdXmV, dFdX, lV);
 
        add_lfvectorS_lfvectorS(B, lF, dt, dFdXmV, (dt*dt), numverts);
+       
+       itstart();
+       
        cg_filtered(dV, A, B, z, S); /* conjugate gradient algorithm to solve Ax=b */
-       // cg_filtered_pre(dV, A, B, z, olddV, dt);
+       // cg_filtered_pre(dV, A, B, z, olddV, P, Pinv, dt);
+       
+       itend();
+       // printf("cg_filtered calc time: %f\n", (float)itval());
+       
        cp_lfvector(olddV, dV, numverts);
 
        // advance velocities
        add_lfvector_lfvector(Vnew, lV, dV, numverts);
+       
 
        del_lfvector(dFdXmV);
 }
 
-int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors,
-                                        CM_COLLISION_SELF self_collision, CM_COLLISION_OBJ obj_collision)
+int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors)
 {              
        unsigned int i=0, j;
        float step=0.0f, tf=1.0f;
@@ -1397,7 +1442,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase
        Implicit_Data *id = cloth->implicit;
        int result = 0;
        
-       if(clmd->sim_parms.flags & CSIMSETT_FLAG_GOAL) /* do goal stuff */
+       if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) /* do goal stuff */
        {
                for(i = 0; i < numverts; i++)
                {                       
@@ -1415,73 +1460,82 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase
                effectors= pdInitEffectors(ob,NULL);
                
                // calculate 
-               calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step );    
-               simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt, id->A, id->B, id->dV, id->S, id->z, id->olddV);
+               cloth_calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step );      
+               simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt, id->A, id->B, id->dV, id->S, id->z, id->olddV, id->P, id->Pinv);
                
                add_lfvector_lfvectorS(id->Xnew, id->X, id->Vnew, dt, numverts);
                
-               // collisions 
-               itstart();
-               
-               // update verts to current positions
-               for(i = 0; i < numverts; i++)
-               {               
-                       if(clmd->sim_parms.flags & CSIMSETT_FLAG_GOAL) /* do goal stuff */
-                       {                       
-                               if(verts [i].goal >= SOFTGOALSNAP)
+               if(clmd->coll_parms.flags & CLOTH_COLLISIONSETTINGS_FLAG_ENABLED)
+               {
+                       // collisions 
+                       // itstart();
+                       
+                       // update verts to current positions
+                       for(i = 0; i < numverts; i++)
+                       {               
+                               if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) /* do goal stuff */
                                {                       
-                                       float tvect[3] = {.0,.0,.0};
-                                       // VECSUB(tvect, id->Xnew[i], verts[i].xold);
-                                       mul_fvector_S(tvect, id->V[i], step+dt);
-                                       VECADD(tvect, tvect, verts[i].xold);
-                                       VECCOPY(id->Xnew[i], tvect);
+                                       if(verts [i].goal >= SOFTGOALSNAP)
+                                       {                       
+                                               float tvect[3] = {.0,.0,.0};
+                                               // VECSUB(tvect, id->Xnew[i], verts[i].xold);
+                                               mul_fvector_S(tvect, id->V[i], step+dt);
+                                               VECADD(tvect, tvect, verts[i].xold);
+                                               VECCOPY(id->Xnew[i], tvect);
+                                       }
+                                               
                                }
+                               
+                               VECCOPY(verts[i].tx, id->Xnew[i]);
+                               
+                               VECSUB(verts[i].tv, verts[i].tx, verts[i].txold);
+                               VECCOPY(verts[i].v, verts[i].tv);
+                       }
+       
+                       // call collision function
+                       result = 0; // cloth_bvh_objcollision(clmd, step + dt, dt);
+       
+                       // copy corrected positions back to simulation
+                       for(i = 0; i < numverts; i++)
+                       {               
+                               if(result)
+                               {
+                                       // VECADD(verts[i].tx, verts[i].txold, verts[i].tv);
+                                       
+                                       VECCOPY(verts[i].txold, verts[i].tx);
+                                       
+                                       VECCOPY(id->Xnew[i], verts[i].tx);
                                        
+                                       VECCOPY(id->Vnew[i], verts[i].tv);
+                                       VecMulf(id->Vnew[i], 1.0f / dt);
+                               }
+                               else
+                               {
+                                       VECCOPY(verts[i].txold, id->Xnew[i]);
+                               }
                        }
                        
-                       VECCOPY(verts[i].tx, id->Xnew[i]);
+                       // X = Xnew;
+                       cp_lfvector(id->X, id->Xnew, numverts);
                        
-                       VECSUB(verts[i].tv, verts[i].tx, verts[i].txold);
-               }
-
-               // call collision function
-               result = cloth_bvh_objcollision(clmd, step + dt, bvh_collision_response, dt);
-
-               // copy corrected positions back to simulation
-               for(i = 0; i < numverts; i++)
-               {               
+                       // if there were collisions, advance the velocity from v_n+1/2 to v_n+1
                        if(result)
                        {
-                               VECADD(verts[i].tx, verts[i].txold, verts[i].tv);
+                               // V = Vnew;
+                               cp_lfvector(id->V, id->Vnew, numverts);
                                
-                               VECCOPY(verts[i].txold, verts[i].tx);
-                               
-                               VECCOPY(id->Xnew[i], verts[i].tx);
-                               
-                               VECCOPY(id->Vnew[i], verts[i].tv);
-                               VecMulf(id->Vnew[i], 1.0f / dt);
-                       }
-                       else
-                       {
-                               VECCOPY(verts[i].txold, id->Xnew[i]);
+                               // calculate 
+                               cloth_calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step);       
+                               simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt / 2.0f, id->A, id->B, id->dV, id->S, id->z, id->olddV, id->P, id->Pinv);
                        }
                }
-               
-               // X = Xnew;
-               cp_lfvector(id->X, id->Xnew, numverts);
-               
-               // if there were collisions, advance the velocity from v_n+1/2 to v_n+1
-               if(result)
+               else
                {
-                       // V = Vnew;
-                       cp_lfvector(id->V, id->Vnew, numverts);
-                       
-                       // calculate 
-                       calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step);     
-                       simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt / 2.0f, id->A, id->B, id->dV, id->S, id->z, id->olddV);
+                       // X = Xnew;
+                       cp_lfvector(id->X, id->Xnew, numverts);
                }
                
-               itend();
+               // itend();
                // printf("collision time: %f\n", (float)itval());
                
                // V = Vnew;
@@ -1494,7 +1548,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase
 
        for(i = 0; i < numverts; i++)
        {                               
-               if(clmd->sim_parms.flags & CSIMSETT_FLAG_GOAL)
+               if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL)
                {
                        if(verts [i].goal < SOFTGOALSNAP)
                        {
@@ -1532,3 +1586,841 @@ void implicit_set_positions (ClothModifierData *clmd)
                VECCOPY(id->V[i], verts[i].v);
        }       
 }
+
+
+int collisions_collision_response_static(ClothModifierData *clmd, ClothModifierData *coll_clmd)
+{
+       /*
+       unsigned int i = 0;
+       int result = 0;
+       LinkNode *search = NULL;
+       CollPair *collpair = NULL;
+       Cloth *cloth1, *cloth2;
+       float w1, w2, w3, u1, u2, u3;
+       float v1[3], v2[3], relativeVelocity[3];
+       float magrelVel;
+       
+       cloth1 = clmd->clothObject;
+       cloth2 = coll_clmd->clothObject;
+
+       // search = clmd->coll_parms.collision_list;
+       
+       while(search)
+       {
+       collpair = search->link;
+               
+               // compute barycentric coordinates for both collision points
+       collisions_compute_barycentric(collpair->pa,
+       cloth1->verts[collpair->ap1].txold,
+       cloth1->verts[collpair->ap2].txold,
+       cloth1->verts[collpair->ap3].txold, 
+       &w1, &w2, &w3);
+       
+       collisions_compute_barycentric(collpair->pb,
+       cloth2->verts[collpair->bp1].txold,
+       cloth2->verts[collpair->bp2].txold,
+       cloth2->verts[collpair->bp3].txold,
+       &u1, &u2, &u3);
+       
+               // Calculate relative "velocity".
+       interpolateOnTriangle(v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, cloth1->verts[collpair->ap3].tv, w1, w2, w3);
+               
+       interpolateOnTriangle(v2, cloth2->verts[collpair->bp1].tv, cloth2->verts[collpair->bp2].tv, cloth2->verts[collpair->bp3].tv, u1, u2, u3);
+               
+       VECSUB(relativeVelocity, v1, v2);
+                       
+               // Calculate the normal component of the relative velocity (actually only the magnitude - the direction is stored in 'normal').
+       magrelVel = INPR(relativeVelocity, collpair->normal);
+               
+               // printf("magrelVel: %f\n", magrelVel);
+                               
+               // Calculate masses of points.
+               
+               // If v_n_mag < 0 the edges are approaching each other.
+       if(magrelVel < -ALMOST_ZERO) 
+       {
+                       // Calculate Impulse magnitude to stop all motion in normal direction.
+                       // const double I_mag = v_n_mag / (1/m1 + 1/m2);
+       float magnitude_i = magrelVel / 2.0f; // TODO implement masses
+       float tangential[3], magtangent, magnormal, collvel[3];
+       float vrel_t_pre[3];
+       float vrel_t[3];
+       double impulse;
+       float epsilon = clmd->coll_parms.epsilon;
+       float overlap = (epsilon + ALMOST_ZERO-collpair->distance);
+                       
+                       // calculateFrictionImpulse(tangential, relativeVelocity, collpair->normal, magrelVel, clmd->coll_parms.friction*0.01, magrelVel);
+                       
+                       // magtangent = INPR(tangential, tangential);
+                       
+                       // Apply friction impulse.
+       if (magtangent < -ALMOST_ZERO) 
+       {
+                               
+                               // printf("friction applied: %f\n", magtangent);
+                               // TODO check original code 
+}
+                       
+
+       impulse = -2.0f * magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3);
+                       
+                       // printf("impulse: %f\n", impulse);
+                       
+                       // face A
+       VECADDMUL(cloth1->verts[collpair->ap1].impulse, collpair->normal, w1 * impulse); 
+       cloth1->verts[collpair->ap1].impulse_count++;
+                       
+       VECADDMUL(cloth1->verts[collpair->ap2].impulse, collpair->normal, w2 * impulse); 
+       cloth1->verts[collpair->ap2].impulse_count++;
+                       
+       VECADDMUL(cloth1->verts[collpair->ap3].impulse, collpair->normal, w3 * impulse); 
+       cloth1->verts[collpair->ap3].impulse_count++;
+                       
+                       // face B
+       VECADDMUL(cloth2->verts[collpair->bp1].impulse, collpair->normal, u1 * impulse); 
+       cloth2->verts[collpair->bp1].impulse_count++;
+                       
+       VECADDMUL(cloth2->verts[collpair->bp2].impulse, collpair->normal, u2 * impulse); 
+       cloth2->verts[collpair->bp2].impulse_count++;
+                       
+       VECADDMUL(cloth2->verts[collpair->bp3].impulse, collpair->normal, u3 * impulse); 
+       cloth2->verts[collpair->bp3].impulse_count++;
+                       
+                       
+       result = 1;     
+               
+                       // printf("magnitude_i: %f\n", magnitude_i); // negative before collision in my case
+                       
+                       // Apply the impulse and increase impulse counters.
+       
+                       
+}
+               
+       search = search->next;
+}
+       
+       
+       return result;
+       */
+       return 0;
+}
+
+
+int collisions_collision_response_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd)
+{
+       
+}
+
+
+int collisions_collision_response_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd)
+{
+       
+}
+
+void cloth_collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2)
+{
+       /*
+       CollPair *collpair = NULL;
+       Cloth *cloth1=NULL, *cloth2=NULL;
+       MFace *face1=NULL, *face2=NULL;
+       ClothVertex *verts1=NULL, *verts2=NULL;
+       double distance = 0;
+       float epsilon = clmd->coll_parms.epsilon;
+       unsigned int i = 0;
+
+       for(i = 0; i < 4; i++)
+       {
+       collpair = (CollPair *)MEM_callocN(sizeof(CollPair), "cloth coll pair");                
+               
+       cloth1 = clmd->clothObject;
+       cloth2 = coll_clmd->clothObject;
+               
+       verts1 = cloth1->verts;
+       verts2 = cloth2->verts;
+       
+       face1 = &(cloth1->mfaces[tree1->tri_index]);
+       face2 = &(cloth2->mfaces[tree2->tri_index]);
+               
+               // check all possible pairs of triangles
+       if(i == 0)
+       {
+       collpair->ap1 = face1->v1;
+       collpair->ap2 = face1->v2;
+       collpair->ap3 = face1->v3;
+                       
+       collpair->bp1 = face2->v1;
+       collpair->bp2 = face2->v2;
+       collpair->bp3 = face2->v3;
+                       
+}
+               
+       if(i == 1)
+       {
+       if(face1->v4)
+       {
+       collpair->ap1 = face1->v3;
+       collpair->ap2 = face1->v4;
+       collpair->ap3 = face1->v1;
+                               
+       collpair->bp1 = face2->v1;
+       collpair->bp2 = face2->v2;
+       collpair->bp3 = face2->v3;
+}
+       else
+       i++;
+}
+               
+       if(i == 2)
+       {
+       if(face2->v4)
+       {
+       collpair->ap1 = face1->v1;
+       collpair->ap2 = face1->v2;
+       collpair->ap3 = face1->v3;
+                               
+       collpair->bp1 = face2->v3;
+       collpair->bp2 = face2->v4;
+       collpair->bp3 = face2->v1;
+}
+       else
+       i+=2;
+}
+               
+       if(i == 3)
+       {
+       if((face1->v4)&&(face2->v4))
+       {
+       collpair->ap1 = face1->v3;
+       collpair->ap2 = face1->v4;
+       collpair->ap3 = face1->v1;
+                               
+       collpair->bp1 = face2->v3;
+       collpair->bp2 = face2->v4;
+       collpair->bp3 = face2->v1;
+}
+       else
+       i++;
+}
+               
+               // calc SIPcode (?)
+               
+       if(i < 4)
+       {
+                       // calc distance + normal       
+       distance = plNearestPoints(
+       verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, verts2[collpair->bp1].txold, verts2[collpair->bp2].txold, verts2[collpair->bp3].txold, collpair->pa,collpair->pb,collpair->vector);
+                       
+       if (distance <= (epsilon + ALMOST_ZERO))
+       {
+                               // printf("dist: %f\n", (float)distance);
+                               
+                               // collpair->face1 = tree1->tri_index;
+                               // collpair->face2 = tree2->tri_index;
+                               
+                               // VECCOPY(collpair->normal, collpair->vector);
+                               // Normalize(collpair->normal);
+                               
+                               // collpair->distance = distance;
+                               
+}
+       else
+       {
+       MEM_freeN(collpair);
+}
+}
+       else
+       {
+       MEM_freeN(collpair);
+}
+}
+       */
+}
+
+int collisions_are_edges_adjacent(ClothModifierData *clmd, ClothModifierData *coll_clmd, EdgeCollPair *edgecollpair)
+{
+       Cloth *cloth1, *cloth2;
+       ClothVertex *verts1, *verts2;
+       float temp[3];
+        
+       cloth1 = clmd->clothObject;
+       cloth2 = coll_clmd->clothObject;
+       
+       verts1 = cloth1->verts;
+       verts2 = cloth2->verts;
+       
+       VECSUB(temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p21].xold);
+       if(ABS(INPR(temp, temp)) < ALMOST_ZERO)
+               return 1;
+       
+       VECSUB(temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p22].xold);
+       if(ABS(INPR(temp, temp)) < ALMOST_ZERO)
+               return 1;
+       
+       VECSUB(temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p21].xold);
+       if(ABS(INPR(temp, temp)) < ALMOST_ZERO)
+               return 1;
+       
+       VECSUB(temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p22].xold);
+       if(ABS(INPR(temp, temp)) < ALMOST_ZERO)
+               return 1;
+               
+       return 0;
+}
+
+
+void collisions_collision_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2)
+{
+       /*
+       EdgeCollPair edgecollpair;
+       Cloth *cloth1=NULL, *cloth2=NULL;
+       MFace *face1=NULL, *face2=NULL;
+       ClothVertex *verts1=NULL, *verts2=NULL;
+       double distance = 0;
+       float epsilon = clmd->coll_parms.epsilon;
+       unsigned int i = 0, j = 0, k = 0;
+       int numsolutions = 0;
+       float a[3], b[3], c[3], d[3], e[3], f[3], solution[3];
+       
+       cloth1 = clmd->clothObject;
+       cloth2 = coll_clmd->clothObject;
+       
+       verts1 = cloth1->verts;
+       verts2 = cloth2->verts;
+
+       face1 = &(cloth1->mfaces[tree1->tri_index]);
+       face2 = &(cloth2->mfaces[tree2->tri_index]);
+       
+       for( i = 0; i < 5; i++)
+       {
+       if(i == 0) 
+       {
+       edgecollpair.p11 = face1->v1;
+       edgecollpair.p12 = face1->v2;
+}
+       else if(i == 1) 
+       {
+       edgecollpair.p11 = face1->v2;
+       edgecollpair.p12 = face1->v3;
+}
+       else if(i == 2) 
+       {
+       if(face1->v4) 
+       {
+       edgecollpair.p11 = face1->v3;
+       edgecollpair.p12 = face1->v4;
+}
+       else 
+       {
+       edgecollpair.p11 = face1->v3;
+       edgecollpair.p12 = face1->v1;
+       i+=5; // get out of here after this edge pair is handled
+}
+}
+       else if(i == 3) 
+       {
+       if(face1->v4) 
+       {
+       edgecollpair.p11 = face1->v4;
+       edgecollpair.p12 = face1->v1;
+}      
+       else
+       continue;
+}
+       else
+       {
+       edgecollpair.p11 = face1->v3;
+       edgecollpair.p12 = face1->v1;
+}
+
+               
+       for( j = 0; j < 5; j++)
+       {
+       if(j == 0)
+       {
+       edgecollpair.p21 = face2->v1;
+       edgecollpair.p22 = face2->v2;
+}
+       else if(j == 1)
+       {
+       edgecollpair.p21 = face2->v2;
+       edgecollpair.p22 = face2->v3;
+}
+       else if(j == 2)
+       {
+       if(face2->v4) 
+       {
+       edgecollpair.p21 = face2->v3;
+       edgecollpair.p22 = face2->v4;
+}
+       else 
+       {
+       edgecollpair.p21 = face2->v3;
+       edgecollpair.p22 = face2->v1;
+}
+}
+       else if(j == 3)
+       {
+       if(face2->v4) 
+       {
+       edgecollpair.p21 = face2->v4;
+       edgecollpair.p22 = face2->v1;
+}
+       else
+       continue;
+}
+       else
+       {
+       edgecollpair.p21 = face2->v3;
+       edgecollpair.p22 = face2->v1;
+}
+                       
+                       
+       if(!collisions_are_edges_adjacent(clmd, coll_clmd, &edgecollpair))
+       {
+       VECSUB(a, verts1[edgecollpair.p12].xold, verts1[edgecollpair.p11].xold);
+       VECSUB(b, verts1[edgecollpair.p12].v, verts1[edgecollpair.p11].v);
+       VECSUB(c, verts1[edgecollpair.p21].xold, verts1[edgecollpair.p11].xold);
+       VECSUB(d, verts1[edgecollpair.p21].v, verts1[edgecollpair.p11].v);
+       VECSUB(e, verts2[edgecollpair.p22].xold, verts1[edgecollpair.p11].xold);
+       VECSUB(f, verts2[edgecollpair.p22].v, verts1[edgecollpair.p11].v);
+                               
+       numsolutions = collisions_get_collision_time(a, b, c, d, e, f, solution);
+                               
+       for (k = 0; k < numsolutions; k++) 
+       {                                                               
+       if ((solution[k] >= 0.0) && (solution[k] <= 1.0)) 
+       {
+       float out_collisionTime = solution[k];
+                                               
+                                               // TODO: check for collisions 
+                                               
+                                               // TODO: put into (edge) collision list
+                                               
+       printf("Moving edge found!\n");
+}
+}
+}
+}
+}      
+       */      
+}
+
+void collisions_collision_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2)
+{
+       /*
+       CollPair collpair;
+       Cloth *cloth1=NULL, *cloth2=NULL;
+       MFace *face1=NULL, *face2=NULL;
+       ClothVertex *verts1=NULL, *verts2=NULL;
+       double distance = 0;
+       float epsilon = clmd->coll_parms.epsilon;
+       unsigned int i = 0, j = 0, k = 0;
+       int numsolutions = 0;
+       float a[3], b[3], c[3], d[3], e[3], f[3], solution[3];
+
+       for(i = 0; i < 2; i++)
+       {               
+       cloth1 = clmd->clothObject;
+       cloth2 = coll_clmd->clothObject;
+               
+       verts1 = cloth1->verts;
+       verts2 = cloth2->verts;
+       
+       face1 = &(cloth1->mfaces[tree1->tri_index]);
+       face2 = &(cloth2->mfaces[tree2->tri_index]);
+               
+               // check all possible pairs of triangles
+       if(i == 0)
+       {
+       collpair.ap1 = face1->v1;
+       collpair.ap2 = face1->v2;
+       collpair.ap3 = face1->v3;
+                       
+       collpair.pointsb[0] = face2->v1;
+       collpair.pointsb[1] = face2->v2;
+       collpair.pointsb[2] = face2->v3;
+       collpair.pointsb[3] = face2->v4;
+}
+               
+       if(i == 1)
+       {
+       if(face1->v4)
+       {
+       collpair.ap1 = face1->v3;
+       collpair.ap2 = face1->v4;
+       collpair.ap3 = face1->v1;
+                               
+       collpair.pointsb[0] = face2->v1;
+       collpair.pointsb[1] = face2->v2;
+       collpair.pointsb[2] = face2->v3;
+       collpair.pointsb[3] = face2->v4;
+}
+       else
+       i++;
+}
+               
+               // calc SIPcode (?)
+               
+       if(i < 2)
+       {
+       VECSUB(a, verts1[collpair.ap2].xold, verts1[collpair.ap1].xold);
+       VECSUB(b, verts1[collpair.ap2].v, verts1[collpair.ap1].v);
+       VECSUB(c, verts1[collpair.ap3].xold, verts1[collpair.ap1].xold);
+       VECSUB(d, verts1[collpair.ap3].v, verts1[collpair.ap1].v);
+                               
+       for(j = 0; j < 4; j++)
+       {                                       
+       if((j==3) && !(face2->v4))
+       break;
+                               
+       VECSUB(e, verts2[collpair.pointsb[j]].xold, verts1[collpair.ap1].xold);
+       VECSUB(f, verts2[collpair.pointsb[j]].v, verts1[collpair.ap1].v);
+                               
+       numsolutions = collisions_get_collision_time(a, b, c, d, e, f, solution);
+                               
+       for (k = 0; k < numsolutions; k++) 
+       {                                                               
+       if ((solution[k] >= 0.0) && (solution[k] <= 1.0)) 
+       {
+       float out_collisionTime = solution[k];
+                                               
+                                               // TODO: check for collisions 
+                                               
+                                               // TODO: put into (point-face) collision list
+                                               
+       printf("Moving found!\n");
+                                               
+}
+}
+                               
+                               // TODO: check borders for collisions
+}
+                       
+}
+}
+       */
+}
+
+
+// move collision objects forward in time and update static bounding boxes
+void collisions_update_collision_objects(float step)
+{
+       Base *base=NULL;
+       ClothModifierData *coll_clmd=NULL;
+       Object *coll_ob=NULL;
+       unsigned int i=0;
+       
+       // search all objects for collision object
+       for (base = G.scene->base.first; base; base = base->next)
+       {
+
+               coll_ob = base->object;
+               coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth);
+               if (!coll_clmd)
+                       continue;
+
+               // if collision object go on
+               if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ)
+               {
+                       if (coll_clmd->clothObject && coll_clmd->clothObject->tree) 
+                       {
+                               Cloth *coll_cloth = coll_clmd->clothObject;
+                               BVH *coll_bvh = coll_clmd->clothObject->tree;
+                               unsigned int coll_numverts = coll_cloth->numverts;
+
+                               // update position of collision object
+                               for(i = 0; i < coll_numverts; i++)
+                               {
+                                       VECCOPY(coll_cloth->verts[i].txold, coll_cloth->verts[i].tx);
+
+                                       VECADDS(coll_cloth->verts[i].tx, coll_cloth->verts[i].xold, coll_cloth->verts[i].v, step);
+                                       
+                                       // no dt here because of float rounding errors
+                                       VECSUB(coll_cloth->verts[i].tv, coll_cloth->verts[i].tx, coll_cloth->verts[i].txold);
+                               }
+                               
+                               // update BVH of collision object
+                               // bvh_update(coll_clmd, coll_bvh, 0); // 0 means STATIC, 1 means MOVING 
+                       }
+                       else
+                               printf ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n");
+               }
+       }
+}
+
+
+void collisions_collision_moving(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2)
+{
+       /*
+       // TODO: check for adjacent
+       collisions_collision_moving_edges(clmd, coll_clmd, tree1, tree2);
+       
+       collisions_collision_moving_tris(clmd, coll_clmd, tree1, tree2);
+       collisions_collision_moving_tris(coll_clmd, clmd, tree2, tree1);
+       */
+}
+
+// cloth - object collisions
+int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt)
+{
+       /*
+       Base *base=NULL;
+       ClothModifierData *coll_clmd=NULL;
+       Cloth *cloth=NULL;
+       Object *coll_ob=NULL;
+       BVH *collisions_bvh=NULL;
+       unsigned int i=0, j = 0, numfaces = 0, numverts = 0;
+       unsigned int result = 0, ic = 0, rounds = 0; // result counts applied collisions; ic is for debug output; 
+       ClothVertex *verts = NULL;
+       float tnull[3] = {0,0,0};
+       int ret = 0;
+       LinkNode *collision_list = NULL; 
+
+       if ((clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) || !(((Cloth *)clmd->clothObject)->tree))
+       {
+               return 0;
+       }
+       cloth = clmd->clothObject;
+       verts = cloth->verts;
+       collisions_bvh = (BVH *) cloth->tree;
+       numfaces = clmd->clothObject->numfaces;
+       numverts = clmd->clothObject->numverts;
+       
+       ////////////////////////////////////////////////////////////
+       // static collisions
+       ////////////////////////////////////////////////////////////
+
+       // update cloth bvh
+       // bvh_update(clmd, collisions_bvh, 0); // 0 means STATIC, 1 means MOVING (see later in this function)
+       
+       // update collision objects
+       collisions_update_collision_objects(step);
+       
+       do
+       {
+               result = 0;
+               ic = 0;
+               
+               // check all collision objects
+               for (base = G.scene->base.first; base; base = base->next)
+               {
+                       coll_ob = base->object;
+                       coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth);
+                       
+                       if (!coll_clmd)
+                               continue;
+                       
+                       // if collision object go on
+                       if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ)
+                       {
+                               if (coll_clmd->clothObject && coll_clmd->clothObject->tree) 
+                               {
+                                       BVH *coll_bvh = coll_clmd->clothObject->tree;
+                                       
+                                       // fill collision list 
+                                       bvh_traverse(collisions_bvh->root, coll_bvh->root, collision_list);
+                                       
+                                       // process all collisions (calculate impulses, TODO: also repulses if distance too short)
+                                       result = 1;
+                                       for(j = 0; j < 10; j++) // 10 is just a value that ensures convergence
+                                       {
+                                               result = 0;
+                                               
+                                               // result += collisions_collision_response_static_tris(clmd, coll_clmd, collision_list, 0);
+                       
+                                               // result += collisions_collision_response_static_tris(coll_clmd, clmd, collision_list, 1);
+                                       
+                                               // apply impulses in parallel
+                                               ic=0;
+                                               for(i = 0; i < numverts; i++)
+                                               {
+                                                       // calculate "velocities" (just xnew = xold + v; no dt in v)
+                                                       if(verts[i].impulse_count)
+                                                       {
+                                                               VECADDMUL(verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count);
+                                                               VECCOPY(verts[i].impulse, tnull);
+                                                               verts[i].impulse_count = 0;
+                               
+                                                               ic++;
+                                                               ret++;
+                                                       }
+                                               }
+                                       }
+                                       
+                                       // free collision list
+                                       if(collision_list)
+                                       {
+                                               LinkNode *search = collision_list;
+                                               while(search)
+                                               {
+                                                       CollisionPair *coll_pair = search->link;
+                                                       
+                                                       MEM_freeN(coll_pair);
+                                                       search = search->next;
+                                               }
+                                               BLI_linklist_free(collision_list,NULL);
+                       
+                                               collision_list = NULL;
+                                       }
+                               }
+                               else
+                                       printf ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n");
+                       }
+               }
+               
+               printf("ic: %d\n", ic);
+               rounds++;
+       }
+       while(result && (10>rounds));// CLOTH_MAX_THRESHOLD
+       
+       printf("\n");
+                       
+       ////////////////////////////////////////////////////////////
+       // update positions
+       // this is needed for bvh_calc_DOP_hull_moving() [kdop.c]
+       ////////////////////////////////////////////////////////////
+       
+       // verts come from clmd
+       for(i = 0; i < numverts; i++)
+       {
+               VECADD(verts[i].tx, verts[i].txold, verts[i].tv);
+       }
+       ////////////////////////////////////////////////////////////
+
+       ////////////////////////////////////////////////////////////
+       // moving collisions
+       ////////////////////////////////////////////////////////////
+
+       
+       // update cloth bvh
+       // bvh_update(clmd, collisions_bvh, 1);  // 0 means STATIC, 1 means MOVING 
+       
+       // update moving bvh for collision object once
+       for (base = G.scene->base.first; base; base = base->next)
+       {
+               
+               coll_ob = base->object;
+               coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth);
+               if (!coll_clmd)
+                       continue;
+               
+               if(!coll_clmd->clothObject)
+                       continue;
+               
+                               // if collision object go on
+               if (coll_clmd->clothObject && coll_clmd->clothObject->tree) 
+               {
+                       BVH *coll_bvh = coll_clmd->clothObject->tree;
+                       
+                       // bvh_update(coll_clmd, coll_bvh, 1);  // 0 means STATIC, 1 means MOVING       
+               }
+       }
+       
+       
+       do
+       {
+               result = 0;
+               ic = 0;
+               
+               // check all collision objects
+               for (base = G.scene->base.first; base; base = base->next)
+               {
+                       coll_ob = base->object;
+                       coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth);
+                       
+                       if (!coll_clmd)
+                               continue;
+                       
+                       // if collision object go on
+                       if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ)
+                       {
+                               if (coll_clmd->clothObject && coll_clmd->clothObject->tree) 
+                               {
+                                       BVH *coll_bvh = coll_clmd->clothObject->tree;
+                                       
+                                       bvh_traverse(collisions_bvh->root, coll_bvh->root, collision_list);
+                                       
+                                       // process all collisions (calculate impulses, TODO: also repulses if distance too short)
+                                       result = 1;
+                                       for(j = 0; j < 10; j++) // 10 is just a value that ensures convergence
+                                       {
+                                               result = 0;
+                               
+                                               // handle all collision objects
+                                               
+                                               
+                                               if (coll_clmd->clothObject) 
+                                               result += collisions_collision_response_moving_tris(clmd, coll_clmd);
+                                               else
+                                               printf ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n");
+                                               
+                                               
+                                               // apply impulses in parallel
+                                               ic=0;
+                                               for(i = 0; i < numverts; i++)
+                                               {
+                                               // calculate "velocities" (just xnew = xold + v; no dt in v)
+                                                       if(verts[i].impulse_count)
+                                                       {
+                                                               VECADDMUL(verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count);
+                                                               VECCOPY(verts[i].impulse, tnull);
+                                                               verts[i].impulse_count = 0;
+                                                       
+                                                               ic++;
+                                                               ret++;
+                                                       }
+                                               }
+                                       }
+               
+               
+                                       // verts come from clmd
+                                       for(i = 0; i < numverts; i++)
+                                       {
+                                               VECADD(verts[i].tx, verts[i].txold, verts[i].tv);
+                                       }
+               
+                                       // update cloth bvh
+                                       // bvh_update(clmd, collisions_bvh, 1);  // 0 means STATIC, 1 means MOVING 
+               
+               
+                                       // free collision list
+                                       if(collision_list)
+                                       {
+                                               LinkNode *search = collision_list;
+                                               while(search)
+                                               {
+                                                       CollisionPair *coll_pair = search->link;
+                                                       
+                                                       MEM_freeN(coll_pair);
+                                                       search = search->next;
+                                               }
+                                               BLI_linklist_free(collision_list,NULL);
+                       
+                                               collision_list = NULL;
+                                       }
+                               }
+                               else
+                                       printf ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n");
+                       }
+               }
+                               
+               printf("ic: %d\n", ic);
+               rounds++;
+       }
+       while(result && (10>rounds)); // CLOTH_MAX_THRESHOLD
+       
+       
+       ////////////////////////////////////////////////////////////
+       // update positions + velocities
+       ////////////////////////////////////////////////////////////
+       
+       // verts come from clmd
+       for(i = 0; i < numverts; i++)
+       {
+               VECADD(verts[i].tx, verts[i].txold, verts[i].tv);
+       }
+       ////////////////////////////////////////////////////////////
+
+       return MIN2(ret, 1);
+       */
+}
\ No newline at end of file