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:
Luca Rood 2018-08-29 00:29:37 +02:00
parent ec3357e03a
commit e3d31b8dfb
Notes: blender-bot 2024-02-23 15:37:12 +01:00
Referenced by commit 0885484aa6, Fix T59587: Hair dynamics works different when opened in 2.8
Referenced by commit 4b8b369218, Fix T58448: Cloth presets fails to load due to missing attribute structural_stiffness.
Referenced by pull request #118028, Fix: Cloth could ignore "Shear" vertexgroup
Referenced by commit c75d2d09e3, Fix: Cloth could ignore "Shear" vertexgroup
11 changed files with 301 additions and 71 deletions

View File

@ -74,20 +74,38 @@ class PHYSICS_PT_cloth(PhysicButtonsPanel, Panel):
col = flow.column()
col.prop(cloth, "quality", text="Quality Steps")
col.prop(cloth, "time_scale", text="Speed Multiplier")
col.prop(cloth, "bending_model")
col.separator()
col = flow.column()
col.prop(cloth, "mass", text="Material Mass")
col.prop(cloth, "structural_stiffness", text="Structural")
col.prop(cloth, "air_damping", text="Air")
col.prop(cloth, "vel_damping", text="Velocity")
col.separator()
col = flow.column()
if cloth.bending_model == 'ANGULAR':
col.prop(cloth, "tension_stiffness", text="Stiffness Tension")
col.prop(cloth, "compression_stiffness", text="Compression")
else:
col.prop(cloth, "tension_stiffness", text="Stiffness Structural")
col.prop(cloth, "shear_stiffness", text="Shear")
col.prop(cloth, "bending_stiffness", text="Bending")
col.separator()
col = flow.column()
col.prop(cloth, "spring_damping", text="Damping Spring")
col.prop(cloth, "air_damping", text="Air")
col.prop(cloth, "vel_damping", text="Velocity")
if cloth.bending_model == 'ANGULAR':
col.prop(cloth, "tension_damping", text="Damping Tension")
col.prop(cloth, "compression_damping", text="Compression")
else:
col.prop(cloth, "tension_damping", text="Damping Structural")
col.prop(cloth, "shear_damping", text="Shear")
col.prop(cloth, "bending_damping", text="Bending")
col = flow.column()
col.prop(cloth, "use_dynamic_mesh", text="Dynamic Mesh")
@ -248,7 +266,17 @@ class PHYSICS_PT_cloth_stiffness(PhysicButtonsPanel, Panel):
cloth, "vertex_group_structural_stiffness", ob, "vertex_groups",
text="Structural Group"
)
col.prop(cloth, "structural_stiffness_max", text="Max")
col.prop(cloth, "tension_stiffness_max", text="Max Tension")
col.prop(cloth, "compression_stiffness_max", text="Compression")
col.separator()
col = flow.column()
col.prop_search(
cloth, "vertex_group_shear_stiffness", ob, "vertex_groups",
text="Shear Group"
)
col.prop(cloth, "shear_stiffness_max", text="Max")
col.separator()

View File

