Fixed some collision response issues. (weekend commit, some half done work in)
authorDaniel Genrich <daniel.genrich@gmx.net>
Fri, 21 Sep 2007 13:34:19 +0000 (13:34 +0000)
committerDaniel Genrich <daniel.genrich@gmx.net>
Fri, 21 Sep 2007 13:34:19 +0000 (13:34 +0000)
extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-Api.cpp
source/blender/blenkernel/BKE_cloth.h
source/blender/blenkernel/intern/cloth.c
source/blender/blenkernel/intern/collision.c
source/blender/blenkernel/intern/implicit.c
source/blender/blenkernel/intern/modifier.c
source/blender/makesdna/DNA_cloth_types.h
source/blender/src/buttons_object.c

index 2ae30e851dc00fe2283908006695496327c709b2..1b843774609901f9f9e6c1876ca957752ddaf1b3 100644 (file)
@@ -41,11 +41,10 @@ double plNearestPoints(float p[3][3], float q[3][3], float *pa, float *pb, float
        
        static btGjkEpaPenetrationDepthSolver Solver0;
        static btMinkowskiPenetrationDepthSolver Solver1;
-       
+               
        btConvexPenetrationDepthSolver* Solver = NULL;
        
-       Solver = &Solver1;
-       
+       Solver = &Solver0;      
                
        btGjkPairDetector convexConvex(&trishapeA ,&trishapeB,&sGjkSimplexSolver,Solver);
        
index b9861049fb494d1e00b712f1b7b58d5d45792190..e4d1fb0ca99de435a9d75319120b7f3dc984cd5b 100644 (file)
@@ -60,7 +60,7 @@ struct DerivedMesh;
 
 /* This is approximately the smallest number that can be
 * represented by a float, given its precision. */
-#define ALMOST_ZERO            0.0000001
+#define ALMOST_ZERO            0.00001
 
 /* Bits to or into the ClothVertex.flags. */
 #define CVERT_FLAG_PINNED      1
@@ -91,6 +91,7 @@ typedef enum
        CSIMSETT_FLAG_CCACHE_FREE_ALL = (1 << 4),  // delete all from cache
        CSIMSETT_FLAG_CCACHE_FREE_PART = (1 << 5), // delete some part of cache
        CSIMSETT_FLAG_TEARING_ENABLED = (1 << 6), // true if tearing is enabled
+       CSIMSETT_FLAG_CCACHE_PROTECT = (1 << 7), // true if tearing is enabled
 } CSIMSETT_FLAGS;
 
 /* Spring types as defined in the paper.*/
index 635da0515cba236366664c074a2a3dbe75aa6bc4..7059c59c65bf7eb664e6584f5aaa3c10d2d2055b 100644 (file)
@@ -153,7 +153,7 @@ void cloth_init (ClothModifierData *clmd)
        clmd->sim_parms.mass = 1.0f;
        clmd->sim_parms.stepsPerFrame = 5;
        clmd->sim_parms.sim_time = 1.0;
-       clmd->sim_parms.flags = CSIMSETT_FLAG_RESET;
+       clmd->sim_parms.flags = CSIMSETT_FLAG_RESET | CSIMSETT_FLAG_CCACHE_PROTECT;
        clmd->sim_parms.solver_type = 0; 
        clmd->sim_parms.preroll = 0;
        clmd->sim_parms.maxspringlen = 10;
@@ -576,6 +576,7 @@ void cloth_cache_set_frame(ClothModifierData *clmd, float time)
        }
 }
 
+// free cloth cache
 void cloth_cache_free(ClothModifierData *clmd, float time)
 {
        Frame *frame = NULL;
@@ -659,7 +660,8 @@ void clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm,
        float deltaTime = current_time - clmd->sim_parms.sim_time;      
                
        
-       // only be active during a specific period
+       // only be active during a specific period:
+       // that's "first frame" and "last frame" on GUI
        if (!(clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ))
        {
                if(current_time < clmd->sim_parms.firstframe)
@@ -681,7 +683,7 @@ void clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm,
                }
        }
        
-       // unused in the moment
+       // unused in the moment, calculated seperately in implicit.c
        clmd->sim_parms.dt = 1.0f / clmd->sim_parms.stepsPerFrame;
        
        clmd->sim_parms.sim_time = current_time;
@@ -812,46 +814,49 @@ void cloth_free_modifier (ClothModifierData *clmd)
                return;
 
        cloth = clmd->clothObject;
