diff options
Diffstat (limited to 'source/blender/blenkernel/intern/collision.c')
-rw-r--r-- | source/blender/blenkernel/intern/collision.c | 301 |
1 files changed, 121 insertions, 180 deletions
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index f358355912b..05c521e3b94 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -647,6 +647,31 @@ DO_INLINE void collision_interpolateOnTriangle(float to[3], VECADDMUL(to, v3, w3); } +static void cloth_selfcollision_impulse_vert(const float clamp_sq, + const float impulse[3], + struct ClothVertex *vert) +{ + float impulse_len_sq = len_squared_v3(impulse); + + if ((clamp_sq > 0.0f) && (impulse_len_sq > clamp_sq)) { + return; + } + + if (fabsf(vert->impulse[0]) < fabsf(impulse[0])) { + vert->impulse[0] = impulse[0]; + } + + if (fabsf(vert->impulse[1]) < fabsf(impulse[1])) { + vert->impulse[1] = impulse[1]; + } + + if (fabsf(vert->impulse[2]) < fabsf(impulse[2])) { + vert->impulse[2] = impulse[2]; + } + + vert->impulse_count++; +} + static int cloth_collision_response_static(ClothModifierData *clmd, CollisionModifierData *collmd, Object *collob, @@ -655,18 +680,17 @@ static int cloth_collision_response_static(ClothModifierData *clmd, const float dt) { 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_get_epsilon(collmd->bvhtree); - const bool is_hair = (clmd->hairdata != NULL); - - cloth1 = clmd->clothObject; + Cloth *cloth = clmd->clothObject; + const float clamp_sq = square_f(clmd->coll_parms->self_clamp * dt); + const float time_multiplier = 1.0f / (clmd->sim_parms->dt * clmd->sim_parms->timescale); + const float epsilon2 = BLI_bvhtree_get_epsilon(collmd->bvhtree); + const float min_distance = (clmd->coll_parms->epsilon + epsilon2) * (8.0f / 9.0f); + const bool is_hair = (clmd->hairdata != NULL); for (int i = 0; i < collision_count; i++, collpair++) { float i1[3], i2[3], i3[3]; - + float w1, w2, w3, u1, u2, u3; + float v1[3], v2[3], relativeVelocity[3]; zero_v3(i1); zero_v3(i2); zero_v3(i3); @@ -679,25 +703,25 @@ static int cloth_collision_response_static(ClothModifierData *clmd, /* Compute barycentric coordinates and relative "velocity" for both collision points. */ if (is_hair) { w2 = line_point_factor_v3( - collpair->pa, cloth1->verts[collpair->ap1].tx, cloth1->verts[collpair->ap2].tx); + collpair->pa, cloth->verts[collpair->ap1].tx, cloth->verts[collpair->ap2].tx); w1 = 1.0f - w2; - interp_v3_v3v3(v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, w2); + interp_v3_v3v3(v1, cloth->verts[collpair->ap1].tv, cloth->verts[collpair->ap2].tv, w2); } else { collision_compute_barycentric(collpair->pa, - cloth1->verts[collpair->ap1].tx, - cloth1->verts[collpair->ap2].tx, - cloth1->verts[collpair->ap3].tx, + cloth->verts[collpair->ap1].tx, + cloth->verts[collpair->ap2].tx, + cloth->verts[collpair->ap3].tx, &w1, &w2, &w3); collision_interpolateOnTriangle(v1, - cloth1->verts[collpair->ap1].tv, - cloth1->verts[collpair->ap2].tv, - cloth1->verts[collpair->ap3].tv, + cloth->verts[collpair->ap1].tv, + cloth->verts[collpair->ap2].tv, + cloth->verts[collpair->ap3].tv, w1, w2, w3); @@ -723,16 +747,16 @@ static int cloth_collision_response_static(ClothModifierData *clmd, /* Calculate the normal component of the relative velocity * (actually only the magnitude - the direction is stored in 'normal'). */ - magrelVel = dot_v3v3(relativeVelocity, collpair->normal); + const float magrelVel = dot_v3v3(relativeVelocity, collpair->normal); + const float d = min_distance - collpair->distance; /* If magrelVel < 0 the edges are approaching each other. */ if (magrelVel > 0.0f) { /* Calculate Impulse magnitude to stop all motion in normal direction. */ - float magtangent = 0, repulse = 0, d = 0; + float magtangent = 0, repulse = 0; double impulse = 0.0; float vrel_t_pre[3]; float temp[3]; - float time_multiplier; /* Calculate tangential velocity. */ copy_v3_v3(temp, collpair->normal); @@ -750,32 +774,23 @@ static int cloth_collision_response_static(ClothModifierData *clmd, impulse = magtangent / 1.5; - VECADDMUL(i1, vrel_t_pre, w1 * impulse); - VECADDMUL(i2, vrel_t_pre, w2 * impulse); + VECADDMUL(i1, vrel_t_pre, (double)w1 * impulse); + VECADDMUL(i2, vrel_t_pre, (double)w2 * impulse); if (!is_hair) { - VECADDMUL(i3, vrel_t_pre, w3 * impulse); + VECADDMUL(i3, vrel_t_pre, (double)w3 * impulse); } } /* Apply velocity stopping impulse. */ impulse = magrelVel / 1.5f; - VECADDMUL(i1, collpair->normal, w1 * impulse); - cloth1->verts[collpair->ap1].impulse_count++; - - VECADDMUL(i2, collpair->normal, w2 * impulse); - cloth1->verts[collpair->ap2].impulse_count++; - + VECADDMUL(i1, collpair->normal, (double)w1 * impulse); + VECADDMUL(i2, collpair->normal, (double)w2 * impulse); if (!is_hair) { - VECADDMUL(i3, collpair->normal, w3 * impulse); - cloth1->verts[collpair->ap3].impulse_count++; + VECADDMUL(i3, collpair->normal, (double)w3 * impulse); } - time_multiplier = 1.0f / (clmd->sim_parms->dt * clmd->sim_parms->timescale); - - d = clmd->coll_parms->epsilon * 8.0f / 9.0f + epsilon2 * 8.0f / 9.0f - collpair->distance; - if ((magrelVel < 0.1f * d * time_multiplier) && (d > ALMOST_ZERO)) { repulse = MIN2(d / time_multiplier, 0.1f * d * time_multiplier - magrelVel); @@ -790,7 +805,6 @@ static int cloth_collision_response_static(ClothModifierData *clmd, VECADDMUL(i1, collpair->normal, impulse); VECADDMUL(i2, collpair->normal, impulse); - if (!is_hair) { VECADDMUL(i3, collpair->normal, impulse); } @@ -798,60 +812,26 @@ static int cloth_collision_response_static(ClothModifierData *clmd, result = 1; } - else { - float time_multiplier = 1.0f / (clmd->sim_parms->dt * clmd->sim_parms->timescale); - float d; - - d = clmd->coll_parms->epsilon * 8.0f / 9.0f + epsilon2 * 8.0f / 9.0f - collpair->distance; - - if (d > ALMOST_ZERO) { - /* Stay on the safe side and clamp repulse. */ - float repulse = d / time_multiplier; - float impulse = repulse / 4.5f; - - VECADDMUL(i1, collpair->normal, w1 * impulse); - VECADDMUL(i2, collpair->normal, w2 * impulse); + else if (d > ALMOST_ZERO) { + /* Stay on the safe side and clamp repulse. */ + float repulse = d / time_multiplier; + float impulse = repulse / 4.5f; - if (!is_hair) { - VECADDMUL(i3, collpair->normal, w3 * impulse); - } - - cloth1->verts[collpair->ap1].impulse_count++; - cloth1->verts[collpair->ap2].impulse_count++; - - if (!is_hair) { - cloth1->verts[collpair->ap3].impulse_count++; - } + VECADDMUL(i1, collpair->normal, w1 * impulse); + VECADDMUL(i2, collpair->normal, w2 * impulse); - result = 1; + if (!is_hair) { + VECADDMUL(i3, collpair->normal, w3 * impulse); } + + result = 1; } if (result) { - float clamp = clmd->coll_parms->clamp * dt; - - if ((clamp > 0.0f) && - ((len_v3(i1) > clamp) || (len_v3(i2) > clamp) || (len_v3(i3) > clamp))) { - return 0; - } - - for (int j = 0; j < 3; j++) { - if (cloth1->verts[collpair->ap1].impulse_count > 0 && - fabsf(cloth1->verts[collpair->ap1].impulse[j]) < fabsf(i1[j])) { - cloth1->verts[collpair->ap1].impulse[j] = i1[j]; - } - - if (cloth1->verts[collpair->ap2].impulse_count > 0 && - fabsf(cloth1->verts[collpair->ap2].impulse[j]) < fabsf(i2[j])) { - cloth1->verts[collpair->ap2].impulse[j] = i2[j]; - } - - if (!is_hair) { - if (cloth1->verts[collpair->ap3].impulse_count > 0 && - fabsf(cloth1->verts[collpair->ap3].impulse[j]) < fabsf(i3[j])) { - cloth1->verts[collpair->ap3].impulse[j] = i3[j]; - } - } + cloth_selfcollision_impulse_vert(clamp_sq, i1, &cloth->verts[collpair->ap1]); + cloth_selfcollision_impulse_vert(clamp_sq, i2, &cloth->verts[collpair->ap2]); + if (!is_hair) { + cloth_selfcollision_impulse_vert(clamp_sq, i3, &cloth->verts[collpair->ap3]); } } } @@ -859,47 +839,22 @@ static int cloth_collision_response_static(ClothModifierData *clmd, return result; } -static void cloth_selfcollision_impulse_vert(const float clamp_sq, - const float impulse[3], - struct ClothVertex *vert) -{ - float impulse_len_sq = len_squared_v3(impulse); - - if ((clamp_sq > 0.0f) && (impulse_len_sq > clamp_sq)) { - return; - } - - if (fabsf(vert->impulse[0]) < fabsf(impulse[0])) { - vert->impulse[0] = impulse[0]; - } - - if (fabsf(vert->impulse[1]) < fabsf(impulse[1])) { - vert->impulse[1] = impulse[1]; - } - - if (fabsf(vert->impulse[2]) < fabsf(impulse[2])) { - vert->impulse[2] = impulse[2]; - } - - vert->impulse_count++; -} - static int cloth_selfcollision_response_static(ClothModifierData *clmd, CollPair *collpair, uint collision_count, const float dt) { int result = 0; - Cloth *cloth1; - float w1, w2, w3, u1, u2, u3; - float v1[3], v2[3], relativeVelocity[3]; - float magrelVel; - - cloth1 = clmd->clothObject; + Cloth *cloth = clmd->clothObject; + const float clamp_sq = square_f(clmd->coll_parms->self_clamp * dt); + const float time_multiplier = 1.0f / (clmd->sim_parms->dt * clmd->sim_parms->timescale); + const float min_distance = (2.0f * clmd->coll_parms->selfepsilon) * (8.0f / 9.0f); for (int i = 0; i < collision_count; i++, collpair++) { float ia[3][3] = {{0.0f}}; float ib[3][3] = {{0.0f}}; + float w1, w2, w3, u1, u2, u3; + float v1[3], v2[3], relativeVelocity[3]; /* Only handle static collisions here. */ if (collpair->flag & (COLLISION_IN_FUTURE | COLLISION_INACTIVE)) { @@ -908,34 +863,34 @@ static int cloth_selfcollision_response_static(ClothModifierData *clmd, /* Compute barycentric coordinates for both collision points. */ collision_compute_barycentric(collpair->pa, - cloth1->verts[collpair->ap1].tx, - cloth1->verts[collpair->ap2].tx, - cloth1->verts[collpair->ap3].tx, + cloth->verts[collpair->ap1].tx, + cloth->verts[collpair->ap2].tx, + cloth->verts[collpair->ap3].tx, &w1, &w2, &w3); collision_compute_barycentric(collpair->pb, - cloth1->verts[collpair->bp1].tx, - cloth1->verts[collpair->bp2].tx, - cloth1->verts[collpair->bp3].tx, + cloth->verts[collpair->bp1].tx, + cloth->verts[collpair->bp2].tx, + cloth->verts[collpair->bp3].tx, &u1, &u2, &u3); /* Calculate relative "velocity". */ collision_interpolateOnTriangle(v1, - cloth1->verts[collpair->ap1].tv, - cloth1->verts[collpair->ap2].tv, - cloth1->verts[collpair->ap3].tv, + cloth->verts[collpair->ap1].tv, + cloth->verts[collpair->ap2].tv, + cloth->verts[collpair->ap3].tv, w1, w2, w3); collision_interpolateOnTriangle(v2, - cloth1->verts[collpair->bp1].tv, - cloth1->verts[collpair->bp2].tv, - cloth1->verts[collpair->bp3].tv, + cloth->verts[collpair->bp1].tv, + cloth->verts[collpair->bp2].tv, + cloth->verts[collpair->bp3].tv, u1, u2, u3); @@ -944,7 +899,8 @@ static int cloth_selfcollision_response_static(ClothModifierData *clmd, /* Calculate the normal component of the relative velocity * (actually only the magnitude - the direction is stored in 'normal'). */ - magrelVel = dot_v3v3(relativeVelocity, collpair->normal); + const float magrelVel = dot_v3v3(relativeVelocity, collpair->normal); + const float d = min_distance - collpair->distance; /* TODO: Impulses should be weighed by mass as this is self col, * this has to be done after mass distribution is implemented. */ @@ -952,10 +908,10 @@ static int cloth_selfcollision_response_static(ClothModifierData *clmd, /* If magrelVel < 0 the edges are approaching each other. */ if (magrelVel > 0.0f) { /* Calculate Impulse magnitude to stop all motion in normal direction. */ - float magtangent = 0, repulse = 0, d = 0; + float magtangent = 0, repulse = 0; double impulse = 0.0; float vrel_t_pre[3]; - float temp[3], time_multiplier; + float temp[3]; /* Calculate tangential velocity. */ copy_v3_v3(temp, collpair->normal); @@ -973,29 +929,25 @@ static int cloth_selfcollision_response_static(ClothModifierData *clmd, impulse = magtangent / 1.5; - VECADDMUL(ia[0], vrel_t_pre, w1 * impulse); - VECADDMUL(ia[1], vrel_t_pre, w2 * impulse); - VECADDMUL(ia[2], vrel_t_pre, w3 * impulse); + VECADDMUL(ia[0], vrel_t_pre, (double)w1 * impulse); + VECADDMUL(ia[1], vrel_t_pre, (double)w2 * impulse); + VECADDMUL(ia[2], vrel_t_pre, (double)w3 * impulse); - VECADDMUL(ib[0], vrel_t_pre, -u1 * impulse); - VECADDMUL(ib[1], vrel_t_pre, -u2 * impulse); - VECADDMUL(ib[2], vrel_t_pre, -u3 * impulse); + VECADDMUL(ib[0], vrel_t_pre, (double)u1 * -impulse); + VECADDMUL(ib[1], vrel_t_pre, (double)u2 * -impulse); + VECADDMUL(ib[2], vrel_t_pre, (double)u3 * -impulse); } /* Apply velocity stopping impulse. */ impulse = magrelVel / 3.0f; - VECADDMUL(ia[0], collpair->normal, w1 * impulse); - VECADDMUL(ia[1], collpair->normal, w2 * impulse); - VECADDMUL(ia[2], collpair->normal, w3 * impulse); - - VECADDMUL(ib[0], collpair->normal, -u1 * impulse); - VECADDMUL(ib[1], collpair->normal, -u2 * impulse); - VECADDMUL(ib[2], collpair->normal, -u3 * impulse); + VECADDMUL(ia[0], collpair->normal, (double)w1 * impulse); + VECADDMUL(ia[1], collpair->normal, (double)w2 * impulse); + VECADDMUL(ia[2], collpair->normal, (double)w3 * impulse); - time_multiplier = 1.0f / (clmd->sim_parms->dt * clmd->sim_parms->timescale); - - d = clmd->coll_parms->selfepsilon * 8.0f / 9.0f * 2.0f - collpair->distance; + VECADDMUL(ib[0], collpair->normal, (double)u1 * -impulse); + VECADDMUL(ib[1], collpair->normal, (double)u2 * -impulse); + VECADDMUL(ib[2], collpair->normal, (double)u3 * -impulse); if ((magrelVel < 0.1f * d * time_multiplier) && (d > ALMOST_ZERO)) { repulse = MIN2(d / time_multiplier, 0.1f * d * time_multiplier - magrelVel); @@ -1005,54 +957,43 @@ static int cloth_selfcollision_response_static(ClothModifierData *clmd, } repulse = max_ff(impulse, repulse); - impulse = repulse / 1.5f; - VECADDMUL(ia[0], collpair->normal, w1 * impulse); - VECADDMUL(ia[1], collpair->normal, w2 * impulse); - VECADDMUL(ia[2], collpair->normal, w3 * impulse); + VECADDMUL(ia[0], collpair->normal, (double)w1 * impulse); + VECADDMUL(ia[1], collpair->normal, (double)w2 * impulse); + VECADDMUL(ia[2], collpair->normal, (double)w3 * impulse); - VECADDMUL(ib[0], collpair->normal, -u1 * impulse); - VECADDMUL(ib[1], collpair->normal, -u2 * impulse); - VECADDMUL(ib[2], collpair->normal, -u3 * impulse); + VECADDMUL(ib[0], collpair->normal, (double)u1 * -impulse); + VECADDMUL(ib[1], collpair->normal, (double)u2 * -impulse); + VECADDMUL(ib[2], collpair->normal, (double)u3 * -impulse); } result = 1; } - else { - float time_multiplier = 1.0f / (clmd->sim_parms->dt * clmd->sim_parms->timescale); - float d; - - d = clmd->coll_parms->selfepsilon * 8.0f / 9.0f * 2.0f - collpair->distance; - - if (d > ALMOST_ZERO) { - /* Stay on the safe side and clamp repulse. */ - float repulse = d * 1.0f / time_multiplier; - float impulse = repulse / 9.0f; + else if (d > ALMOST_ZERO) { + /* Stay on the safe side and clamp repulse. */ + float repulse = d * 1.0f / time_multiplier; + float impulse = repulse / 9.0f; - VECADDMUL(ia[0], collpair->normal, w1 * impulse); - VECADDMUL(ia[1], collpair->normal, w2 * impulse); - VECADDMUL(ia[2], collpair->normal, w3 * impulse); + VECADDMUL(ia[0], collpair->normal, w1 * impulse); + VECADDMUL(ia[1], collpair->normal, w2 * impulse); + VECADDMUL(ia[2], collpair->normal, w3 * impulse); - VECADDMUL(ib[0], collpair->normal, -u1 * impulse); - VECADDMUL(ib[1], collpair->normal, -u2 * impulse); - VECADDMUL(ib[2], collpair->normal, -u3 * impulse); + VECADDMUL(ib[0], collpair->normal, u1 * -impulse); + VECADDMUL(ib[1], collpair->normal, u2 * -impulse); + VECADDMUL(ib[2], collpair->normal, u3 * -impulse); - result = 1; - } + result = 1; } if (result) { - float clamp_sq = clmd->coll_parms->self_clamp * dt; - clamp_sq *= clamp_sq; - - cloth_selfcollision_impulse_vert(clamp_sq, ia[0], &cloth1->verts[collpair->ap1]); - cloth_selfcollision_impulse_vert(clamp_sq, ia[1], &cloth1->verts[collpair->ap2]); - cloth_selfcollision_impulse_vert(clamp_sq, ia[2], &cloth1->verts[collpair->ap3]); + cloth_selfcollision_impulse_vert(clamp_sq, ia[0], &cloth->verts[collpair->ap1]); + cloth_selfcollision_impulse_vert(clamp_sq, ia[1], &cloth->verts[collpair->ap2]); + cloth_selfcollision_impulse_vert(clamp_sq, ia[2], &cloth->verts[collpair->ap3]); - cloth_selfcollision_impulse_vert(clamp_sq, ib[0], &cloth1->verts[collpair->bp1]); - cloth_selfcollision_impulse_vert(clamp_sq, ib[1], &cloth1->verts[collpair->bp2]); - cloth_selfcollision_impulse_vert(clamp_sq, ib[2], &cloth1->verts[collpair->bp3]); + cloth_selfcollision_impulse_vert(clamp_sq, ib[0], &cloth->verts[collpair->bp1]); + cloth_selfcollision_impulse_vert(clamp_sq, ib[1], &cloth->verts[collpair->bp2]); + cloth_selfcollision_impulse_vert(clamp_sq, ib[2], &cloth->verts[collpair->bp3]); } } |