@ -167,11 +167,17 @@ typedef enum {
CLOTH_SIMSETTINGS_FLAG_TEARING = ( 1 << 4 ),// true if tearing is enabled
CLOTH_SIMSETTINGS_FLAG_SCALING = ( 1 << 8 ), /* is advanced scaling active? */
CLOTH_SIMSETTINGS_FLAG_CCACHE_EDIT = (1 << 12), /* edit cache in editmode */
CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS = (1 << 13), /* don't allow spring compression */
CLOTH_SIMSETTINGS_FLAG_RESIST_SPRING_COMPRESS = (1 << 13), /* don't allow spring compression */
CLOTH_SIMSETTINGS_FLAG_SEW = (1 << 14), /* pull ends of loose edges together */
CLOTH_SIMSETTINGS_FLAG_DYNAMIC_BASEMESH = (1 << 15), /* make simulation respect deformations in the base object */
} CLOTH_SIMSETTINGS_FLAGS;
/* ClothSimSettings.bending_model. */
typedef enum {
CLOTH_BENDING_LINEAR = 0,
CLOTH_BENDING_ANGULAR = 1,
} CLOTH_BENDING_MODEL;
/* COLLISION FLAGS */
typedef enum {
CLOTH_COLLSETTINGS_FLAG_ENABLED = ( 1 << 1 ), /* enables cloth - object collisions */

View File

@ -85,13 +85,18 @@ void cloth_init(ClothModifierData *clmd )
clmd->sim_parms->gravity[0] = 0.0;
clmd->sim_parms->gravity[1] = 0.0;
clmd->sim_parms->gravity[2] = -9.81;
clmd->sim_parms->structural = 15.0;
clmd->sim_parms->max_struct = 15.0;
clmd->sim_parms->shear = 15.0;
clmd->sim_parms->tension = 15.0;
clmd->sim_parms->max_tension = 15.0;
clmd->sim_parms->compression = 15.0;
clmd->sim_parms->max_compression = 15.0;
clmd->sim_parms->shear = 5.0;
clmd->sim_parms->max_shear = 5.0;
clmd->sim_parms->bending = 0.5;
clmd->sim_parms->max_bend = 0.5;
clmd->sim_parms->tension_damp = 5.0;
clmd->sim_parms->compression_damp = 5.0;
clmd->sim_parms->shear_damp = 5.0;
clmd->sim_parms->bending_damping = 0.5;
clmd->sim_parms->Cdis = 5.0;
clmd->sim_parms->Cvi = 1.0;
clmd->sim_parms->mass = 0.3f;
clmd->sim_parms->stepsPerFrame = 5;
@ -134,6 +139,8 @@ void cloth_init(ClothModifierData *clmd )
clmd->sim_parms->voxel_cell_size = 0.1f;
clmd->sim_parms->bending_model = CLOTH_BENDING_ANGULAR;
if (!clmd->sim_parms->effector_weights)
clmd->sim_parms->effector_weights = BKE_add_effector_weights(NULL);
@ -728,6 +735,9 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, Mesh *mesh )
if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SCALING ) {
if ( dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_struct-1)) {
verts->struct_stiff = dvert->dw [j].weight;
}
if ( dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_shear-1)) {
verts->shear_stiff = dvert->dw [j].weight;
}

View File

@ -3171,7 +3171,7 @@ static void do_hair_dynamics(ParticleSimulationData *sim)
psys->clmd = (ClothModifierData*)modifier_new(eModifierType_Cloth);
psys->clmd->sim_parms->goalspring = 0.0f;
psys->clmd->sim_parms->vel_damping = 1.0f;
psys->clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_GOAL|CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS;
psys->clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_GOAL|CLOTH_SIMSETTINGS_FLAG_RESIST_SPRING_COMPRESS;
psys->clmd->coll_parms->flags &= ~CLOTH_COLLSETTINGS_FLAG_SELF;
}

View File

@ -40,6 +40,7 @@
#include "DNA_object_types.h"
#include "DNA_camera_types.h"
#include "DNA_cloth_types.h"
#include "DNA_collection_types.h"
#include "DNA_constraint_types.h"
#include "DNA_gpu_types.h"
@ -80,6 +81,7 @@
#include "BKE_gpencil.h"
#include "BKE_paint.h"
#include "BKE_object.h"
#include "BKE_cloth.h"
#include "BLT_translation.h"
@ -1920,5 +1922,27 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
}
if (!DNA_struct_elem_find(fd->filesdna, "ClothSimSettings", "short", "bending_model")) {
for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
for (ModifierData *md = ob->modifiers.first; md; md = md->next) {
if (md->type == eModifierType_Cloth) {
ClothModifierData *clmd = (ClothModifierData *)md;
clmd->sim_parms->bending_model = CLOTH_BENDING_LINEAR;
clmd->sim_parms->tension = clmd->sim_parms->structural;
clmd->sim_parms->compression = clmd->sim_parms->structural;
clmd->sim_parms->shear = clmd->sim_parms->structural;
clmd->sim_parms->max_tension = clmd->sim_parms->max_struct;
clmd->sim_parms->max_compression = clmd->sim_parms->max_struct;
clmd->sim_parms->max_shear = clmd->sim_parms->max_struct;
clmd->sim_parms->vgroup_shear = clmd->sim_parms->vgroup_struct;
clmd->sim_parms->tension_damp = clmd->sim_parms->Cdis;
clmd->sim_parms->compression_damp = clmd->sim_parms->Cdis;
clmd->sim_parms->shear_damp = clmd->sim_parms->Cdis;
}
}
}
}
}
}