-
-       // free our frame cache
-       clmd->sim_parms.flags |= CSIMSETT_FLAG_CCACHE_FREE_ALL;
-       cloth_cache_free(clmd, 0);
-
-       if (cloth) 
-       {       
-               // If our solver provides a free function, call it
-               if (cloth->old_solver_type < 255 && solvers [cloth->old_solver_type].free) 
+       
+       if(!(clmd->sim_parms.flags & CSIMSETT_FLAG_CCACHE_PROTECT))
+       {
+               // free our frame cache
+               clmd->sim_parms.flags |= CSIMSETT_FLAG_CCACHE_FREE_ALL;
+               cloth_cache_free(clmd, 0);
+       
+               if (cloth) 
                {       
-                       solvers [cloth->old_solver_type].free (clmd);
-               }
-               
-               // Free the verts.
-               if (cloth->verts != NULL)
-                       MEM_freeN (cloth->verts);
-
-               cloth->verts = NULL;
-               cloth->numverts = -1;
-               
-               // Free the springs.
-               if (cloth->springs != NULL)
-                       MEM_freeN (cloth->springs);
-
-               cloth->springs = NULL;
-               cloth->numsprings = -1;         
-               
-               // free BVH collision tree
-               if(cloth->tree)
-                       bvh_free((BVH *)cloth->tree);
-               
-               // we save our faces for collision objects
-               if(cloth->mfaces)
-                       MEM_freeN(cloth->mfaces);
+                       // If our solver provides a free function, call it
+                       if (cloth->old_solver_type < 255 && solvers [cloth->old_solver_type].free) 
+                       {       
+                               solvers [cloth->old_solver_type].free (clmd);
+                       }
+                       
+                       // Free the verts.
+                       if (cloth->verts != NULL)
+                               MEM_freeN (cloth->verts);
        
-               if(clmd->clothObject->facemarks)
-                       MEM_freeN(clmd->clothObject->facemarks);
+                       cloth->verts = NULL;
+                       cloth->numverts = -1;
+                       
+                       // Free the springs.
+                       if (cloth->springs != NULL)
+                               MEM_freeN (cloth->springs);
+       
+                       cloth->springs = NULL;
+                       cloth->numsprings = -1;         
+                       
+                       // free BVH collision tree
+                       if(cloth->tree)
+                               bvh_free((BVH *)cloth->tree);
+                       
+                       // we save our faces for collision objects
+                       if(cloth->mfaces)
+                               MEM_freeN(cloth->mfaces);
                
-               MEM_freeN (cloth);
-               clmd->clothObject = NULL;
+                       if(clmd->clothObject->facemarks)
+                               MEM_freeN(clmd->clothObject->facemarks);
+                       
+                       MEM_freeN (cloth);
+                       clmd->clothObject = NULL;
+               }
        }
 }
 
@@ -952,6 +957,7 @@ static int collobj_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh
        unsigned int i;
        MVert *mvert = NULL; 
        ClothVertex *verts = NULL;
+       float tnull[3] = {0,0,0}; 
        
        /* If we have a clothObject, free it. */
        if (clmd->clothObject != NULL)
@@ -993,7 +999,9 @@ static int collobj_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh
                                VECCOPY(verts->xold, verts->x);
                                VECCOPY(verts->txold, verts->x);
                                VECCOPY(verts->tx, verts->x);
-                               VecMulf(verts->v, 0.0f);                                
+                               VecMulf(verts->v, 0.0f);
+                               verts->impulse_count = 0;
+                               VECCOPY(verts->impulse, tnull);
                        }
                        clmd->clothObject->tree =  bvh_build(clmd,clmd->coll_parms.epsilon);
                        
@@ -1159,6 +1167,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d
        // dm->getNumVerts(dm);
        MVert *mvert = NULL; // CDDM_get_verts(dm);
        ClothVertex *verts = NULL;
+       float tnull[3] = {0,0,0};
        
        /* If we have a clothObject, free it. */
        if (clmd->clothObject != NULL)
@@ -1220,6 +1229,9 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d
                                VECCOPY(verts->xconst, verts->x);
                                VECCOPY(verts->txold, verts->x);
                                VecMulf(verts->v, 0.0f);
+                               
+                               verts->impulse_count = 0;
+                               VECCOPY(verts->impulse, tnull);
                        }
 
                        /* apply / set vertex groups */
@@ -1363,17 +1375,20 @@ int cloth_build_springs(Cloth *cloth, DerivedMesh *dm)
 
                shear_springs++;
                temp_index++;
