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:
parent
e77fdc62b7
commit
62ef59aa0c
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue