Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Parborg <darkdefende@gmail.com>2019-12-09 21:10:55 +0300
committerSebastian Parborg <darkdefende@gmail.com>2019-12-09 21:18:10 +0300
commit62ef59aa0cca736b09192b67cc924180d9c2f9f9 (patch)
treef0f76383b9536a5186abe0072b1a535e587cef22
parente77fdc62b75a3b96e4c3ca5c2fc4025d8091ff99 (diff)
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
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_cloth.py41
-rw-r--r--source/blender/blenkernel/BKE_cloth.h6
-rw-r--r--source/blender/blenkernel/intern/cloth.c172
-rw-r--r--source/blender/blenloader/intern/versioning_280.c14
-rw-r--r--source/blender/makesdna/DNA_cloth_types.h16
-rw-r--r--source/blender/makesrna/intern/rna_cloth.c170
-rw-r--r--source/blender/physics/intern/BPH_mass_spring.cpp43
7 files changed, 454 insertions, 8 deletions
diff --git a/release/scripts/startup/bl_ui/properties_physics_cloth.py b/release/scripts/startup/bl_ui/properties_physics_cloth.py
index d5ac140dc98..cd7e99f255c 100644
--- a/release/scripts/startup/bl_ui/properties_physics_cloth.py
+++ b/release/scripts/startup/bl_ui/properties_physics_cloth.py
@@ -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,
diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h
index d59a81c1baf..17de53be42a 100644
--- a/source/blender/blenkernel/BKE_cloth.h
+++ b/source/blender/blenkernel/BKE_cloth.h
@@ -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 */
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index d80fae29cc8..c26800aefba 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -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;
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index 6c8b14ad5c7..5c7fda67ff0 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -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;
+ }
+ }
+ }
}
}
diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h
index aca29fe1bdd..8f3a26cf9c0 100644
--- a/source/blender/makesdna/DNA_cloth_types.h
+++ b/source/blender/makesdna/DNA_cloth_types.h
@@ -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 {
diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c
index 9f6f15b8379..c000e1059e6 100644
--- a/source/blender/makesrna/intern/rna_cloth.c
+++ b/source/blender/makesrna/intern/rna_cloth.c
@@ -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);
diff --git a/source/blender/physics/intern/BPH_mass_spring.cpp b/source/blender/physics/intern/BPH_mass_spring.cpp
index 7521efa5cbd..999cefde104 100644
--- a/source/blender/physics/intern/BPH_mass_spring.cpp
+++ b/source/blender/physics/intern/BPH_mass_spring.cpp
@@ -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) {