-
-               springs[temp_index].ij = mface[i].v2;
-               springs[temp_index].kl = mface[i].v4;
-               VECSUB(temp, mvert[springs[temp_index].kl].co, mvert[springs[temp_index].ij].co);
-               springs[temp_index].restlen =  sqrt(INPR(temp, temp));
-               springs[temp_index].type = SHEAR;
-
-               BLI_linklist_append(&edgelist[springs[temp_index].ij], &(springs[temp_index]));         
-               BLI_linklist_append(&edgelist[springs[temp_index].kl], &(springs[temp_index]));
-
-               shear_springs++;
+               
+               if(mface[i].v4)
+               {
+                       springs[temp_index].ij = mface[i].v2;
+                       springs[temp_index].kl = mface[i].v4;
+                       VECSUB(temp, mvert[springs[temp_index].kl].co, mvert[springs[temp_index].ij].co);
+                       springs[temp_index].restlen =  sqrt(INPR(temp, temp));
+                       springs[temp_index].type = SHEAR;
+       
+                       BLI_linklist_append(&edgelist[springs[temp_index].ij], &(springs[temp_index]));         
+                       BLI_linklist_append(&edgelist[springs[temp_index].kl], &(springs[temp_index]));
+       
+                       shear_springs++;
+               }
        }
 
        // bending springs
index 32a2f820894169ea32d22759f79dc899e9e3f95f..8c6a17c4e425ca951f4f8c13f84cbeb2e564a6d0 100644 (file)
@@ -186,15 +186,15 @@ void generateTriangleMarks()
        */
 }
 
-
+// w3 is not perfect
 void bvh_compute_barycentric (float pv[3], float p1[3], float p2[3], float p3[3], double *w1, double *w2, double *w3)
 {
-       float   tempV1[3], tempV2[3], tempV4[3];
-       double  a,b,c,e,f;
+       double  tempV1[3], tempV2[3], tempV4[3];
+       double  a,b,c,d,e,f;
 
-       VECSUB (tempV1, p1, p3);        /* x1 - x3 */
-       VECSUB (tempV2, p2, p3);        /* x2 - x3 */
-       VECSUB (tempV4, pv, p3);        /* pv - x3 */
+       VECSUB (tempV1, p1, p3);        
+       VECSUB (tempV2, p2, p3);        
+       VECSUB (tempV4, pv, p3);        
        
        a = INPR (tempV1, tempV1);      
        b = INPR (tempV1, tempV2);      
@@ -202,10 +202,24 @@ void bvh_compute_barycentric (float pv[3], float p1[3], float p2[3], float p3[3]
        e = INPR (tempV1, tempV4);      
        f = INPR (tempV2, tempV4);      
        
+       d = (a * c - b * b);
+       
+       if (ABS(d) < ALMOST_ZERO) {
+               *w1 = *w2 = *w3 = 1.0f / 3.0f;
+               return;
+       }
+       
+       w1[0] = (e * c - b * f) / d;
+       
+       if(w1[0] < 0)
+               w1[0] = 0.0;
        
-       w1[0] = (e * c - b * f) / (a * c - b * b);
        w2[0] = (f - b * w1[0]) / c;
-       w3[0] = 1.0 - w1[0] - w2[0];
+       
+       if(w2[0] < 0)
+               w2[0] = 0.0;
+       
+       w3[0] = 1.0f - w1[0] - w2[0];
 }
 
 DO_INLINE void interpolateOnTriangle(float to[3], float v1[3], float v2[3], float v3[3], double w1, double w2, double w3) 
@@ -230,36 +244,22 @@ DO_INLINE void calculateFrictionImpulse(float to[3], float vrel[3], float normal
                
 int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, LinkNode **collision_list)
 {
-       unsigned int i = 0, numverts=0;
+       unsigned int i = 0, numfaces = 0;
        int result = 0;
        LinkNode *search = NULL;
        CollPair *collpair = NULL;
        Cloth *cloth1, *cloth2;
        MFace *face1, *face2;
-       double w1, w2, w3, u1, u2, u3;
+       double w1, w2, w3, u1, u2, u3, a1, a2, a3;
        float v1[3], v2[3], relativeVelocity[3];
        float magrelVel;
        
        cloth1 = clmd->clothObject;
        cloth2 = coll_clmd->clothObject;
        
-       numverts = clmd->clothObject->numverts;
-       
-       /*
-       for(i = 0; i < LIST_LENGTH; i++)
-       {
-               // calc SIP-code
-               //  TODO for later: calculateSipCode()
-       
-               // calc distance (?)
+       numfaces = clmd->clothObject->numfaces;
                
-               // calc impulse
-               
-               // apply impulse
-       }
-       */
-       
-       for(i = 0; i < numverts; i++)
+       for(i = 0; i < numfaces; i++)
        {
                search = collision_list[i];
                
@@ -273,11 +273,13 @@ int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, Link
                        // compute barycentric coordinates for both collision points
                        
                        if(!collpair->quadA)
+                       {       
                                bvh_compute_barycentric(collpair->p1,
                                                        cloth1->verts[face1->v1].txold,
                                                        cloth1->verts[face1->v2].txold,
                                                        cloth1->verts[face1->v3].txold, 
                                                                &w1, &w2, &w3);
+                       }
                        else
                                bvh_compute_barycentric(collpair->p1,
                                                        cloth1->verts[face1->v4].txold,
@@ -317,25 +319,26 @@ int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, Link
                                        
                        // Calculate masses of points.
                        
-                       // printf("relativeVelocity -> x: %f, y: %f, z: %f\n", relativeVelocity[0], relativeVelocity[1],relativeVelocity[2]); 
-                       
                        // If v_n_mag > 0 the edges are approaching each other.
-                       if(magrelVel > ALMOST_ZERO)
+                       
+                       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], impulse;
+                               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) 
+                               if (magtangent < ALMOST_ZERO) 
                                {
                                        
                                        // printf("friction applied: %f\n", magtangent);
@@ -347,57 +350,64 @@ int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, Link
                                        VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v4].tv,tangential);
                                        */
                                }
