Fix T43406: Bring back cloth collisions.

This was disabled during the course of hair dynamics work. The cloth
collision solution is based on a secondary velocity-only solver step.

While this approach is usable in general, the collision response
calculation still does not work well for hair meshes. Better contact
point generation is needed here (Bullet) and preferably an improved
solver for unilateral constraints.
This commit is contained in:
2015-03-01 12:33:30 +01:00
parent 9f6f151536
commit dfefd36837
3 changed files with 116 additions and 5 deletions

View File

@@ -51,6 +51,11 @@ extern "C" {
#include "BPH_mass_spring.h" #include "BPH_mass_spring.h"
#include "implicit.h" #include "implicit.h"
/* old collision stuff for cloth, use for continuity
* until a good replacement is ready
*/
#define USE_COLLISION_DOUBLE_SOLVE
static float I3[3][3] = {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; static float I3[3][3] = {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}};
/* Number of off-diagonal non-zero matrix blocks. /* Number of off-diagonal non-zero matrix blocks.
@@ -214,6 +219,8 @@ static void cloth_setup_constraints(ClothModifierData *clmd, ColliderContacts *c
const float ZERO[3] = {0.0f, 0.0f, 0.0f}; const float ZERO[3] = {0.0f, 0.0f, 0.0f};
BPH_mass_spring_clear_constraints(data);
for (v = 0; v < numverts; v++) { for (v = 0; v < numverts; v++) {
if (verts[v].flags & CLOTH_VERT_FLAG_PINNED) { if (verts[v].flags & CLOTH_VERT_FLAG_PINNED) {
/* pinned vertex constraints */ /* pinned vertex constraints */
@@ -848,6 +855,86 @@ static void cloth_calc_volume_force(ClothModifierData *clmd)
} }
#endif #endif
static void cloth_collision_solve_extra(Object *ob, ClothModifierData *clmd, ListBase *effectors, float frame, float step, float dt)
{
Cloth *cloth = clmd->clothObject;
Implicit_Data *id = cloth->implicit;
ClothVertex *verts = cloth->verts;
int numverts = cloth->numverts;
const float spf = (float)clmd->sim_parms->stepsPerFrame / clmd->sim_parms->timescale;;
bool do_extra_solve;
int i;
if (!(clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED))
return;
if (!clmd->clothObject->bvhtree)
return;
// update verts to current positions
for (i = 0; i < numverts; 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; i<cloth->numverts; 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(ob, clmd, step/clmd->sim_parms->timescale, dt/clmd->sim_parms->timescale);
// copy corrected positions back to simulation
for (i = 0; i < numverts; 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);
}
if (do_extra_solve) {
// cloth_calc_helper_forces(ob, clmd, initial_cos, step/clmd->sim_parms->timescale, dt/clmd->sim_parms->timescale);
for (i = 0; i < numverts; i++) {
float newv[3];
if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (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);
}
}
// 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(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) static void cloth_clear_result(ClothModifierData *clmd)
{ {
ClothSolverResult *sres = clmd->solver_result; ClothSolverResult *sres = clmd->solver_result;
@@ -897,8 +984,10 @@ int BPH_cloth_solve(Object *ob, float frame, ClothModifierData *clmd, ListBase *
unsigned int numverts = cloth->numverts; unsigned int numverts = cloth->numverts;
float dt = clmd->sim_parms->timescale / clmd->sim_parms->stepsPerFrame; float dt = clmd->sim_parms->timescale / clmd->sim_parms->stepsPerFrame;
Implicit_Data *id = cloth->implicit; Implicit_Data *id = cloth->implicit;
#ifndef USE_COLLISION_DOUBLE_SOLVE
ColliderContacts *contacts = NULL; ColliderContacts *contacts = NULL;
int totcolliders = 0; int totcolliders = 0;
#endif
BKE_sim_debug_data_clear_category("collision"); BKE_sim_debug_data_clear_category("collision");
@@ -921,16 +1010,13 @@ int BPH_cloth_solve(Object *ob, float frame, ClothModifierData *clmd, ListBase *
while (step < tf) { while (step < tf) {
ImplicitSolverResult result; ImplicitSolverResult result;
/* initialize forces to zero */
BPH_mass_spring_clear_forces(id);
BPH_mass_spring_clear_constraints(id);
/* copy velocities for collision */ /* copy velocities for collision */
for (i = 0; i < numverts; i++) { for (i = 0; i < numverts; i++) {
BPH_mass_spring_get_motion_state(id, i, NULL, verts[i].tv); BPH_mass_spring_get_motion_state(id, i, NULL, verts[i].tv);
copy_v3_v3(verts[i].v, verts[i].tv); copy_v3_v3(verts[i].v, verts[i].tv);
} }
#ifndef USE_COLLISION_DOUBLE_SOLVE
/* determine contact points */ /* determine contact points */
if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED) { if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED) {
if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_POINTS) { if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_POINTS) {
@@ -940,6 +1026,13 @@ int BPH_cloth_solve(Object *ob, float frame, ClothModifierData *clmd, ListBase *
/* setup vertex constraints for pinned vertices and contacts */ /* setup vertex constraints for pinned vertices and contacts */
cloth_setup_constraints(clmd, contacts, totcolliders, dt); cloth_setup_constraints(clmd, contacts, totcolliders, dt);
#else
/* setup vertex constraints for pinned vertices */
cloth_setup_constraints(clmd, NULL, 0, dt);
#endif
/* initialize forces to zero */
BPH_mass_spring_clear_forces(id);
// damping velocity for artistic reasons // damping velocity for artistic reasons
// this is a bad way to do it, should be removed imo - lukas_t // this is a bad way to do it, should be removed imo - lukas_t
@@ -963,6 +1056,10 @@ int BPH_cloth_solve(Object *ob, float frame, ClothModifierData *clmd, ListBase *
BPH_mass_spring_solve_positions(id, dt); BPH_mass_spring_solve_positions(id, dt);
#ifdef USE_COLLISION_DOUBLE_SOLVE
cloth_collision_solve_extra(ob, clmd, effectors, frame, step, dt);
#endif
BPH_mass_spring_apply_result(id); BPH_mass_spring_apply_result(id);
/* move pinned verts to correct position */ /* move pinned verts to correct position */
@@ -978,10 +1075,12 @@ int BPH_cloth_solve(Object *ob, float frame, ClothModifierData *clmd, ListBase *
BPH_mass_spring_get_motion_state(id, i, verts[i].txold, NULL); BPH_mass_spring_get_motion_state(id, i, verts[i].txold, NULL);
} }
#ifndef USE_COLLISION_DOUBLE_SOLVE
/* free contact points */ /* free contact points */
if (contacts) { if (contacts) {
cloth_free_contacts(contacts, totcolliders); cloth_free_contacts(contacts, totcolliders);
} }
#endif
step += dt; step += dt;
} }

View File

@@ -82,7 +82,9 @@ void BPH_mass_spring_set_velocity(struct Implicit_Data *data, int index, const f
void BPH_mass_spring_get_motion_state(struct Implicit_Data *data, int index, float x[3], float v[3]); void BPH_mass_spring_get_motion_state(struct Implicit_Data *data, int index, float x[3], float v[3]);
void BPH_mass_spring_get_position(struct Implicit_Data *data, int index, float x[3]); void BPH_mass_spring_get_position(struct Implicit_Data *data, int index, float x[3]);
/* modified velocity during solver step */ /* access to modified motion state during solver step */
void BPH_mass_spring_get_new_position(struct Implicit_Data *data, int index, float x[3]);
void BPH_mass_spring_set_new_position(struct Implicit_Data *data, int index, const float x[3]);
void BPH_mass_spring_get_new_velocity(struct Implicit_Data *data, int index, float v[3]); void BPH_mass_spring_get_new_velocity(struct Implicit_Data *data, int index, float v[3]);
void BPH_mass_spring_set_new_velocity(struct Implicit_Data *data, int index, const float v[3]); void BPH_mass_spring_set_new_velocity(struct Implicit_Data *data, int index, const float v[3]);

View File

@@ -1225,6 +1225,16 @@ void BPH_mass_spring_get_position(struct Implicit_Data *data, int index, float x
root_to_world_v3(data, index, x, data->X[index]); root_to_world_v3(data, index, x, data->X[index]);
} }
void BPH_mass_spring_get_new_position(struct Implicit_Data *data, int index, float x[3])
{
root_to_world_v3(data, index, x, data->Xnew[index]);
}
void BPH_mass_spring_set_new_position(struct Implicit_Data *data, int index, const float x[3])
{
world_to_root_v3(data, index, data->Xnew[index], x);
}
void BPH_mass_spring_get_new_velocity(struct Implicit_Data *data, int index, float v[3]) void BPH_mass_spring_get_new_velocity(struct Implicit_Data *data, int index, float v[3])
{ {
root_to_world_v3(data, index, v, data->Vnew[index]); root_to_world_v3(data, index, v, data->Vnew[index]);