Add the ability to create internal springs to the cloth sim

This can be used to make closed surfaces behave more like a soft body.

Reviewed By: Jacques Lucke

Differential Revision: http://developer.blender.org/D5788
This commit is contained in:
Sebastian Parborg 2019-12-09 19:10:55 +01:00
parent e77fdc62b7
commit 62ef59aa0c
7 changed files with 454 additions and 8 deletions

View File

@ -160,6 +160,46 @@ class PHYSICS_PT_cloth_damping(PhysicButtonsPanel, Panel):
col = flow.column()
col.prop(cloth, "bending_damping", text="Bending")
class PHYSICS_PT_cloth_internal_springs(PhysicButtonsPanel, Panel):
bl_label = "Internal Springs"
bl_parent_id = 'PHYSICS_PT_cloth_physical_properties'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
def draw_header(self, context):
cloth = context.cloth.settings
self.layout.active = cloth_panel_enabled(context.cloth)
self.layout.prop(cloth, "use_internal_springs", text="")
def draw(self, context):
layout = self.layout
layout.use_property_split = True
cloth = context.cloth.settings
md = context.cloth
ob = context.object
layout.active = cloth.use_internal_springs and cloth_panel_enabled(md)
flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True)
col = flow.column()
col.prop(cloth, "internal_spring_max_length", text="Max Spring Creation Length")
col = flow.column()
col.prop(cloth, "internal_spring_max_diversion", text="Max Creation Diversion")
col = flow.column()
col.prop(cloth, "internal_spring_normal_check", text="Check Surface Normals")
col = flow.column()
col.prop(cloth, "internal_tension_stiffness", text="Tension")
col = flow.column()
col.prop(cloth, "internal_compression_stiffness", text="Compression")
col = flow.column()
col.prop_search(cloth, "vertex_group_intern", ob, "vertex_groups", text="Vertex Group")
col = flow.column()
col.prop(cloth, "internal_tension_stiffness_max", text="Max Tension")
col = flow.column()
col.prop(cloth, "internal_compression_stiffness_max", text="Max Compression")
class PHYSICS_PT_cloth_pressure(PhysicButtonsPanel, Panel):
bl_label = "Pressure"
@ -422,6 +462,7 @@ classes = (
PHYSICS_PT_cloth_physical_properties,
PHYSICS_PT_cloth_stiffness,
PHYSICS_PT_cloth_damping,
PHYSICS_PT_cloth_internal_springs,
PHYSICS_PT_cloth_pressure,
PHYSICS_PT_cloth_cache,
PHYSICS_PT_cloth_shape,

View File

@ -115,6 +115,7 @@ typedef struct ClothVertex {
float shear_stiff;
int spring_count; /* how many springs attached? */
float shrink_factor; /* how much to shrink this cloth */
float internal_stiff; /* internal spring stiffness scaling */
float pressure_factor; /* how much pressure should affect this vertex */
} ClothVertex;
@ -198,8 +199,12 @@ typedef enum {
CLOTH_SIMSETTINGS_FLAG_PRESSURE = (1 << 5),
/** Use the user defined target volume. */
CLOTH_SIMSETTINGS_FLAG_PRESSURE_VOL = (1 << 6),
/** True if internal spring generation is enabled. */
CLOTH_SIMSETTINGS_FLAG_INTERNAL_SPRINGS = (1 << 7),
/** DEPRECATED, for versioning only. */
CLOTH_SIMSETTINGS_FLAG_SCALING = (1 << 8),
/** Require internal springs to be created between points with opposite normals. */
CLOTH_SIMSETTINGS_FLAG_INTERNAL_SPRINGS_NORMAL = (1 << 9),
/** Edit cache in edit-mode. */
CLOTH_SIMSETTINGS_FLAG_CCACHE_EDIT = (1 << 12),
/** Don't allow spring compression. */
@ -230,6 +235,7 @@ typedef enum {
CLOTH_SPRING_TYPE_GOAL = (1 << 4),
CLOTH_SPRING_TYPE_SEWING = (1 << 5),
CLOTH_SPRING_TYPE_BENDING_HAIR = (1 << 6),
CLOTH_SPRING_TYPE_INTERNAL = (1 << 7),
} CLOTH_SPRING_TYPES;
/* SPRING FLAGS */

View File

@ -31,6 +31,7 @@
#include "BLI_utildefines.h"
#include "BLI_math.h"
#include "BLI_rand.h"
#include "BLI_edgehash.h"
#include "BLI_linklist.h"
@ -130,6 +131,16 @@ void cloth_init(ClothModifierData *clmd)
clmd->sim_parms->eff_force_scale = 1000.0;
clmd->sim_parms->eff_wind_scale = 250.0;
/* Internal spring settings */
clmd->sim_parms->internal_spring_max_length = 0.0f;
clmd->sim_parms->internal_spring_max_diversion = M_PI / 4.0f;
clmd->sim_parms->internal_tension = 15.0f;
clmd->sim_parms->max_internal_tension = 15.0f;
clmd->sim_parms->internal_compression = 15.0f;
clmd->sim_parms->max_internal_compression = 15.0f;
clmd->sim_parms->vgroup_intern = 0;
clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_INTERNAL_SPRINGS_NORMAL;
/* Pressure settings */
clmd->sim_parms->uniform_pressure_force = 0.0f;
clmd->sim_parms->target_volume = 0.0f;
@ -654,7 +665,7 @@ int cloth_uses_vgroup(ClothModifierData *clmd)
(clmd->coll_parms->vgroup_selfcol > 0)) ||
(clmd->sim_parms->vgroup_pressure > 0) || (clmd->sim_parms->vgroup_struct > 0) ||
(clmd->sim_parms->vgroup_bend > 0) || (clmd->sim_parms->vgroup_shrink > 0) ||
(clmd->sim_parms->vgroup_mass > 0));
(clmd->sim_parms->vgroup_intern > 0) || (clmd->sim_parms->vgroup_mass > 0));
}
/**
@ -729,8 +740,14 @@ static void cloth_apply_vgroup(ClothModifierData *clmd, Mesh *mesh)
verts->shrink_factor = dvert->dw[j].weight;
}
if (dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_intern - 1)) {
/* Used to define the stiffness weight on the internal spring connected to this vertex.
*/
verts->internal_stiff = dvert->dw[j].weight;
}
if (dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_pressure - 1)) {
/* Used to define how much the pressure settings should affect the given vertex */
/* Used to define how much the pressure settings should affect the given vertex. */
verts->pressure_factor = dvert->dw[j].weight;
}
}
@ -1144,6 +1161,11 @@ static void cloth_update_springs(ClothModifierData *clmd)
cloth->verts[spring->ij].bend_stiff) /
2.0f;
}
else if (spring->type & CLOTH_SPRING_TYPE_INTERNAL) {
spring->lin_stiffness = (cloth->verts[spring->kl].internal_stiff +
cloth->verts[spring->ij].internal_stiff) /
2.0f;
}
else if (spring->type == CLOTH_SPRING_TYPE_BENDING_HAIR) {
ClothVertex *v1 = &cloth->verts[spring->ij];
ClothVertex *v2 = &cloth->verts[spring->kl];
@ -1208,8 +1230,8 @@ static void cloth_update_spring_lengths(ClothModifierData *clmd, Mesh *mesh)
ClothSpring *spring = search->link;
if (spring->type != CLOTH_SPRING_TYPE_SEWING) {
if (spring->type &
(CLOTH_SPRING_TYPE_STRUCTURAL | CLOTH_SPRING_TYPE_SHEAR | CLOTH_SPRING_TYPE_BENDING)) {
if (spring->type & (CLOTH_SPRING_TYPE_STRUCTURAL | CLOTH_SPRING_TYPE_SHEAR |
CLOTH_SPRING_TYPE_BENDING | CLOTH_SPRING_TYPE_INTERNAL)) {
shrink_factor = cloth_shrink_factor(clmd, cloth->verts, spring->ij, spring->kl);
}
else {
@ -1385,6 +1407,85 @@ BLI_INLINE bool cloth_bend_set_poly_vert_array(int **poly, int len, const MLoop
return true;
}
static bool find_internal_spring_target_vertex(BVHTreeFromMesh *treedata,
unsigned int v_idx,
RNG *rng,
float max_length,
float max_diversion,
bool check_normal,
unsigned int *r_tar_v_idx)
{
float co[3], no[3], new_co[3];
float radius;
copy_v3_v3(co, treedata->vert[v_idx].co);
normal_short_to_float_v3(no, treedata->vert[v_idx].no);
negate_v3(no);
float vec_len = sin(max_diversion);
float offset[3];
offset[0] = 0.5f - BLI_rng_get_float(rng);
offset[1] = 0.5f - BLI_rng_get_float(rng);
offset[2] = 0.5f - BLI_rng_get_float(rng);
normalize_v3(offset);
mul_v3_fl(offset, vec_len);
add_v3_v3(no, offset);
normalize_v3(no);
/* Nudge the start point so we do not hit it with the ray. */
copy_v3_v3(new_co, no);
mul_v3_fl(new_co, FLT_EPSILON);
add_v3_v3(new_co, co);
radius = 0.0f;
if (max_length == 0.0f) {
max_length = FLT_MAX;
}
BVHTreeRayHit rayhit = {0};
rayhit.index = -1;
rayhit.dist = max_length;
BLI_bvhtree_ray_cast(
treedata->tree, new_co, no, radius, &rayhit, treedata->raycast_callback, treedata);
unsigned int vert_idx = -1;
const MLoop *mloop = treedata->loop;
const MLoopTri *lt = NULL;
if (rayhit.index != -1 && rayhit.dist <= max_length) {
if (check_normal && dot_v3v3(rayhit.no, no) < 0.0f) {
/* We hit a point that points in the same direction as our starting point. */
return false;
}
float min_len = FLT_MAX;
lt = &treedata->looptri[rayhit.index];
for (int i = 0; i < 3; i++) {
unsigned int tmp_vert_idx = mloop[lt->tri[i]].v;
if (tmp_vert_idx == v_idx) {
/* We managed to hit ourselves. */
return false;
}
float len = len_v3v3(co, rayhit.co);
if (len < min_len) {
min_len = len;
vert_idx = tmp_vert_idx;
}
}
*r_tar_v_idx = vert_idx;
return true;
}
else {
return false;
}
}
static int cloth_build_springs(ClothModifierData *clmd, Mesh *mesh)
{
Cloth *cloth = clmd->clothObject;
@ -1431,6 +1532,69 @@ static int cloth_build_springs(ClothModifierData *clmd, Mesh *mesh)
}
}
bool use_internal_springs = (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_INTERNAL_SPRINGS);
if (use_internal_springs) {
BVHTreeFromMesh treedata = {NULL};
unsigned int tar_v_idx;
BLI_bitmap *verts_used = NULL;
RNG *rng;
verts_used = BLI_BITMAP_NEW(mvert_num * mvert_num, __func__);
BKE_bvhtree_from_mesh_get(&treedata, mesh, BVHTREE_FROM_LOOPTRI, 2);
rng = BLI_rng_new_srandom(0);
for (int i = 0; i < mvert_num; i++) {
if (find_internal_spring_target_vertex(
&treedata,
i,
rng,
clmd->sim_parms->internal_spring_max_length,
clmd->sim_parms->internal_spring_max_diversion,
(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_INTERNAL_SPRINGS_NORMAL),
&tar_v_idx)) {
if (BLI_BITMAP_TEST_BOOL(verts_used, i * mvert_num + tar_v_idx)) {
continue;
}
BLI_BITMAP_ENABLE(verts_used, i * mvert_num + tar_v_idx);
BLI_BITMAP_ENABLE(verts_used, tar_v_idx * mvert_num + i);
spring = (ClothSpring *)MEM_callocN(sizeof(ClothSpring), "cloth spring");
if (spring) {
spring_verts_ordered_set(spring, i, tar_v_idx);
shrink_factor = cloth_shrink_factor(clmd, cloth->verts, spring->ij, spring->kl);
spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest,
cloth->verts[spring->ij].xrest) *
shrink_factor;
spring->lin_stiffness = (cloth->verts[spring->kl].internal_stiff +
cloth->verts[spring->ij].internal_stiff) /
2.0f;
spring->type = CLOTH_SPRING_TYPE_INTERNAL;
spring->flags = 0;
BLI_linklist_prepend(&cloth->springs, spring);
if (spring_ref) {
spring_ref[i].spring = spring;
}
}
else {
cloth_free_errorsprings(cloth, edgelist, spring_ref);
MEM_freeN(verts_used);
free_bvhtree_from_mesh(&treedata);
return 0;
}
}
}
MEM_freeN(verts_used);
free_bvhtree_from_mesh(&treedata);
BLI_rng_free(rng);
}
clmd->sim_parms->avg_spring_len = 0.0f;
for (int i = 0; i < mvert_num; i++) {
cloth->verts[i].avg_spring_len = 0.0f;

View File

@ -4268,5 +4268,19 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
{
/* Versioning code until next subversion bump goes here. */
/* Cloth internal springs */
for (Object *ob = bmain->objects.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->internal_tension = 15.0f;
clmd->sim_parms->max_internal_tension = 15.0f;
clmd->sim_parms->internal_compression = 15.0f;
clmd->sim_parms->max_internal_compression = 15.0f;
clmd->sim_parms->internal_spring_max_diversion = M_PI / 4.0f;
}
}
}
}
}