-                       
-                               // printf("magnitude_i: %f\n", magnitude_i); // negative before collision in my case
                                
-                               // Apply the impulse and increase impulse counters.
-                               // my try, works better than the papers ones (maybe i did just something wrong)
-                               VECSUB(collvel, cloth1->verts[face1->v1].tv, v2);
-                               magnormal = INPR(collvel, collpair->normal);
-                               if(magnormal<ALMOST_ZERO)
-                                       magnormal = 0.0f;
+                               impulse = -magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3);
+                               VECADDMUL(cloth1->verts[face1->v1].impulse, collpair->normal, impulse); 
+                               cloth1->verts[face1->v1].impulse_count++;
                                
-                               impulse = (epsilon + ALMOST_ZERO-collpair->distance) / 4.0f;
-                               VECADDMUL(cloth1->verts[face1->v1].tv, collpair->normal, -magnormal + impulse); 
+                               VECADDMUL(cloth1->verts[face1->v2].impulse, collpair->normal, impulse); 
+                               cloth1->verts[face1->v2].impulse_count++;
                                
-                               // calculateFrictionImpulse(tangential, collvel, collpair->normal, magtangent, clmd->coll_parms.friction*0.01, magtangent);
+                               VECADDMUL(cloth1->verts[face1->v3].impulse, collpair->normal, impulse); 
+                               cloth1->verts[face1->v3].impulse_count++;
                                
-/*
-                               VECSUBS(vrel_t_pre, collvel, collpair->normal, magnormal);
-                               // VecMulf(vrel_t_pre, clmd->coll_parms.friction*0.01f/INPR(vrel_t_pre,vrel_t_pre));
-                               magtangent = Normalize(vrel_t_pre);
-                               VecMulf(vrel_t_pre, MIN2(clmd->coll_parms.friction*0.01f*magnormal,magtangent));
+                               if(face1->v4)
+                               {
+                                       VECADDMUL(cloth1->verts[face1->v4].impulse, collpair->normal, impulse); 
+                                       cloth1->verts[face1->v4].impulse_count++;
+                               }
                                
-                               VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v1].tv,vrel_t_pre);
-*/                             
                                
-                               VECSUB(collvel, cloth1->verts[face1->v2].tv, v2);
-                               magnormal = INPR(collvel, collpair->normal);
-                               if(magnormal<ALMOST_ZERO)
-                                       magnormal = 0.0f;
+                               if (overlap > ALMOST_ZERO) {
+                                       double I_mag  = overlap * 0.1;
+                                       
+                                       impulse = I_mag / ( 1.0 + w1*w1 + w2*w2 + w3*w3);
+                                       
+                                       VECADDMUL(cloth1->verts[face1->v1].impulse, collpair->normal, impulse); 
+                                       cloth1->verts[face1->v1].impulse_count++;
+                                                               
+                                       VECADDMUL(cloth1->verts[face1->v2].impulse, collpair->normal, impulse); 
+                                       cloth1->verts[face1->v2].impulse_count++;
                                
-                               impulse = (epsilon + ALMOST_ZERO-collpair->distance) / 4.0f;
-                               VECADDMUL(cloth1->verts[face1->v2].tv, collpair->normal, -magnormal+ impulse); 
+                                       VECADDMUL(cloth1->verts[face1->v3].impulse, collpair->normal, impulse); 
+                                       cloth1->verts[face1->v3].impulse_count++;
                                
+                                       if(face1->v4)
+                                       {
+                                               VECADDMUL(cloth1->verts[face1->v4].impulse, collpair->normal, impulse); 
+                                               cloth1->verts[face1->v4].impulse_count++;
+                                       }
                                
-                               VECSUB(collvel, cloth1->verts[face1->v3].tv, v2);
-                               magnormal = INPR(collvel, collpair->normal);
-                               if(magnormal<ALMOST_ZERO)
-                                       magnormal = 0.0f;
+                               }
                                
