diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 378cc72beb1..998c90ad488 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -211,7 +211,7 @@ void implicit_set_positions (struct ClothModifierData *clmd ); void cloth_free_modifier_extern (struct ClothModifierData *clmd ); void cloth_free_modifier (struct ClothModifierData *clmd ); void cloth_init (struct ClothModifierData *clmd ); -void clothModifier_do (struct ClothModifierData *clmd, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm, float (*vertexCos)[3]); +struct DerivedMesh *clothModifier_do (struct ClothModifierData *clmd, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm); int cloth_uses_vgroup(struct ClothModifierData *clmd); diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index b521285c626..df746143d19 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -93,7 +93,7 @@ static CM_SOLVER_DEF solvers [] = /* ********** cloth engine ******* */ /* Prototypes for internal functions. */ -static void cloth_to_object (Object *ob, ClothModifierData *clmd, float (*vertexCos)[3]); +static void cloth_to_object (Object *ob, ClothModifierData *clmd, DerivedMesh *dm); static void cloth_from_mesh ( ClothModifierData *clmd, DerivedMesh *dm ); static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float framenr, int first); static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ); @@ -419,16 +419,71 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul return ret; } + +static DerivedMesh *cloth_to_triangles(DerivedMesh *dm) +{ + DerivedMesh *result = NULL; + unsigned int i = 0, j = 0; + unsigned int quads = 0, numfaces = dm->getNumTessFaces(dm); + MFace *mface = dm->getTessFaceArray(dm); + MFace *mface2 = NULL; + + /* calc faces */ + for(i = 0; i < numfaces; i++) + { + if(mface[i].v4) + quads++; + } + + result = CDDM_from_template(dm, dm->getNumVerts(dm), 0, numfaces + quads, 0, 0); + + DM_copy_vert_data(dm, result, 0, 0, dm->getNumVerts(dm)); + DM_copy_tessface_data(dm, result, 0, 0, numfaces); + + DM_ensure_tessface(result); + mface2 = result->getTessFaceArray(result); + + for(i = 0, j = numfaces; i < numfaces; i++) + { + // DG TODO: is this necessary? + mface2[i].v1 = mface[i].v1; + mface2[i].v2 = mface[i].v2; + mface2[i].v3 = mface[i].v3; + + mface2[i].v4 = 0; + //test_index_face(&mface2[i], &result->faceData, i, 3); + + if(mface[i].v4) + { + DM_copy_tessface_data(dm, result, i, j, 1); + + mface2[j].v1 = mface[i].v1; + mface2[j].v2 = mface[i].v3; + mface2[j].v3 = mface[i].v4; + mface2[j].v4 = 0; + //test_index_face(&mface2[j], &result->faceData, j, 3); + + j++; + } + } + + CDDM_calc_edges_tessface(result); + CDDM_tessfaces_to_faces(result); /* builds ngon faces from tess (mface) faces */ + + return result; +} + /************************************************ * clothModifier_do - main simulation function ************************************************/ -void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, DerivedMesh *dm, float (*vertexCos)[3]) +DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, DerivedMesh *dm) { PointCache *cache; PTCacheID pid; float timescale; int framenr, startframe, endframe; int cache_result; + DerivedMesh *result = NULL; clmd->scene= scene; /* nice to pass on later :) */ framenr= (int)scene->r.cfra; @@ -448,7 +503,7 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived BKE_ptcache_validate(cache, 0); cache->last_exact= 0; cache->flag &= ~PTCACHE_REDO_NEEDED; - return; + return NULL; } // unused in the moment, calculated separately in implicit.c @@ -460,20 +515,21 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived /* do simulation */ if (!do_init_cloth(ob, clmd, dm, framenr)) - return; + return NULL; do_step_cloth(ob, clmd, dm, framenr); - cloth_to_object(ob, clmd, vertexCos); + result = cloth_to_triangles(dm); + cloth_to_object(ob, clmd, result); clmd->clothObject->last_frame= framenr; - return; + return result; } /* simulation is only active during a specific period */ if (framenr < startframe) { BKE_ptcache_invalidate(cache); - return; + return NULL; } else if (framenr > endframe) { framenr= endframe; @@ -481,7 +537,7 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived /* initialize simulation data if it didn't exist already */ if (!do_init_cloth(ob, clmd, dm, framenr)) - return; + return NULL; if ((framenr == startframe) && (clmd->sim_parms->preroll == 0)) { BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); @@ -489,7 +545,7 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived BKE_ptcache_validate(cache, framenr); cache->flag &= ~PTCACHE_REDO_NEEDED; clmd->clothObject->last_frame= framenr; - return; + return NULL; } /* try to read from cache */ @@ -497,7 +553,8 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived if (cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) { implicit_set_positions(clmd); - cloth_to_object (ob, clmd, vertexCos); + result = cloth_to_triangles(dm); + cloth_to_object (ob, clmd, result); BKE_ptcache_validate(cache, framenr); @@ -506,7 +563,7 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived clmd->clothObject->last_frame= framenr; - return; + return result; } else if (cache_result==PTCACHE_READ_OLD) { implicit_set_positions(clmd); @@ -514,11 +571,11 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived else if ( /*ob->id.lib ||*/ (cache->flag & PTCACHE_BAKED)) { /* 2.4x disabled lib, but this can be used in some cases, testing further - campbell */ /* if baked and nothing in cache, do nothing */ BKE_ptcache_invalidate(cache); - return; + return NULL; } if (framenr!=clmd->clothObject->last_frame+1) - return; + return NULL; /* if on second frame, write cache for first frame */ if (cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) @@ -535,8 +592,11 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived else BKE_ptcache_write(&pid, framenr); - cloth_to_object (ob, clmd, vertexCos); + result = cloth_to_triangles(dm); + cloth_to_object (ob, clmd, result); clmd->clothObject->last_frame= framenr; + + return result; } /* frees all */ @@ -683,18 +743,19 @@ void cloth_free_modifier_extern(ClothModifierData *clmd ) * cloth_to_object - copies the deformed vertices to the object. * **/ -static void cloth_to_object (Object *ob, ClothModifierData *clmd, float (*vertexCos)[3]) +static void cloth_to_object (Object *ob, ClothModifierData *clmd, DerivedMesh *dm) { unsigned int i = 0; Cloth *cloth = clmd->clothObject; + MVert *verts = dm->getVertArray(dm); if (clmd->clothObject) { /* inverse matrix is not uptodate... */ invert_m4_m4(ob->imat, ob->obmat); for (i = 0; i < cloth->numverts; i++) { - copy_v3_v3 (vertexCos[i], cloth->verts[i].x); - mul_m4_v3(ob->imat, vertexCos[i]); /* cloth is in global coords */ + copy_v3_v3 (verts[i].co, cloth->verts[i].x); + mul_m4_v3(ob->imat, verts[i].co); /* cloth is in global coords */ } } } diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 609b2d3496c..35d06234aa2 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -161,284 +161,7 @@ void bvhtree_update_from_mvert(BVHTree * bvhtree, MFace *faces, int numfaces, MV /*********************************** Collision modifier code end ***********************************/ - -/** -* gsl_poly_solve_cubic - -* -* copied from SOLVE_CUBIC.C --> GSL -*/ - #define mySWAP(a, b) do { double tmp = b ; b = a ; a = tmp ; } while (0) -#if 0 /* UNUSED */ -static int -gsl_poly_solve_cubic (double a, double b, double c, - double *x0, double *x1, double *x2) -{ - double q = (a * a - 3 * b); - double r = (2 * a * a * a - 9 * a * b + 27 * c); - - double Q = q / 9; - double R = r / 54; - - double Q3 = Q * Q * Q; - double R2 = R * R; - - double CR2 = 729 * r * r; - double CQ3 = 2916 * q * q * q; - - if (R == 0 && Q == 0) - { - *x0 = - a / 3; - *x1 = - a / 3; - *x2 = - a / 3; - return 3; - } - else if (CR2 == CQ3) - { - /* this test is actually R2 == Q3, written in a form suitable - for exact computation with integers */ - - /* Due to finite precision some double roots may be missed, and - considered to be a pair of complex roots z = x +/- epsilon i - close to the real axis. */ - - double sqrtQ = sqrt (Q); - - if (R > 0) - { - *x0 = -2 * sqrtQ - a / 3; - *x1 = sqrtQ - a / 3; - *x2 = sqrtQ - a / 3; - } - else - { - *x0 = - sqrtQ - a / 3; - *x1 = - sqrtQ - a / 3; - *x2 = 2 * sqrtQ - a / 3; - } - return 3; - } - else if (CR2 < CQ3) /* equivalent to R2 < Q3 */ - { - double sqrtQ = sqrt (Q); - double sqrtQ3 = sqrtQ * sqrtQ * sqrtQ; - double theta = acos (R / sqrtQ3); - double norm = -2 * sqrtQ; - *x0 = norm * cos (theta / 3) - a / 3; - *x1 = norm * cos ((theta + 2.0 * M_PI) / 3) - a / 3; - *x2 = norm * cos ((theta - 2.0 * M_PI) / 3) - a / 3; - - /* Sort *x0, *x1, *x2 into increasing order */ - - if (*x0 > *x1) - mySWAP(*x0, *x1); - - if (*x1 > *x2) - { - mySWAP(*x1, *x2); - - if (*x0 > *x1) - mySWAP(*x0, *x1); - } - - return 3; - } - else - { - double sgnR = (R >= 0 ? 1 : -1); - double A = -sgnR * pow (fabs (R) + sqrt (R2 - Q3), 1.0/3.0); - double B = Q / A; - *x0 = A + B - a / 3; - return 1; - } -} - - - -/** -* gsl_poly_solve_quadratic -* -* copied from GSL -*/ -static int -gsl_poly_solve_quadratic (double a, double b, double c, - double *x0, double *x1) -{ - double disc = b * b - 4 * a * c; - - if (a == 0) /* Handle linear case */ - { - if (b == 0) - { - return 0; - } - else - { - *x0 = -c / b; - return 1; - }; - } - - if (disc > 0) - { - if (b == 0) - { - double r = fabs (0.5 * sqrt (disc) / a); - *x0 = -r; - *x1 = r; - } - else - { - double sgnb = (b > 0 ? 1 : -1); - double temp = -0.5 * (b + sgnb * sqrt (disc)); - double r1 = temp / a; - double r2 = c / temp; - - if (r1 < r2) - { - *x0 = r1; - *x1 = r2; - } - else - { - *x0 = r2; - *x1 = r1; - } - } - return 2; - } - else if (disc == 0) - { - *x0 = -0.5 * b / a; - *x1 = -0.5 * b / a; - return 2; - } - else - { - return 0; - } -} -#endif /* UNUSED */ - - - -/* -* See Bridson et al. "Robust Treatment of Collision, Contact and Friction for Cloth Animation" -* page 4, left column -*/ -#if 0 -static int cloth_get_collision_time ( double a[3], double b[3], double c[3], double d[3], double e[3], double f[3], double solution[3] ) -{ - int num_sols = 0; - - // x^0 - checked - double g = a[0] * c[1] * e[2] - a[0] * c[2] * e[1] + - a[1] * c[2] * e[0] - a[1] * c[0] * e[2] + - a[2] * c[0] * e[1] - a[2] * c[1] * e[0]; - - // x^1 - double h = -b[2] * c[1] * e[0] + b[1] * c[2] * e[0] - a[2] * d[1] * e[0] + - a[1] * d[2] * e[0] + b[2] * c[0] * e[1] - b[0] * c[2] * e[1] + - a[2] * d[0] * e[1] - a[0] * d[2] * e[1] - b[1] * c[0] * e[2] + - b[0] * c[1] * e[2] - a[1] * d[0] * e[2] + a[0] * d[1] * e[2] - - a[2] * c[1] * f[0] + a[1] * c[2] * f[0] + a[2] * c[0] * f[1] - - a[0] * c[2] * f[1] - a[1] * c[0] * f[2] + a[0] * c[1] * f[2]; - - // x^2 - double i = -b[2] * d[1] * e[0] + b[1] * d[2] * e[0] + - b[2] * d[0] * e[1] - b[0] * d[2] * e[1] - - b[1] * d[0] * e[2] + b[0] * d[1] * e[2] - - b[2] * c[1] * f[0] + b[1] * c[2] * f[0] - - a[2] * d[1] * f[0] + a[1] * d[2] * f[0] + - b[2] * c[0] * f[1] - b[0] * c[2] * f[1] + - a[2] * d[0] * f[1] - a[0] * d[2] * f[1] - - b[1] * c[0] * f[2] + b[0] * c[1] * f[2] - - a[1] * d[0] * f[2] + a[0] * d[1] * f[2]; - - // x^3 - checked - double j = -b[2] * d[1] * f[0] + b[1] * d[2] * f[0] + - b[2] * d[0] * f[1] - b[0] * d[2] * f[1] - - b[1] * d[0] * f[2] + b[0] * d[1] * f[2]; - - /* - printf("r1: %lf\n", a[0] * c[1] * e[2] - a[0] * c[2] * e[1]); - printf("r2: %lf\n", a[1] * c[2] * e[0] - a[1] * c[0] * e[2]); - printf("r3: %lf\n", a[2] * c[0] * e[1] - a[2] * c[1] * e[0]); - - printf("x1 x: %f, y: %f, z: %f\n", a[0], a[1], a[2]); - printf("x2 x: %f, y: %f, z: %f\n", c[0], c[1], c[2]); - printf("x3 x: %f, y: %f, z: %f\n", e[0], e[1], e[2]); - - printf("v1 x: %f, y: %f, z: %f\n", b[0], b[1], b[2]); - printf("v2 x: %f, y: %f, z: %f\n", d[0], d[1], d[2]); - printf("v3 x: %f, y: %f, z: %f\n", f[0], f[1], f[2]); - - printf("t^3: %lf, t^2: %lf, t^1: %lf, t^0: %lf\n", j, i, h, g); - -*/ - // Solve cubic equation to determine times t1, t2, t3, when the collision will occur. - if ( ABS ( j ) > DBL_EPSILON ) - { - i /= j; - h /= j; - g /= j; - num_sols = gsl_poly_solve_cubic ( i, h, g, &solution[0], &solution[1], &solution[2] ); - } - else - { - num_sols = gsl_poly_solve_quadratic ( i, h, g, &solution[0], &solution[1] ); - solution[2] = -1.0; - } - - // printf("num_sols: %d, sol1: %lf, sol2: %lf, sol3: %lf\n", num_sols, solution[0], solution[1], solution[2]); - - // Discard negative solutions - if ( ( num_sols >= 1 ) && ( solution[0] < DBL_EPSILON ) ) - { - --num_sols; - solution[0] = solution[num_sols]; - } - if ( ( num_sols >= 2 ) && ( solution[1] < DBL_EPSILON ) ) - { - --num_sols; - solution[1] = solution[num_sols]; - } - if ( ( num_sols == 3 ) && ( solution[2] < DBL_EPSILON ) ) - { - --num_sols; - } - - // Sort - if ( num_sols == 2 ) - { - if ( solution[0] > solution[1] ) - { - double tmp = solution[0]; - solution[0] = solution[1]; - solution[1] = tmp; - } - } - else if ( num_sols == 3 ) - { - - // Bubblesort - if ( solution[0] > solution[1] ) - { - double tmp = solution[0]; solution[0] = solution[1]; solution[1] = tmp; - } - if ( solution[1] > solution[2] ) - { - double tmp = solution[1]; solution[1] = solution[2]; solution[2] = tmp; - } - if ( solution[0] > solution[1] ) - { - double tmp = solution[0]; solution[0] = solution[1]; solution[1] = tmp; - } - } - - return num_sols; -} -#endif // w3 is not perfect @@ -485,7 +208,6 @@ DO_INLINE void collision_interpolateOnTriangle ( float to[3], float v1[3], float VECADDMUL(to, v3, w3); } -#ifndef WITH_ELTOPO static int cloth_collision_response_static ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) { int result = 0; @@ -538,6 +260,11 @@ static int cloth_collision_response_static ( ClothModifierData *clmd, CollisionM double impulse = 0.0; float vrel_t_pre[3]; float temp[3], spf; + float i1[3], i2[3], i3[3]; + + zero_v3(i1); + zero_v3(i2); + zero_v3(i3); // calculate tangential velocity copy_v3_v3 ( temp, collpair->normal ); @@ -553,9 +280,9 @@ static int cloth_collision_response_static ( ClothModifierData *clmd, CollisionM normalize_v3(vrel_t_pre); impulse = magtangent / ( 1.0f + w1*w1 + w2*w2 + w3*w3 ); // 2.0 * - VECADDMUL ( cloth1->verts[collpair->ap1].impulse, vrel_t_pre, w1 * impulse ); - VECADDMUL ( cloth1->verts[collpair->ap2].impulse, vrel_t_pre, w2 * impulse ); - VECADDMUL ( cloth1->verts[collpair->ap3].impulse, vrel_t_pre, w3 * impulse ); + VECADDMUL ( i1, vrel_t_pre, w1 * impulse ); + VECADDMUL ( i2, vrel_t_pre, w2 * impulse ); + VECADDMUL ( i3, vrel_t_pre, w3 * impulse ); } // Apply velocity stopping impulse @@ -563,13 +290,13 @@ static int cloth_collision_response_static ( ClothModifierData *clmd, CollisionM // no 2.0 * magrelVel normally, but looks nicer DG impulse = magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3 ); - VECADDMUL ( cloth1->verts[collpair->ap1].impulse, collpair->normal, w1 * impulse ); + VECADDMUL ( i1, collpair->normal, w1 * impulse ); cloth1->verts[collpair->ap1].impulse_count++; - VECADDMUL ( cloth1->verts[collpair->ap2].impulse, collpair->normal, w2 * impulse ); + VECADDMUL ( i2, collpair->normal, w2 * impulse ); cloth1->verts[collpair->ap2].impulse_count++; - VECADDMUL ( cloth1->verts[collpair->ap3].impulse, collpair->normal, w3 * impulse ); + VECADDMUL ( i3, collpair->normal, w3 * impulse ); cloth1->verts[collpair->ap3].impulse_count++; // Apply repulse impulse if distance too short @@ -586,9 +313,25 @@ static int cloth_collision_response_static ( ClothModifierData *clmd, CollisionM repulse = MAX2 ( impulse, repulse ); impulse = repulse / ( 1.0f + w1*w1 + w2*w2 + w3*w3 ); // original 2.0 / 0.25 - VECADDMUL ( cloth1->verts[collpair->ap1].impulse, collpair->normal, impulse ); - VECADDMUL ( cloth1->verts[collpair->ap2].impulse, collpair->normal, impulse ); - VECADDMUL ( cloth1->verts[collpair->ap3].impulse, collpair->normal, impulse ); + VECADDMUL ( i1, collpair->normal, impulse ); + VECADDMUL ( i2, collpair->normal, impulse ); + VECADDMUL ( i3, collpair->normal, impulse ); + } + + { + int i = 0; + + for(i = 0; i < 3; i++) + { + if(cloth1->verts[collpair->ap1].impulse_count > 0 && ABS(cloth1->verts[collpair->ap1].impulse[i]) < ABS(i1[i])) + cloth1->verts[collpair->ap1].impulse[i] = i1[i]; + + if(cloth1->verts[collpair->ap2].impulse_count > 0 && ABS(cloth1->verts[collpair->ap2].impulse[i]) < ABS(i2[i])) + cloth1->verts[collpair->ap2].impulse[i] = i2[i]; + + if(cloth1->verts[collpair->ap3].impulse_count > 0 && ABS(cloth1->verts[collpair->ap3].impulse[i]) < ABS(i3[i])) + cloth1->verts[collpair->ap3].impulse[i] = i3[i]; + } } result = 1; @@ -596,767 +339,6 @@ static int cloth_collision_response_static ( ClothModifierData *clmd, CollisionM } return result; } -#endif /* !WITH_ELTOPO */ - -#ifdef WITH_ELTOPO -typedef struct edgepairkey { - int a1, a2, b1, b2; -} edgepairkey; - -unsigned int edgepair_hash(void *vkey) -{ - edgepairkey *key = vkey; - int keys[4] = {key->a1, key->a2, key->b1, key->b2}; - int i, j; - - for (i=0; i<4; i++) { - for (j=0; j<3; j++) { - if (keys[j] >= keys[j+1]) { - SWAP(int, keys[j], keys[j+1]); - } - } - } - - return keys[0]*101 + keys[1]*72 + keys[2]*53 + keys[3]*34; -} - -int edgepair_cmp(const void *va, const void *vb) -{ - edgepairkey *a = va, *b = vb; - int keysa[4] = {a->a1, a->a2, a->b1, a->b2}; - int keysb[4] = {b->a1, b->a2, b->b1, b->b2}; - int i; - - for (i=0; i<4; i++) { - int j, ok=0; - for (j=0; j<4; j++) { - if (keysa[i] == keysa[j]) { - ok = 1; - break; - } - } - if (!ok) - return -1; - } - - return 0; -} - -static void get_edgepairkey(edgepairkey *key, int a1, int a2, int b1, int b2) -{ - key->a1 = a1; - key->a2 = a2; - key->b1 = b1; - key->b2 = b2; -} - -/*an immense amount of duplication goes on here. . .a major performance hit, I'm sure*/ -static CollPair* cloth_edge_collision ( ModifierData *md1, ModifierData *md2, - BVHTreeOverlap *overlap, CollPair *collpair, - GHash *visithash, MemArena *arena) -{ - ClothModifierData *clmd = (ClothModifierData *)md1; - CollisionModifierData *collmd = (CollisionModifierData *) md2; - MFace *face1=NULL, *face2 = NULL; - ClothVertex *verts1 = clmd->clothObject->verts; - double distance = 0; - edgepairkey *key, tstkey; - float epsilon1 = clmd->coll_parms->epsilon; - float epsilon2 = BLI_bvhtree_getepsilon ( collmd->bvhtree ); - float no[3], uv[3], t, relnor; - int i, i1, i2, i3, i4, i5, i6; - Cloth *cloth = clmd->clothObject; - float n1[3], n2[3], off[3], v1[2][3], v2[2][3], v3[2][3], v4[2][3], v5[2][3], v6[2][3]; - void **verts[] = {v1, v2, v3, v4, v5, v6}; - int j, ret, bp1, bp2, bp3, ap1, ap2, ap3, table[6]; - - face1 = & ( clmd->clothObject->mfaces[overlap->indexA] ); - face2 = & ( collmd->mfaces[overlap->indexB] ); - - // check all 4 possible collisions - for ( i = 0; i < 4; i++ ) { - if ( i == 0 ) { - // fill faceA - ap1 = face1->v1; - ap2 = face1->v2; - ap3 = face1->v3; - - // fill faceB - bp1 = face2->v1; - bp2 = face2->v2; - bp3 = face2->v3; - } - else if ( i == 1 ) { - if ( face1->v4 ) { - // fill faceA - ap1 = face1->v1; - ap2 = face1->v3; - ap3 = face1->v4; - - // fill faceB - bp1 = face2->v1; - bp2 = face2->v2; - bp3 = face2->v3; - } - else { - continue; - } - } - if ( i == 2 ) { - if ( face2->v4 ) { - // fill faceA - ap1 = face1->v1; - ap2 = face1->v2; - ap3 = face1->v3; - - // fill faceB - bp1 = face2->v1; - bp2 = face2->v3; - bp3 = face2->v4; - } - else { - continue; - } - } - else if ( i == 3 ) { - if ( face1->v4 && face2->v4 ) { - // fill faceA - ap1 = face1->v1; - ap2 = face1->v3; - ap3 = face1->v4; - - // fill faceB - bp1 = face2->v1; - bp2 = face2->v3; - bp3 = face2->v4; - } - else { - continue; - } - } - - copy_v3_v3(v1[0], cloth->verts[ap1].txold); - copy_v3_v3(v1[1], cloth->verts[ap1].tx); - copy_v3_v3(v2[0], cloth->verts[ap2].txold); - copy_v3_v3(v2[1], cloth->verts[ap2].tx); - copy_v3_v3(v3[0], cloth->verts[ap3].txold); - copy_v3_v3(v3[1], cloth->verts[ap3].tx); - - copy_v3_v3(v4[0], collmd->current_x[bp1].co); - copy_v3_v3(v4[1], collmd->current_xnew[bp1].co); - copy_v3_v3(v5[0], collmd->current_x[bp2].co); - copy_v3_v3(v5[1], collmd->current_xnew[bp2].co); - copy_v3_v3(v6[0], collmd->current_x[bp3].co); - copy_v3_v3(v6[1], collmd->current_xnew[bp3].co); - - normal_tri_v3(n2, v4[1], v5[1], v6[1]); - - /*offset new positions a bit, to account for margins*/ - i1 = ap1; i2 = ap2; i3 = ap3; - i4 = bp1; i5 = bp2; i6 = bp3; - - for (j=0; j<3; j++) { - int collp1, collp2, k, j2 = (j+1)%3; - - table[0] = ap1; table[1] = ap2; table[2] = ap3; - table[3] = bp1; table[4] = bp2; table[5] = bp3; - for (k=0; k<3; k++) { - float p1[3], p2[3]; - int k2 = (k+1)%3; - - get_edgepairkey(&tstkey, table[j], table[j2], table[k+3], table[k2+3]); - //if (BLI_ghash_haskey(visithash, &tstkey)) - // continue; - - key = BLI_memarena_alloc(arena, sizeof(edgepairkey)); - *key = tstkey; - BLI_ghash_insert(visithash, key, NULL); - - sub_v3_v3v3(p1, verts[j], verts[j2]); - sub_v3_v3v3(p2, verts[k+3], verts[k2+3]); - - cross_v3_v3v3(off, p1, p2); - normalize_v3(off); - - if (dot_v3v3(n2, off) < 0.0) - negate_v3(off); - - mul_v3_fl(off, epsilon1 + epsilon2 + ALMOST_ZERO); - copy_v3_v3(p1, verts[k+3]); - copy_v3_v3(p2, verts[k2+3]); - add_v3_v3(p1, off); - add_v3_v3(p2, off); - - ret = eltopo_line_line_moving_isect_v3v3_f(verts[j], table[j], verts[j2], table[j2], - p1, table[k+3], p2, table[k2+3], - no, uv, &t, &relnor); - /*cloth vert versus coll face*/ - if (ret) { - collpair->ap1 = table[j]; collpair->ap2 = table[j2]; - collpair->bp1 = table[k+3]; collpair->bp2 = table[k2+3]; - - /*I'm not sure if this is correct, but hopefully it's - better then simply ignoring back edges*/ - if (dot_v3v3(n2, no) < 0.0) { - negate_v3(no); - } - - copy_v3_v3(collpair->normal, no); - mul_v3_v3fl(collpair->vector, collpair->normal, relnor); - collpair->distance = relnor; - collpair->time = t; - - copy_v2_v2(collpair->bary, uv); - - collpair->flag = COLLISION_IS_EDGES; - collpair++; - } - } - } - } - - return collpair; -} - -static int cloth_edge_collision_response_moving ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) -{ - int result = 0; - Cloth *cloth1; - float w1, w2; - float v1[3], v2[3], relativeVelocity[3]; - float magrelVel, pimpulse[3]; - - cloth1 = clmd->clothObject; - - for ( ; collpair != collision_end; collpair++ ) { - if (!(collpair->flag & COLLISION_IS_EDGES)) - continue; - - // was: txold - w1 = collpair->bary[0]; w2 = collpair->bary[1]; - - // Calculate relative "velocity". - VECADDFAC(v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, w1); - VECADDFAC(v2, collmd->current_v[collpair->bp1].co, collmd->current_v[collpair->bp2].co, w2); - - sub_v3_v3v3(relativeVelocity, v2, v1); - - // Calculate the normal component of the relative velocity (actually only the magnitude - the direction is stored in 'normal'). - magrelVel = dot_v3v3 ( relativeVelocity, collpair->normal ); - - // 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. - float magtangent = 0, repulse = 0, d = 0; - double impulse = 0.0; - float vrel_t_pre[3]; - float temp[3], spf; - - zero_v3(pimpulse); - - // calculate tangential velocity - copy_v3_v3 ( temp, collpair->normal ); - mul_v3_fl(temp, magrelVel); - sub_v3_v3v3(vrel_t_pre, relativeVelocity, temp); - - // Decrease in magnitude of relative tangential velocity due to coulomb friction - // in original formula "magrelVel" should be the "change of relative velocity in normal direction" - magtangent = MIN2 ( clmd->coll_parms->friction * 0.01 * magrelVel, sqrt ( dot_v3v3 ( vrel_t_pre, vrel_t_pre ) ) ); - - // Apply friction impulse. - if ( magtangent > ALMOST_ZERO ) { - normalize_v3(vrel_t_pre); - - impulse = magtangent; - VECADDMUL ( pimpulse, vrel_t_pre, impulse); - } - - // Apply velocity stopping impulse - // I_c = m * v_N / 2.0 - // no 2.0 * magrelVel normally, but looks nicer DG - impulse = magrelVel; - - mul_v3_fl(collpair->normal, 0.5); - VECADDMUL ( pimpulse, collpair->normal, impulse); - - // Apply repulse impulse if distance too short - // I_r = -min(dt*kd, m(0, 1d/dt - v_n)) - spf = (float)clmd->sim_parms->stepsPerFrame / clmd->sim_parms->timescale; - - d = collpair->distance; - if ( ( magrelVel < 0.1*d*spf && ( d > ALMOST_ZERO ) ) ) { - repulse = MIN2 ( d*1.0/spf, 0.1*d*spf - magrelVel ); - - // stay on the safe side and clamp repulse - if ( impulse > ALMOST_ZERO ) - repulse = MIN2 ( repulse, 5.0*impulse ); - repulse = MAX2 ( impulse, repulse ); - - impulse = repulse / ( 5.0 ); // original 2.0 / 0.25 - VECADDMUL ( pimpulse, collpair->normal, impulse); - } - - w2 = 1.0f-w1; - if (w1 < 0.5) - w1 *= 2.0; - else - w2 *= 2.0; - - VECADDFAC(cloth1->verts[collpair->ap1].impulse, cloth1->verts[collpair->ap1].impulse, pimpulse, w1*2.0); - VECADDFAC(cloth1->verts[collpair->ap2].impulse, cloth1->verts[collpair->ap2].impulse, pimpulse, w2*2.0); - - cloth1->verts[collpair->ap1].impulse_count++; - cloth1->verts[collpair->ap2].impulse_count++; - - result = 1; - } - } - - return result; -} - -static int cloth_collision_response_moving ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) -{ - int result = 0; - Cloth *cloth1; - float w1, w2, w3, u1, u2, u3; - float v1[3], v2[3], relativeVelocity[3]; - float magrelVel; - float epsilon2 = BLI_bvhtree_getepsilon ( collmd->bvhtree ); - - cloth1 = clmd->clothObject; - - for ( ; collpair != collision_end; collpair++ ) { - if (collpair->flag & COLLISION_IS_EDGES) - continue; - - if ( collpair->flag & COLLISION_USE_COLLFACE ) { - // was: txold - w1 = collpair->bary[0]; w2 = collpair->bary[1]; w3 = collpair->bary[2]; - - // Calculate relative "velocity". - collision_interpolateOnTriangle ( v1, collmd->current_v[collpair->bp1].co, collmd->current_v[collpair->bp2].co, collmd->current_v[collpair->bp3].co, w1, w2, w3); - - sub_v3_v3v3(relativeVelocity, v1, cloth1->verts[collpair->collp].tv); - - // Calculate the normal component of the relative velocity (actually only the magnitude - the direction is stored in 'normal'). - magrelVel = dot_v3v3 ( relativeVelocity, collpair->normal ); - - // 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. - float magtangent = 0, repulse = 0, d = 0; - double impulse = 0.0; - float vrel_t_pre[3]; - float temp[3], spf; - - // calculate tangential velocity - copy_v3_v3 ( temp, collpair->normal ); - mul_v3_fl(temp, magrelVel); - sub_v3_v3v3(vrel_t_pre, relativeVelocity, temp); - - // Decrease in magnitude of relative tangential velocity due to coulomb friction - // in original formula "magrelVel" should be the "change of relative velocity in normal direction" - magtangent = MIN2 ( clmd->coll_parms->friction * 0.01 * magrelVel, sqrt ( dot_v3v3 ( vrel_t_pre, vrel_t_pre ) ) ); - - // Apply friction impulse. - if ( magtangent > ALMOST_ZERO ) { - normalize_v3(vrel_t_pre); - - impulse = magtangent; // 2.0 * - VECADDMUL ( cloth1->verts[collpair->collp].impulse, vrel_t_pre, impulse); - } - - // Apply velocity stopping impulse - // I_c = m * v_N / 2.0 - // no 2.0 * magrelVel normally, but looks nicer DG - impulse = magrelVel/2.0; - - VECADDMUL ( cloth1->verts[collpair->collp].impulse, collpair->normal, impulse); - cloth1->verts[collpair->collp].impulse_count++; - - // Apply repulse impulse if distance too short - // I_r = -min(dt*kd, m(0, 1d/dt - v_n)) - spf = (float)clmd->sim_parms->stepsPerFrame / clmd->sim_parms->timescale; - - d = -collpair->distance; - if ( ( magrelVel < 0.1*d*spf ) && ( d > ALMOST_ZERO ) ) { - repulse = MIN2 ( d*1.0/spf, 0.1*d*spf - magrelVel ); - - // stay on the safe side and clamp repulse - if ( impulse > ALMOST_ZERO ) - repulse = MIN2 ( repulse, 5.0*impulse ); - repulse = MAX2 ( impulse, repulse ); - - impulse = repulse / ( 5.0 ); // original 2.0 / 0.25 - VECADDMUL ( cloth1->verts[collpair->collp].impulse, collpair->normal, impulse); - } - - result = 1; - } - } - else { - w1 = collpair->bary[0]; w2 = collpair->bary[1]; w3 = collpair->bary[2]; - - // Calculate relative "velocity". - collision_interpolateOnTriangle ( v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, cloth1->verts[collpair->ap3].tv, w1, w2, w3 ); - - sub_v3_v3v3(relativeVelocity, collmd->current_v[collpair->collp].co, v1); - - // Calculate the normal component of the relative velocity (actually only the magnitude - the direction is stored in 'normal'). - magrelVel = dot_v3v3 ( relativeVelocity, collpair->normal ); - - // 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. - float magtangent = 0, repulse = 0, d = 0; - double impulse = 0.0; - float vrel_t_pre[3], pimpulse[3] = {0.0f, 0.0f, 0.0f}; - float temp[3], spf; - - // calculate tangential velocity - copy_v3_v3 ( temp, collpair->normal ); - mul_v3_fl(temp, magrelVel); - sub_v3_v3v3(vrel_t_pre, relativeVelocity, temp); - - // Decrease in magnitude of relative tangential velocity due to coulomb friction - // in original formula "magrelVel" should be the "change of relative velocity in normal direction" - magtangent = MIN2 ( clmd->coll_parms->friction * 0.01 * magrelVel, sqrt ( dot_v3v3 ( vrel_t_pre, vrel_t_pre ) ) ); - - // Apply friction impulse. - if ( magtangent > ALMOST_ZERO ) { - normalize_v3(vrel_t_pre); - - impulse = magtangent; // 2.0 * - VECADDMUL ( pimpulse, vrel_t_pre, impulse); - } - - // Apply velocity stopping impulse - // I_c = m * v_N / 2.0 - // no 2.0 * magrelVel normally, but looks nicer DG - impulse = magrelVel/2.0; - - VECADDMUL ( pimpulse, collpair->normal, impulse); - - // Apply repulse impulse if distance too short - // I_r = -min(dt*kd, m(0, 1d/dt - v_n)) - spf = (float)clmd->sim_parms->stepsPerFrame / clmd->sim_parms->timescale; - - d = -collpair->distance; - if ( ( magrelVel < 0.1*d*spf ) && ( d > ALMOST_ZERO ) ) { - repulse = MIN2 ( d*1.0/spf, 0.1*d*spf - magrelVel ); - - // stay on the safe side and clamp repulse - if ( impulse > ALMOST_ZERO ) - repulse = MIN2 ( repulse, 5.0*impulse ); - repulse = MAX2 ( impulse, repulse ); - - impulse = repulse / ( 2.0 ); // original 2.0 / 0.25 - VECADDMUL ( pimpulse, collpair->normal, impulse); - } - - if (w1 < 0.5) w1 *= 2.0; - if (w2 < 0.5) w2 *= 2.0; - if (w3 < 0.5) w3 *= 2.0; - - VECADDMUL(cloth1->verts[collpair->ap1].impulse, pimpulse, w1*2.0); - VECADDMUL(cloth1->verts[collpair->ap2].impulse, pimpulse, w2*2.0); - VECADDMUL(cloth1->verts[collpair->ap3].impulse, pimpulse, w3*2.0); - cloth1->verts[collpair->ap1].impulse_count++; - cloth1->verts[collpair->ap2].impulse_count++; - cloth1->verts[collpair->ap3].impulse_count++; - - result = 1; - } - } - } - - return result; -} - - -typedef struct tripairkey { - int p, a1, a2, a3; -} tripairkey; - -unsigned int tripair_hash(void *vkey) -{ - tripairkey *key = vkey; - int keys[4] = {key->p, key->a1, key->a2, key->a3}; - int i, j; - - for (i=0; i<4; i++) { - for (j=0; j<3; j++) { - if (keys[j] >= keys[j+1]) { - SWAP(int, keys[j], keys[j+1]); - } - } - } - - return keys[0]*101 + keys[1]*72 + keys[2]*53 + keys[3]*34; -} - -int tripair_cmp(const void *va, const void *vb) -{ - tripairkey *a = va, *b = vb; - int keysa[4] = {a->p, a->a1, a->a2, a->a3}; - int keysb[4] = {b->p, b->a1, b->a2, b->a3}; - int i; - - for (i=0; i<4; i++) { - int j, ok=0; - for (j=0; j<4; j++) { - if (keysa[i] == keysa[j]) { - ok = 1; - break; - } - } - if (!ok) - return -1; - } - - return 0; -} - -static void get_tripairkey(tripairkey *key, int p, int a1, int a2, int a3) -{ - key->a1 = a1; - key->a2 = a2; - key->a3 = a3; - key->p = p; -} - -static int checkvisit(MemArena *arena, GHash *gh, int p, int a1, int a2, int a3) -{ - tripairkey key, *key2; - - get_tripairkey(&key, p, a1, a2, a3); - if (BLI_ghash_haskey(gh, &key)) - return 1; - - key2 = BLI_memarena_alloc(arena, sizeof(*key2)); - *key2 = key; - BLI_ghash_insert(gh, key2, NULL); - - return 0; -} - -int cloth_point_tri_moving_v3v3_f(float v1[2][3], int i1, float v2[2][3], int i2, - float v3[2][3], int i3, float v4[2][3], int i4, - float normal[3], float bary[3], float *t, - float *relnor, GHash *gh, MemArena *arena) -{ - if (checkvisit(arena, gh, i1, i2, i3, i4)) - return 0; - - return eltopo_point_tri_moving_v3v3_f(v1, i1, v2, i2, v3, i3, v4, i4, normal, bary, t, relnor); -} - -static CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, BVHTreeOverlap *overlap, - CollPair *collpair, double dt, GHash *gh, MemArena *arena) -{ - ClothModifierData *clmd = (ClothModifierData *)md1; - CollisionModifierData *collmd = (CollisionModifierData *) md2; - MFace *face1=NULL, *face2 = NULL; - ClothVertex *verts1 = clmd->clothObject->verts; - double distance = 0; - float epsilon1 = clmd->coll_parms->epsilon; - float epsilon2 = BLI_bvhtree_getepsilon ( collmd->bvhtree ); - float no[3], uv[3], t, relnor; - int i, i1, i2, i3, i4, i5, i6; - Cloth *cloth = clmd->clothObject; - float n1[3], sdis, p[3], l, n2[3], off[3], v1[2][3], v2[2][3], v3[2][3], v4[2][3], v5[2][3], v6[2][3]; - int j, ret, bp1, bp2, bp3, ap1, ap2, ap3; - - face1 = & ( clmd->clothObject->mfaces[overlap->indexA] ); - face2 = & ( collmd->mfaces[overlap->indexB] ); - - // check all 4 possible collisions - for ( i = 0; i < 4; i++ ) { - if ( i == 0 ) { - // fill faceA - ap1 = face1->v1; - ap2 = face1->v2; - ap3 = face1->v3; - - // fill faceB - bp1 = face2->v1; - bp2 = face2->v2; - bp3 = face2->v3; - } - else if ( i == 1 ) { - if ( face1->v4 ) { - // fill faceA - ap1 = face1->v1; - ap2 = face1->v3; - ap3 = face1->v4; - - // fill faceB - bp1 = face2->v1; - bp2 = face2->v2; - bp3 = face2->v3; - } - else { - continue; - } - } - if ( i == 2 ) { - if ( face2->v4 ) { - // fill faceA - ap1 = face1->v1; - ap2 = face1->v2; - ap3 = face1->v3; - - // fill faceB - bp1 = face2->v1; - bp2 = face2->v3; - bp3 = face2->v4; - } - else { - continue; - } - } - else if ( i == 3 ) { - if ( face1->v4 && face2->v4 ) { - // fill faceA - ap1 = face1->v1; - ap2 = face1->v3; - ap3 = face1->v4; - - // fill faceB - bp1 = face2->v1; - bp2 = face2->v3; - bp3 = face2->v4; - } - else { - continue; - } - } - - copy_v3_v3(v1[0], cloth->verts[ap1].txold); - copy_v3_v3(v1[1], cloth->verts[ap1].tx); - copy_v3_v3(v2[0], cloth->verts[ap2].txold); - copy_v3_v3(v2[1], cloth->verts[ap2].tx); - copy_v3_v3(v3[0], cloth->verts[ap3].txold); - copy_v3_v3(v3[1], cloth->verts[ap3].tx); - - copy_v3_v3(v4[0], collmd->current_x[bp1].co); - copy_v3_v3(v4[1], collmd->current_xnew[bp1].co); - copy_v3_v3(v5[0], collmd->current_x[bp2].co); - copy_v3_v3(v5[1], collmd->current_xnew[bp2].co); - copy_v3_v3(v6[0], collmd->current_x[bp3].co); - copy_v3_v3(v6[1], collmd->current_xnew[bp3].co); - - normal_tri_v3(n2, v4[1], v5[1], v6[1]); - - sdis = clmd->coll_parms->distance_repel + epsilon2 + FLT_EPSILON; - - /*apply a repulsion force, to help the solver along*/ - copy_v3_v3(off, n2); - negate_v3(off); - if (isect_ray_plane_v3(v1[1], off, v4[1], v5[1], v6[1], &l, 0)) { - if (l >= 0.0 && l < sdis) { - mul_v3_fl(off, (l-sdis)*cloth->verts[ap1].mass*dt*clmd->coll_parms->repel_force*0.1); - - add_v3_v3(cloth->verts[ap1].tv, off); - add_v3_v3(cloth->verts[ap2].tv, off); - add_v3_v3(cloth->verts[ap3].tv, off); - } - } - - /*offset new positions a bit, to account for margins*/ - copy_v3_v3(off, n2); - mul_v3_fl(off, epsilon1 + epsilon2 + ALMOST_ZERO); - add_v3_v3(v4[1], off); add_v3_v3(v5[1], off); add_v3_v3(v6[1], off); - - i1 = ap1; i2 = ap2; i3 = ap3; - i4 = bp1+cloth->numverts; i5 = bp2+cloth->numverts; i6 = bp3+cloth->numverts; - - for (j=0; j<6; j++) { - int collp; - - switch (j) { - case 0: - ret = cloth_point_tri_moving_v3v3_f(v1, i1, v4, i4, v5, i5, v6, i6, no, uv, &t, &relnor, gh, arena); - collp = ap1; - break; - case 1: - collp = ap2; - ret = cloth_point_tri_moving_v3v3_f(v2, i2, v4, i4, v5, i5, v6, i6, no, uv, &t, &relnor, gh, arena); - break; - case 2: - collp = ap3; - ret = cloth_point_tri_moving_v3v3_f(v3, i3, v4, i4, v5, i5, v6, i6, no, uv, &t, &relnor, gh, arena); - break; - case 3: - collp = bp1; - ret = cloth_point_tri_moving_v3v3_f(v4, i4, v1, i1, v2, i2, v3, i3, no, uv, &t, &relnor, gh, arena); - break; - case 4: - collp = bp2; - ret = cloth_point_tri_moving_v3v3_f(v5, i5, v1, i1, v2, i2, v3, i3, no, uv, &t, &relnor, gh, arena); - break; - case 5: - collp = bp3; - ret = cloth_point_tri_moving_v3v3_f(v6, i6, v1, i1, v2, i2, v3, i3, no, uv, &t, &relnor, gh, arena); - break; - } - - /*cloth vert versus coll face*/ - if (ret && j < 3) { - collpair->bp1 = bp1; collpair->bp2 = bp2; collpair->bp3 = bp3; - collpair->collp = collp; - - copy_v3_v3(collpair->normal, no); - mul_v3_v3fl(collpair->vector, collpair->normal, relnor); - collpair->distance = relnor; - collpair->time = t; - - copy_v3_v3(collpair->bary, uv); - - collpair->flag = COLLISION_USE_COLLFACE; - collpair++; - } - else if (ret && j >= 3) { /*coll vert versus cloth face*/ - collpair->ap1 = ap1; collpair->ap2 = ap2; collpair->ap3 = ap3; - collpair->collp = collp; - - copy_v3_v3(collpair->normal, no); - mul_v3_v3fl(collpair->vector, collpair->normal, relnor); - collpair->distance = relnor; - collpair->time = t; - - copy_v3_v3(collpair->bary, uv); - - collpair->flag = 0; - collpair++; - } - } - } - - return collpair; -} - -static void machine_epsilon_offset(Cloth *cloth) -{ - ClothVertex *cv; - int i, j; - - cv = cloth->verts; - for (i=0; inumverts; i++, cv++) { - /*aggrevatingly enough, it's necessary to offset the coordinates - by a multiple of the 32-bit floating point epsilon when switching - into doubles*/ - #define RNDSIGN (float)(-1*(BLI_rand()%2==0)|1) - for (j=0; j<3; j++) { - cv->tx[j] += FLT_EPSILON*30.0f*RNDSIGN; - cv->txold[j] += FLT_EPSILON*30.0f*RNDSIGN; - cv->tv[j] += FLT_EPSILON*30.0f*RNDSIGN; - } - } -} - -#else /* !WITH_ELTOPO */ //Determines collisions on overlap, collisions are written to collpair[i] and collision+number_collision_found is returned static CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, @@ -1372,7 +354,6 @@ static CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, double distance = 0; float epsilon1 = clmd->coll_parms->epsilon; float epsilon2 = BLI_bvhtree_getepsilon ( collmd->bvhtree ); - float n2[3], sdis, l; int i; face1 = & ( clmd->clothObject->mfaces[overlap->indexA] ); @@ -1395,8 +376,8 @@ static CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, if ( face1->v4 ) { // fill faceA collpair->ap1 = face1->v1; - collpair->ap2 = face1->v4; - collpair->ap3 = face1->v3; + collpair->ap2 = face1->v3; + collpair->ap3 = face1->v4; // fill faceB collpair->bp1 = face2->v1; @@ -1425,39 +406,18 @@ static CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, if ( face1->v4 && face2->v4 ) { // fill faceA collpair->ap1 = face1->v1; - collpair->ap2 = face1->v4; - collpair->ap3 = face1->v3; + collpair->ap2 = face1->v3; + collpair->ap3 = face1->v4; // fill faceB collpair->bp1 = face2->v1; - collpair->bp2 = face2->v4; - collpair->bp3 = face2->v3; + collpair->bp2 = face2->v3; + collpair->bp3 = face2->v4; } else break; } - normal_tri_v3(n2, collmd->current_xnew[collpair->bp1].co, - collmd->current_xnew[collpair->bp2].co, - collmd->current_xnew[collpair->bp3].co); - - sdis = clmd->coll_parms->distance_repel + epsilon2 + FLT_EPSILON; - - /* apply a repulsion force, to help the solver along. - * this is kindof crude, it only tests one vert of the triangle */ - if (isect_ray_plane_v3(cloth->verts[collpair->ap1].tx, n2, collmd->current_xnew[collpair->bp1].co, - collmd->current_xnew[collpair->bp2].co, - collmd->current_xnew[collpair->bp3].co, &l, 0)) - { - if (l >= 0.0f && l < sdis) { - mul_v3_fl(n2, (l-sdis)*cloth->verts[collpair->ap1].mass*dt*clmd->coll_parms->repel_force*0.1f); - - add_v3_v3(cloth->verts[collpair->ap1].tv, n2); - add_v3_v3(cloth->verts[collpair->ap2].tv, n2); - add_v3_v3(cloth->verts[collpair->ap3].tv, n2); - } - } - #ifdef USE_BULLET // calc distance + normal distance = plNearestPoints ( @@ -1512,579 +472,6 @@ static CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, } return collpair; } -#endif /* WITH_ELTOPO */ - - -#if 0 -static int cloth_collision_response_moving( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) -{ - int result = 0; - Cloth *cloth1; - float w1, w2, w3, u1, u2, u3; - float v1[3], v2[3], relativeVelocity[3]; - float magrelVel; - - cloth1 = clmd->clothObject; - - for ( ; collpair != collision_end; collpair++ ) - { - // compute barycentric coordinates for both collision points - collision_compute_barycentric ( collpair->pa, - cloth1->verts[collpair->ap1].txold, - cloth1->verts[collpair->ap2].txold, - cloth1->verts[collpair->ap3].txold, - &w1, &w2, &w3 ); - - // was: txold - collision_compute_barycentric ( collpair->pb, - collmd->current_x[collpair->bp1].co, - collmd->current_x[collpair->bp2].co, - collmd->current_x[collpair->bp3].co, - &u1, &u2, &u3 ); - - // Calculate relative "velocity". - collision_interpolateOnTriangle ( v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, cloth1->verts[collpair->ap3].tv, w1, w2, w3 ); - - collision_interpolateOnTriangle ( v2, collmd->current_v[collpair->bp1].co, collmd->current_v[collpair->bp2].co, collmd->current_v[collpair->bp3].co, u1, u2, u3 ); - - sub_v3_v3v3(relativeVelocity, v2, v1); - - // Calculate the normal component of the relative velocity (actually only the magnitude - the direction is stored in 'normal'). - magrelVel = dot_v3v3 ( relativeVelocity, collpair->normal ); - - // printf("magrelVel: %f\n", magrelVel); - - // Calculate masses of points. - // TODO - - // 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. - float magtangent = 0; - double impulse = 0.0; - float vrel_t_pre[3]; - float temp[3]; - - // calculate tangential velocity - copy_v3_v3 ( temp, collpair->normal ); - mul_v3_fl(temp, magrelVel); - sub_v3_v3v3(vrel_t_pre, relativeVelocity, temp); - - // Decrease in magnitude of relative tangential velocity due to coulomb friction - // in original formula "magrelVel" should be the "change of relative velocity in normal direction" - magtangent = MIN2 ( clmd->coll_parms->friction * 0.01 * magrelVel, sqrt ( dot_v3v3 ( vrel_t_pre, vrel_t_pre ) ) ); - - // Apply friction impulse. - if ( magtangent > ALMOST_ZERO ) - { - normalize_v3(vrel_t_pre); - - impulse = 2.0 * magtangent / ( 1.0 + w1*w1 + w2*w2 + w3*w3 ); - VECADDMUL ( cloth1->verts[collpair->ap1].impulse, vrel_t_pre, w1 * impulse ); - VECADDMUL ( cloth1->verts[collpair->ap2].impulse, vrel_t_pre, w2 * impulse ); - VECADDMUL ( cloth1->verts[collpair->ap3].impulse, vrel_t_pre, w3 * impulse ); - } - - // Apply velocity stopping impulse - // I_c = m * v_N / 2.0 - // no 2.0 * magrelVel normally, but looks nicer DG - impulse = magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3 ); - - 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++; - - // Apply repulse impulse if distance too short - // I_r = -min(dt*kd, m(0, 1d/dt - v_n)) - /* - d = clmd->coll_parms->epsilon*8.0/9.0 + epsilon2*8.0/9.0 - collpair->distance; - if ( ( magrelVel < 0.1*d*clmd->sim_parms->stepsPerFrame ) && ( d > ALMOST_ZERO ) ) - { - repulse = MIN2 ( d*1.0/clmd->sim_parms->stepsPerFrame, 0.1*d*clmd->sim_parms->stepsPerFrame - magrelVel ); - - // stay on the safe side and clamp repulse - if ( impulse > ALMOST_ZERO ) - repulse = MIN2 ( repulse, 5.0*impulse ); - repulse = MAX2 ( impulse, repulse ); - - impulse = repulse / ( 1.0 + w1*w1 + w2*w2 + w3*w3 ); // original 2.0 / 0.25 - VECADDMUL ( cloth1->verts[collpair->ap1].impulse, collpair->normal, impulse ); - VECADDMUL ( cloth1->verts[collpair->ap2].impulse, collpair->normal, impulse ); - VECADDMUL ( cloth1->verts[collpair->ap3].impulse, collpair->normal, impulse ); - } - */ - result = 1; - } - } - return result; -} -#endif - -#if 0 -static float projectPointOntoLine(float *p, float *a, float *b) -{ - float ba[3], pa[3]; - sub_v3_v3v3(ba, b, a); - sub_v3_v3v3(pa, p, a); - return dot_v3v3(pa, ba) / dot_v3v3(ba, ba); -} - -static void calculateEENormal(float *np1, float *np2, float *np3, float *np4, float *out_normal) -{ - float line1[3], line2[3]; - float length; - - sub_v3_v3v3(line1, np2, np1); - sub_v3_v3v3(line2, np3, np1); - - // printf("l1: %f, l1: %f, l2: %f, l2: %f\n", line1[0], line1[1], line2[0], line2[1]); - - cross_v3_v3v3(out_normal, line1, line2); - - - - length = normalize_v3(out_normal); - if (length <= FLT_EPSILON) - { // lines are collinear - sub_v3_v3v3(out_normal, np2, np1); - normalize_v3(out_normal); - } -} - -static void findClosestPointsEE(float *x1, float *x2, float *x3, float *x4, float *w1, float *w2) -{ - float temp[3], temp2[3]; - - double a, b, c, e, f; - - sub_v3_v3v3(temp, x2, x1); - a = dot_v3v3(temp, temp); - - sub_v3_v3v3(temp2, x4, x3); - b = -dot_v3v3(temp, temp2); - - c = dot_v3v3(temp2, temp2); - - sub_v3_v3v3(temp2, x3, x1); - e = dot_v3v3(temp, temp2); - - sub_v3_v3v3(temp, x4, x3); - f = -dot_v3v3(temp, temp2); - - *w1 = (e * c - b * f) / (a * c - b * b); - *w2 = (f - b * *w1) / c; - -} - -// calculates the distance of 2 edges -static float edgedge_distance(float np11[3], float np12[3], float np21[3], float np22[3], float *out_a1, float *out_a2, float *out_normal) -{ - float line1[3], line2[3], cross[3]; - float length; - float temp[3], temp2[3]; - float dist_a1, dist_a2; - - sub_v3_v3v3(line1, np12, np11); - sub_v3_v3v3(line2, np22, np21); - - cross_v3_v3v3(cross, line1, line2); - length = dot_v3v3(cross, cross); - - if (length < FLT_EPSILON) - { - *out_a2 = projectPointOntoLine(np11, np21, np22); - if ((*out_a2 >= -FLT_EPSILON) && (*out_a2 <= 1.0 + FLT_EPSILON)) - { - *out_a1 = 0; - calculateEENormal(np11, np12, np21, np22, out_normal); - sub_v3_v3v3(temp, np22, np21); - mul_v3_fl(temp, *out_a2); - VECADD(temp2, temp, np21); - VECADD(temp2, temp2, np11); - return dot_v3v3(temp2, temp2); - } - - CLAMP(*out_a2, 0.0, 1.0); - if (*out_a2 > .5) - { // == 1.0 - *out_a1 = projectPointOntoLine(np22, np11, np12); - if ((*out_a1 >= -FLT_EPSILON) && (*out_a1 <= 1.0 + FLT_EPSILON)) - { - calculateEENormal(np11, np12, np21, np22, out_normal); - - // return (np22 - (np11 + (np12 - np11) * out_a1)).lengthSquared(); - sub_v3_v3v3(temp, np12, np11); - mul_v3_fl(temp, *out_a1); - VECADD(temp2, temp, np11); - sub_v3_v3v3(temp2, np22, temp2); - return dot_v3v3(temp2, temp2); - } - } - else - { // == 0.0 - *out_a1 = projectPointOntoLine(np21, np11, np12); - if ((*out_a1 >= -FLT_EPSILON) && (*out_a1 <= 1.0 + FLT_EPSILON)) - { - calculateEENormal(np11, np11, np21, np22, out_normal); - - // return (np21 - (np11 + (np12 - np11) * out_a1)).lengthSquared(); - sub_v3_v3v3(temp, np12, np11); - mul_v3_fl(temp, *out_a1); - VECADD(temp2, temp, np11); - sub_v3_v3v3(temp2, np21, temp2); - return dot_v3v3(temp2, temp2); - } - } - - CLAMP(*out_a1, 0.0, 1.0); - calculateEENormal(np11, np12, np21, np22, out_normal); - if (*out_a1 > .5) - { - if (*out_a2 > .5) - { - sub_v3_v3v3(temp, np12, np22); - } - else - { - sub_v3_v3v3(temp, np12, np21); - } - } - else - { - if (*out_a2 > .5) - { - sub_v3_v3v3(temp, np11, np22); - } - else - { - sub_v3_v3v3(temp, np11, np21); - } - } - - return dot_v3v3(temp, temp); - } - else - { - - // If the lines aren't parallel (but coplanar) they have to intersect - - findClosestPointsEE(np11, np12, np21, np22, out_a1, out_a2); - - // If both points are on the finite edges, we're done. - if (*out_a1 >= 0.0 && *out_a1 <= 1.0 && *out_a2 >= 0.0 && *out_a2 <= 1.0) - { - float p1[3], p2[3]; - - // p1= np11 + (np12 - np11) * out_a1; - sub_v3_v3v3(temp, np12, np11); - mul_v3_fl(temp, *out_a1); - VECADD(p1, np11, temp); - - // p2 = np21 + (np22 - np21) * out_a2; - sub_v3_v3v3(temp, np22, np21); - mul_v3_fl(temp, *out_a2); - VECADD(p2, np21, temp); - - calculateEENormal(np11, np12, np21, np22, out_normal); - sub_v3_v3v3(temp, p1, p2); - return dot_v3v3(temp, temp); - } - - - /* - * Clamp both points to the finite edges. - * The one that moves most during clamping is one part of the solution. - */ - dist_a1 = *out_a1; - CLAMP(dist_a1, 0.0, 1.0); - dist_a2 = *out_a2; - CLAMP(dist_a2, 0.0, 1.0); - - // Now project the "most clamped" point on the other line. - if (dist_a1 > dist_a2) - { - /* keep out_a1 */ - float p1[3]; - - // p1 = np11 + (np12 - np11) * out_a1; - sub_v3_v3v3(temp, np12, np11); - mul_v3_fl(temp, *out_a1); - VECADD(p1, np11, temp); - - *out_a2 = projectPointOntoLine(p1, np21, np22); - CLAMP(*out_a2, 0.0, 1.0); - - calculateEENormal(np11, np12, np21, np22, out_normal); - - // return (p1 - (np21 + (np22 - np21) * out_a2)).lengthSquared(); - sub_v3_v3v3(temp, np22, np21); - mul_v3_fl(temp, *out_a2); - VECADD(temp, temp, np21); - sub_v3_v3v3(temp, p1, temp); - return dot_v3v3(temp, temp); - } - else - { - /* keep out_a2 */ - float p2[3]; - - // p2 = np21 + (np22 - np21) * out_a2; - sub_v3_v3v3(temp, np22, np21); - mul_v3_fl(temp, *out_a2); - VECADD(p2, np21, temp); - - *out_a1 = projectPointOntoLine(p2, np11, np12); - CLAMP(*out_a1, 0.0, 1.0); - - calculateEENormal(np11, np12, np21, np22, out_normal); - - // return ((np11 + (np12 - np11) * out_a1) - p2).lengthSquared(); - sub_v3_v3v3(temp, np12, np11); - mul_v3_fl(temp, *out_a1); - VECADD(temp, temp, np11); - sub_v3_v3v3(temp, temp, p2); - return dot_v3v3(temp, temp); - } - } - - printf("Error in edgedge_distance: end of function\n"); - return 0; -} - -static int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair ) -{ - EdgeCollPair edgecollpair; - Cloth *cloth1=NULL; - ClothVertex *verts1=NULL; - unsigned int i = 0, k = 0; - int numsolutions = 0; - double x1[3], v1[3], x2[3], v2[3], x3[3], v3[3]; - double solution[3], solution2[3]; - MVert *verts2 = collmd->current_x; // old x - MVert *velocity2 = collmd->current_v; // velocity - float distance = 0; - float triA[3][3], triB[3][3]; - int result = 0; - - cloth1 = clmd->clothObject; - verts1 = cloth1->verts; - - for (i = 0; i < 9; i++) - { - // 9 edge - edge possibilities - - if (i == 0) // cloth edge: 1-2; coll edge: 1-2 - { - edgecollpair.p11 = collpair->ap1; - edgecollpair.p12 = collpair->ap2; - - edgecollpair.p21 = collpair->bp1; - edgecollpair.p22 = collpair->bp2; - } - else if (i == 1) // cloth edge: 1-2; coll edge: 2-3 - { - edgecollpair.p11 = collpair->ap1; - edgecollpair.p12 = collpair->ap2; - - edgecollpair.p21 = collpair->bp2; - edgecollpair.p22 = collpair->bp3; - } - else if (i == 2) // cloth edge: 1-2; coll edge: 1-3 - { - edgecollpair.p11 = collpair->ap1; - edgecollpair.p12 = collpair->ap2; - - edgecollpair.p21 = collpair->bp1; - edgecollpair.p22 = collpair->bp3; - } - else if (i == 3) // cloth edge: 2-3; coll edge: 1-2 - { - edgecollpair.p11 = collpair->ap2; - edgecollpair.p12 = collpair->ap3; - - edgecollpair.p21 = collpair->bp1; - edgecollpair.p22 = collpair->bp2; - } - else if (i == 4) // cloth edge: 2-3; coll edge: 2-3 - { - edgecollpair.p11 = collpair->ap2; - edgecollpair.p12 = collpair->ap3; - - edgecollpair.p21 = collpair->bp2; - edgecollpair.p22 = collpair->bp3; - } - else if (i == 5) // cloth edge: 2-3; coll edge: 1-3 - { - edgecollpair.p11 = collpair->ap2; - edgecollpair.p12 = collpair->ap3; - - edgecollpair.p21 = collpair->bp1; - edgecollpair.p22 = collpair->bp3; - } - else if (i ==6) // cloth edge: 1-3; coll edge: 1-2 - { - edgecollpair.p11 = collpair->ap1; - edgecollpair.p12 = collpair->ap3; - - edgecollpair.p21 = collpair->bp1; - edgecollpair.p22 = collpair->bp2; - } - else if (i ==7) // cloth edge: 1-3; coll edge: 2-3 - { - edgecollpair.p11 = collpair->ap1; - edgecollpair.p12 = collpair->ap3; - - edgecollpair.p21 = collpair->bp2; - edgecollpair.p22 = collpair->bp3; - } - else if (i == 8) // cloth edge: 1-3; coll edge: 1-3 - { - edgecollpair.p11 = collpair->ap1; - edgecollpair.p12 = collpair->ap3; - - edgecollpair.p21 = collpair->bp1; - edgecollpair.p22 = collpair->bp3; - } - /* - if ((edgecollpair.p11 == 3) && (edgecollpair.p12 == 16)) - printf("Ahier!\n"); - if ((edgecollpair.p11 == 16) && (edgecollpair.p12 == 3)) - printf("Ahier!\n"); - */ - - // if ( !cloth_are_edges_adjacent ( clmd, collmd, &edgecollpair ) ) - { - // always put coll points in p21/p22 - sub_v3_v3v3(x1, verts1[edgecollpair.p12].txold, verts1[edgecollpair.p11].txold); - sub_v3_v3v3(v1, verts1[edgecollpair.p12].tv, verts1[edgecollpair.p11].tv); - - sub_v3_v3v3(x2, verts2[edgecollpair.p21].co, verts1[edgecollpair.p11].txold); - sub_v3_v3v3(v2, velocity2[edgecollpair.p21].co, verts1[edgecollpair.p11].tv); - - sub_v3_v3v3(x3, verts2[edgecollpair.p22].co, verts1[edgecollpair.p11].txold); - sub_v3_v3v3(v3, velocity2[edgecollpair.p22].co, verts1[edgecollpair.p11].tv); - - numsolutions = cloth_get_collision_time ( x1, v1, x2, v2, x3, v3, solution ); - - if ((edgecollpair.p11 == 3 && edgecollpair.p12==16)|| (edgecollpair.p11==16 && edgecollpair.p12==3)) - { - if (edgecollpair.p21==6 || edgecollpair.p22 == 6) - { - printf("dist: %f, sol[k]: %f, sol2[k]: %f\n", distance, solution[k], solution2[k]); - printf("a1: %f, a2: %f, b1: %f, b2: %f\n", x1[0], x2[0], x3[0], v1[0]); - printf("b21: %d, b22: %d\n", edgecollpair.p21, edgecollpair.p22); - } - } - - for ( k = 0; k < numsolutions; k++ ) - { - // printf("sol %d: %lf\n", k, solution[k]); - if ( ( solution[k] >= ALMOST_ZERO ) && ( solution[k] <= 1.0 ) && ( solution[k] > ALMOST_ZERO)) - { - float a, b; - float out_normal[3]; - float distance; - float impulse = 0; - float I_mag; - - // move verts - VECADDS(triA[0], verts1[edgecollpair.p11].txold, verts1[edgecollpair.p11].tv, solution[k]); - VECADDS(triA[1], verts1[edgecollpair.p12].txold, verts1[edgecollpair.p12].tv, solution[k]); - - VECADDS(triB[0], collmd->current_x[edgecollpair.p21].co, collmd->current_v[edgecollpair.p21].co, solution[k]); - VECADDS(triB[1], collmd->current_x[edgecollpair.p22].co, collmd->current_v[edgecollpair.p22].co, solution[k]); - - // TODO: check for collisions - distance = edgedge_distance(triA[0], triA[1], triB[0], triB[1], &a, &b, out_normal); - - if ((distance <= clmd->coll_parms->epsilon + BLI_bvhtree_getepsilon ( collmd->bvhtree ) + ALMOST_ZERO) && (dot_v3v3(out_normal, out_normal) > 0)) - { - float vrel_1_to_2[3], temp[3], temp2[3], out_normalVelocity; - float desiredVn; - - copy_v3_v3(vrel_1_to_2, verts1[edgecollpair.p11].tv); - mul_v3_fl(vrel_1_to_2, 1.0 - a); - copy_v3_v3(temp, verts1[edgecollpair.p12].tv); - mul_v3_fl(temp, a); - - VECADD(vrel_1_to_2, vrel_1_to_2, temp); - - copy_v3_v3(temp, verts1[edgecollpair.p21].tv); - mul_v3_fl(temp, 1.0 - b); - copy_v3_v3(temp2, verts1[edgecollpair.p22].tv); - mul_v3_fl(temp2, b); - VECADD(temp, temp, temp2); - - sub_v3_v3v3(vrel_1_to_2, vrel_1_to_2, temp); - - out_normalVelocity = dot_v3v3(vrel_1_to_2, out_normal); -/* - // this correction results in wrong normals sometimes? - if (out_normalVelocity < 0.0) - { - out_normalVelocity*= -1.0; - negate_v3(out_normal); - } -*/ - /* Inelastic repulsion impulse. */ - - // Calculate which normal velocity we need. - desiredVn = (out_normalVelocity * (float)solution[k] - (.1 * (clmd->coll_parms->epsilon + BLI_bvhtree_getepsilon ( collmd->bvhtree )) - sqrt(distance)) - ALMOST_ZERO); - - // Now calculate what impulse we need to reach that velocity. - I_mag = (out_normalVelocity - desiredVn) / 2.0; // / (1/m1 + 1/m2); - - // Finally apply that impulse. - impulse = (2.0 * -I_mag) / (a*a + (1.0-a)*(1.0-a) + b*b + (1.0-b)*(1.0-b)); - - VECADDMUL ( verts1[edgecollpair.p11].impulse, out_normal, (1.0-a) * impulse ); - verts1[edgecollpair.p11].impulse_count++; - - VECADDMUL ( verts1[edgecollpair.p12].impulse, out_normal, a * impulse ); - verts1[edgecollpair.p12].impulse_count++; - - // return true; - result = 1; - break; - } - else - { - // missing from collision.hpp - } - // mintime = MIN2(mintime, (float)solution[k]); - - break; - } - } - } - } - return result; -} - -static int cloth_collision_moving ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) -{ - Cloth *cloth1; - cloth1 = clmd->clothObject; - - for ( ; collpair != collision_end; collpair++ ) - { - // only handle moving collisions here - if (!( collpair->flag & COLLISION_IN_FUTURE )) - continue; - - cloth_collision_moving_edges ( clmd, collmd, collpair); - // cloth_collision_moving_tris ( clmd, collmd, collpair); - } - - return 1; -} -#endif static void add_collision_object(Object ***objs, unsigned int *numobj, unsigned int *maxobj, Object *ob, Object *self, int level, unsigned int modifier_type) { @@ -2224,37 +611,14 @@ static void cloth_bvh_objcollisions_nearcheck ( ClothModifierData * clmd, Collis CollPair **collisions, CollPair **collisions_index, int numresult, BVHTreeOverlap *overlap, double dt) { int i; -#ifdef WITH_ELTOPO - GHash *visithash = BLI_ghash_new(edgepair_hash, edgepair_cmp, "visthash, collision.c"); - GHash *tri_visithash = BLI_ghash_new(tripair_hash, tripair_cmp, "tri_visthash, collision.c"); - MemArena *arena = BLI_memarena_new(1<<16, "edge hash arena, collision.c"); -#endif *collisions = ( CollPair* ) MEM_mallocN ( sizeof ( CollPair ) * numresult * 64, "collision array" ); //*4 since cloth_collision_static can return more than 1 collision *collisions_index = *collisions; - -#ifdef WITH_ELTOPO - machine_epsilon_offset(clmd->clothObject); - for ( i = 0; i < numresult; i++ ) { - *collisions_index = cloth_collision ( (ModifierData *)clmd, (ModifierData *)collmd, - overlap+i, *collisions_index, dt, tri_visithash, arena ); - } - - for ( i = 0; i < numresult; i++ ) { - *collisions_index = cloth_edge_collision ( (ModifierData *)clmd, (ModifierData *)collmd, - overlap+i, *collisions_index, visithash, arena ); - } - BLI_ghash_free(visithash, NULL, NULL); - BLI_ghash_free(tri_visithash, NULL, NULL); - BLI_memarena_free(arena); -#else /* WITH_ELTOPO */ for ( i = 0; i < numresult; i++ ) { *collisions_index = cloth_collision ( (ModifierData *)clmd, (ModifierData *)collmd, overlap+i, *collisions_index, dt ); } -#endif /* WITH_ELTOPO */ - } static int cloth_bvh_objcollisions_resolve ( ClothModifierData * clmd, CollisionModifierData *collmd, CollPair *collisions, CollPair *collisions_index) @@ -2264,36 +628,26 @@ static int cloth_bvh_objcollisions_resolve ( ClothModifierData * clmd, Collision ClothVertex *verts = NULL; int ret = 0; int result = 0; - float tnull[3] = {0, 0, 0}; - /*numfaces = clmd->clothObject->numfaces;*/ /*UNUSED*/ numverts = clmd->clothObject->numverts; - verts = cloth->verts; // process all collisions (calculate impulses, TODO: also repulses if distance too short) result = 1; - for ( j = 0; j < 5; j++ ) { /* 5 is just a value that ensures convergence */ + for ( j = 0; j < 2; j++ ) { /* 5 is just a value that ensures convergence */ result = 0; if ( collmd->bvhtree ) { -#ifdef WITH_ELTOPO - result += cloth_collision_response_moving(clmd, collmd, collisions, collisions_index); - result += cloth_edge_collision_response_moving(clmd, collmd, collisions, collisions_index); -#else result += cloth_collision_response_static ( clmd, collmd, collisions, collisions_index ); -#endif -#ifdef WITH_ELTOPO - { -#else + // apply impulses in parallel if (result) { -#endif 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 ); - copy_v3_v3 ( verts[i].impulse, tnull ); + // VECADDMUL ( verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count ); + VECADD ( verts[i].tv, verts[i].tv, verts[i].impulse); + zero_v3(verts[i].impulse); verts[i].impulse_count = 0; ret++; @@ -2301,6 +655,9 @@ static int cloth_bvh_objcollisions_resolve ( ClothModifierData * clmd, Collision } } } + + if(!result) + break; } return ret; } @@ -2337,6 +694,18 @@ int cloth_bvh_objcollision(Object *ob, ClothModifierData * clmd, float step, flo if (!collobjs) return 0; + /* move object to position (step) in time */ + for (i = 0; i < numcollobj; i++) { + Object *collob= collobjs[i]; + CollisionModifierData *collmd = (CollisionModifierData*)modifiers_findByType(collob, eModifierType_Collision); + + if (!collmd->bvhtree) + continue; + + /* move object to position (step) in time */ + collision_move_object ( collmd, step + dt, step ); + } + do { CollPair **collisions, **collisions_index; @@ -2356,10 +725,6 @@ int cloth_bvh_objcollision(Object *ob, ClothModifierData * clmd, float step, flo if (!collmd->bvhtree) continue; - /* move object to position (step) in time */ - - collision_move_object ( collmd, step + dt, step ); - /* search for overlapping collision pairs */ overlap = BLI_bvhtree_overlap ( cloth_bvh, collmd->bvhtree, &result ); diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c index 2c38bc42a8f..72e5d792e1f 100644 --- a/source/blender/modifiers/intern/MOD_cloth.c +++ b/source/blender/modifiers/intern/MOD_cloth.c @@ -67,10 +67,10 @@ static void initData(ModifierData *md) cloth_init(clmd); } -static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], - int UNUSED(numVerts), ModifierApplyFlag UNUSED(flag)) +static DerivedMesh *applyModifier(ModifierData *md, Object *ob, + DerivedMesh *dm, + ModifierApplyFlag UNUSED(flag)) { - DerivedMesh *dm; ClothModifierData *clmd = (ClothModifierData *) md; DerivedMesh *result = NULL; @@ -79,25 +79,20 @@ static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, initData(md); if (!clmd->sim_parms || !clmd->coll_parms) - return; + return dm; } - dm = get_dm(ob, NULL, derivedData, NULL, 0); - if (dm == derivedData) - dm = CDDM_copy(dm); - - CDDM_apply_vert_coords(dm, vertexCos); - DM_ensure_tessface(dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */ - clothModifier_do(clmd, md->scene, ob, dm, vertexCos); + result = clothModifier_do(clmd, md->scene, ob, dm); - if (result) { - result->getVertCos(result, vertexCos); - result->release(result); + if(result) + { + CDDM_calc_normals(result); + return result; } - dm->release(dm); + return dm; } static void updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene, Object *ob, DagNode *obNode) @@ -205,17 +200,17 @@ ModifierTypeInfo modifierType_Cloth = { /* name */ "Cloth", /* structName */ "ClothModifierData", /* structSize */ sizeof(ClothModifierData), - /* type */ eModifierTypeType_OnlyDeform, + /* type */ eModifierTypeType_Constructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_UsesPointCache | eModifierTypeFlag_Single, /* copyData */ copyData, - /* deformVerts */ deformVerts, + /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* applyModifier */ applyModifier, /* applyModifierEM */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask,