diff --git a/release/scripts/startup/bl_ui/properties_physics_cloth.py b/release/scripts/startup/bl_ui/properties_physics_cloth.py index 40f7cfca263..6fdb5932d7d 100644 --- a/release/scripts/startup/bl_ui/properties_physics_cloth.py +++ b/release/scripts/startup/bl_ui/properties_physics_cloth.py @@ -199,6 +199,12 @@ class PHYSICS_PT_cloth_shape(PhysicButtonsPanel, Panel): col.separator() + col.prop(cloth, "cloth_pressure") + col.prop(cloth, "init_volume") + col.prop(cloth, "pressure_scale", text="Scale") + + col.separator() + col = flow.column(align=True) col.prop(cloth, "use_sewing_springs", text="Sewing") diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 63d58f7e32e..acdef240564 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; + /* Presure settings */ + clmd->sim_parms->cloth_pressure = 0.0f; + clmd->sim_parms->init_volume = 0.0f; + clmd->sim_parms->pressure_scale = 1.0f; + // also from softbodies clmd->sim_parms->maxgoal = 1.0f; clmd->sim_parms->mingoal = 0.0f; @@ -1742,6 +1747,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/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index 9cedd8f0ebf..c5ec4f87b89 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -98,6 +98,14 @@ typedef struct ClothSimSettings { /** Max amount to shrink cloth by 0.0f (no shrink) - 1.0f (shrink to nothing). */ float shrink_max; + /* some new properties */ + float cloth_pressure; /* air pressure: the pressure differenct of inner and outer air. can be + negative */ + float init_volume; /* air pressure: inner air ammount */ + float pressure_scale; /* air pressure: scaling factor: + pressure=(current_volume/init_volume+cloth_pressure)*pressure_scale */ + 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 548ed656d7b..154fa4ba5e9 100644 --- a/source/blender/makesrna/intern/rna_cloth.c +++ b/source/blender/makesrna/intern/rna_cloth.c @@ -774,6 +774,30 @@ 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); + // new properties + + prop = RNA_def_property(srna, "cloth_pressure", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "cloth_pressure"); + 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 pressure difference of inner and outer air. Can be negative"); + RNA_def_property_update(prop, 0, "rna_cloth_update"); + + prop = RNA_def_property(srna, "init_volume", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "init_volume"); + RNA_def_property_range(prop, 0.0f, 10000.0f); + RNA_def_property_float_default(prop, 0.0f); + RNA_def_property_ui_text(prop, "Volume", "Inner air amount (volume)"); + RNA_def_property_update(prop, 0, "rna_cloth_update"); + + prop = RNA_def_property(srna, "pressure_scale", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "pressure_scale"); + 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/intern/BPH_mass_spring.cpp b/source/blender/physics/intern/BPH_mass_spring.cpp index 95c16c2f033..ba38924a294 100644 --- a/source/blender/physics/intern/BPH_mass_spring.cpp +++ b/source/blender/physics/intern/BPH_mass_spring.cpp @@ -533,6 +533,8 @@ static void cloth_calc_force( const MVertTri *tri = cloth->tri; unsigned int mvert_num = cloth->mvert_num; ClothVertex *vert; + int calc_pressure = 0; + float cloth_pressure = 0.0f; #ifdef CLOTH_FORCE_GRAVITY /* global acceleration (gravitation) */ @@ -571,23 +573,73 @@ static void cloth_calc_force( BPH_mass_spring_force_drag(data, drag); #endif + /* Check if we need to calculate pressure */ + if (fabs(clmd->sim_parms->cloth_pressure) > 1E-6f || clmd->sim_parms->init_volume > 1E-6f) { + calc_pressure = 1; + } + /* handle external forces like wind */ - if (effectors) { + if (effectors || calc_pressure) { /* cache per-vertex forces to avoid redundant calculation */ float(*winvec)[3] = (float(*)[3])MEM_callocN(sizeof(float[3]) * mvert_num, "effector forces"); - for (i = 0; i < cloth->mvert_num; i++) { - float x[3], v[3]; - EffectedPoint epoint; + if (effectors) { + for (i = 0; i < cloth->mvert_num; i++) { + float x[3], v[3]; + EffectedPoint epoint; + + BPH_mass_spring_get_motion_state(data, i, x, v); + pd_point_from_loc(scene, x, v, i, &epoint); + BKE_effectors_apply( + effectors, NULL, clmd->sim_parms->effector_weights, &epoint, winvec[i], NULL); + } + } + + if (calc_pressure) { + // check if we need to calculate volume + if (clmd->sim_parms->init_volume > 1E-6f) { + float f; + + // calc the volume of (closed) cloth + for (i = 0; i < cloth->tri_num; i++) { + const MVertTri *vt = &tri[i]; + unsigned int v1 = vt->tri[0]; + unsigned int v2 = vt->tri[1]; + unsigned int v3 = vt->tri[2]; + + float vol = BPH_volume(data, v1, v2, v3); + + cloth_pressure += vol; + } - BPH_mass_spring_get_motion_state(data, i, x, v); - pd_point_from_loc(scene, x, v, i, &epoint); - BKE_effectors_apply( - effectors, NULL, clmd->sim_parms->effector_weights, &epoint, winvec[i], NULL); + // divide by 6 to get real volume + cloth_pressure /= 6.0f; + + // calculate an artifical maximum value for cloth pressure. + // TODO: adjuatable + f = fabs(clmd->sim_parms->cloth_pressure) + 200.0f; + + // clamp the cloth pressure to the maximum value + if (cloth_pressure * f < clmd->sim_parms->init_volume) { + cloth_pressure = f; + } + else { + cloth_pressure = clmd->sim_parms->init_volume / cloth_pressure; + } + } + + cloth_pressure += clmd->sim_parms->cloth_pressure; + + // do some scaling (?) + cloth_pressure *= 0.1f * clmd->sim_parms->pressure_scale; } for (i = 0; i < cloth->tri_num; i++) { const MVertTri *vt = &tri[i]; BPH_mass_spring_force_face_wind(data, vt->tri[0], vt->tri[1], vt->tri[2], winvec); + + if (calc_pressure) { + BPH_add_pressure(data, vt->tri[0], vt->tri[1], vt->tri[2], cloth_pressure); + } } /* Hair has only edges */ diff --git a/source/blender/physics/intern/implicit.h b/source/blender/physics/intern/implicit.h index a88a5785fee..ed9f662834e 100644 --- a/source/blender/physics/intern/implicit.h +++ b/source/blender/physics/intern/implicit.h @@ -182,6 +182,10 @@ bool BPH_mass_spring_force_spring_goal(struct Implicit_Data *data, float stiffness, float damping); +float BPH_volume(struct Implicit_Data *data, int v1, int v2, int v3); + +void BPH_add_pressure(struct Implicit_Data *data, int v1, int v2, int v3, float cloth_pressure); + /* ======== Hair Volumetric Forces ======== */ struct HairGrid; diff --git a/source/blender/physics/intern/implicit_blender.c b/source/blender/physics/intern/implicit_blender.c index 93df51ce58d..b29e91f735d 100644 --- a/source/blender/physics/intern/implicit_blender.c +++ b/source/blender/physics/intern/implicit_blender.c @@ -1484,6 +1484,38 @@ void BPH_mass_spring_force_face_wind( madd_v3_v3fl(data->F[v3], nor, factor * dot_v3v3(win, nor)); } +float BPH_volume(Implicit_Data *data, int v1, int v2, int v3) +{ + float vol; + // we have 3 vertices, calculate the volume of + // tetrahedra (0,v1,v2,v3) + vol = (data->X[v1][0] * data->X[v2][1] - data->X[v1][1] * data->X[v2][0]) * data->X[v3][2] + + (data->X[v1][1] * data->X[v2][2] - data->X[v1][2] * data->X[v2][1]) * data->X[v3][0] + + (data->X[v1][2] * data->X[v2][0] - data->X[v1][0] * data->X[v2][2]) * data->X[v3][1]; + + return vol; +} + +void BPH_add_pressure(Implicit_Data *data, int v1, int v2, int v3, float cloth_pressure) +{ + const float effector_scale = 0.02f; + float nor[3], area; + float factor; + + area = calc_nor_area_tri(nor, data->X[v1], data->X[v2], data->X[v3]); + factor = effector_scale * area / 3.0f; + factor *= cloth_pressure; + + // add pressure from v1 + madd_v3_v3fl(data->F[v1], nor, cloth_pressure); + + // add pressure from v2 + madd_v3_v3fl(data->F[v2], nor, cloth_pressure); + + // add pressure from v3 + madd_v3_v3fl(data->F[v3], nor, cloth_pressure); +} + static void edge_wind_vertex(const float dir[3], float length, float radius,