-                               impulse = (epsilon + ALMOST_ZERO-collpair->distance) / 4.0f;
-                               VECADDMUL(cloth1->verts[face1->v3].tv, collpair->normal, -magnormal+ impulse); 
+                               result = 1;
                                
+                       
+                               // printf("magnitude_i: %f\n", magnitude_i); // negative before collision in my case
+                               
+                               // Apply the impulse and increase impulse counters.
+
+                               /*                      
+                               // calculateFrictionImpulse(tangential, collvel, collpair->normal, magtangent, clmd->coll_parms.friction*0.01, magtangent);
+                               VECSUBS(vrel_t_pre, collvel, collpair->normal, magnormal);
+                               // VecMulf(vrel_t_pre, clmd->coll_parms.friction*0.01f/INPR(vrel_t_pre,vrel_t_pre));
+                               magtangent = Normalize(vrel_t_pre);
+                               VecMulf(vrel_t_pre, MIN2(clmd->coll_parms.friction*0.01f*magnormal,magtangent));
+                               
+                               VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v1].tv,vrel_t_pre);
+                               */
                                
-                               VECSUB(collvel, cloth1->verts[face1->v4].tv, v2);
-                               magnormal = INPR(collvel, collpair->normal);
-                               if(magnormal<ALMOST_ZERO)
-                                       magnormal = 0.0f;
                                
-                               impulse = (epsilon + ALMOST_ZERO-collpair->distance) / 4.0f;
-                               VECADDMUL(cloth1->verts[face1->v4].tv, collpair->normal, -magnormal+ impulse); 
-                       
-                               result = 1;
                                
                        }
                        
@@ -444,65 +454,86 @@ double implicit_tri_check_coherence (ClothModifierData *clmd, ClothModifierData
        {
                if(i == 0)
                {
-                       indexA = face1->v4;
-                       indexB = face1->v1;
-                       indexC = face1->v3;
-                       
-                       indexD = face2->v1;
-                       indexE = face2->v2;
-                       indexF = face2->v3;
+                       if(face1->v4)
+                       {
+                               indexA = face1->v4;
+                               indexB = face1->v1;
+                               indexC = face1->v3;
+                               
+                               indexD = face2->v1;
+                               indexE = face2->v2;
+                               indexF = face2->v3;
+                       }
+                       else 
+                               i+=2;
                }
-               else if(i == 1)
-               {
-                       indexA = face1->v4;
-                       indexB = face1->v1;
-                       indexC = face1->v3;
                
-                       indexD = face2->v4;
-                       indexE = face2->v1;
-                       indexF = face2->v3;
-               }
-               else if(i == 2)
+               if(i == 1)
                {
-                       indexA = face1->v1;
-                       indexB = face1->v2;
-                       indexC = face1->v3;
-               
-                       indexD = face2->v4;
-                       indexE = face2->v1;
-                       indexF = face2->v3;
+                       if((face1->v4)&&(face2->v4))
+                       {
+                               indexA = face1->v4;
+                               indexB = face1->v1;
+                               indexC = face1->v3;
+                       
+                               indexD = face2->v4;
+                               indexE = face2->v1;
+                               indexF = face2->v3;
+                       }
+                       else
+                               i++;
                }
                
-               // face a2 + face b1
-               VECCOPY(a[0], cloth1->verts[indexA].txold);
-               VECCOPY(a[1], cloth1->verts[indexB].txold);
-               VECCOPY(a[2], cloth1->verts[indexC].txold);
-               
-               
-               VECCOPY(b[0], cloth2->verts[indexD].txold);
-               VECCOPY(b[1], cloth2->verts[indexE].txold);
-               VECCOPY(b[2], cloth2->verts[indexF].txold);
-
-               tempdistance = plNearestPoints(a,b,tpa,tpb,tnormal);
-               
-               if(tempdistance < distance)
+               if(i == 2)
                {
-                       VECCOPY(pa, tpa);
-                       VECCOPY(pb, tpb);
-                       VECCOPY(normal, tnormal);
-                       distance = tempdistance;
-                       
-                       if(i == 0)
+                       if(face2->v4)
                        {
-                               quadA = 1; quadB = 0;
-                       }
-                       else if(i == 1)
-                       {
-                               quadA = quadB = 1;
+                               indexA = face1->v1;
+                               indexB = face1->v2;
+                               indexC = face1->v3;
+                       
+                               indexD = face2->v4;
+                               indexE = face2->v1;
+                               indexF = face2->v3;
                        }
-                       else if(i == 2)
+                       else
+                               i++;
+                       
+               }
+               
+               if(i<3)
+               {
+                       // face a2 + face b1
+                       VECCOPY(a[0], cloth1->verts[indexA].txold);
+                       VECCOPY(a[1], cloth1->verts[indexB].txold);
+                       VECCOPY(a[2], cloth1->verts[indexC].txold);
+                       
+                       
+                       VECCOPY(b[0], cloth2->verts[indexD].txold);
+                       VECCOPY(b[1], cloth2->verts[indexE].txold);
+                       VECCOPY(b[2], cloth2->verts[indexF].txold);
+       
+                       tempdistance = plNearestPoints(a,b,tpa,tpb,tnormal);
+                       
+                       if(tempdistance < distance)
                        {
-                               quadA = 0; quadB = 1;
+                               VECCOPY(pa, tpa);
+                               VECCOPY(pb, tpb);
+                               VECCOPY(normal, tnormal);
+                               distance = tempdistance;
+                               
+                               if(i == 0)
+                               {
+                                       quadA = 1; quadB = 0;
+                               }
+                               else if(i == 1)
+                               {
+                                       quadA = quadB = 1;
+                               }
+                               else if(i == 2)
+                               {
+                                       quadA = 0; quadB = 1;
+                               }
                        }
                }
        }
@@ -524,20 +555,18 @@ void bvh_collision_response(ClothModifierData *clmd, ClothModifierData *coll_clm
        // calc distance + normal       
        distance = implicit_tri_check_coherence(clmd, coll_clmd, tree1->tri_index, tree2->tri_index, collpair->p1, collpair->p2, collpair->vector, collpair->quadA, collpair->quadB);
        
-       if (ABS(distance) <= (epsilon + ALMOST_ZERO))
+       if ((distance <= (epsilon + ALMOST_ZERO)) && (distance > -1.0f)) // max overlap = 1.0 
        {
-               // printf("distance: %f, epsilon: %f\n", (float)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);
                
-               // printf("normal x: %f, y: %f, z: %f\n", collpair->normal[0], collpair->normal[1], collpair->normal[2]);
-               
                collpair->distance = distance;
-               BLI_linklist_append(&linknode[tree1->tri_index], collpair);     
+               BLI_linklist_append(&linknode[tree1->tri_index], collpair);
        }
        else
        {
@@ -545,7 +574,55 @@ void bvh_collision_response(ClothModifierData *clmd, ClothModifierData *coll_clm
        }
 }
 
+// move collision objects forward in time and update static bounding boxes
+void cloth_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 & CSIMSETT_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_static(coll_clmd, coll_bvh);
+                       }
+                       else
+                               printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n");
+               }
+       }
+}
+
+#define CLOTH_MAX_THRESHOLD 5
 