View File

@ -119,7 +119,6 @@ typedef struct ClothSimSettings {
float bending_damping;
/** Size of voxel grid cells for continuum dynamics. */
float voxel_cell_size;
char _pad[4];
/** Number of time steps per frame. */
int stepsPerFrame;
@ -145,7 +144,6 @@ typedef struct ClothSimSettings {
short presets;
short reset;
char _pad0[4];
struct EffectorWeights *effector_weights;
short bending_model;
@ -161,6 +159,20 @@ typedef struct ClothSimSettings {
float compression_damp;
/** Mechanical damping of shear springs. */
float shear_damp;
/** The maximum lenght an internal spring can have during creation. */
float internal_spring_max_length;
/** How much the interal spring can diverge from the vertex normal during creation. */
float internal_spring_max_diversion;
/** Vertex group for scaling structural stiffness. */
short vgroup_intern;
char _pad1[2];
float internal_tension;
float internal_compression;
float max_internal_tension;
float max_internal_compression;
char _pad0[4];
} ClothSimSettings;
typedef struct ClothCollSettings {

View File

@ -29,6 +29,8 @@
#include "rna_internal.h"
#include "BLI_math.h"
#include "BKE_cloth.h"
#include "BKE_modifier.h"
@ -201,6 +203,54 @@ static void rna_ClothSettings_shrink_max_set(struct PointerRNA *ptr, float value
settings->shrink_max = value;
}
static void rna_ClothSettings_internal_tension_set(struct PointerRNA *ptr, float value)
{
ClothSimSettings *settings = (ClothSimSettings *)ptr->data;
settings->internal_tension = value;
/* check for max clipping */
if (value > settings->max_internal_tension) {
settings->max_internal_tension = value;
}
}
static void rna_ClothSettings_max_internal_tension_set(struct PointerRNA *ptr, float value)
{
ClothSimSettings *settings = (ClothSimSettings *)ptr->data;
/* check for clipping */
if (value < settings->internal_tension) {
value = settings->internal_tension;
}
settings->max_internal_tension = value;
}
static void rna_ClothSettings_internal_compression_set(struct PointerRNA *ptr, float value)
{
ClothSimSettings *settings = (ClothSimSettings *)ptr->data;
settings->internal_compression = value;
/* check for max clipping */
if (value > settings->max_internal_compression) {
settings->max_internal_compression = value;
}
}
static void rna_ClothSettings_max_internal_compression_set(struct PointerRNA *ptr, float value)
{
ClothSimSettings *settings = (ClothSimSettings *)ptr->data;
/* check for clipping */
if (value < settings->internal_compression) {
value = settings->internal_compression;
}
settings->max_internal_compression = value;
}
static void rna_ClothSettings_mass_vgroup_get(PointerRNA *ptr, char *value)
{
ClothSimSettings *sim = (ClothSimSettings *)ptr->data;
@ -291,6 +341,24 @@ static void rna_ClothSettings_bend_vgroup_set(PointerRNA *ptr, const char *value
rna_object_vgroup_name_index_set(ptr, value, &sim->vgroup_bend);
}
static void rna_ClothSettings_internal_vgroup_get(PointerRNA *ptr, char *value)
{
ClothSimSettings *sim = (ClothSimSettings *)ptr->data;
rna_object_vgroup_name_index_get(ptr, value, sim->vgroup_intern);
}
static int rna_ClothSettings_internal_vgroup_length(PointerRNA *ptr)
{
ClothSimSettings *sim = (ClothSimSettings *)ptr->data;
return rna_object_vgroup_name_index_length(ptr, sim->vgroup_intern);
}
static void rna_ClothSettings_internal_vgroup_set(PointerRNA *ptr, const char *value)
{
ClothSimSettings *sim = (ClothSimSettings *)ptr->data;
rna_object_vgroup_name_index_set(ptr, value, &sim->vgroup_intern);
}
static void rna_ClothSettings_pressure_vgroup_get(PointerRNA *ptr, char *value)
{
ClothSimSettings *sim = (ClothSimSettings *)ptr->data;
@ -393,6 +461,18 @@ static char *rna_ClothCollisionSettings_path(PointerRNA *ptr)
}
}
static int rna_ClothSettings_internal_editable(struct PointerRNA *ptr, const char **r_info)
{
ClothSimSettings *sim = (ClothSimSettings *)ptr->data;
if (sim && (sim->bending_model == CLOTH_BENDING_LINEAR)) {
*r_info = "Only available with angular bending springs.";
return 0;
}
return sim ? PROP_EDITABLE : 0;
}
#else
static void rna_def_cloth_solver_result(BlenderRNA *brna)
@ -794,6 +874,96 @@ 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, "use_internal_springs", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_SIMSETTINGS_FLAG_INTERNAL_SPRINGS);
RNA_def_property_ui_text(prop,
"Create Internal Springs",
"Simulate an internal volume structure by creating springs connecting "
"the opposite sides of the mesh");
RNA_def_property_update(prop, 0, "rna_cloth_update");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
prop = RNA_def_property(srna, "internal_spring_normal_check", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(
prop, NULL, "flags", CLOTH_SIMSETTINGS_FLAG_INTERNAL_SPRINGS_NORMAL);
RNA_def_property_ui_text(prop,
"Check Internal Spring Normals",
"Require the points the internal springs connect to have opposite "
"normal directions");
RNA_def_property_editable_func(prop, "rna_ClothSettings_internal_editable");
RNA_def_property_update(prop, 0, "rna_cloth_update");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
prop = RNA_def_property(srna, "internal_spring_max_length", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "internal_spring_max_length");
RNA_def_property_range(prop, 0.0f, 1000.0f);
RNA_def_property_ui_text(
prop,
"Internal Spring Max Length",
"The maximum length an internal spring can have during creation. If the distance between "
"internal points is greater than this, no internal spring will be created between these "
"points. "
"A length of zero means that there is no length limit");
RNA_def_property_editable_func(prop, "rna_ClothSettings_internal_editable");
RNA_def_property_update(prop, 0, "rna_cloth_update");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
prop = RNA_def_property(srna, "internal_spring_max_diversion", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "internal_spring_max_diversion");
RNA_def_property_range(prop, 0.0f, M_PI / 4.0f);
RNA_def_property_ui_text(prop,
"Internal Spring Max Diversion",
"How much the rays used to connect the internal points can diverge "
"from the vertex normal");
RNA_def_property_editable_func(prop, "rna_ClothSettings_internal_editable");
RNA_def_property_update(prop, 0, "rna_cloth_update");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
prop = RNA_def_property(srna, "internal_tension_stiffness", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "internal_tension");
RNA_def_property_range(prop, 0.0f, 10000.0f);
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_internal_tension_set", NULL);
RNA_def_property_ui_text(prop, "Tension Stiffness", "How much the material resists stretching");
RNA_def_property_editable_func(prop, "rna_ClothSettings_internal_editable");
RNA_def_property_update(prop, 0, "rna_cloth_update");
prop = RNA_def_property(srna, "internal_tension_stiffness_max", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "max_internal_tension");
RNA_def_property_range(prop, 0.0f, 10000.0f);
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_max_internal_tension_set", NULL);
RNA_def_property_ui_text(prop, "Tension Stiffness Maximum", "Maximum tension stiffness value");
RNA_def_property_editable_func(prop, "rna_ClothSettings_internal_editable");
RNA_def_property_update(prop, 0, "rna_cloth_update");
prop = RNA_def_property(srna, "internal_compression_stiffness", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "internal_compression");
RNA_def_property_range(prop, 0.0f, 10000.0f);
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_internal_compression_set", NULL);
RNA_def_property_ui_text(
prop, "Compression Stiffness", "How much the material resists compression");
RNA_def_property_editable_func(prop, "rna_ClothSettings_internal_editable");
RNA_def_property_update(prop, 0, "rna_cloth_update");
prop = RNA_def_property(srna, "internal_compression_stiffness_max", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "max_internal_compression");
RNA_def_property_range(prop, 0.0f, 10000.0f);
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_max_internal_compression_set", NULL);
RNA_def_property_ui_text(
prop, "Compression Stiffness Maximum", "Maximum compression stiffness value");
RNA_def_property_editable_func(prop, "rna_ClothSettings_internal_editable");
RNA_def_property_update(prop, 0, "rna_cloth_update");
prop = RNA_def_property(srna, "vertex_group_intern", PROP_STRING, PROP_NONE);
RNA_def_property_string_funcs(prop,
"rna_ClothSettings_internal_vgroup_get",
"rna_ClothSettings_internal_vgroup_length",
"rna_ClothSettings_internal_vgroup_set");
RNA_def_property_ui_text(prop,
"Internal Springs Vertex Group",
"Vertex group for fine control over the internal spring stiffness");
RNA_def_property_editable_func(prop, "rna_ClothSettings_internal_editable");
RNA_def_property_update(prop, 0, "rna_cloth_update");
/* Pressure */
prop = RNA_def_property(srna, "use_pressure", PROP_BOOLEAN, PROP_NONE);

View File

@ -427,7 +427,8 @@ BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s)
}
/* Calculate force of structural + shear springs. */
if (s->type & (CLOTH_SPRING_TYPE_STRUCTURAL | CLOTH_SPRING_TYPE_SEWING)) {
if (s->type &
(CLOTH_SPRING_TYPE_STRUCTURAL | CLOTH_SPRING_TYPE_SEWING | CLOTH_SPRING_TYPE_INTERNAL)) {
#ifdef CLOTH_FORCE_SPRING_STRUCTURAL
float k_tension, scaling_tension;
@ -453,7 +454,7 @@ BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s)
false,
parms->max_sewing);
}
else {
else if (s->type & CLOTH_SPRING_TYPE_STRUCTURAL) {
float k_compression, scaling_compression;
scaling_compression = parms->compression +
s->lin_stiffness * fabsf(parms->max_compression - parms->compression);
@ -471,6 +472,44 @@ BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s)
using_angular,
0.0f);
}
else {
/* CLOTH_SPRING_TYPE_INTERNAL */
BLI_assert(s->type & CLOTH_SPRING_TYPE_INTERNAL);
scaling_tension = parms->internal_tension +
s->lin_stiffness *
fabsf(parms->max_internal_tension - parms->internal_tension);
k_tension = scaling_tension / (parms->avg_spring_len + FLT_EPSILON);
float scaling_compression = parms->internal_compression +
s->lin_stiffness * fabsf(parms->max_internal_compression -
parms->internal_compression);
float k_compression = scaling_compression / (parms->avg_spring_len + FLT_EPSILON);
float k_tension_damp = parms->tension_damp;
float k_compression_damp = parms->compression_damp;
if (k_tension == 0.0f) {
/* No damping so it behaves as if no tension spring was there at all. */
k_tension_damp = 0.0f;
}
if (k_compression == 0.0f) {
/* No damping so it behaves as if no compression spring was there at all. */
k_compression_damp = 0.0f;
}
BPH_mass_spring_force_spring_linear(data,
s->ij,
s->kl,
s->restlen,
k_tension,
k_tension_damp,
k_compression,
k_compression_damp,
resist_compress,
using_angular,
0.0f);
}
#endif
}
else if (s->type & CLOTH_SPRING_TYPE_SHEAR) {