diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index e4d1fb0ca99..ec58382b86a 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -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.00001 +#define ALMOST_ZERO 0.000001 /* Bits to or into the ClothVertex.flags. */ #define CVERT_FLAG_PINNED 1 @@ -240,7 +240,7 @@ typedef struct CollPair float p1[3], p2[3]; // collision point p1 on face1, p2 on face2 int lastsign; // indicates if the distance sign has changed, unused itm float time; // collision time, from 0 up to 1 - int quadA, quadB; // indicates the used triangle of the quad: 0 means verts 1,2,3; 1 means verts 4,1,3 + unsigned int Aindex1, Aindex2, Aindex3, Aindex4, Bindex1, Bindex2, Bindex3, Bindex4; } CollPair; diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 7059c59c65b..d9f0bef9f43 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -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 | CSIMSETT_FLAG_CCACHE_PROTECT; + clmd->sim_parms.flags = CSIMSETT_FLAG_RESET; clmd->sim_parms.solver_type = 0; clmd->sim_parms.preroll = 0; clmd->sim_parms.maxspringlen = 10; diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 8c6a17c4e42..7eec315e386 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -211,14 +211,8 @@ void bvh_compute_barycentric (float pv[3], float p1[3], float p2[3], float p3[3] w1[0] = (e * c - b * f) / d; - if(w1[0] < 0) - w1[0] = 0.0; - w2[0] = (f - b * w1[0]) / c; - if(w2[0] < 0) - w2[0] = 0.0; - w3[0] = 1.0f - w1[0] - w2[0]; } @@ -241,7 +235,7 @@ DO_INLINE void calculateFrictionImpulse(float to[3], float vrel[3], float normal VecMulf(to, MAX2(1.0f - frictionConstant * delta_V_n / INPR(vrel_t_pre,vrel_t_pre), 0.0f)); } - +/* int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, LinkNode **collision_list) { unsigned int i = 0, numfaces = 0; @@ -343,12 +337,12 @@ int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, Link // printf("friction applied: %f\n", magtangent); // TODO check original code - /* + VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v1].tv,tangential); VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v2].tv,tangential); VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v3].tv,tangential); VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v4].tv,tangential); - */ + } impulse = -magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3); @@ -397,7 +391,7 @@ int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, Link // 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)); @@ -405,7 +399,7 @@ int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, Link 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); - */ + @@ -417,7 +411,8 @@ int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, Link return result; } - +*/ + // return distance between two triangles using bullet engine double implicit_tri_check_coherence (ClothModifierData *clmd, ClothModifierData *coll_clmd, unsigned int tri_index1, unsigned int tri_index2, float pa[3], float pb[3], float normal[3], int quadA, int quadB) { @@ -540,37 +535,331 @@ double implicit_tri_check_coherence (ClothModifierData *clmd, ClothModifierData return distance; } +// calculate plane normal +void calcPlaneNormal(float normal[3], float p11[3], float p12[3], float p13[3]) +{ + float temp1[3], temp2[3]; + float tnormal[3]; + + VECSUB(temp1, p12,p11); + VECSUB(temp2, p13,p11); + Crossf(normal, temp1, temp2); + Normalize(normal); + // VECCOPY(normal, tnormal); +} + +float distance_triangle_point( float p11[3], float p12[3], float p13[3], float p21[3], float normal[3]) +{ + float temp[3]; + float magnitude = 0; + + VECSUB(temp, p21, p13); + magnitude = INPR(temp, normal); + + if(magnitude < 0) + { + magnitude *= -1.0f; + // VecMulf(normal, -1.0f); + } + + return magnitude; +} + +float nearest_point_triangle_triangle(float p11[3], float p12[3], float p13[3], float p21[3], float p22[3], float p23[3], float normal[3]) +{ + float distance = 0, tdistance = 0, tnormal[3]; + + // first triangle 1-2-3 versus second triangle 1-2-3 + calcPlaneNormal(normal, p11, p12, p13); + distance = distance_triangle_point(p11, p12, p13, p21, normal); + + tdistance = distance_triangle_point(p11, p12, p13, p22, normal); + + if(tdistance < distance) + { + distance = tdistance; + } + + tdistance = distance_triangle_point(p11, p12, p13, p23, normal); + + if(tdistance < distance) + { + distance = tdistance; + } + + // second triangle 1-2-3 versus first triangle 1-2-3 + calcPlaneNormal(tnormal, p21, p22, p23); + + tdistance = distance_triangle_point(p21, p22, p23, p11, tnormal); + + if(tdistance < distance) + { + distance = tdistance; + VECCOPY(normal, tnormal); + } + + tdistance = distance_triangle_point(p21, p22, p23, p12, tnormal); + + if(tdistance < distance) + { + distance = tdistance; + VECCOPY(normal, tnormal); + } + + tdistance = distance_triangle_point(p21, p22, p23, p13, tnormal); + + if(tdistance < distance) + { + distance = tdistance; + VECCOPY(normal, tnormal); + } + + + if (distance < 0) { + VecMulf(normal, -1.0f); + distance = -distance; + } + + return distance; +} + + +int collision_static2(ClothModifierData *clmd, ClothModifierData *coll_clmd, LinkNode **collision_list) +{ + 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, a1, a2, a3; + float v1[3], v2[3], relativeVelocity[3]; + float magrelVel; + + cloth1 = clmd->clothObject; + cloth2 = coll_clmd->clothObject; + + numfaces = clmd->clothObject->numfaces; + + for(i = 0; i < numfaces; i++) + { + search = collision_list[i]; + + while(search) + { + collpair = search->link; + + face1 = &(cloth1->mfaces[collpair->face1]); + face2 = &(cloth2->mfaces[collpair->face2]); + + // compute barycentric coordinates for both collision points + + + bvh_compute_barycentric(collpair->p1, + cloth1->verts[collpair->Aindex1].txold, + cloth1->verts[collpair->Aindex2].txold, + cloth1->verts[collpair->Aindex3].txold, + &w1, &w2, &w3); + + bvh_compute_barycentric(collpair->p2, + cloth2->verts[collpair->Bindex1].txold, + cloth2->verts[collpair->Bindex1].txold, + cloth2->verts[collpair->Bindex3].txold, + &u1, &u2, &u3); + + // Calculate relative "velocity". + interpolateOnTriangle(v1, cloth1->verts[collpair->Aindex1].tv, cloth1->verts[collpair->Aindex2].tv, cloth1->verts[collpair->Aindex3].tv, w1, w2, w3); + + interpolateOnTriangle(v2, cloth2->verts[collpair->Bindex1].tv, cloth2->verts[collpair->Bindex2].tv, cloth2->verts[collpair->Bindex3].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); + + // 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); + + /* + 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++; + + VECADDMUL(cloth1->verts[face1->v2].impulse, collpair->normal, impulse); + cloth1->verts[face1->v2].impulse_count++; + + VECADDMUL(cloth1->verts[face1->v3].impulse, collpair->normal, impulse); + cloth1->verts[face1->v3].impulse_count++; + */ + + + /* + 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++; + + 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++; + } + + } + */ + + result = 1; + } + + search = search->next; + } + } + + return result; +} + void bvh_collision_response(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree * tree1, Tree * tree2) { CollPair *collpair = NULL; LinkNode **linknode; double distance = 0; - float epsilon = clmd->coll_parms.epsilon; - - collpair = (CollPair *)MEM_callocN(sizeof(CollPair), "cloth coll pair"); + float epsilon = clmd->coll_parms.epsilon, tdistance=0; + MFace *face1, *face2; + ClothVertex *verts1, *verts2; + Cloth *cloth1=NULL, *cloth2=NULL; + int i = 0; + linknode = clmd->coll_parms.temp; + cloth1 = clmd->clothObject; + cloth2 = coll_clmd->clothObject; + // calc SIPcode (?) - // 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 ((distance <= (epsilon + ALMOST_ZERO)) && (distance > -1.0f)) // max overlap = 1.0 + for(i = 0; i < 4; i++) { - // printf("dist: %f\n", (float)distance); + collpair = (CollPair *)MEM_callocN(sizeof(CollPair), "cloth coll pair"); - collpair->face1 = tree1->tri_index; - collpair->face2 = tree2->tri_index; + face1 = &(cloth1->mfaces[tree1->tri_index]); + face2 = &(cloth2->mfaces[tree2->tri_index]); + + verts1 = cloth1->verts; + verts2 = cloth2->verts; - VECCOPY(collpair->normal, collpair->vector); - Normalize(collpair->normal); + if(i == 0) + { + collpair->Aindex1 = face1->v1; + collpair->Aindex2 = face1->v2; + collpair->Aindex3 = face1->v3; + collpair->Aindex4 = face1->v4; + + collpair->Bindex1 = face2->v1; + collpair->Bindex2 = face2->v2; + collpair->Bindex3 = face2->v3; + collpair->Bindex4 = face2->v4; + + } - collpair->distance = distance; - BLI_linklist_append(&linknode[tree1->tri_index], collpair); - } - else - { - MEM_freeN(collpair); + if(i == 1) + { + if(face2->v4) + { + collpair->Aindex1 = face1->v1; + collpair->Aindex2 = face1->v2; + collpair->Aindex3 = face1->v3; + collpair->Aindex4 = face1->v4; + + collpair->Bindex1 = face2->v4; + collpair->Bindex2 = face2->v3; + collpair->Bindex3 = face2->v1; + collpair->Bindex4 = face2->v1; + } + else + i++; + + } + + if(i == 2) + { + if(face1->v4) + { + collpair->Aindex1 = face1->v4; + collpair->Aindex2 = face1->v3; + collpair->Aindex3 = face1->v1; + collpair->Aindex4 = face1->v2; + + collpair->Bindex1 = face2->v1; + collpair->Bindex2 = face2->v2; + collpair->Bindex3 = face2->v3; + collpair->Bindex4 = face2->v4; + } + else + i++; + } + + if(i == 3) + { + if((face2->v4) && (face1->v4)) + { + collpair->Aindex1 = face1->v4; + collpair->Aindex2 = face1->v3; + collpair->Aindex3 = face1->v1; + collpair->Aindex4 = face1->v2; + + collpair->Bindex1 = face2->v4; + collpair->Bindex2 = face2->v3; + collpair->Bindex3 = face2->v1; + collpair->Bindex4 = face2->v2; + } + else + i++; + } + + if(i < 4) + { + distance = nearest_point_triangle_triangle(verts1[collpair->Aindex1].txold, verts1[collpair->Aindex2].txold, verts1[collpair->Aindex3].txold, verts2[collpair->Bindex1].txold, verts2[collpair->Bindex2].txold, verts2[collpair->Bindex3].txold, collpair->normal); + + // 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 (distance <= (epsilon + ALMOST_ZERO)) // max overlap = 1.0 + { + + printf("dist: %f, tdist: %f\n", (float)distance, tdistance); + + collpair->face1 = tree1->tri_index; + collpair->face2 = tree2->tri_index; + + collpair->distance = distance; + BLI_linklist_append(&linknode[tree1->tri_index], collpair); + } + else + { + MEM_freeN(collpair); + } + } } } @@ -684,7 +973,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, CM_COLLISION_RE bvh_traverse(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, collision_response); - result += collision_static(clmd, coll_clmd, collision_list); + result += collision_static2(clmd, coll_clmd, collision_list); // calculate velocities