+// cloth - object collisions
 int cloth_bvh_objcollision(ClothModifierData * clmd, float step, CM_COLLISION_RESPONSE collision_response, float dt)
 {
        Base *base=NULL;
@@ -553,15 +630,19 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, CM_COLLISION_RE
        Cloth *cloth=NULL;
        Object *coll_ob=NULL;
        BVH *cloth_bvh=NULL;
-       unsigned int i=0, numverts=0;
-       int result = 0;
+       unsigned int i=0, numfaces = 0, numverts = 0;
+       unsigned int result = 0, ic = 0, rounds = 0;
+       ClothVertex *verts = NULL;
+       float tnull[3] = {0,0,0};
 
        if ((clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ) || !(((Cloth *)clmd->clothObject)->tree))
        {
                return 0;
        }
        cloth = clmd->clothObject;
+       verts = cloth->verts;
        cloth_bvh = (BVH *) cloth->tree;
+       numfaces = clmd->clothObject->numfaces;
        numverts = clmd->clothObject->numverts;
        
        ////////////////////////////////////////////////////////////
@@ -570,87 +651,94 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, CM_COLLISION_RE
 
        // update cloth bvh
        bvh_update_static(clmd, cloth_bvh);
+       
+       // update collision objects
+       cloth_update_collision_objects(step);
 
-       // search all objects for collision object
-       for (base = G.scene->base.first; base; base = base->next)
+       do
        {
-
-               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 & CSIMSETT_FLAG_COLLOBJ)
+               result = 0;
+               ic = 0;
+                       
+               // handle all collision objects
+               for (base = G.scene->base.first; base; base = base->next)
                {
-                       if (coll_clmd->clothObject && coll_clmd->clothObject->tree) 
-                       {                       
-                               unsigned int coll_numverts = coll_clmd->clothObject->numverts;
-                               Cloth *coll_cloth = coll_clmd->clothObject;
-
-                               LinkNode **collision_list = MEM_callocN (sizeof(LinkNode *)*numverts, "collision_list");
-                               BVH *coll_bvh = coll_clmd->clothObject->tree;
-
-                               if(collision_list)
-                               {                                       
-                                       // memset(collision_list, 0, sizeof(LinkNode *)*numverts); 
-                                       
-                                       for(i = 0; i < numverts; i++)
-                                       {
-                                               collision_list[i] = NULL;
-                                       }
-
-                                       clmd->coll_parms.temp = collision_list;
-                                       
-                                       // 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);
+       
+                       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 & CSIMSETT_FLAG_COLLOBJ)
+                       {
+                               if (coll_clmd->clothObject && coll_clmd->clothObject->tree) 
+                               {
+                                       LinkNode **collision_list = MEM_callocN (sizeof(LinkNode *)*(numfaces), "collision_list");
+                                       BVH *coll_bvh = coll_clmd->clothObject->tree;
+       
+                                       if(collision_list)
+                                       {                                       
+                                               memset(collision_list, 0, sizeof(LinkNode *)*numfaces);
+                                               clmd->coll_parms.temp = collision_list;
+       
+                                               bvh_traverse(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, collision_response);
                                                
-                                               VECSUB(coll_cloth->verts[i].tv, coll_cloth->verts[i].tx, coll_cloth->verts[i].txold);
-                                       }
-                                                       
-                                       // update BVH of collision object
-                                       bvh_update_static(coll_clmd, coll_bvh);
-
-                                       bvh_traverse(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, collision_response);
-                                       
-                                       result += collision_static(clmd, coll_clmd, collision_list);
-                                       
-                                       // calculate velocities
-                                       
-                                       // free temporary list 
-                                       for(i = 0; i < numverts; i++)
-                                       {
-                                               LinkNode *search = collision_list[i];
-                                               while(search)
+                                               result += collision_static(clmd, coll_clmd, collision_list);
+                                               
+                                               // calculate velocities
+                                               
+                                               // free temporary list 
+                                               for(i = 0; i < numfaces; i++)
                                                {
-                                                       LinkNode *next= search->next;
-                                                       CollPair *collpair = search->link;
-                                                       
-                                                       if(collpair)
-                                                               MEM_freeN(collpair);    
-
-                                                       search = next;
+                                                       LinkNode *search = collision_list[i];
+                                                       while(search)
+                                                       {
+                                                               LinkNode *next= search->next;
+                                                               CollPair *collpair = search->link;
+                                                               
+                                                               if(collpair)
+                                                                       MEM_freeN(collpair);    
+       
+                                                               search = next;
+                                                       }
+       
+                                                       BLI_linklist_free(collision_list[i],NULL); 
                                                }
-
-                                               BLI_linklist_free(collision_list[i],NULL); 
+                                               if(collision_list)
+                                                       MEM_freeN(collision_list);
+       
+                                               clmd->coll_parms.temp = NULL;
                                        }
-                                       if(collision_list)
-                                               MEM_freeN(collision_list);
-
-                                       clmd->coll_parms.temp = NULL;
+                                       
+       
                                }
+                               else
+                                       printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n");
+                       }
+               }
+               
+               // now apply impulses parallel
+               
+               for(i = 0; i < numverts; i++)
+               {
+                       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++;
                        }
-                       else
-                               printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n");
                }
+               
+               printf("ic: %d\n", ic);
+               rounds++;
        }