View File

@ -49,17 +49,17 @@
typedef struct ClothSimSettings {
struct LinkNode *cache; /* UNUSED atm */
float mingoal; /* see SB */
float Cdis; /* Mechanical damping of springs. */
float Cdis DNA_DEPRECATED; /* Mechanical damping of springs. */
float Cvi; /* Viscous/fluid damping. */
float gravity[3]; /* Gravity/external force vector. */
float dt; /* This is the duration of our time step, computed. */
float mass; /* The mass of the entire cloth. */
float structural; /* Structural spring stiffness. */
float structural DNA_DEPRECATED; /* Structural spring stiffness. */
float shear; /* Shear spring stiffness. */
float bending; /* Flexion spring stiffness. */
float max_bend; /* max bending scaling value, min is "bending" */
float max_struct; /* max structural scaling value, min is "structural" */
float max_shear; /* max shear scaling value, UNUSED */
float max_struct DNA_DEPRECATED; /* max structural scaling value, min is "structural" */
float max_shear; /* max shear scaling value */
float max_sewing; /* max sewing force */
float avg_spring_len; /* used for normalized springs */
float timescale; /* parameter how fast cloth runs */
@ -101,6 +101,16 @@ typedef struct ClothSimSettings {
char pad0[4];
struct EffectorWeights *effector_weights;
short bending_model;
short vgroup_shear; /* Vertex group for scaling structural stiffness. */
float tension;
float compression;
float max_tension;
float max_compression;
float tension_damp; /* Mechanical damping of tension springs. */
float compression_damp; /* Mechanical damping of compression springs. */
float shear_damp; /* Mechanical damping of shear springs. */
} ClothSimSettings;

View File

@ -97,26 +97,70 @@ static void rna_ClothSettings_max_bend_set(struct PointerRNA *ptr, float value)
settings->max_bend = value;
}
static void rna_ClothSettings_structural_set(struct PointerRNA *ptr, float value)
static void rna_ClothSettings_tension_set(struct PointerRNA *ptr, float value)
{
ClothSimSettings *settings = (ClothSimSettings *)ptr->data;
settings->structural = value;
settings->tension = value;
/* check for max clipping */
if (value > settings->max_struct)
settings->max_struct = value;
if (value > settings->max_tension)
settings->max_tension = value;
}
static void rna_ClothSettings_max_struct_set(struct PointerRNA *ptr, float value)
static void rna_ClothSettings_max_tension_set(struct PointerRNA *ptr, float value)
{
ClothSimSettings *settings = (ClothSimSettings *)ptr->data;
/* check for clipping */
if (value < settings->structural)
value = settings->structural;
if (value < settings->tension)
value = settings->tension;
settings->max_struct = value;
settings->max_tension = value;
}
static void rna_ClothSettings_compression_set(struct PointerRNA *ptr, float value)
{
ClothSimSettings *settings = (ClothSimSettings *)ptr->data;
settings->compression = value;
/* check for max clipping */
if (value > settings->max_compression)
settings->max_compression = value;
}
static void rna_ClothSettings_max_compression_set(struct PointerRNA *ptr, float value)
{
ClothSimSettings *settings = (ClothSimSettings *)ptr->data;
/* check for clipping */
if (value < settings->compression)
value = settings->compression;
settings->max_compression = value;
}
static void rna_ClothSettings_shear_set(struct PointerRNA *ptr, float value)
{
ClothSimSettings *settings = (ClothSimSettings *)ptr->data;
settings->shear = value;
/* check for max clipping */
if (value > settings->max_shear)
settings->max_shear = value;
}
static void rna_ClothSettings_max_shear_set(struct PointerRNA *ptr, float value)
{
ClothSimSettings *settings = (ClothSimSettings *)ptr->data;
/* check for clipping */
if (value < settings->shear)
value = settings->shear;
settings->max_shear = value;
}
static void rna_ClothSettings_max_sewing_set(struct PointerRNA *ptr, float value)
@ -184,6 +228,24 @@ static void rna_ClothSettings_struct_vgroup_set(PointerRNA *ptr, const char *val
rna_object_vgroup_name_index_set(ptr, value, &sim->vgroup_struct);
}
static void rna_ClothSettings_shear_vgroup_get(PointerRNA *ptr, char *value)
{
ClothSimSettings *sim = (ClothSimSettings *)ptr->data;
rna_object_vgroup_name_index_get(ptr, value, sim->vgroup_shear);
}
static int rna_ClothSettings_shear_vgroup_length(PointerRNA *ptr)
{
ClothSimSettings *sim = (ClothSimSettings *)ptr->data;
return rna_object_vgroup_name_index_length(ptr, sim->vgroup_shear);
}
static void rna_ClothSettings_shear_vgroup_set(PointerRNA *ptr, const char *value)
{
ClothSimSettings *sim = (ClothSimSettings *)ptr->data;
rna_object_vgroup_name_index_set(ptr, value, &sim->vgroup_shear);
}
static void rna_ClothSettings_bend_vgroup_get(PointerRNA *ptr, char *value)
{
ClothSimSettings *sim = (ClothSimSettings *)ptr->data;
@ -350,6 +412,12 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
static const EnumPropertyItem prop_bending_model_items[] = {
{CLOTH_BENDING_ANGULAR, "ANGULAR", 0, "Angular", "Cloth model with angular bending springs"},
{CLOTH_BENDING_LINEAR, "LINEAR", 0, "Linear", "Cloth model with linear bending springs (legacy)"},
{0, NULL, 0, NULL, NULL}
};
srna = RNA_def_struct(brna, "ClothSettings", NULL);
RNA_def_struct_ui_text(srna, "Cloth Settings", "Cloth simulation settings for an object");
RNA_def_struct_sdna(srna, "ClothSimSettings");
@ -511,25 +579,67 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_cloth_update");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
prop = RNA_def_property(srna, "spring_damping", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "Cdis");
prop = RNA_def_property(srna, "tension_damping", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "tension_damp");
RNA_def_property_range(prop, 0.0f, 50.0f);
RNA_def_property_ui_text(prop, "Spring Damping",
"Damping of cloth velocity (higher = more smooth, less jiggling)");
RNA_def_property_ui_text(prop, "Tension Spring Damping",
"Damping of spring velocity (higher = more smooth, less jiggling)");
RNA_def_property_update(prop, 0, "rna_cloth_update");
prop = RNA_def_property(srna, "structural_stiffness", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "structural");
RNA_def_property_range(prop, 0.0f, 10000.0f);
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_structural_set", NULL);
RNA_def_property_ui_text(prop, "Structural Stiffness", "Overall stiffness of structure");
prop = RNA_def_property(srna, "compression_damping", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "compression_damp");
RNA_def_property_range(prop, 0.0f, 50.0f);
RNA_def_property_ui_text(prop, "Compression Spring Damping",
"Damping of spring velocity (higher = more smooth, less jiggling)");
RNA_def_property_update(prop, 0, "rna_cloth_update");
prop = RNA_def_property(srna, "structural_stiffness_max", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "max_struct");
prop = RNA_def_property(srna, "shear_damping", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "shear_damp");
RNA_def_property_range(prop, 0.0f, 50.0f);
RNA_def_property_ui_text(prop, "Shear Spring Damping",
"Damping of spring velocity (higher = more smooth, less jiggling)");
RNA_def_property_update(prop, 0, "rna_cloth_update");
prop = RNA_def_property(srna, "tension_stiffness", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "tension");
RNA_def_property_range(prop, 0.0f, 10000.0f);
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_max_struct_set", NULL);
RNA_def_property_ui_text(prop, "Structural Stiffness Maximum", "Maximum structural stiffness value");
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_tension_set", NULL);
RNA_def_property_ui_text(prop, "Tension Stiffness", "Tension stiffness of structure");
RNA_def_property_update(prop, 0, "rna_cloth_update");
prop = RNA_def_property(srna, "tension_stiffness_max", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "max_tension");
RNA_def_property_range(prop, 0.0f, 10000.0f);
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_max_tension_set", NULL);
RNA_def_property_ui_text(prop, "Tension Stiffness Maximum", "Maximum tension stiffness value");
RNA_def_property_update(prop, 0, "rna_cloth_update");
prop = RNA_def_property(srna, "compression_stiffness", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "compression");
RNA_def_property_range(prop, 0.0f, 10000.0f);
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_compression_set", NULL);
RNA_def_property_ui_text(prop, "Compression Stiffness", "Compression stiffness of structure");
RNA_def_property_update(prop, 0, "rna_cloth_update");
prop = RNA_def_property(srna, "compression_stiffness_max", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "max_compression");
RNA_def_property_range(prop, 0.0f, 10000.0f);
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_max_compression_set", NULL);
RNA_def_property_ui_text(prop, "Compression Stiffness Maximum", "Maximum compression stiffness value");
RNA_def_property_update(prop, 0, "rna_cloth_update");
prop = RNA_def_property(srna, "shear_stiffness", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "shear");
RNA_def_property_range(prop, 0.0f, 10000.0f);
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_shear_set", NULL);
RNA_def_property_ui_text(prop, "Shear Stiffness", "Shear spring stiffness");
RNA_def_property_update(prop, 0, "rna_cloth_update");
prop = RNA_def_property(srna, "shear_stiffness_max", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "max_shear");
RNA_def_property_range(prop, 0.0f, 10000.0f);
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_max_shear_set", NULL);
RNA_def_property_ui_text(prop, "Shear Stiffness Maximum", "Maximum shear scaling value");
RNA_def_property_update(prop, 0, "rna_cloth_update");
prop = RNA_def_property(srna, "sewing_force_max", PROP_FLOAT, PROP_NONE);
@ -547,6 +657,14 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
"Vertex group for fine control over structural stiffness");
RNA_def_property_update(prop, 0, "rna_cloth_update");
prop = RNA_def_property(srna, "vertex_group_shear_stiffness", PROP_STRING, PROP_NONE);
RNA_def_property_string_funcs(prop, "rna_ClothSettings_shear_vgroup_get",
"rna_ClothSettings_shear_vgroup_length",
"rna_ClothSettings_shear_vgroup_set");
RNA_def_property_ui_text(prop, "Shear Stiffness Vertex Group",
"Vertex group for fine control over shear stiffness");
RNA_def_property_update(prop, 0, "rna_cloth_update");
prop = RNA_def_property(srna, "bending_stiffness", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "bending");
RNA_def_property_range(prop, 0.0f, 10000.0f);
@ -601,22 +719,15 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_cloth_update");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
prop = RNA_def_property(srna, "bending_model", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "bending_model");
RNA_def_property_enum_items(prop, prop_bending_model_items);
RNA_def_property_ui_text(prop, "Bending Model", "Physical model for simulating bending forces");
RNA_def_property_update(prop, 0, "rna_cloth_update");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
/* unused */
/* unused still */
#if 0
prop = RNA_def_property(srna, "shear_stiffness", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "shear");
RNA_def_property_range(prop, 0.0f, 1000.0f);
RNA_def_property_ui_text(prop, "Shear Stiffness", "Shear spring stiffness");
#endif
/* unused still */
#if 0
prop = RNA_def_property(srna, "shear_stiffness_max", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "max_shear");
RNA_def_property_range(prop, 0.0f, upperLimitf);
RNA_def_property_ui_text(prop, "Shear Stiffness Maximum", "Maximum shear scaling value");
#endif
/* unused still */
#if 0
prop = RNA_def_property(srna, "effector_force_scale", PROP_FLOAT, PROP_NONE);

View File

@ -755,7 +755,7 @@ static void rna_Particle_hair_dynamics_update(Main *bmain, Scene *scene, Pointer
if (psys && !psys->clmd) {
psys->clmd = (ClothModifierData *)modifier_new(eModifierType_Cloth);
psys->clmd->sim_parms->goalspring = 0.0f;
psys->clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_GOAL | CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS;
psys->clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_GOAL | CLOTH_SIMSETTINGS_FLAG_RESIST_SPRING_COMPRESS;
psys->clmd->coll_parms->flags &= ~CLOTH_COLLSETTINGS_FLAG_SELF;
rna_Particle_redo(bmain, scene, ptr);
}

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) */