diff options
-rw-r--r-- | release/scripts/startup/bl_ui/properties_physics_cloth.py | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_cloth.h | 5 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/cloth.c | 57 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_cloth_types.h | 9 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_cloth.c | 43 | ||||
-rw-r--r-- | source/blender/physics/intern/BPH_mass_spring.cpp | 67 | ||||
-rw-r--r-- | source/blender/physics/intern/implicit.h | 8 | ||||
-rw-r--r-- | source/blender/physics/intern/implicit_blender.c | 8 |
8 files changed, 146 insertions, 55 deletions
diff --git a/release/scripts/startup/bl_ui/properties_physics_cloth.py b/release/scripts/startup/bl_ui/properties_physics_cloth.py index 1921521669e..d5ac140dc98 100644 --- a/release/scripts/startup/bl_ui/properties_physics_cloth.py +++ b/release/scripts/startup/bl_ui/properties_physics_cloth.py @@ -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" diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 0543021afef..d59a81c1baf 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -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; /** diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 2be312bc4d9..d26dca4a252 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -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. */ diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index 5653e8a0450..aca29fe1bdd 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -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 diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c index cf48ed549e6..9f6f15b8379 100644 --- a/source/blender/makesrna/intern/rna_cloth.c +++ b/source/blender/makesrna/intern/rna_cloth.c @@ -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 */ diff --git a/source/blender/physics/intern/BPH_mass_spring.cpp b/source/blender/physics/intern/BPH_mass_spring.cpp index 259eed88756..7521efa5cbd 100644 --- a/source/blender/physics/intern/BPH_mass_spring.cpp +++ b/source/blender/physics/intern/BPH_mass_spring.cpp @@ -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; + + if (verts[vt->tri[j]].pressure_factor == 0.0f) { + skip_face = true; + } + } + if (skip_face) { + continue; + } - /* We need to divide by 6 to get the actual volume */ + 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); + } } } } diff --git a/source/blender/physics/intern/implicit.h b/source/blender/physics/intern/implicit.h index 82a3f61e1e1..490e727b5f2 100644 --- a/source/blender/physics/intern/implicit.h +++ b/source/blender/physics/intern/implicit.h @@ -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 ======== */ diff --git a/source/blender/physics/intern/implicit_blender.c b/source/blender/physics/intern/implicit_blender.c index fa093f482f7..02d7fd50797 100644 --- a/source/blender/physics/intern/implicit_blender.c +++ b/source/blender/physics/intern/implicit_blender.c @@ -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], |