-
+       while(result && (CLOTH_MAX_THRESHOLD>rounds));
+       
+       printf("\n");
+                       
        ////////////////////////////////////////////////////////////
        // update positions + velocities
        ////////////////////////////////////////////////////////////
index c54897cc89c75f9a94f1f5e1fa535f16cde0e701..0d0c7ff0f7b5842154060671213c4408204501e8 100644 (file)
@@ -1484,7 +1484,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase
                        VECCOPY(verts[i].tx, id->Xnew[i]);
                        
                        VECSUB(verts[i].tv, verts[i].tx, verts[i].txold);
-                       VECSUB(verts[i].v, verts[i].tx, verts[i].txold);
+                       VECCOPY(verts[i].v, verts[i].tv);
                }
 
                // call collision function
index 546247f8e35f571a83368ca91527b0454c575653..5ba3df9a720655b9cc7acdb6534e1b7d81a29a2a 100644 (file)
@@ -4941,9 +4941,12 @@ static int clothModifier_dependsOnTime(ModifierData *md)
 static void clothModifier_freeData(ModifierData *md)
 {
        ClothModifierData *clmd = (ClothModifierData*) md;
-
+       
        if (clmd) 
-           cloth_free_modifier (clmd);  
+       {
+               clmd->sim_parms.flags &= ~CSIMSETT_FLAG_CCACHE_PROTECT;
+               cloth_free_modifier (clmd);
+       }
 }
 
 /* Boolean */
