Cloth: Componentize forces

This separates cloth stiffness and damping forces into tension,
compression, and shearing components, allowing more control over the
cloth behaviour.

This also adds a bending model selector (although the new bending model
itself is not implemented in this commit). This is because some of the
features implemented here only make sense within the new bending model,
while the old model is kept for compatibility.

This commit makes non-breaking changes, and thus maintains full
compatibility with existing simulations.

Reviewed By: brecht

Differential Revision: http://developer.blender.org/D3655
This commit is contained in:
2018-08-29 00:29:37 +02:00
parent ec3357e03a
commit e3d31b8dfb
11 changed files with 301 additions and 71 deletions

View File

@@ -341,29 +341,51 @@ BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s)
Cloth *cloth = clmd->clothObject;
ClothSimSettings *parms = clmd->sim_parms;
Implicit_Data *data = cloth->implicit;
bool no_compress = parms->flags & CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS;
bool new_compress = parms->bending_model == CLOTH_BENDING_ANGULAR;
bool resist_compress = (parms->flags & CLOTH_SIMSETTINGS_FLAG_RESIST_SPRING_COMPRESS) && !new_compress;
s->flags &= ~CLOTH_SPRING_FLAG_NEEDED;
// calculate force of structural + shear springs
if ((s->type & CLOTH_SPRING_TYPE_STRUCTURAL) || (s->type & CLOTH_SPRING_TYPE_SHEAR) || (s->type & CLOTH_SPRING_TYPE_SEWING) ) {
if ((s->type & CLOTH_SPRING_TYPE_STRUCTURAL) || (s->type & CLOTH_SPRING_TYPE_SEWING)) {
#ifdef CLOTH_FORCE_SPRING_STRUCTURAL
float k, scaling;
float k_tension, scaling_tension;
s->flags |= CLOTH_SPRING_FLAG_NEEDED;
scaling = parms->structural + s->stiffness * fabsf(parms->max_struct - parms->structural);
k = scaling / (parms->avg_spring_len + FLT_EPSILON);
scaling_tension = parms->tension + s->stiffness * fabsf(parms->max_tension - parms->tension);
k_tension = scaling_tension / (parms->avg_spring_len + FLT_EPSILON);
if (s->type & CLOTH_SPRING_TYPE_SEWING) {
// TODO: verify, half verified (couldn't see error)
// sewing springs usually have a large distance at first so clamp the force so we don't get tunnelling through colission objects
BPH_mass_spring_force_spring_linear(data, s->ij, s->kl, s->restlen, k, parms->Cdis, no_compress, parms->max_sewing);
BPH_mass_spring_force_spring_linear(data, s->ij, s->kl, s->restlen,
k_tension, parms->tension_damp,
0.0f, 0.0f, false, false, parms->max_sewing);
}
else {
BPH_mass_spring_force_spring_linear(data, s->ij, s->kl, s->restlen, k, parms->Cdis, no_compress, 0.0f);
float k_compression, scaling_compression;
scaling_compression = parms->compression + s->stiffness * fabsf(parms->max_compression - parms->compression);
k_compression = scaling_compression / (parms->avg_spring_len + FLT_EPSILON);
BPH_mass_spring_force_spring_linear(data, s->ij, s->kl, s->restlen,
k_tension, parms->tension_damp,
k_compression, parms->compression_damp,
resist_compress, new_compress, 0.0f);
}
#endif
}
else if (s->type & CLOTH_SPRING_TYPE_SHEAR) {
#ifdef CLOTH_FORCE_SPRING_SHEAR
float k, scaling;
s->flags |= CLOTH_SPRING_FLAG_NEEDED;
scaling = parms->shear + s->stiffness * fabsf(parms->max_shear - parms->shear);
k = scaling / (parms->avg_spring_len + FLT_EPSILON);
BPH_mass_spring_force_spring_linear(data, s->ij, s->kl, s->restlen, k, parms->shear_damp,
0.0f, 0.0f, resist_compress, false, 0.0f);
#endif
}
else if (s->type & CLOTH_SPRING_TYPE_BENDING) { /* calculate force of bending springs */

View File

@@ -50,6 +50,7 @@ extern "C" {
#define CLOTH_FORCE_GRAVITY
#define CLOTH_FORCE_DRAG
#define CLOTH_FORCE_SPRING_STRUCTURAL
#define CLOTH_FORCE_SPRING_SHEAR
#define CLOTH_FORCE_SPRING_BEND
#define CLOTH_FORCE_SPRING_GOAL
#define CLOTH_FORCE_EFFECTORS
@@ -114,7 +115,9 @@ void BPH_mass_spring_force_edge_wind(struct Implicit_Data *data, int v1, int v2,
void BPH_mass_spring_force_vertex_wind(struct Implicit_Data *data, int v, float radius, const float (*winvec)[3]);
/* Linear spring force between two points */
bool BPH_mass_spring_force_spring_linear(struct Implicit_Data *data, int i, int j, float restlen,
float stiffness, float damping, bool no_compress, float clamp_force);
float stiffness_tension, float damping_tension,
float stiffness_compression, float damping_compression,
bool resist_compress, bool new_compress, float clamp_force);
/* Bending force, forming a triangle at the base of two structural springs */
bool BPH_mass_spring_force_spring_bending(struct Implicit_Data *data, int i, int j, float restlen, float kb, float cb);
/* Angular bending force based on local target vectors */

View File

@@ -1585,9 +1585,13 @@ BLI_INLINE void apply_spring(Implicit_Data *data, int i, int j, const float f[3]
}
bool BPH_mass_spring_force_spring_linear(Implicit_Data *data, int i, int j, float restlen,
float stiffness, float damping, bool no_compress, float clamp_force)
float stiffness_tension, float damping_tension,
float stiffness_compression, float damping_compression,
bool resist_compress, bool new_compress, float clamp_force)
{
float extent[3], length, dir[3], vel[3];
float f[3], dfdx[3][3], dfdv[3][3];
float damping = 0;
// calculate elonglation
spring_length(data, i, j, extent, dir, &length, vel);
@@ -1595,29 +1599,41 @@ bool BPH_mass_spring_force_spring_linear(Implicit_Data *data, int i, int j, floa
/* This code computes not only the force, but also its derivative.
Zero derivative effectively disables the spring for the implicit solver.
Thus length > restlen makes cloth unconstrained at the start of simulation. */
if ((length >= restlen && length > 0) || no_compress) {
float stretch_force, f[3], dfdx[3][3], dfdv[3][3];
if ((length >= restlen && length > 0) || resist_compress) {
float stretch_force;
stretch_force = stiffness * (length - restlen);
damping = damping_tension;
stretch_force = stiffness_tension * (length - restlen);
if (clamp_force > 0.0f && stretch_force > clamp_force) {
stretch_force = clamp_force;
}
mul_v3_v3fl(f, dir, stretch_force);
// Ascher & Boxman, p.21: Damping only during elonglation
// something wrong with it...
madd_v3_v3fl(f, dir, damping * dot_v3v3(vel, dir));
dfdx_spring(dfdx, dir, length, restlen, stiffness_tension);
}
else if (new_compress) {
/* This is based on the Choi and Ko bending model, which works surprisingly well for compression. */
float kb = stiffness_compression;
float cb = kb; /* cb equal to kb seems to work, but a factor can be added if necessary */
dfdx_spring(dfdx, dir, length, restlen, stiffness);
dfdv_damp(dfdv, dir, damping);
damping = damping_compression;
apply_spring(data, i, j, f, dfdx, dfdv);
mul_v3_v3fl(f, dir, fbstar(length, restlen, kb, cb));
return true;
outerproduct(dfdx, dir, dir);
mul_m3_fl(dfdx, fbstar_jacobi(length, restlen, kb, cb));
}
else {
return false;
}
madd_v3_v3fl(f, dir, damping * dot_v3v3(vel, dir));
dfdv_damp(dfdv, dir, damping);
apply_spring(data, i, j, f, dfdx, dfdv);
return true;
}
/* See "Stable but Responsive Cloth" (Choi, Ko 2005) */