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 3994bbf2b4057cc049e9636d7748b8ad24dca014..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"
@@ -700,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");
@@ -749,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++)
@@ -1170,7 +1176,7 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s,
        VECSUB(vel, V[s->kl], V[s->ij]);
        length = sqrt(INPR(extent, extent));
        
-       s->flags &= ~CSPRING_FLAG_NEEDED;
+       s->flags &= ~CLOTH_SPRING_FLAG_NEEDED;
        
        if(length > ABS(ALMOST_ZERO))
        {
@@ -1193,12 +1199,12 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s,
        }
        
        
-       // 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
                {
-                       s->flags |= CSPRING_FLAG_NEEDED;
+                       s->flags |= CLOTH_SPRING_FLAG_NEEDED;
 
                        k = clmd->sim_parms.structural; 
 
@@ -1219,7 +1225,7 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s,
        {
                if(length < L)
                {
-                       s->flags |= CSPRING_FLAG_NEEDED;
+                       s->flags |= CLOTH_SPRING_FLAG_NEEDED;
                        
                        k = clmd->sim_parms.bending;    
 
@@ -1231,6 +1237,27 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s,
        }
 }
 
+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)
+       {
+               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); 
+               }
+
+               VECADD(lF[s->ij], lF[s->ij], s->f);
+               VECSUB(lF[s->kl], lF[s->kl], s->f);
+
+               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)
 {
        float v1[3], v2[3];
@@ -1239,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);
@@ -1280,12 +1308,12 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec
        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);
@@ -1301,7 +1329,7 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec
        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++)
                {                       
@@ -1350,53 +1378,25 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec
                }
        }
        
-       /* calculate and apply spring forces */
-#pragma omp parallel private(i)
-{
-#pragma omp for nowait
-       for(i = 0; i < cloth->numsprings/2; i++)
-       {
-               // 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, &springs[i], lF, lX, lV, dFdV, dFdX);
-               // }
-       }
-#pragma omp for nowait
-       for(i = cloth->numsprings/2; i < cloth->numsprings; i++)
+       // 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, &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_calc_spring_force(clmd, search->link, lF, lX, lV, dFdV, dFdX);
+
+               search = search->next;
        }
-} // pragma omp parallel
        
-       for(i = 0; i < cloth->numsprings; i++)
+       // 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))
-               {
-                       ClothSpring *s = &springs[i];
-                       if(s->flags & CSPRING_FLAG_NEEDED)
-                       {
-                               if(s->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); 
-                               }
-               
-                               VECADD(lF[s->ij], lF[s->ij], s->f);
-                               VECSUB(lF[s->kl], lF[s->kl], s->f);
-               
-                               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);
-                       }       
-               }
+               // 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;
        }
 }
 
@@ -1431,8 +1431,7 @@ void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVecto
        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;
@@ -1443,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++)
                {                       
@@ -1466,66 +1465,74 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase
                
                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);
-                       VECCOPY(verts[i].v, verts[i].tv);
-               }
-
-               // 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);
-                               
-                               VECCOPY(verts[i].txold, verts[i].tx);
-                               
-                               VECCOPY(id->Xnew[i], verts[i].tx);
+                               // V = Vnew;
+                               cp_lfvector(id->V, id->Vnew, numverts);
                                
-                               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 
-                       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);
                }
                
                // itend();
@@ -1541,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)
                        {
@@ -1579,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