Add cloth pressure vertex group and unlock cloth shrink values range
Introduced a way to specify cloth pressure force influence with a vertex group. This will allow users to only have pressure affect certain parts of the mesh. In addition to this, the "shrink factor" is now also unlocked to allow negative values and thus allowing the cloth mesh to grow as well. Reviewed By: Jaques Lucke Differential Revision: http://developer.blender.org/D6347
This commit is contained in:
@@ -178,6 +178,7 @@ class PHYSICS_PT_cloth_pressure(PhysicButtonsPanel, Panel):
|
||||
|
||||
cloth = context.cloth.settings
|
||||
md = context.cloth
|
||||
ob = context.object
|
||||
|
||||
layout.active = cloth.use_pressure and cloth_panel_enabled(md)
|
||||
|
||||
@@ -196,6 +197,9 @@ class PHYSICS_PT_cloth_pressure(PhysicButtonsPanel, Panel):
|
||||
col = flow.column()
|
||||
col.prop(cloth, "pressure_factor", text="Factor")
|
||||
|
||||
col = flow.column()
|
||||
col.prop_search(cloth, "vertex_group_pressure", ob, "vertex_groups", text="Vertex Group")
|
||||
|
||||
|
||||
class PHYSICS_PT_cloth_cache(PhysicButtonsPanel, Panel):
|
||||
bl_label = "Cache"
|
||||
|
||||
@@ -113,8 +113,9 @@ typedef struct ClothVertex {
|
||||
float struct_stiff;
|
||||
float bend_stiff;
|
||||
float shear_stiff;
|
||||
int spring_count; /* how many springs attached? */
|
||||
float shrink_factor; /* how much to shrink this cloth */
|
||||
int spring_count; /* how many springs attached? */
|
||||
float shrink_factor; /* how much to shrink this cloth */
|
||||
float pressure_factor; /* how much pressure should affect this vertex */
|
||||
} ClothVertex;
|
||||
|
||||
/**
|
||||
|
||||
@@ -134,6 +134,7 @@ void cloth_init(ClothModifierData *clmd)
|
||||
clmd->sim_parms->uniform_pressure_force = 0.0f;
|
||||
clmd->sim_parms->target_volume = 0.0f;
|
||||
clmd->sim_parms->pressure_factor = 1.0f;
|
||||
clmd->sim_parms->vgroup_pressure = 0;
|
||||
|
||||
// also from softbodies
|
||||
clmd->sim_parms->maxgoal = 1.0f;
|
||||
@@ -651,8 +652,9 @@ int cloth_uses_vgroup(ClothModifierData *clmd)
|
||||
{
|
||||
return (((clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF) &&
|
||||
(clmd->coll_parms->vgroup_selfcol > 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_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));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -660,27 +662,16 @@ int cloth_uses_vgroup(ClothModifierData *clmd)
|
||||
*/
|
||||
static void cloth_apply_vgroup(ClothModifierData *clmd, Mesh *mesh)
|
||||
{
|
||||
/* Can be optimized to do all groups in one loop. */
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
MDeformVert *dvert = NULL;
|
||||
Cloth *clothObj = NULL;
|
||||
int mvert_num;
|
||||
/* float goalfac = 0; */ /* UNUSED */
|
||||
ClothVertex *verts = NULL;
|
||||
|
||||
if (!clmd || !mesh) {
|
||||
return;
|
||||
}
|
||||
|
||||
clothObj = clmd->clothObject;
|
||||
int mvert_num = mesh->totvert;
|
||||
|
||||
mvert_num = mesh->totvert;
|
||||
|
||||
verts = clothObj->verts;
|
||||
ClothVertex *verts = clmd->clothObject->verts;
|
||||
|
||||
if (cloth_uses_vgroup(clmd)) {
|
||||
for (i = 0; i < mvert_num; i++, verts++) {
|
||||
for (int i = 0; i < mvert_num; i++, verts++) {
|
||||
|
||||
/* Reset Goal values to standard */
|
||||
if (clmd->sim_parms->vgroup_mass > 0) {
|
||||
@@ -697,9 +688,9 @@ static void cloth_apply_vgroup(ClothModifierData *clmd, Mesh *mesh)
|
||||
verts->flags &= ~CLOTH_VERT_FLAG_PINNED;
|
||||
verts->flags &= ~CLOTH_VERT_FLAG_NOSELFCOLL;
|
||||
|
||||
dvert = CustomData_get(&mesh->vdata, i, CD_MDEFORMVERT);
|
||||
MDeformVert *dvert = CustomData_get(&mesh->vdata, i, CD_MDEFORMVERT);
|
||||
if (dvert) {
|
||||
for (j = 0; j < dvert->totweight; j++) {
|
||||
for (int j = 0; j < dvert->totweight; j++) {
|
||||
if (dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_mass - 1)) {
|
||||
verts->goal = dvert->dw[j].weight;
|
||||
|
||||
@@ -726,19 +717,21 @@ static void cloth_apply_vgroup(ClothModifierData *clmd, Mesh *mesh)
|
||||
verts->bend_stiff = dvert->dw[j].weight;
|
||||
}
|
||||
|
||||
if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF) {
|
||||
if (dvert->dw[j].def_nr == (clmd->coll_parms->vgroup_selfcol - 1)) {
|
||||
if (dvert->dw[j].weight > 0.0f) {
|
||||
verts->flags |= CLOTH_VERT_FLAG_NOSELFCOLL;
|
||||
}
|
||||
if (dvert->dw[j].def_nr == (clmd->coll_parms->vgroup_selfcol - 1)) {
|
||||
if (dvert->dw[j].weight > 0.0f) {
|
||||
verts->flags |= CLOTH_VERT_FLAG_NOSELFCOLL;
|
||||
}
|
||||
}
|
||||
if (clmd->sim_parms->vgroup_shrink > 0) {
|
||||
if (dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_shrink - 1)) {
|
||||
/* Used for linear interpolation between min and max
|
||||
* shrink factor based on weight. */
|
||||
verts->shrink_factor = dvert->dw[j].weight;
|
||||
}
|
||||
|
||||
if (dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_shrink - 1)) {
|
||||
/* Used for linear interpolation between min and max
|
||||
* shrink factor based on weight. */
|
||||
verts->shrink_factor = 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 */
|
||||
verts->pressure_factor = dvert->dw[j].weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -750,10 +743,10 @@ static float cloth_shrink_factor(ClothModifierData *clmd, ClothVertex *verts, in
|
||||
{
|
||||
/* Linear interpolation between min and max shrink factor based on weight. */
|
||||
float base = 1.0f - clmd->sim_parms->shrink_min;
|
||||
float delta = clmd->sim_parms->shrink_min - clmd->sim_parms->shrink_max;
|
||||
float shrink_factor_delta = clmd->sim_parms->shrink_min - clmd->sim_parms->shrink_max;
|
||||
|
||||
float k1 = base + delta * verts[i1].shrink_factor;
|
||||
float k2 = base + delta * verts[i2].shrink_factor;
|
||||
float k1 = base + shrink_factor_delta * verts[i1].shrink_factor;
|
||||
float k2 = base + shrink_factor_delta * verts[i2].shrink_factor;
|
||||
|
||||
/* Use geometrical mean to average two factors since it behaves better
|
||||
* for diagonals when a rectangle transforms into a trapezoid. */
|
||||
|
||||
@@ -93,9 +93,11 @@ typedef struct ClothSimSettings {
|
||||
float collider_friction;
|
||||
/** Damp the velocity to speed up getting to the resting position. */
|
||||
float vel_damping DNA_DEPRECATED;
|
||||
/** Min amount to shrink cloth by 0.0f (no shrink) - 1.0f (shrink to nothing). */
|
||||
/** Min amount to shrink cloth by 0.0f (no shrink), 1.0f (shrink to nothing), -1.0f (double the
|
||||
* edge length). */
|
||||
float shrink_min;
|
||||
/** Max amount to shrink cloth by 0.0f (no shrink) - 1.0f (shrink to nothing). */
|
||||
/** Max amount to shrink cloth by 0.0f (no shrink), 1.0f (shrink to nothing), -1.0f (double the
|
||||
* edge length). */
|
||||
float shrink_max;
|
||||
|
||||
/* Air pressure */
|
||||
@@ -107,7 +109,8 @@ typedef struct ClothSimSettings {
|
||||
pressure=( (current_volume/target_volume) - 1 + uniform_pressure_force) *
|
||||
pressure_factor */
|
||||
float pressure_factor;
|
||||
char _pad7[4];
|
||||
short vgroup_pressure;
|
||||
char _pad7[2];
|
||||
|
||||
/* XXX various hair stuff
|
||||
* should really be separate, this struct is a horrible mess already
|
||||
|
||||
@@ -291,6 +291,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_pressure_vgroup_get(PointerRNA *ptr, char *value)
|
||||
{
|
||||
ClothSimSettings *sim = (ClothSimSettings *)ptr->data;
|
||||
rna_object_vgroup_name_index_get(ptr, value, sim->vgroup_pressure);
|
||||
}
|
||||
|
||||
static int rna_ClothSettings_pressure_vgroup_length(PointerRNA *ptr)
|
||||
{
|
||||
ClothSimSettings *sim = (ClothSimSettings *)ptr->data;
|
||||
return rna_object_vgroup_name_index_length(ptr, sim->vgroup_pressure);
|
||||
}
|
||||
|
||||
static void rna_ClothSettings_pressure_vgroup_set(PointerRNA *ptr, const char *value)
|
||||
{
|
||||
ClothSimSettings *sim = (ClothSimSettings *)ptr->data;
|
||||
rna_object_vgroup_name_index_set(ptr, value, &sim->vgroup_pressure);
|
||||
}
|
||||
|
||||
static void rna_CollSettings_selfcol_vgroup_get(PointerRNA *ptr, char *value)
|
||||
{
|
||||
ClothCollSettings *coll = (ClothCollSettings *)ptr->data;
|
||||
@@ -595,14 +613,16 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
|
||||
|
||||
prop = RNA_def_property(srna, "shrink_min", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, NULL, "shrink_min");
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
RNA_def_property_range(prop, -FLT_MAX, 1.0f);
|
||||
RNA_def_property_ui_range(prop, -1.0f, 1.0f, 0.05f, 3);
|
||||
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_shrink_min_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Shrink Factor", "Factor by which to shrink cloth");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "shrink_max", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, NULL, "shrink_max");
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
RNA_def_property_range(prop, -FLT_MAX, 1.0f);
|
||||
RNA_def_property_ui_range(prop, -1.0f, 1.0f, 0.05f, 3);
|
||||
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_shrink_max_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Shrink Factor Max", "Max amount to shrink cloth by");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
@@ -803,8 +823,10 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
|
||||
RNA_def_property_float_sdna(prop, NULL, "target_volume");
|
||||
RNA_def_property_range(prop, 0.0f, 10000.0f);
|
||||
RNA_def_property_float_default(prop, 0.0f);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Target Volume", "The mesh volume where the inner/outer pressure will be the same");
|
||||
RNA_def_property_ui_text(prop,
|
||||
"Target Volume",
|
||||
"The mesh volume where the inner/outer pressure will be the same. If "
|
||||
"set to zero the volume will not contribute to the total pressure");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "pressure_factor", PROP_FLOAT, PROP_NONE);
|
||||
@@ -814,6 +836,19 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Pressure Scale", "Air pressure scaling factor");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
prop = RNA_def_property(srna, "vertex_group_pressure", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_funcs(prop,
|
||||
"rna_ClothSettings_pressure_vgroup_get",
|
||||
"rna_ClothSettings_pressure_vgroup_length",
|
||||
"rna_ClothSettings_pressure_vgroup_set");
|
||||
RNA_def_property_ui_text(
|
||||
prop,
|
||||
"Pressure Vertex Group",
|
||||
"Vertex Group for where to apply pressure. Zero weight means no "
|
||||
"pressure while a weight of one means full pressure. Faces with a vertex "
|
||||
"that has zero weight will be excluded from the volume calculation");
|
||||
RNA_def_property_update(prop, 0, "rna_cloth_update");
|
||||
|
||||
/* unused */
|
||||
|
||||
/* unused still */
|
||||
|
||||
@@ -76,18 +76,39 @@ static int cloth_count_nondiag_blocks(Cloth *cloth)
|
||||
|
||||
static float cloth_calc_volume(ClothModifierData *clmd)
|
||||
{
|
||||
/* calc the (closed) cloth volume */
|
||||
/* Calculate the (closed) cloth volume. */
|
||||
Cloth *cloth = clmd->clothObject;
|
||||
const MVertTri *tri = cloth->tri;
|
||||
Implicit_Data *data = cloth->implicit;
|
||||
float vol = 0;
|
||||
|
||||
for (unsigned int i = 0; i < cloth->tri_num; i++) {
|
||||
const MVertTri *vt = &tri[i];
|
||||
vol += BPH_tri_tetra_volume_signed_6x(data, vt->tri[0], vt->tri[1], vt->tri[2]);
|
||||
}
|
||||
if (clmd->sim_parms->vgroup_pressure > 0) {
|
||||
for (unsigned int i = 0; i < cloth->tri_num; i++) {
|
||||
bool skip_face = false;
|
||||
/* We have custom vertex weights for pressure. */
|
||||
const MVertTri *vt = &tri[i];
|
||||
for (unsigned int j = 0; j < 3; j++) {
|
||||
/* If any weight is zero, don't take this face into account for volume calculation. */
|
||||
ClothVertex *verts = clmd->clothObject->verts;
|
||||
|
||||
/* We need to divide by 6 to get the actual volume */
|
||||
if (verts[vt->tri[j]].pressure_factor == 0.0f) {
|
||||
skip_face = true;
|
||||
}
|
||||
}
|
||||
if (skip_face) {
|
||||
continue;
|
||||
}
|
||||
|
||||
vol += BPH_tri_tetra_volume_signed_6x(data, vt->tri[0], vt->tri[1], vt->tri[2]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (unsigned int i = 0; i < cloth->tri_num; i++) {
|
||||
const MVertTri *vt = &tri[i];
|
||||
vol += BPH_tri_tetra_volume_signed_6x(data, vt->tri[0], vt->tri[1], vt->tri[2]);
|
||||
}
|
||||
}
|
||||
/* We need to divide by 6 to get the actual volume. */
|
||||
vol = vol / 6.0f;
|
||||
|
||||
return vol;
|
||||
@@ -634,8 +655,38 @@ static void cloth_calc_force(
|
||||
for (i = 0; i < cloth->tri_num; i++) {
|
||||
const MVertTri *vt = &tri[i];
|
||||
if (fabs(pressure_difference) > 1E-6f) {
|
||||
BPH_mass_spring_force_pressure(
|
||||
data, vt->tri[0], vt->tri[1], vt->tri[2], pressure_difference);
|
||||
if (clmd->sim_parms->vgroup_pressure > 0) {
|
||||
/* We have custom vertex weights for pressure. */
|
||||
ClothVertex *verts = clmd->clothObject->verts;
|
||||
int v1, v2, v3;
|
||||
v1 = vt->tri[0];
|
||||
v2 = vt->tri[1];
|
||||
v3 = vt->tri[2];
|
||||
|
||||
float weights[3];
|
||||
bool skip_face = false;
|
||||
|
||||
weights[0] = verts[v1].pressure_factor;
|
||||
weights[1] = verts[v2].pressure_factor;
|
||||
weights[2] = verts[v3].pressure_factor;
|
||||
for (unsigned int j = 0; j < 3; j++) {
|
||||
if (weights[j] == 0.0f) {
|
||||
/* Exclude faces which has a zero weight vert. */
|
||||
skip_face = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (skip_face) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BPH_mass_spring_force_pressure(data, v1, v2, v3, pressure_difference, weights);
|
||||
}
|
||||
else {
|
||||
float weights[3] = {1.0f, 1.0f, 1.0f};
|
||||
BPH_mass_spring_force_pressure(
|
||||
data, vt->tri[0], vt->tri[1], vt->tri[2], pressure_difference, weights);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,8 +184,12 @@ bool BPH_mass_spring_force_spring_goal(struct Implicit_Data *data,
|
||||
|
||||
float BPH_tri_tetra_volume_signed_6x(struct Implicit_Data *data, int v1, int v2, int v3);
|
||||
|
||||
void BPH_mass_spring_force_pressure(
|
||||
struct Implicit_Data *data, int v1, int v2, int v3, float pressure_difference);
|
||||
void BPH_mass_spring_force_pressure(struct Implicit_Data *data,
|
||||
int v1,
|
||||
int v2,
|
||||
int v3,
|
||||
float pressure_difference,
|
||||
float weights[3]);
|
||||
|
||||
/* ======== Hair Volumetric Forces ======== */
|
||||
|
||||
|
||||
@@ -1489,7 +1489,7 @@ float BPH_tri_tetra_volume_signed_6x(Implicit_Data *data, int v1, int v2, int v3
|
||||
}
|
||||
|
||||
void BPH_mass_spring_force_pressure(
|
||||
Implicit_Data *data, int v1, int v2, int v3, float pressure_difference)
|
||||
Implicit_Data *data, int v1, int v2, int v3, float pressure_difference, float weights[3])
|
||||
{
|
||||
float nor[3], area;
|
||||
float factor;
|
||||
@@ -1500,9 +1500,9 @@ void BPH_mass_spring_force_pressure(
|
||||
factor = pressure_difference * area / 3.0f;
|
||||
|
||||
/* add pressure to each of the face verts */
|
||||
madd_v3_v3fl(data->F[v1], nor, factor);
|
||||
madd_v3_v3fl(data->F[v2], nor, factor);
|
||||
madd_v3_v3fl(data->F[v3], nor, factor);
|
||||
madd_v3_v3fl(data->F[v1], nor, factor * weights[0]);
|
||||
madd_v3_v3fl(data->F[v2], nor, factor * weights[1]);
|
||||
madd_v3_v3fl(data->F[v3], nor, factor * weights[2]);
|
||||
}
|
||||
|
||||
static void edge_wind_vertex(const float dir[3],
|
||||
|
||||
Reference in New Issue
Block a user