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
path: root/source
diff options
context:
space:
mode:
authorAlexander Gavrilov <angavrilov@gmail.com>2020-06-12 21:33:38 +0300
committerAlexander Gavrilov <angavrilov@gmail.com>2020-06-19 12:17:02 +0300
commit9e7012995249281b041d55607e7e7408857aa8c4 (patch)
treec798c27f235113ed4909fb6e11f68d84653ed8c6 /source
parentf382109f3885fc48d7becc526796d3324ab0aa42 (diff)
Cloth: allow forces to act parallel to cloth.
Currently all force effectors can only act on cloth when the force is perpendicular to the surface. This makes sense for wind, but not for other forces; and the user may want even wind to have some friction. This changes effector code to output two force vectors - although you of course can pass the same pointer for both. The force is split between the two outputs based on a new per-effector setting. Differential Revision: https://developer.blender.org/D8017
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_effect.h1
-rw-r--r--source/blender/blenkernel/intern/boids.c1
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c2
-rw-r--r--source/blender/blenkernel/intern/effect.c40
-rw-r--r--source/blender/blenkernel/intern/fluid.c2
-rw-r--r--source/blender/blenkernel/intern/particle.c1
-rw-r--r--source/blender/blenkernel/intern/particle_system.c9
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c2
-rw-r--r--source/blender/blenkernel/intern/softbody.c5
-rw-r--r--source/blender/blenloader/intern/versioning_280.c17
-rw-r--r--source/blender/makesdna/DNA_object_force_types.h4
-rw-r--r--source/blender/makesrna/intern/rna_object_force.c9
-rw-r--r--source/blender/physics/intern/BPH_mass_spring.cpp29
-rw-r--r--source/blender/physics/intern/implicit.h5
-rw-r--r--source/blender/physics/intern/implicit_blender.c63
15 files changed, 154 insertions, 36 deletions
diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h
index 6935b3aecce..0518ce8ffa3 100644
--- a/source/blender/blenkernel/BKE_effect.h
+++ b/source/blender/blenkernel/BKE_effect.h
@@ -130,6 +130,7 @@ void BKE_effectors_apply(struct ListBase *effectors,
struct EffectorWeights *weights,
struct EffectedPoint *point,
float *force,
+ float *wind_force,
float *impulse);
void BKE_effectors_free(struct ListBase *lb);
diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c
index 639437f8251..d5064629451 100644
--- a/source/blender/blenkernel/intern/boids.c
+++ b/source/blender/blenkernel/intern/boids.c
@@ -1388,6 +1388,7 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa)
bbd->part->effector_weights,
&epoint,
force,
+ NULL,
NULL);
if (ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing)) {
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index dae8a59fe43..2e1fa519284 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -5112,7 +5112,7 @@ static void dynamic_paint_prepare_effect_cb(void *__restrict userdata,
EffectedPoint epoint;
pd_point_from_loc(scene, realCoord[bData->s_pos[index]].v, vel, index, &epoint);
epoint.vel_to_sec = 1.0f;
- BKE_effectors_apply(effectors, NULL, surface->effector_weights, &epoint, forc, NULL);
+ BKE_effectors_apply(effectors, NULL, surface->effector_weights, &epoint, forc, NULL, NULL);
}
/* if global gravity is enabled, add it too */
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index 7ed04c6976a..235c834fde9 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -108,7 +108,8 @@ PartDeflect *BKE_partdeflect_new(int type)
break;
case PFIELD_WIND:
pd->shape = PFIELD_SHAPE_PLANE;
- pd->f_flow = 1.0f; /* realistic wind behavior */
+ pd->f_flow = 1.0f; /* realistic wind behavior */
+ pd->f_wind_factor = 1.0f; /* only act perpendicularly to a surface */
break;
case PFIELD_TEXTURE:
pd->f_size = 1.0f;
@@ -1072,7 +1073,8 @@ static void do_physical_effector(EffectorCache *eff,
* scene = scene where it runs in, for time and stuff
* lb = listbase with objects that take part in effecting
* opco = global coord, as input
- * force = force accumulator
+ * force = accumulator for force
+ * wind_force = accumulator for force only acting perpendicular to a surface
* speed = actual current speed which can be altered
* cur_time = "external" time in frames, is constant for static particles
* loc_time = "local" time in frames, range <0-1> for the lifetime of particle
@@ -1085,6 +1087,7 @@ void BKE_effectors_apply(ListBase *effectors,
EffectorWeights *weights,
EffectedPoint *point,
float *force,
+ float *wind_force,
float *impulse)
{
/*
@@ -1120,22 +1123,27 @@ void BKE_effectors_apply(ListBase *effectors,
if (efd.falloff > 0.0f) {
efd.falloff *= eff_calc_visibility(colliders, eff, &efd, point);
}
- if (efd.falloff <= 0.0f) {
- /* don't do anything */
- }
- else if (eff->pd->forcefield == PFIELD_TEXTURE) {
- do_texture_effector(eff, &efd, point, force);
- }
- else {
- float temp1[3] = {0, 0, 0}, temp2[3];
- copy_v3_v3(temp1, force);
+ if (efd.falloff > 0.0f) {
+ float out_force[3] = {0, 0, 0};
- do_physical_effector(eff, &efd, point, force);
+ if (eff->pd->forcefield == PFIELD_TEXTURE) {
+ do_texture_effector(eff, &efd, point, out_force);
+ }
+ else {
+ do_physical_effector(eff, &efd, point, out_force);
- /* for softbody backward compatibility */
- if (point->flag & PE_WIND_AS_SPEED && impulse) {
- sub_v3_v3v3(temp2, force, temp1);
- sub_v3_v3v3(impulse, impulse, temp2);
+ /* for softbody backward compatibility */
+ if (point->flag & PE_WIND_AS_SPEED && impulse) {
+ sub_v3_v3v3(impulse, impulse, out_force);
+ }
+ }
+
+ if (wind_force) {
+ madd_v3_v3fl(force, out_force, 1.0f - eff->pd->f_wind_factor);
+ madd_v3_v3fl(wind_force, out_force, eff->pd->f_wind_factor);
+ }
+ else {
+ add_v3_v3(force, out_force);
}
}
}
diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c
index b75592836e0..521210e7bb5 100644
--- a/source/blender/blenkernel/intern/fluid.c
+++ b/source/blender/blenkernel/intern/fluid.c
@@ -3175,7 +3175,7 @@ static void update_effectors_task_cb(void *__restrict userdata,
/* do effectors */
pd_point_from_loc(data->scene, voxel_center, vel, index, &epoint);
- BKE_effectors_apply(data->effectors, NULL, mds->effector_weights, &epoint, retvel, NULL);
+ BKE_effectors_apply(data->effectors, NULL, mds->effector_weights, &epoint, retvel, NULL, NULL);
/* convert retvel to local space */
mag = len_v3(retvel);
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index c201cb83c44..94b677c649c 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -2262,6 +2262,7 @@ static void do_path_effectors(ParticleSimulationData *sim,
sim->psys->part->effector_weights,
&epoint,
force,
+ NULL,
NULL);
mul_v3_fl(force,
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 606291a9ae0..d09f9a8eb09 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -2243,8 +2243,13 @@ static void basic_force_cb(void *efdata_v, ParticleKey *state, float *force, flo
/* add effectors */
pd_point_from_particle(efdata->sim, efdata->pa, state, &epoint);
if (part->type != PART_HAIR || part->effector_weights->flag & EFF_WEIGHT_DO_HAIR) {
- BKE_effectors_apply(
- sim->psys->effectors, sim->colliders, part->effector_weights, &epoint, force, impulse);
+ BKE_effectors_apply(sim->psys->effectors,
+ sim->colliders,
+ part->effector_weights,
+ &epoint,
+ force,
+ NULL,
+ impulse);
}
mul_v3_fl(force, efdata->ptex.field);
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index 02ce0c6f996..4752782eaeb 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -1647,7 +1647,7 @@ static void rigidbody_update_sim_ob(
/* Calculate net force of effectors, and apply to sim object:
* - we use 'central force' since apply force requires a "relative position"
* which we don't have... */
- BKE_effectors_apply(effectors, NULL, effector_weights, &epoint, eff_force, NULL);
+ BKE_effectors_apply(effectors, NULL, effector_weights, &epoint, eff_force, NULL, NULL);
if (G.f & G_DEBUG) {
printf("\tapplying force (%f,%f,%f) to '%s'\n",
eff_force[0],
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 68d0822a223..9c7abbdf876 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -1479,7 +1479,8 @@ static void _scan_for_ext_spring_forces(
mid_v3_v3v3(pos, sb->bpoint[bs->v1].pos, sb->bpoint[bs->v2].pos);
mid_v3_v3v3(vel, sb->bpoint[bs->v1].vec, sb->bpoint[bs->v2].vec);
pd_point_from_soft(scene, pos, vel, -1, &epoint);
- BKE_effectors_apply(effectors, NULL, sb->effector_weights, &epoint, force, speed);
+ BKE_effectors_apply(
+ effectors, NULL, sb->effector_weights, &epoint, force, NULL, speed);
mul_v3_fl(speed, windfactor);
add_v3_v3(vel, speed);
@@ -2107,7 +2108,7 @@ static int _softbody_calc_forces_slice_in_a_thread(Scene *scene,
float eval_sb_fric_force_scale = sb_fric_force_scale(ob);
pd_point_from_soft(scene, bp->pos, bp->vec, sb->bpoint - bp, &epoint);
- BKE_effectors_apply(effectors, NULL, sb->effector_weights, &epoint, force, speed);
+ BKE_effectors_apply(effectors, NULL, sb->effector_weights, &epoint, force, NULL, speed);
/* apply forcefield*/
mul_v3_fl(force, fieldfactor * eval_sb_fric_force_scale);
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index 6211c58d7d4..0648264466d 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -5075,6 +5075,23 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
* \note Keep this message at the bottom of the function.
*/
{
+ /* Set the cloth wind factor to 1 for old forces. */
+ if (!DNA_struct_elem_find(fd->filesdna, "PartDeflect", "float", "f_wind_factor")) {
+ LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
+ if (ob->pd) {
+ ob->pd->f_wind_factor = 1.0f;
+ }
+ }
+ LISTBASE_FOREACH (ParticleSettings *, part, &bmain->particles) {
+ if (part->pd) {
+ part->pd->f_wind_factor = 1.0f;
+ }
+ if (part->pd2) {
+ part->pd2->f_wind_factor = 1.0f;
+ }
+ }
+ }
+
/* Keep this block, even when empty. */
}
}
diff --git a/source/blender/makesdna/DNA_object_force_types.h b/source/blender/makesdna/DNA_object_force_types.h
index 7f022f104e6..78f645deaa2 100644
--- a/source/blender/makesdna/DNA_object_force_types.h
+++ b/source/blender/makesdna/DNA_object_force_types.h
@@ -92,6 +92,10 @@ typedef struct PartDeflect {
* How much force is converted into "air flow", i.e.
* force used as the velocity of surrounding medium. */
float f_flow;
+ /** How much force is reduced when acting parallel to a surface, e.g. cloth. */
+ float f_wind_factor;
+
+ char _pad0[4];
/** Noise size for noise effector, restlength for harmonic effector. */
float f_size;
diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c
index 30e0ba19608..0a4e714c2ef 100644
--- a/source/blender/makesrna/intern/rna_object_force.c
+++ b/source/blender/makesrna/intern/rna_object_force.c
@@ -1517,6 +1517,15 @@ static void rna_def_field(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Flow", "Convert effector force into air flow velocity");
RNA_def_property_update(prop, 0, "rna_FieldSettings_update");
+ prop = RNA_def_property(srna, "wind_factor", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "f_wind_factor");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(
+ prop,
+ "Wind Factor",
+ "How much the force is reduced when acting parallel to a surface, e.g. cloth");
+ RNA_def_property_update(prop, 0, "rna_FieldSettings_update");
+
/* different ui range to above */
prop = RNA_def_property(srna, "inflow", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "f_flow");
diff --git a/source/blender/physics/intern/BPH_mass_spring.cpp b/source/blender/physics/intern/BPH_mass_spring.cpp
index 18fab5215a6..3b6e39ef48f 100644
--- a/source/blender/physics/intern/BPH_mass_spring.cpp
+++ b/source/blender/physics/intern/BPH_mass_spring.cpp
@@ -683,23 +683,42 @@ static void cloth_calc_force(
/* handle external forces like wind */
if (effectors) {
+ bool is_not_hair = (clmd->hairdata == NULL) && (cloth->primitive_num > 0);
+ bool has_wind = false, has_force = false;
+
/* cache per-vertex forces to avoid redundant calculation */
- float(*winvec)[3] = (float(*)[3])MEM_callocN(sizeof(float[3]) * mvert_num, "effector forces");
+ float(*winvec)[3] = (float(*)[3])MEM_callocN(sizeof(float[3]) * mvert_num * 2,
+ "effector forces");
+ float(*forcevec)[3] = is_not_hair ? winvec + mvert_num : winvec;
+
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);
+ BKE_effectors_apply(effectors,
+ NULL,
+ clmd->sim_parms->effector_weights,
+ &epoint,
+ forcevec[i],
+ winvec[i],
+ NULL);
+
+ has_wind = has_wind || !is_zero_v3(winvec[i]);
+ has_force = has_force || !is_zero_v3(forcevec[i]);
}
/* Hair has only edges. */
- if ((clmd->hairdata == NULL) && (cloth->primitive_num > 0)) {
+ if (is_not_hair) {
for (i = 0; i < cloth->primitive_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 (has_wind) {
+ BPH_mass_spring_force_face_wind(data, vt->tri[0], vt->tri[1], vt->tri[2], winvec);
+ }
+ if (has_force) {
+ BPH_mass_spring_force_face_extern(data, vt->tri[0], vt->tri[1], vt->tri[2], forcevec);
+ }
}
}
else {
diff --git a/source/blender/physics/intern/implicit.h b/source/blender/physics/intern/implicit.h
index 69b50f7fa48..8bc09755180 100644
--- a/source/blender/physics/intern/implicit.h
+++ b/source/blender/physics/intern/implicit.h
@@ -126,9 +126,12 @@ void BPH_mass_spring_force_drag(struct Implicit_Data *data, float drag);
/* Custom external force */
void BPH_mass_spring_force_extern(
struct Implicit_Data *data, int i, const float f[3], float dfdx[3][3], float dfdv[3][3]);
-/* Wind force, acting on a face */
+/* Wind force, acting on a face (only generates pressure from the normal component) */
void BPH_mass_spring_force_face_wind(
struct Implicit_Data *data, int v1, int v2, int v3, const float (*winvec)[3]);
+/* Arbitrary per-unit-area vector force field acting on a face. */
+void BPH_mass_spring_force_face_extern(
+ struct Implicit_Data *data, int v1, int v2, int v3, const float (*forcevec)[3]);
/* Wind force, acting on an edge */
void BPH_mass_spring_force_edge_wind(struct Implicit_Data *data,
int v1,
diff --git a/source/blender/physics/intern/implicit_blender.c b/source/blender/physics/intern/implicit_blender.c
index 063c224f158..5ec4c750d5d 100644
--- a/source/blender/physics/intern/implicit_blender.c
+++ b/source/blender/physics/intern/implicit_blender.c
@@ -1469,22 +1469,71 @@ void BPH_mass_spring_force_face_wind(
Implicit_Data *data, int v1, int v2, int v3, const float (*winvec)[3])
{
const float effector_scale = 0.02f;
+ int vs[3] = {v1, v2, v3};
float win[3], nor[3], area;
- float factor;
+ float factor, base_force;
+ float force[3];
/* 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]);
- madd_v3_v3fl(data->F[v1], nor, factor * dot_v3v3(win, nor));
+ /* Calculate wind pressure at each vertex by projecting the wind field on the normal. */
+ for (int i = 0; i < 3; i++) {
+ world_to_root_v3(data, vs[i], win, winvec[vs[i]]);
- world_to_root_v3(data, v2, win, winvec[v2]);
- madd_v3_v3fl(data->F[v2], nor, factor * dot_v3v3(win, nor));
+ force[i] = dot_v3v3(win, nor);
+ }
- world_to_root_v3(data, v3, win, winvec[v3]);
- madd_v3_v3fl(data->F[v3], nor, factor * dot_v3v3(win, nor));
+ /* Compute per-vertex force values from local pressures.
+ * From integrating the pressure over the triangle and deriving
+ * equivalent vertex forces, it follows that:
+ *
+ * force[idx] = (sum(pressure) + pressure[idx]) * area / 12
+ *
+ * Effectively, 1/4 of the pressure acts just on its vertex,
+ * while 3/4 is split evenly over all three.
+ */
+ mul_v3_fl(force, factor / 4.0f);
+
+ base_force = force[0] + force[1] + force[2];
+
+ /* add pressure to each of the face verts */
+ madd_v3_v3fl(data->F[v1], nor, base_force + force[0]);
+ madd_v3_v3fl(data->F[v2], nor, base_force + force[1]);
+ madd_v3_v3fl(data->F[v3], nor, base_force + force[2]);
+}
+
+void BPH_mass_spring_force_face_extern(
+ Implicit_Data *data, int v1, int v2, int v3, const float (*forcevec)[3])
+{
+ const float effector_scale = 0.02f;
+ int vs[3] = {v1, v2, v3};
+ float nor[3], area;
+ float factor, base_force[3];
+ float force[3][3];
+
+ /* 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;
+
+ /* Compute common and per-vertex force vectors from the original inputs. */
+ zero_v3(base_force);
+
+ for (int i = 0; i < 3; i++) {
+ world_to_root_v3(data, vs[i], force[i], forcevec[vs[i]]);
+
+ mul_v3_fl(force[i], factor / 4.0f);
+ add_v3_v3(base_force, force[i]);
+ }
+
+ /* Apply the common and vertex components to all vertices. */
+ for (int i = 0; i < 3; i++) {
+ add_v3_v3(force[i], base_force);
+ add_v3_v3(data->F[vs[i]], force[i]);
+ }
}
float BPH_tri_tetra_volume_signed_6x(Implicit_Data *data, int v1, int v2, int v3)