index c0a47452e3e480ec3ce1d92880803fd0089fbe12..574537f258958e68fce5a9008e22db0301858e27 100644 (file)
 * is reached.
 */
 typedef struct ClothVertex {
-       int     flags;                  /* General flags per vertex.                    */
-       float   v [3];                  /* The velocity of the point.                   */
-       float   xconst [3];             /* constrained position         */
-       float   x [3];                  /* The current position of this vertice.        */
-       float   xold [3];               /* The previous position of this vertice.       */
-       float   tx [3]; 
-       float   txold [3];
-       float   tv[3];
-       float   mass;                   /* mass / weight of the vertex                  */
-       float   goal;                   /* goal, from SB                                */
+       int     flags;          /* General flags per vertex.            */
+       float   v [3];          /* The velocity of the point.           */
+       float   xconst [3];     /* constrained position                 */
+       float   x [3];          /* The current position of this vertex. */
+       float   xold [3];       /* The previous position of this vertex.*/
+       float   tx [3];         /* temporary position */
+       float   txold [3];      /* temporary old position */
+       float   tv[3];          /* temporary "velocity", mostly used as tv = tx-txold */
+       float   mass;           /* mass / weight of the vertex          */
+       float   goal;           /* goal, from SB                        */
+       float   impulse[3];     /* used in collision.c */
+       unsigned int impulse_count; /* same as above */
 } ClothVertex;
 
 
index 1e3439d41b521342ca9c6bad0f1dd83c95625afa..a10ffa094424e065f0127834333a3f989fed8a93 100644 (file)
@@ -3118,8 +3118,8 @@ static void object_panel_cloth(Object *ob)
                        /* GENERAL STUFF */
                        uiClearButLock();
                        uiBlockBeginAlign(block);
-                       uiDefButF(block, NUM, B_CLOTH_RENEW, "StructStiff:",       10,170,150,20, &clmd->sim_parms.structural, 1.0, 5000.0, 100, 0, "Overall stiffness of structure");
-                       uiDefButF(block, NUM, B_CLOTH_RENEW, "BendStiff:",         160,170,150,20, &clmd->sim_parms.bending, 0.0, 1000.0, 1000, 0, "Wrinkle possibility");
+                       uiDefButF(block, NUM, B_CLOTH_RENEW, "StructStiff:",       10,170,150,20, &clmd->sim_parms.structural, 1.0, 10000.0, 100, 0, "Overall stiffness of structure");
+                       uiDefButF(block, NUM, B_CLOTH_RENEW, "BendStiff:",         160,170,150,20, &clmd->sim_parms.bending, 0.0, 10000.0, 1000, 0, "Wrinkle possibility");
                        uiDefButI(block, NUM, B_CLOTH_RENEW, "Steps per Frame:",           10,150,150,20, &clmd->sim_parms.stepsPerFrame, 1.0, 100.0, 5, 0, "Quality of the simulation (higher=better=slower)");
                        uiBlockEndAlign(block);
                        uiBlockBeginAlign(block);
@@ -3249,12 +3249,13 @@ static void object_panel_cloth_II(Object *ob)
                                uiDefBut(block, BUT, B_CLOTH_CLEARCACHEALL, "All", 10, 100,145,20, NULL, 0.0, 0.0, 0, 0, "Free cloth cache without preroll");
                                uiDefBut(block, BUT, B_CLOTH_CLEARCACHEFRAME, "From next frame", 155, 100,145,20, NULL, 0.0, 0.0, 0, 0, "Free cloth cache");    
                                if(length>1) // B_CLOTH_CHANGEPREROLL
-                                       uiDefButI(block, NUM, B_CLOTH_CHANGEPREROLL, "Preroll:", 10,80,145,20, &clmd->sim_parms.preroll, 0, length-1, 1, 0, "Simulation starts on this frame");
+                                       uiDefButI(block, NUM, B_CLOTH_CHANGEPREROLL, "Preroll:", 10,80,145,20, &clmd->sim_parms.preroll, 0, length-1, 1, 0, "Simulation starts on this frame"); 
                        }
                        else
                        {
                                uiDefBut(block, LABEL, 0, "No frames cached.",  10,120,290,20, NULL, 0.0, 0, 0, 0, "");
                        }
+                       uiDefButBitI(block, TOG, CSIMSETT_FLAG_CCACHE_PROTECT, REDRAWVIEW3D, "Protect Cache",   10,50,145,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Protect cache from automatic freeing when scene changed");
                        uiBlockEndAlign(block);
                }
        }