diff options
Diffstat (limited to 'source/blender/blenkernel/intern/effect.c')
-rw-r--r-- | source/blender/blenkernel/intern/effect.c | 283 |
1 files changed, 150 insertions, 133 deletions
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 89f85530439..adf5b5da35e 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -57,6 +57,7 @@ #include "PIL_time.h" #include "BKE_anim.h" /* needed for where_on_path */ +#include "BKE_collection.h" #include "BKE_collision.h" #include "BKE_curve.h" #include "BKE_displist.h" @@ -64,6 +65,7 @@ #include "BKE_cdderivedmesh.h" #include "BKE_effect.h" #include "BKE_global.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_modifier.h" #include "BKE_object.h" @@ -71,6 +73,9 @@ #include "BKE_scene.h" #include "BKE_smoke.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_physics.h" +#include "DEG_depsgraph_query.h" #include "RE_render_ext.h" #include "RE_shader_ext.h" @@ -82,7 +87,7 @@ #include <string.h> #endif // WITH_MOD_FLUID -EffectorWeights *BKE_add_effector_weights(Group *group) +EffectorWeights *BKE_add_effector_weights(Collection *collection) { EffectorWeights *weights = MEM_callocN(sizeof(EffectorWeights), "EffectorWeights"); int i; @@ -92,7 +97,7 @@ EffectorWeights *BKE_add_effector_weights(Group *group) weights->global_gravity = 1.0f; - weights->group = group; + weights->group = collection; return weights; } @@ -131,9 +136,8 @@ PartDeflect *object_add_collision_fields(int type) return pd; } -/* ***************** PARTICLES ***************** */ +/************************ PARTICLES ***************************/ -/* -------------------------- Effectors ------------------ */ void free_partdeflect(PartDeflect *pd) { if (!pd) @@ -145,175 +149,187 @@ void free_partdeflect(PartDeflect *pd) MEM_freeN(pd); } -static EffectorCache *new_effector_cache(Scene *scene, Object *ob, ParticleSystem *psys, PartDeflect *pd) -{ - EffectorCache *eff = MEM_callocN(sizeof(EffectorCache), "EffectorCache"); - eff->scene = scene; - eff->ob = ob; - eff->psys = psys; - eff->pd = pd; - eff->frame = -1; - return eff; -} -static void add_object_to_effectors(ListBase **effectors, Scene *scene, EffectorWeights *weights, Object *ob, Object *ob_src, bool for_simulation) +/******************** EFFECTOR RELATIONS ***********************/ + +static void precalculate_effector(struct Depsgraph *depsgraph, EffectorCache *eff) { - EffectorCache *eff = NULL; + float ctime = DEG_get_ctime(depsgraph); + unsigned int cfra = (unsigned int)(ctime >= 0 ? ctime : -ctime); + if (!eff->pd->rng) + eff->pd->rng = BLI_rng_new(eff->pd->seed + cfra); + else + BLI_rng_srandom(eff->pd->rng, eff->pd->seed + cfra); - if ( ob == ob_src ) - return; + if (eff->pd->forcefield == PFIELD_GUIDE && eff->ob->type==OB_CURVE) { + Curve *cu= eff->ob->data; + if (cu->flag & CU_PATH) { + if (eff->ob->curve_cache == NULL || eff->ob->curve_cache->path==NULL || eff->ob->curve_cache->path->data==NULL) + BKE_displist_make_curveTypes(depsgraph, eff->scene, eff->ob, 0); - if (for_simulation) { - if (weights->weight[ob->pd->forcefield] == 0.0f ) - return; + if (eff->ob->curve_cache->path && eff->ob->curve_cache->path->data) { + where_on_path(eff->ob, 0.0, eff->guide_loc, eff->guide_dir, NULL, &eff->guide_radius, NULL); + mul_m4_v3(eff->ob->obmat, eff->guide_loc); + mul_mat3_m4_v3(eff->ob->obmat, eff->guide_dir); + } + } + } + else if (eff->pd->shape == PFIELD_SHAPE_SURFACE) { + eff->surmd = (SurfaceModifierData *)modifiers_findByType( eff->ob, eModifierType_Surface ); + if (eff->ob->type == OB_CURVE) + eff->flag |= PE_USE_NORMAL_DATA; + } + else if (eff->psys) + psys_update_particle_tree(eff->psys, ctime); - if (ob->pd->shape == PFIELD_SHAPE_POINTS && !ob->derivedFinal ) - return; + /* Store object velocity */ + if (eff->ob) { + float old_vel[3]; + + BKE_object_where_is_calc_time(depsgraph, eff->scene, eff->ob, cfra - 1.0f); + copy_v3_v3(old_vel, eff->ob->obmat[3]); + BKE_object_where_is_calc_time(depsgraph, eff->scene, eff->ob, cfra); + sub_v3_v3v3(eff->velocity, eff->ob->obmat[3], old_vel); } +} - if (*effectors == NULL) - *effectors = MEM_callocN(sizeof(ListBase), "effectors list"); +static void add_effector_relation(ListBase *relations, Object *ob, ParticleSystem *psys, PartDeflect *pd) +{ + EffectorRelation *relation = MEM_callocN(sizeof(EffectorRelation), "EffectorRelation"); + relation->ob = ob; + relation->psys = psys; + relation->pd = pd; - eff = new_effector_cache(scene, ob, NULL, ob->pd); + BLI_addtail(relations, relation); +} - /* make sure imat is up to date */ - invert_m4_m4(ob->imat, ob->obmat); +static void add_effector_evaluation(ListBase **effectors, Depsgraph *depsgraph, Scene *scene, Object *ob, ParticleSystem *psys, PartDeflect *pd) +{ + if (*effectors == NULL) { + *effectors = MEM_callocN(sizeof(ListBase), "effector effectors"); + } + EffectorCache *eff = MEM_callocN(sizeof(EffectorCache), "EffectorCache"); + eff->depsgraph = depsgraph; + eff->scene = scene; + eff->ob = ob; + eff->psys = psys; + eff->pd = pd; + eff->frame = -1; BLI_addtail(*effectors, eff); + + precalculate_effector(depsgraph, eff); } -static void add_particles_to_effectors(ListBase **effectors, Scene *scene, EffectorWeights *weights, Object *ob, ParticleSystem *psys, ParticleSystem *psys_src, bool for_simulation) + +/* Create list of effector relations in the collection or entire scene. + * This is used by the depsgraph to build relations, as well as faster + * lookup of effectors during evaluation. */ +ListBase *BKE_effector_relations_create( + Depsgraph *depsgraph, + ViewLayer *view_layer, + Collection *collection) { - ParticleSettings *part= psys->part; + const bool for_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); + Base *base = BKE_collection_or_layer_objects(NULL, NULL, view_layer, collection); + ListBase *relations = MEM_callocN(sizeof(ListBase), "effector relations"); - if ( !psys_check_enabled(ob, psys, G.is_rendering) ) - return; + for (; base; base = base->next) { + Object *ob = base->object; - if ( psys == psys_src && (part->flag & PART_SELF_EFFECT) == 0) - return; + if (ob->pd && ob->pd->forcefield) { + add_effector_relation(relations, ob, NULL, ob->pd); + } - if ( part->pd && part->pd->forcefield && (!for_simulation || weights->weight[part->pd->forcefield] != 0.0f)) { - if (*effectors == NULL) - *effectors = MEM_callocN(sizeof(ListBase), "effectors list"); + for (ParticleSystem *psys = ob->particlesystem.first; psys; psys = psys->next) { + ParticleSettings *part = psys->part; - BLI_addtail(*effectors, new_effector_cache(scene, ob, psys, part->pd)); + if (psys_check_enabled(ob, psys, for_render)) { + if (part->pd && part->pd->forcefield) { + add_effector_relation(relations, ob, psys, part->pd); + } + if (part->pd2 && part->pd2->forcefield) { + add_effector_relation(relations, ob, psys, part->pd2); + } + } + } } - if (part->pd2 && part->pd2->forcefield && (!for_simulation || weights->weight[part->pd2->forcefield] != 0.0f)) { - if (*effectors == NULL) - *effectors = MEM_callocN(sizeof(ListBase), "effectors list"); + return relations; +} - BLI_addtail(*effectors, new_effector_cache(scene, ob, psys, part->pd2)); +void BKE_effector_relations_free(ListBase *lb) +{ + if (lb) { + BLI_freelistN(lb); + MEM_freeN(lb); } } -/* returns ListBase handle with objects taking part in the effecting */ -ListBase *pdInitEffectors(Scene *scene, Object *ob_src, ParticleSystem *psys_src, - EffectorWeights *weights, bool for_simulation) +/* Create effective list of effectors from relations built beforehand. */ +ListBase *BKE_effectors_create( + Depsgraph *depsgraph, + Scene *scene, + Object *ob_src, + ParticleSystem *psys_src, + EffectorWeights *weights) { - Base *base; - unsigned int layer= ob_src->lay; + ListBase *relations = DEG_get_effector_relations(depsgraph, weights->group); ListBase *effectors = NULL; - if (weights->group) { - GroupObject *go; + if (!relations) { + return NULL; + } - for (go= weights->group->gobject.first; go; go= go->next) { - if ( (go->ob->lay & layer) ) { - if ( go->ob->pd && go->ob->pd->forcefield ) - add_object_to_effectors(&effectors, scene, weights, go->ob, ob_src, for_simulation); + for (EffectorRelation *relation = relations->first; relation; relation = relation->next) { + /* Get evaluated object. */ + Object *ob = (Object*)DEG_get_evaluated_id(depsgraph, &relation->ob->id); - if ( go->ob->particlesystem.first ) { - ParticleSystem *psys= go->ob->particlesystem.first; + if (relation->psys) { + /* Get evaluated particle system. */ + ParticleSystem *psys = BLI_findstring(&ob->particlesystem, + relation->psys->name, offsetof(ParticleSystem, name)); + ParticleSettings *part = psys->part; - for ( ; psys; psys=psys->next ) - add_particles_to_effectors(&effectors, scene, weights, go->ob, psys, psys_src, for_simulation); - } + if (psys == psys_src && (part->flag & PART_SELF_EFFECT) == 0) { + continue; } - } - } - else { - for (base = scene->base.first; base; base= base->next) { - if ( (base->lay & layer) ) { - if ( base->object->pd && base->object->pd->forcefield ) - add_object_to_effectors(&effectors, scene, weights, base->object, ob_src, for_simulation); - if ( base->object->particlesystem.first ) { - ParticleSystem *psys= base->object->particlesystem.first; + PartDeflect *pd = (relation->pd == relation->psys->part->pd) ? part->pd : part->pd2; + if (weights->weight[pd->forcefield] == 0.0f) { + continue; + } - for ( ; psys; psys=psys->next ) - add_particles_to_effectors(&effectors, scene, weights, base->object, psys, psys_src, for_simulation); - } + add_effector_evaluation(&effectors, depsgraph, scene, ob, psys, pd); + } + else { + /* Object effector. */ + if (ob == ob_src) { + continue; } + else if (weights->weight[ob->pd->forcefield] == 0.0f) { + continue; + } + else if (ob->pd->shape == PFIELD_SHAPE_POINTS && !ob->derivedFinal) { + continue; + } + + add_effector_evaluation(&effectors, depsgraph, scene, ob, NULL, ob->pd); } } - if (for_simulation) - pdPrecalculateEffectors(effectors); - return effectors; } -void pdEndEffectors(ListBase **effectors) +void BKE_effectors_free(ListBase *lb) { - if (*effectors) { - EffectorCache *eff = (*effectors)->first; - - for (; eff; eff=eff->next) { - if (eff->guide_data) + if (lb) { + for (EffectorCache *eff = lb->first; eff; eff = eff->next) { + if (eff->guide_data) { MEM_freeN(eff->guide_data); - } - - BLI_freelistN(*effectors); - MEM_freeN(*effectors); - *effectors = NULL; - } -} - -static void precalculate_effector(EffectorCache *eff) -{ - unsigned int cfra = (unsigned int)(eff->scene->r.cfra >= 0 ? eff->scene->r.cfra : -eff->scene->r.cfra); - if (!eff->pd->rng) - eff->pd->rng = BLI_rng_new(eff->pd->seed + cfra); - else - BLI_rng_srandom(eff->pd->rng, eff->pd->seed + cfra); - - if (eff->pd->forcefield == PFIELD_GUIDE && eff->ob->type==OB_CURVE) { - Curve *cu= eff->ob->data; - if (cu->flag & CU_PATH) { - if (eff->ob->curve_cache == NULL || eff->ob->curve_cache->path==NULL || eff->ob->curve_cache->path->data==NULL) - BKE_displist_make_curveTypes(eff->scene, eff->ob, 0); - - if (eff->ob->curve_cache->path && eff->ob->curve_cache->path->data) { - where_on_path(eff->ob, 0.0, eff->guide_loc, eff->guide_dir, NULL, &eff->guide_radius, NULL); - mul_m4_v3(eff->ob->obmat, eff->guide_loc); - mul_mat3_m4_v3(eff->ob->obmat, eff->guide_dir); } } - } - else if (eff->pd->shape == PFIELD_SHAPE_SURFACE) { - eff->surmd = (SurfaceModifierData *)modifiers_findByType( eff->ob, eModifierType_Surface ); - if (eff->ob->type == OB_CURVE) - eff->flag |= PE_USE_NORMAL_DATA; - } - else if (eff->psys) - psys_update_particle_tree(eff->psys, eff->scene->r.cfra); - - /* Store object velocity */ - if (eff->ob) { - float old_vel[3]; - BKE_object_where_is_calc_time(eff->scene, eff->ob, cfra - 1.0f); - copy_v3_v3(old_vel, eff->ob->obmat[3]); - BKE_object_where_is_calc_time(eff->scene, eff->ob, cfra); - sub_v3_v3v3(eff->velocity, eff->ob->obmat[3], old_vel); - } -} - -void pdPrecalculateEffectors(ListBase *effectors) -{ - if (effectors) { - EffectorCache *eff = effectors->first; - for (; eff; eff=eff->next) - precalculate_effector(eff); + BLI_freelistN(lb); + MEM_freeN(lb); } } @@ -565,7 +581,7 @@ int closest_point_on_surface(SurfaceModifierData *surmd, const float co[3], floa } int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, int real_velocity) { - float cfra = eff->scene->r.cfra; + float cfra = DEG_get_ctime(eff->depsgraph); int ret = 0; /* In case surface object is in Edit mode when loading the .blend, surface modifier is never executed @@ -612,6 +628,7 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin } else { ParticleSimulationData sim= {NULL}; + sim.depsgraph = eff->depsgraph; sim.scene= eff->scene; sim.ob= eff->ob; sim.psys= eff->psys; @@ -971,7 +988,7 @@ static void do_physical_effector(EffectorCache *eff, EffectorData *efd, Effected } } -/* -------- pdDoEffectors() -------- +/* -------- BKE_effectors_apply() -------- * generic force/speed system, now used for particles and softbodies * scene = scene where it runs in, for time and stuff * lb = listbase with objects that take part in effecting @@ -984,7 +1001,7 @@ static void do_physical_effector(EffectorCache *eff, EffectorData *efd, Effected * flags = only used for softbody wind now * guide = old speed of particle */ -void pdDoEffectors(ListBase *effectors, ListBase *colliders, EffectorWeights *weights, EffectedPoint *point, float *force, float *impulse) +void BKE_effectors_apply(ListBase *effectors, ListBase *colliders, EffectorWeights *weights, EffectedPoint *point, float *force, float *impulse) { /* * Modifies the force on a particle according to its |