From 0666ece2e2f96571200d693d9d7bee1ca72d026f Mon Sep 17 00:00:00 2001 From: Luca Rood Date: Wed, 26 Sep 2018 17:18:16 +0200 Subject: Cloth: Collision improvements This commit includes several performance, stability, and reliability improvements to cloth collisions. Most notably: * The implementation of a new self-collisions system. * Multithreading of collision detection. * Implementation of single sided collisions and normal overrides. * Replacement of the `plNearestPoints` function from Bullet with a dedicated solution. Further, this also includes several bug fixes, and algorithmic improvements. Reviewed By: brecht Differential Revision: http://developer.blender.org/D3712 --- source/blender/physics/intern/BPH_mass_spring.cpp | 102 +++++----------------- 1 file changed, 23 insertions(+), 79 deletions(-) (limited to 'source/blender/physics') diff --git a/source/blender/physics/intern/BPH_mass_spring.cpp b/source/blender/physics/intern/BPH_mass_spring.cpp index d94f2094f81..d43ce37cbfe 100644 --- a/source/blender/physics/intern/BPH_mass_spring.cpp +++ b/source/blender/physics/intern/BPH_mass_spring.cpp @@ -884,20 +884,13 @@ static void cloth_calc_volume_force(ClothModifierData *clmd) } #endif -/* old collision stuff for cloth, use for continuity - * until a good replacement is ready - */ -static void cloth_collision_solve_extra( - Depsgraph *depsgraph, Scene *scene, Object *ob, ClothModifierData *clmd, ListBase *effectors, - float frame, float step, float dt) +static void cloth_solve_collisions(Depsgraph *depsgraph, Object *ob, ClothModifierData *clmd, float step, float dt) { Cloth *cloth = clmd->clothObject; Implicit_Data *id = cloth->implicit; ClothVertex *verts = cloth->verts; int mvert_num = cloth->mvert_num; - const float spf = (float)clmd->sim_parms->stepsPerFrame / clmd->sim_parms->timescale; - - bool do_extra_solve; + const float time_multiplier = 1.0f / (clmd->sim_parms->dt * clmd->sim_parms->timescale); int i; if (!(clmd->coll_parms->flags & (CLOTH_COLLSETTINGS_FLAG_ENABLED | CLOTH_COLLSETTINGS_FLAG_SELF))) @@ -906,69 +899,26 @@ static void cloth_collision_solve_extra( if (!clmd->clothObject->bvhtree) return; - // update verts to current positions + BPH_mass_spring_solve_positions(id, dt); + + /* Update verts to current positions. */ for (i = 0; i < mvert_num; i++) { BPH_mass_spring_get_new_position(id, i, verts[i].tx); sub_v3_v3v3(verts[i].tv, verts[i].tx, verts[i].txold); - copy_v3_v3(verts[i].v, verts[i].tv); - } - -#if 0 /* unused */ - for (i=0, cv=cloth->verts; imvert_num; i++, cv++) { - copy_v3_v3(initial_cos[i], cv->tx); - } -#endif - - // call collision function - // TODO: check if "step" or "step+dt" is correct - dg - do_extra_solve = cloth_bvh_objcollision( - depsgraph, ob, clmd, step / clmd->sim_parms->timescale, dt / clmd->sim_parms->timescale); - - // copy corrected positions back to simulation - for (i = 0; i < mvert_num; i++) { - float curx[3]; - BPH_mass_spring_get_position(id, i, curx); - // correct velocity again, just to be sure we had to change it due to adaptive collisions - sub_v3_v3v3(verts[i].tv, verts[i].tx, curx); + zero_v3(verts[i].dcvel); } - if (do_extra_solve) { -// cloth_calc_helper_forces(ob, clmd, initial_cos, step/clmd->sim_parms->timescale, dt/clmd->sim_parms->timescale); - + if (cloth_bvh_collision(depsgraph, ob, clmd, step / clmd->sim_parms->timescale, dt / clmd->sim_parms->timescale)) { for (i = 0; i < mvert_num; i++) { - - float newv[3]; - - if ((clmd->sim_parms->vgroup_mass > 0) && (verts [i].flags & CLOTH_VERT_FLAG_PINNED)) + if ((clmd->sim_parms->vgroup_mass > 0) && (verts[i].flags & CLOTH_VERT_FLAG_PINNED)) continue; - BPH_mass_spring_set_new_position(id, i, verts[i].tx); - mul_v3_v3fl(newv, verts[i].tv, spf); - BPH_mass_spring_set_new_velocity(id, i, newv); + BPH_mass_spring_get_new_velocity(id, i, verts[i].tv); + madd_v3_v3fl(verts[i].tv, verts[i].dcvel, time_multiplier); + BPH_mass_spring_set_new_velocity(id, i, verts[i].tv); } } - - // X = Xnew; - BPH_mass_spring_apply_result(id); - - if (do_extra_solve) { - ImplicitSolverResult result; - - /* initialize forces to zero */ - BPH_mass_spring_clear_forces(id); - - // calculate forces - cloth_calc_force(scene, clmd, frame, effectors, step); - - // calculate new velocity and position - BPH_mass_spring_solve_velocities(id, dt, &result); -// cloth_record_result(clmd, &result, clmd->sim_parms->stepsPerFrame); - - /* note: positions are advanced only once in the main solver step! */ - - BPH_mass_spring_apply_result(id); - } } static void cloth_clear_result(ClothModifierData *clmd) @@ -981,7 +931,7 @@ static void cloth_clear_result(ClothModifierData *clmd) sres->avg_iterations = 0.0f; } -static void cloth_record_result(ClothModifierData *clmd, ImplicitSolverResult *result, int steps) +static void cloth_record_result(ClothModifierData *clmd, ImplicitSolverResult *result, float dt) { ClothSolverResult *sres = clmd->solver_result; @@ -990,22 +940,22 @@ static void cloth_record_result(ClothModifierData *clmd, ImplicitSolverResult *r if (result->status == BPH_SOLVER_SUCCESS) { sres->min_error = min_ff(sres->min_error, result->error); sres->max_error = max_ff(sres->max_error, result->error); - sres->avg_error += result->error / (float)steps; + sres->avg_error += result->error * dt; } sres->min_iterations = min_ii(sres->min_iterations, result->iterations); sres->max_iterations = max_ii(sres->max_iterations, result->iterations); - sres->avg_iterations += (float)result->iterations / (float)steps; + sres->avg_iterations += (float)result->iterations * dt; } else { /* error only makes sense for successful iterations */ if (result->status == BPH_SOLVER_SUCCESS) { sres->min_error = sres->max_error = result->error; - sres->avg_error += result->error / (float)steps; + sres->avg_error += result->error * dt; } sres->min_iterations = sres->max_iterations = result->iterations; - sres->avg_iterations += (float)result->iterations / (float)steps; + sres->avg_iterations += (float)result->iterations * dt; } sres->status |= result->status; @@ -1025,7 +975,7 @@ int BPH_cloth_solve(Depsgraph *depsgraph, Object *ob, float frame, ClothModifier Cloth *cloth = clmd->clothObject; ClothVertex *verts = cloth->verts/*, *cv*/; unsigned int mvert_num = cloth->mvert_num; - float dt = clmd->sim_parms->timescale / clmd->sim_parms->stepsPerFrame; + float dt = clmd->sim_parms->dt * clmd->sim_parms->timescale; Implicit_Data *id = cloth->implicit; ColliderContacts *contacts = NULL; int totcolliders = 0; @@ -1053,12 +1003,6 @@ int BPH_cloth_solve(Depsgraph *depsgraph, Object *ob, float frame, ClothModifier while (step < tf) { ImplicitSolverResult result; - /* copy velocities for collision */ - for (i = 0; i < mvert_num; i++) { - BPH_mass_spring_get_motion_state(id, i, NULL, verts[i].tv); - copy_v3_v3(verts[i].v, verts[i].tv); - } - if (is_hair) { /* determine contact points */ if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED) { @@ -1081,18 +1025,18 @@ int BPH_cloth_solve(Depsgraph *depsgraph, Object *ob, float frame, ClothModifier // calculate new velocity and position BPH_mass_spring_solve_velocities(id, dt, &result); - cloth_record_result(clmd, &result, clmd->sim_parms->stepsPerFrame); + cloth_record_result(clmd, &result, dt); + + /* Calculate collision impulses. */ + if (!is_hair) { + cloth_solve_collisions(depsgraph, ob, clmd, step, dt); + } if (is_hair) { cloth_continuum_step(clmd, dt); } BPH_mass_spring_solve_positions(id, dt); - - if (!is_hair) { - cloth_collision_solve_extra(depsgraph, scene, ob, clmd, effectors, frame, step, dt); - } - BPH_mass_spring_apply_result(id); /* move pinned verts to correct position */ -- cgit v1.2.3