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:
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_common.py1
-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
16 files changed, 155 insertions, 36 deletions
diff --git a/release/scripts/startup/bl_ui/properties_physics_common.py b/release/scripts/startup/bl_ui/properties_physics_common.py
index 210d850ad06..db33fda3b17 100644
--- a/release/scripts/startup/bl_ui/properties_physics_common.py
+++ b/release/scripts/startup/bl_ui/properties_physics_common.py
@@ -330,6 +330,7 @@ def basic_force_field_settings_ui(self, field):
col.prop(field, "use_gravity_falloff", text="Gravitation")
col.prop(field, "use_absorption")
+ col.prop(field, "wind_factor")
def basic_force_field_falloff_ui(self, field):
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)