diff options
author | Lukas Tönne <lukas.toenne@gmail.com> | 2015-03-01 14:33:30 +0300 |
---|---|---|
committer | Lukas Tönne <lukas.toenne@gmail.com> | 2015-03-01 14:33:30 +0300 |
commit | dfefd3683710a4bf70cf90c874b65a9c118d2c06 (patch) | |
tree | ccf13a6ec8a4d8172e4c5721a12ebceb6d6c547c /source/blender | |
parent | 9f6f151536b24f3329e357c8cbe05c2069578866 (diff) |
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.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/physics/intern/BPH_mass_spring.cpp | 107 | ||||
-rw-r--r-- | source/blender/physics/intern/implicit.h | 4 | ||||
-rw-r--r-- | source/blender/physics/intern/implicit_blender.c | 10 |
3 files changed, 116 insertions, 5 deletions
diff --git a/source/blender/physics/intern/BPH_mass_spring.cpp b/source/blender/physics/intern/BPH_mass_spring.cpp index 6cddbc6aa46..483dfd08abd 100644 --- a/source/blender/physics/intern/BPH_mass_spring.cpp +++ b/source/blender/physics/intern/BPH_mass_spring.cpp @@ -51,6 +51,11 @@ extern "C" { #include "BPH_mass_spring.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}};
/* 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};
+ BPH_mass_spring_clear_constraints(data);
+
for (v = 0; v < numverts; v++) {
if (verts[v].flags & CLOTH_VERT_FLAG_PINNED) {
/* pinned vertex constraints */
@@ -848,6 +855,86 @@ static void cloth_calc_volume_force(ClothModifierData *clmd) }
#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)
{
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;
float dt = clmd->sim_parms->timescale / clmd->sim_parms->stepsPerFrame;
Implicit_Data *id = cloth->implicit;
+#ifndef USE_COLLISION_DOUBLE_SOLVE
ColliderContacts *contacts = NULL;
int totcolliders = 0;
+#endif
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) {
ImplicitSolverResult result;
- /* initialize forces to zero */
- BPH_mass_spring_clear_forces(id);
- BPH_mass_spring_clear_constraints(id);
-
/* copy velocities for collision */
for (i = 0; i < numverts; i++) {
BPH_mass_spring_get_motion_state(id, i, NULL, verts[i].tv);
copy_v3_v3(verts[i].v, verts[i].tv);
}
+#ifndef USE_COLLISION_DOUBLE_SOLVE
/* determine contact points */
if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED) {
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 */
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
// 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);
+#ifdef USE_COLLISION_DOUBLE_SOLVE
+ cloth_collision_solve_extra(ob, clmd, effectors, frame, step, dt);
+#endif
+
BPH_mass_spring_apply_result(id);
/* 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);
}
+#ifndef USE_COLLISION_DOUBLE_SOLVE
/* free contact points */
if (contacts) {
cloth_free_contacts(contacts, totcolliders);
}
+#endif
step += dt;
}
diff --git a/source/blender/physics/intern/implicit.h b/source/blender/physics/intern/implicit.h index 7ded479f578..d286d3df1a5 100644 --- a/source/blender/physics/intern/implicit.h +++ b/source/blender/physics/intern/implicit.h @@ -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_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_set_new_velocity(struct Implicit_Data *data, int index, const float v[3]); diff --git a/source/blender/physics/intern/implicit_blender.c b/source/blender/physics/intern/implicit_blender.c index e6ba55ab605..5b1d83a3eef 100644 --- a/source/blender/physics/intern/implicit_blender.c +++ b/source/blender/physics/intern/implicit_blender.c @@ -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]); } +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]) { root_to_world_v3(data, index, v, data->Vnew[index]); |