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-11-27 16:56:16 +0300
committerSebastian Parborg <darkdefende@gmail.com>2019-11-27 17:01:15 +0300
commitf6cefbef22c8c6583b4927c179dabac3eb57aa22 (patch)
tree96785e2ee93f34bb14975a53bc2a4e003ee3fb59
parenteb798de101ac7946e2d719e763ad1f0fd3e26acd (diff)
Fix T30941: Add cloth air pressure simulation
This adds some basic simulation of internal air pressure inside of closed cloth mesh objects. Reviewed By: Jacques Lucke Differential Revision: http://developer.blender.org/D5473
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_cloth.py37
-rw-r--r--source/blender/blenkernel/BKE_cloth.h7
-rw-r--r--source/blender/blenkernel/intern/cloth.c17
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c4
-rw-r--r--source/blender/blenlib/BLI_math_geom.h3
-rw-r--r--source/blender/blenlib/intern/math_geom.c19
-rw-r--r--source/blender/blenloader/intern/versioning_280.c10
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.c5
-rw-r--r--source/blender/makesdna/DNA_cloth_types.h11
-rw-r--r--source/blender/makesrna/intern/rna_cloth.c40
-rw-r--r--source/blender/physics/BPH_mass_spring.h1
-rw-r--r--source/blender/physics/intern/BPH_mass_spring.cpp69
-rw-r--r--source/blender/physics/intern/implicit.h5
-rw-r--r--source/blender/physics/intern/implicit_blender.c24
14 files changed, 242 insertions, 10 deletions
diff --git a/release/scripts/startup/bl_ui/properties_physics_cloth.py b/release/scripts/startup/bl_ui/properties_physics_cloth.py
index 3e87c9cd0c0..1921521669e 100644
--- a/release/scripts/startup/bl_ui/properties_physics_cloth.py
+++ b/release/scripts/startup/bl_ui/properties_physics_cloth.py
@@ -161,6 +161,42 @@ class PHYSICS_PT_cloth_damping(PhysicButtonsPanel, Panel):
col.prop(cloth, "bending_damping", text="Bending")
+class PHYSICS_PT_cloth_pressure(PhysicButtonsPanel, Panel):
+ bl_label = "Pressure"
+ 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_pressure", text="")
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ cloth = context.cloth.settings
+ md = context.cloth
+
+ layout.active = cloth.use_pressure 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, "uniform_pressure_force")
+
+ col = flow.column()
+ col.prop(cloth, "use_pressure_volume", text="Custom volume")
+
+ col = flow.column()
+ col.active = cloth.use_pressure_volume
+ col.prop(cloth, "target_volume")
+
+ col = flow.column()
+ col.prop(cloth, "pressure_factor", text="Factor")
+
+
class PHYSICS_PT_cloth_cache(PhysicButtonsPanel, Panel):
bl_label = "Cache"
bl_parent_id = 'PHYSICS_PT_cloth'
@@ -382,6 +418,7 @@ classes = (
PHYSICS_PT_cloth_physical_properties,
PHYSICS_PT_cloth_stiffness,
PHYSICS_PT_cloth_damping,
+ PHYSICS_PT_cloth_pressure,
PHYSICS_PT_cloth_cache,
PHYSICS_PT_cloth_shape,
PHYSICS_PT_cloth_collision,
diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h
index 01f94c39215..0543021afef 100644
--- a/source/blender/blenkernel/BKE_cloth.h
+++ b/source/blender/blenkernel/BKE_cloth.h
@@ -87,7 +87,8 @@ typedef struct Cloth {
struct MVertTri *tri;
struct Implicit_Data *implicit; /* our implicit solver connects to this pointer */
struct EdgeSet *edgeset; /* used for selfcollisions */
- int last_frame, pad4;
+ int last_frame;
+ float initial_mesh_volume; /* Initial volume of the mesh. Used for pressure */
} Cloth;
/**
@@ -192,6 +193,10 @@ typedef enum {
CLOTH_SIMSETTINGS_FLAG_GOAL = (1 << 3),
/** True if tearing is enabled. */
CLOTH_SIMSETTINGS_FLAG_TEARING = (1 << 4),
+ /** True if pressure sim is enabled. */
+ CLOTH_SIMSETTINGS_FLAG_PRESSURE = (1 << 5),
+ /** Use the user defined target volume. */
+ CLOTH_SIMSETTINGS_FLAG_PRESSURE_VOL = (1 << 6),
/** DEPRECATED, for versioning only. */
CLOTH_SIMSETTINGS_FLAG_SCALING = (1 << 8),
/** Edit cache in edit-mode. */
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index 463cbd4f378..2be312bc4d9 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -130,6 +130,11 @@ void cloth_init(ClothModifierData *clmd)
clmd->sim_parms->eff_force_scale = 1000.0;
clmd->sim_parms->eff_wind_scale = 250.0;
+ /* Pressure settings */
+ clmd->sim_parms->uniform_pressure_force = 0.0f;
+ clmd->sim_parms->target_volume = 0.0f;
+ clmd->sim_parms->pressure_factor = 1.0f;
+
// also from softbodies
clmd->sim_parms->maxgoal = 1.0f;
clmd->sim_parms->mingoal = 0.0f;
@@ -291,6 +296,12 @@ static int do_init_cloth(Object *ob, ClothModifierData *clmd, Mesh *result, int
BKE_cloth_solver_set_positions(clmd);
+ ClothSimSettings *parms = clmd->sim_parms;
+ if (parms->flags & CLOTH_SIMSETTINGS_FLAG_PRESSURE &&
+ !(parms->flags & CLOTH_SIMSETTINGS_FLAG_PRESSURE_VOL)) {
+ BKE_cloth_solver_set_volume(clmd);
+ }
+
clmd->clothObject->last_frame = MINFRAME - 1;
clmd->sim_parms->dt = 1.0f / clmd->sim_parms->stepsPerFrame;
}
@@ -1742,6 +1753,6 @@ static int cloth_build_springs(ClothModifierData *clmd, Mesh *mesh)
return 1;
} /* cloth_build_springs */
-/***************************************************************************************
- * SPRING NETWORK GPU_BATCH_BUILDING IMPLEMENTATION END
- ***************************************************************************************/
+ /***************************************************************************************
+ * SPRING NETWORK GPU_BATCH_BUILDING IMPLEMENTATION END
+ ***************************************************************************************/
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index 2b3051b766a..7b655b2d8fc 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -2392,9 +2392,7 @@ static float mesh_calc_poly_volume_centroid(const MPoly *mpoly,
/* Calculate the 6x volume of the tetrahedron formed by the 3 vertices
* of the triangle and the origin as the fourth vertex */
- float v_cross[3];
- cross_v3_v3v3(v_cross, v_pivot, v_step1);
- const float tetra_volume = dot_v3v3(v_cross, v_step2);
+ const float tetra_volume = volume_tri_tetrahedron_signed_v3_6x(v_pivot, v_step1, v_step2);
total_volume += tetra_volume;
/* Calculate the centroid of the tetrahedron formed by the 3 vertices
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h
index eec5d214473..4f8810d50e1 100644
--- a/source/blender/blenlib/BLI_math_geom.h
+++ b/source/blender/blenlib/BLI_math_geom.h
@@ -92,6 +92,9 @@ float volume_tetrahedron_signed_v3(const float v1[3],
const float v3[3],
const float v4[3]);
+float volume_tri_tetrahedron_signed_v3_6x(const float v1[3], const float v2[3], const float v3[3]);
+float volume_tri_tetrahedron_signed_v3(const float v1[3], const float v2[3], const float v3[3]);
+
bool is_edge_convex_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3]);
bool is_quad_convex_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3]);
bool is_quad_convex_v2(const float v1[2], const float v2[2], const float v3[2], const float v4[2]);
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index 27715ed49b5..ba2a8605dec 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -300,6 +300,25 @@ float volume_tetrahedron_signed_v3(const float v1[3],
return determinant_m3_array(m) / 6.0f;
}
+/**
+ * The volume from a triangle that is made into a tetrahedron.
+ * This uses a simplified formula where the tip of the tetrahedron is in the world origin.
+ * Using this method, the total volume of a closed triangle mesh can be calculated.
+ * Note that you need to divide the result by 6 to get the actual volume.
+ */
+float volume_tri_tetrahedron_signed_v3_6x(const float v1[3], const float v2[3], const float v3[3])
+{
+ float v_cross[3];
+ cross_v3_v3v3(v_cross, v1, v2);
+ float tetra_volume = dot_v3v3(v_cross, v3);
+ return tetra_volume;
+}
+
+float volume_tri_tetrahedron_signed_v3(const float v1[3], const float v2[3], const float v3[3])
+{
+ return volume_tri_tetrahedron_signed_v3_6x(v1, v2, v3) / 6.0f;
+}
+
/********************************* Distance **********************************/
/* distance p to line v1-v2
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index 8a3ec61bbc8..0cb68cfd7fe 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -3977,5 +3977,15 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
br->pose_smooth_iterations = 4;
}
}
+ /* Cloth pressure */
+ 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->pressure_factor = 1;
+ }
+ }
+ }
}
}
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c
index bb96b4ba10c..e4d73c2b229 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.c
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.c
@@ -2048,14 +2048,13 @@ static float p_collapse_cost(PEdge *edge, PEdge *pair)
float *co2 = e->next->next->vert->co;
if ((e->face != oldf1) && (e->face != oldf2)) {
- float tetrav2[3], tetrav3[3], c[3];
+ float tetrav2[3], tetrav3[3];
/* tetrahedron volume = (1/3!)*|a.(b x c)| */
sub_v3_v3v3(tetrav2, co1, oldv->co);
sub_v3_v3v3(tetrav3, co2, oldv->co);
- cross_v3_v3v3(c, tetrav2, tetrav3);
+ volumecost += fabsf(volume_tri_tetrahedron_signed_v3(tetrav2, tetrav3, edgevec));
- volumecost += fabsf(dot_v3v3(edgevec, c) / 6.0f);
# if 0
shapecost += dot_v3v3(co1, keepv->co);
diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h
index 9cedd8f0ebf..5653e8a0450 100644
--- a/source/blender/makesdna/DNA_cloth_types.h
+++ b/source/blender/makesdna/DNA_cloth_types.h
@@ -98,6 +98,17 @@ typedef struct ClothSimSettings {
/** Max amount to shrink cloth by 0.0f (no shrink) - 1.0f (shrink to nothing). */
float shrink_max;
+ /* Air pressure */
+ /* The uniform pressure that is constanty applied to the mesh. Can be negative */
+ float uniform_pressure_force;
+ /* User set volume. This is the volume the mesh wants to expand to (the equilibrium volume). */
+ float target_volume;
+ /* The scaling factor to apply to the actual pressure.
+ pressure=( (current_volume/target_volume) - 1 + uniform_pressure_force) *
+ pressure_factor */
+ float pressure_factor;
+ char _pad7[4];
+
/* 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 e1a06a76235..cf48ed549e6 100644
--- a/source/blender/makesrna/intern/rna_cloth.c
+++ b/source/blender/makesrna/intern/rna_cloth.c
@@ -774,6 +774,46 @@ 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);
+ /* Pressure */
+
+ prop = RNA_def_property(srna, "use_pressure", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_SIMSETTINGS_FLAG_PRESSURE);
+ RNA_def_property_ui_text(prop, "Use Pressure", "Simulate pressure inside a closed cloth mesh");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, 0, "rna_cloth_update");
+
+ prop = RNA_def_property(srna, "use_pressure_volume", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_SIMSETTINGS_FLAG_PRESSURE_VOL);
+ RNA_def_property_ui_text(
+ prop, "Use Custom Volume", "Use the Volume parameter as the initial volume");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, 0, "rna_cloth_update");
+
+ prop = RNA_def_property(srna, "uniform_pressure_force", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "uniform_pressure_force");
+ RNA_def_property_range(prop, -10000.0f, 10000.0f);
+ RNA_def_property_float_default(prop, 0.0f);
+ RNA_def_property_ui_text(
+ prop,
+ "Pressure",
+ "The uniform pressure that is constanty applied to the mesh. Can be negative");
+ RNA_def_property_update(prop, 0, "rna_cloth_update");
+
+ prop = RNA_def_property(srna, "target_volume", PROP_FLOAT, PROP_NONE);
+ 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_update(prop, 0, "rna_cloth_update");
+
+ prop = RNA_def_property(srna, "pressure_factor", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "pressure_factor");
+ RNA_def_property_range(prop, 0.0f, 10000.0f);
+ RNA_def_property_float_default(prop, 1.0f);
+ RNA_def_property_ui_text(prop, "Pressure Scale", "Air pressure scaling factor");
+ RNA_def_property_update(prop, 0, "rna_cloth_update");
+
/* unused */
/* unused still */
diff --git a/source/blender/physics/BPH_mass_spring.h b/source/blender/physics/BPH_mass_spring.h
index c0ceff4d8cf..5a8c78812a4 100644
--- a/source/blender/physics/BPH_mass_spring.h
+++ b/source/blender/physics/BPH_mass_spring.h
@@ -53,6 +53,7 @@ int BPH_cloth_solve(struct Depsgraph *depsgraph,
struct ClothModifierData *clmd,
struct ListBase *effectors);
void BKE_cloth_solver_set_positions(struct ClothModifierData *clmd);
+void BKE_cloth_solver_set_volume(ClothModifierData *clmd);
#ifdef __cplusplus
}
diff --git a/source/blender/physics/intern/BPH_mass_spring.cpp b/source/blender/physics/intern/BPH_mass_spring.cpp
index c057e74b72b..259eed88756 100644
--- a/source/blender/physics/intern/BPH_mass_spring.cpp
+++ b/source/blender/physics/intern/BPH_mass_spring.cpp
@@ -74,6 +74,25 @@ static int cloth_count_nondiag_blocks(Cloth *cloth)
return nondiag;
}
+static float cloth_calc_volume(ClothModifierData *clmd)
+{
+ /* calc 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]);
+ }
+
+ /* We need to divide by 6 to get the actual volume */
+ vol = vol / 6.0f;
+
+ return vol;
+}
+
int BPH_cloth_solver_init(Object *UNUSED(ob), ClothModifierData *clmd)
{
Cloth *cloth = clmd->clothObject;
@@ -127,6 +146,13 @@ void BKE_cloth_solver_set_positions(ClothModifierData *clmd)
}
}
+void BKE_cloth_solver_set_volume(ClothModifierData *clmd)
+{
+ Cloth *cloth = clmd->clothObject;
+
+ cloth->initial_mesh_volume = cloth_calc_volume(clmd);
+}
+
static bool collision_response(ClothModifierData *clmd,
CollisionModifierData *collmd,
CollPair *collpair,
@@ -526,6 +552,7 @@ static void cloth_calc_force(
{
/* Collect forces and derivatives: F, dFdX, dFdV */
Cloth *cloth = clmd->clothObject;
+ ClothSimSettings *parms = clmd->sim_parms;
Implicit_Data *data = cloth->implicit;
unsigned int i = 0;
float drag = clmd->sim_parms->Cvi * 0.01f; /* viscosity of air scaled in percent */
@@ -570,6 +597,48 @@ static void cloth_calc_force(
#ifdef CLOTH_FORCE_DRAG
BPH_mass_spring_force_drag(data, drag);
#endif
+ /* handle pressure forces */
+ if (parms->flags & CLOTH_SIMSETTINGS_FLAG_PRESSURE) {
+ /* The difference in pressure between the inside and outside of the mesh.*/
+ float pressure_difference = 0.0f;
+
+ float init_vol;
+ if (parms->flags & CLOTH_SIMSETTINGS_FLAG_PRESSURE_VOL) {
+ init_vol = clmd->sim_parms->target_volume;
+ }
+ else {
+ init_vol = cloth->initial_mesh_volume;
+ }
+
+ /* Check if we need to calculate the volume of the mesh. */
+ if (init_vol > 1E-6f) {
+ float f;
+ float vol = cloth_calc_volume(clmd);
+
+ /* Calculate an artifical maximum value for cloth pressure. */
+ f = fabs(clmd->sim_parms->uniform_pressure_force) + 200.0f;
+
+ /* Clamp the cloth pressure to the calculated maximum value. */
+ if (vol * f < init_vol) {
+ pressure_difference = f;
+ }
+ else {
+ /* If the volume is the same don't apply any pressure. */
+ pressure_difference = (init_vol / vol) - 1;
+ }
+ }
+ pressure_difference += clmd->sim_parms->uniform_pressure_force;
+
+ pressure_difference *= clmd->sim_parms->pressure_factor;
+
+ 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);
+ }
+ }
+ }
/* handle external forces like wind */
if (effectors) {
diff --git a/source/blender/physics/intern/implicit.h b/source/blender/physics/intern/implicit.h
index 32416fa01ab..82a3f61e1e1 100644
--- a/source/blender/physics/intern/implicit.h
+++ b/source/blender/physics/intern/implicit.h
@@ -182,6 +182,11 @@ bool BPH_mass_spring_force_spring_goal(struct Implicit_Data *data,
float stiffness,
float damping);
+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);
+
/* ======== Hair Volumetric Forces ======== */
struct HairGrid;
diff --git a/source/blender/physics/intern/implicit_blender.c b/source/blender/physics/intern/implicit_blender.c
index d8b3f647591..fa093f482f7 100644
--- a/source/blender/physics/intern/implicit_blender.c
+++ b/source/blender/physics/intern/implicit_blender.c
@@ -1469,6 +1469,7 @@ void BPH_mass_spring_force_face_wind(
/* calculate face normal and area */
area = calc_nor_area_tri(nor, data->X[v1], data->X[v2], data->X[v3]);
+ /* The force is calculated and split up evenly for each of the three face verts */
factor = effector_scale * area / 3.0f;
world_to_root_v3(data, v1, win, winvec[v1]);
@@ -1481,6 +1482,29 @@ void BPH_mass_spring_force_face_wind(
madd_v3_v3fl(data->F[v3], nor, factor * dot_v3v3(win, nor));
}
+float BPH_tri_tetra_volume_signed_6x(Implicit_Data *data, int v1, int v2, int v3)
+{
+ /* The result will be 6x the volume */
+ return volume_tri_tetrahedron_signed_v3_6x(data->X[v1], data->X[v2], data->X[v3]);
+}
+
+void BPH_mass_spring_force_pressure(
+ Implicit_Data *data, int v1, int v2, int v3, float pressure_difference)
+{
+ float nor[3], area;
+ float factor;
+
+ /* calculate face normal and area */
+ area = calc_nor_area_tri(nor, data->X[v1], data->X[v2], data->X[v3]);
+ /* The force is calculated and split up evenly for each of the three face verts */
+ 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);
+}
+
static void edge_wind_vertex(const float dir[3],
float length,
float radius,