Commit: 1e6de4732697507d7c59e715664375be2c6423af Author: Alexander Gavrilov Date: Sun Sep 12 19:35:48 2021 +0300 Branches: temp-angavrilov https://developer.blender.org/rB1e6de4732697507d7c59e715664375be2c6423af
Force Fields: implement new true power and custom falloff options. The 'power' falloff option in Blender force fields does not actually generate a true power falloff function, as pointed out in D2389. However, that patch adds a special 'gravity' falloff option to Force fields, without addressing the shortcoming in the common options. The reason for not using the true curve in the options, as far as one can tell, is that the power curve goes up to infinity as the distance is reduced to 0, while the falloff options are designed so that the maximum value of the curve is 1. However, in reality forces with a power falloff don't actually go to infinity, because real objects have a nonzero size, and the force reaches its maximum at the surface of the object. This can be used to integrate an option to use a true power falloff with the design of falloff settings, if it requires a nonzero 'minimum' distance to be set, and uses a curve that reaches 1 at that distance. Since this is adding a new feature to the minimum distance value, it is also a good opportunity to add a feature to the maximum distance. Specifically, the new options can be used to apply arbitrary brush-style falloff curves between min and max, including a fully custom curve option. When used together with power falloff, the two curves are multiplied together. While the true power option allows creating more physically correct forces, the custom curves aid artistic effects. Differential Revision: https://developer.blender.org/D8075 =================================================================== M release/scripts/startup/bl_ui/properties_physics_common.py M release/scripts/startup/bl_ui/properties_physics_field.py M source/blender/blenkernel/BKE_effect.h M source/blender/blenkernel/BKE_particle.h M source/blender/blenkernel/intern/effect.c M source/blender/blenkernel/intern/object.c M source/blender/blenkernel/intern/particle.c M source/blender/makesdna/DNA_object_force_types.h M source/blender/makesrna/intern/rna_object_force.c =================================================================== diff --git a/release/scripts/startup/bl_ui/properties_physics_common.py b/release/scripts/startup/bl_ui/properties_physics_common.py index f13a808e324..a535f750279 100644 --- a/release/scripts/startup/bl_ui/properties_physics_common.py +++ b/release/scripts/startup/bl_ui/properties_physics_common.py @@ -355,6 +355,10 @@ def basic_force_field_falloff_ui(self, field): sub.prop(field, "distance_min", text="") row.prop_decorator(field, "distance_min") + col = layout.column() + col.active = field.use_min_distance and field.distance_min > 0 + col.prop(field, "use_true_power") + col = layout.column(align=False, heading="Max Distance") col.use_property_decorate = False row = col.row(align=True) @@ -365,6 +369,13 @@ def basic_force_field_falloff_ui(self, field): sub.prop(field, "distance_max", text="") row.prop_decorator(field, "distance_max") + col = layout.column() + col.active = field.use_max_distance and field.distance_max > field.distance_min + col.prop(field, "falloff_curve_type", text="Curve") + + if field.falloff_curve_type == 'CUSTOM': + col.template_curve_mapping(field, "falloff_curve", type='NONE', brush=True) + classes = ( PHYSICS_PT_add, diff --git a/release/scripts/startup/bl_ui/properties_physics_field.py b/release/scripts/startup/bl_ui/properties_physics_field.py index 7e017b121b3..c22bee4140b 100644 --- a/release/scripts/startup/bl_ui/properties_physics_field.py +++ b/release/scripts/startup/bl_ui/properties_physics_field.py @@ -248,20 +248,36 @@ class PHYSICS_PT_field_falloff_angular(PhysicButtonsPanel, Panel): col = flow.column() col.prop(field, "radial_falloff", text="Power") - col = flow.column() - col.prop(field, "use_radial_min", text="Use Min Angle") - - sub = col.column() + col = layout.column(align=False, heading="Min Angle") + col.use_property_decorate = False + row = col.row(align=True) + sub = row.row(align=True) + sub.prop(field, "use_radial_min", text="") + sub = sub.row(align=True) sub.active = field.use_radial_min - sub.prop(field, "radial_min", text="Min Angle") - - col = flow.column() - col.prop(field, "use_radial_max", text="Use Max Angle") + sub.prop(field, "radial_min", text="") + row.prop_decorator(field, "radial_min") - sub = col.column() + col = layout.column() + col.active = field.use_radial_min and field.radial_min > 0 + col.prop(field, "use_radial_true_power") + + col = layout.column(align=False, heading="Max Angle") + col.use_property_decorate = False + row = col.row(align=True) + sub = row.row(align=True) + sub.prop(field, "use_radial_max", text="") + sub = sub.row(align=True) sub.active = field.use_radial_max - sub.prop(field, "radial_max", text="Max Angle") + sub.prop(field, "radial_max", text="") + row.prop_decorator(field, "radial_max") + + col = layout.column() + col.active = field.use_radial_max and field.radial_max > field.radial_min + col.prop(field, "radial_falloff_curve_type", text="Curve") + if field.radial_falloff_curve_type == 'CUSTOM': + col.template_curve_mapping(field, "radial_falloff_curve", type='NONE', brush=True) class PHYSICS_PT_field_falloff_radial(PhysicButtonsPanel, Panel): bl_label = "Radial" @@ -287,19 +303,36 @@ class PHYSICS_PT_field_falloff_radial(PhysicButtonsPanel, Panel): col = flow.column() col.prop(field, "radial_falloff", text="Power") - col = flow.column() - col.prop(field, "use_radial_min", text="Use Minimum") - - sub = col.column() + col = layout.column(align=False, heading="Min Distance") + col.use_property_decorate = False + row = col.row(align=True) + sub = row.row(align=True) + sub.prop(field, "use_radial_min", text="") + sub = sub.row(align=True) sub.active = field.use_radial_min - sub.prop(field, "radial_min", text="Min Distance") - - col = flow.column() - col.prop(field, "use_radial_max", text="Use Maximum") + sub.prop(field, "radial_min", text="") + row.prop_decorator(field, "radial_min") - sub = col.column() + col = layout.column() + col.active = field.use_radial_min and field.radial_min > 0 + col.prop(field, "use_radial_true_power") + + col = layout.column(align=False, heading="Max Distance") + col.use_property_decorate = False + row = col.row(align=True) + sub = row.row(align=True) + sub.prop(field, "use_radial_max", text="") + sub = sub.row(align=True) sub.active = field.use_radial_max - sub.prop(field, "radial_max", text="Max Distance") + sub.prop(field, "radial_max", text="") + row.prop_decorator(field, "radial_max") + + col = layout.column() + col.active = field.use_radial_max and field.radial_max > field.radial_min + col.prop(field, "radial_falloff_curve_type", text="Curve") + + if field.radial_falloff_curve_type == 'CUSTOM': + col.template_curve_mapping(field, "radial_falloff_curve", type='NONE', brush=True) def collision_warning(layout): diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h index 3a964ddb1aa..770590eab0b 100644 --- a/source/blender/blenkernel/BKE_effect.h +++ b/source/blender/blenkernel/BKE_effect.h @@ -22,12 +22,15 @@ * \ingroup bke */ +#include "DNA_color_types.h" + #include "BLI_utildefines.h" #ifdef __cplusplus extern "C" { #endif +enum eCurveMappingPreset; struct Collection; struct Depsgraph; struct ListBase; @@ -113,6 +116,10 @@ struct PartDeflect *BKE_partdeflect_new(int type); struct PartDeflect *BKE_partdeflect_copy(const struct PartDeflect *pd_src); void BKE_partdeflect_free(struct PartDeflect *pd); +void BKE_partdeflect_falloff_curve_preset(struct PartDeflect *pd, eCurveMappingPreset preset); +void BKE_partdeflect_radial_falloff_curve_preset(struct PartDeflect *pd, + eCurveMappingPreset preset); + struct ListBase *BKE_effector_relations_create(struct Depsgraph *depsgraph, struct ViewLayer *view_layer, struct Collection *collection); diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 78a6e47ec48..aaf4d55e8e3 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -629,6 +629,8 @@ extern void (*BKE_particle_batch_cache_dirty_tag_cb)(struct ParticleSystem *psys extern void (*BKE_particle_batch_cache_free_cb)(struct ParticleSystem *psys); /* .blend file I/O */ +void BKE_particle_partdeflect_blend_write(struct BlendWriter *writer, + const struct PartDeflect *pd); void BKE_particle_partdeflect_blend_read_data(struct BlendDataReader *reader, struct PartDeflect *pd); void BKE_particle_partdeflect_blend_read_lib(struct BlendLibReader *reader, diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index a88339082fe..bdaae0aa7c1 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -53,6 +53,7 @@ #include "BKE_bvhutils.h" #include "BKE_collection.h" #include "BKE_collision.h" +#include "BKE_colortools.h" #include "BKE_curve.h" #include "BKE_displist.h" #include "BKE_effect.h" @@ -131,6 +132,12 @@ PartDeflect *BKE_partdeflect_copy(const struct PartDeflect *pd_src) if (pd_dst->rng != NULL) { pd_dst->rng = BLI_rng_copy(pd_dst->rng); } + if (pd_dst->falloff_curve != NULL) { + pd_dst->falloff_curve = BKE_curvemapping_copy(pd_dst->falloff_curve); + } + if (pd_dst->falloff_curve_r != NULL) { + pd_dst->falloff_curve_r = BKE_curvemapping_copy(pd_dst->falloff_curve_r); + } return pd_dst; } @@ -142,9 +149,43 @@ void BKE_partdeflect_free(PartDeflect *pd) if (pd->rng) { BLI_rng_free(pd->rng); } + if (pd->falloff_curve) { + BKE_curvemapping_free(pd->falloff_curve); + } + if (pd->falloff_curve_r) { + BKE_curvemapping_free(pd->falloff_curve_r); + } MEM_freeN(pd); } +static void init_falloff_curve(CurveMapping **p_curve, eCurveMappingPreset preset) +{ + CurveMapping *cumap = NULL; + CurveMap *cuma = NULL; + + if (!*p_curve) { + *p_curve = BKE_curvemapping_add(1, 0, 0, 1, 1); + } + + cumap = *p_curve; + cumap->flag &= ~CUMA_EXTEND_EXTRAPOLATE; + cumap->preset = preset; + + cuma = cumap->cm; + BKE_curvemap_reset(cuma, &cumap->clipr, cumap->preset, CURVEMAP_SLOPE_NEGATIVE); + BKE_curvemapping_changed(cumap, false); +} + +void BKE_partdeflect_falloff_curve_preset(PartDeflect *pd, eCurveMappingPreset preset) +{ + init_falloff_curve(&pd->falloff_curve, preset); +} + +void BKE_partdeflect_radial_falloff_curve_preset(PartDeflect *pd, eCurveMappingPreset preset) +{ + init_falloff_curve(&pd->falloff_curve_r, preset); +} + /******************** EFFECTOR RELATIONS ***********************/ static void precalculate_effector(struct Depsgraph *depsgraph, EffectorCache *eff) @@ -158,6 +199,13 @@ static void precalculate_effector(struct Depsgraph *depsgraph, EffectorCache *ef BLI_rng_srandom(eff->pd->rng, eff->pd->seed + cfra); } + if (eff->pd->falloff_curve) { + BKE_curvemapping_init(eff->pd->falloff_curve); + } + if (eff->pd->falloff_curve_r) { + BKE_curvemapping_init(eff->pd->falloff_curve_r); + } + if (eff->pd->forcefield == PFIELD_GUIDE && eff->ob->type == OB_CURVE) { Curve *cu = eff->ob->data; if (cu->flag & CU_PATH) { @@ -565,26 +613,101 @@ static float wind_func(struct RNG *rng, float strength) return ret; } -/* maxdist: zero effect from this distance outwards (if usemax) */ -/* mindist: full effect up to this distance (if usemin) */ -/* power: falloff with formula 1/r^power */ -static float falloff_func( - float fac, int usemin, float mindist, @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs