Fix depsgraph to compute more accurate links for collision & force.
authorAlexander Gavrilov <angavrilov@gmail.com>
Fri, 12 Aug 2016 15:23:29 +0000 (18:23 +0300)
committerAlexander Gavrilov <angavrilov@gmail.com>
Tue, 16 Aug 2016 12:46:36 +0000 (15:46 +0300)
Current implementation more or less indiscriminately links physics
objects to colliders and forces, ignoring precise details of layer
checks and collider groups. The new depsgraph seemed to lack some
such links at all. The relevant code in modifiers suffers from a
lot of duplication.

Different physics simulations use independent implementations of
collision and similar things, which results in a lot of variance:

* Cloth collides with objects on same or visible layer with dupli.
* Softbody collides with objects on same layer without dupli.
* Non-hair particles collide on same layer with dupli.
* Smoke uses same code as cloth, but needs different modifier.
* Dynamic paint "collides" with brushes on any layer without dupli.

Force fields with absorption also imply dependency on colliders:

* For most systems, colliders are selected from same layer as field.
* For non-hair particles, it uses the same exact set as the particles.

As a special quirk, smoke ignores smoke flow force fields; on the other
hand dependency on such field implies dependency on the smoke domain.

This introduces two utility functions each for old and new depsgraph
that are flexible enough to handle all these variations, and uses them
to handle particles, cloth, smoke, softbody and dynpaint.

One thing to watch out for is that depsgraph code shouldn't rely on
any properties that don't cause a graph rebuild when changed. This
was violated in the original code that was building force field links,
while taking zero field weights into account.

This change may cause new dependency cycles in cases where necessary
dependencies were missing, but may also remove cycles in situations
where unnecessary links were previously created. It's also now possible
to solve some cycles by switching to explicit groups, since they are
now properly taken into account for dependencies.

Differential Revision: https://developer.blender.org/D2141

17 files changed:
source/blender/blenkernel/BKE_collision.h
source/blender/blenkernel/BKE_effect.h
source/blender/blenkernel/depsgraph_private.h
source/blender/blenkernel/intern/collision.c
source/blender/blenkernel/intern/depsgraph.c
source/blender/blenkernel/intern/effect.c
source/blender/depsgraph/DEG_depsgraph_build.h
source/blender/depsgraph/intern/builder/deg_builder_relations.cc
source/blender/depsgraph/intern/builder/deg_builder_relations.h
source/blender/depsgraph/intern/depsgraph_build.cc
source/blender/makesrna/intern/rna_cloth.c
source/blender/makesrna/intern/rna_object_force.c
source/blender/makesrna/intern/rna_particle.c
source/blender/modifiers/intern/MOD_cloth.c
source/blender/modifiers/intern/MOD_dynamicpaint.c
source/blender/modifiers/intern/MOD_smoke.c
source/blender/modifiers/intern/MOD_softbody.c

index d5b4a584ec674b798cf9efaec3c3c004b28fce81..8fedcd4ab06585c6a389f3fbf3d4ec7a7f0e7df3 100644 (file)
@@ -146,6 +146,10 @@ void collision_get_collider_velocity(float vel_old[3], float vel_new[3], struct
 /////////////////////////////////////////////////
 // used in effect.c
 /////////////////////////////////////////////////
+
+/* explicit control over layer mask and dupli recursion */
+struct Object **get_collisionobjects_ext(struct Scene *scene, struct Object *self, struct Group *group, int layer, unsigned int *numcollobj, unsigned int modifier_type, bool dupli);
+
 struct Object **get_collisionobjects(struct Scene *scene, struct Object *self, struct Group *group, unsigned int *numcollobj, unsigned int modifier_type);
 
 typedef struct ColliderCache {
index f8fee444d9188d2c59733bb8e9edeafd00fc4d97..b934ec7166d2830b46e3d05684ed289f665c75f3 100644 (file)
@@ -110,7 +110,7 @@ typedef struct EffectorCache {
 } EffectorCache;
 
 void            free_partdeflect(struct PartDeflect *pd);
-struct ListBase *pdInitEffectors(struct Scene *scene, struct Object *ob_src, struct ParticleSystem *psys_src, struct EffectorWeights *weights, bool precalc);
+struct ListBase *pdInitEffectors(struct Scene *scene, struct Object *ob_src, struct ParticleSystem *psys_src, struct EffectorWeights *weights, bool for_simulation);
 void            pdEndEffectors(struct ListBase **effectors);
 void            pdPrecalculateEffectors(struct ListBase *effectors);
 void            pdDoEffectors(struct ListBase *effectors, struct ListBase *colliders, struct EffectorWeights *weights, struct EffectedPoint *point, float *force, float *impulse);
index 7b3199efb41ed43dd4464e71813ed7d955f8385e..69ca75836d96650f43481e93d4ca65d78cd17138 100644 (file)
 #include "DNA_constraint_types.h"
 #include "BKE_constraint.h"
 
+struct Scene;
+struct Group;
+struct EffectorWeights;
+struct ModifierData;
+
 /* **** DAG relation types *** */
 
 /* scene link to object */
@@ -152,6 +157,11 @@ DagNode *dag_get_node(DagForest *forest, void *fob);
 DagNode *dag_get_sub_node(DagForest *forest, void *fob);
 void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel, const char *name);
 
+typedef bool (*DagCollobjFilterFunction)(struct Object *obj, struct ModifierData *md);
+
+void dag_add_collision_relations(DagForest *dag, struct Scene *scene, Object *ob, DagNode *node, struct Group *group, int layer, unsigned int modifier_type, DagCollobjFilterFunction fn, bool dupli, const char *name);
+void dag_add_forcefield_relations(DagForest *dag, struct Scene *scene, Object *ob, DagNode *node, struct EffectorWeights *eff, bool add_absorption, int skip_forcefield, const char *name);
+
 void graph_print_queue(DagNodeQueue *nqueue);
 void graph_print_queue_dist(DagNodeQueue *nqueue);
 void graph_print_adj_list(DagForest *dag);
index 8cac856b560b590e51e2ac0523175df8d93b602d..35a7aafdbdefddeeff58779d7859cc572ea797fb 100644 (file)
@@ -503,12 +503,13 @@ static void add_collision_object(Object ***objs, unsigned int *numobj, unsigned
 
 // return all collision objects in scene
 // collision object will exclude self 
-Object **get_collisionobjects(Scene *scene, Object *self, Group *group, unsigned int *numcollobj, unsigned int modifier_type)
+Object **get_collisionobjects_ext(Scene *scene, Object *self, Group *group, int layer, unsigned int *numcollobj, unsigned int modifier_type, bool dupli)
 {
        Base *base;
        Object **objs;
        GroupObject *go;
        unsigned int numobj= 0, maxobj= 100;
+       int level = dupli ? 0 : 1;
        
        objs= MEM_callocN(sizeof(Object *)*maxobj, "CollisionObjectsArray");
 
@@ -516,16 +517,14 @@ Object **get_collisionobjects(Scene *scene, Object *self, Group *group, unsigned
        if (group) {
                /* use specified group */
                for (go= group->gobject.first; go; go= go->next)
-                       add_collision_object(&objs, &numobj, &maxobj, go->ob, self, 0, modifier_type);
+                       add_collision_object(&objs, &numobj, &maxobj, go->ob, self, level, modifier_type);
        }
        else {
                Scene *sce_iter;
                /* add objects in same layer in scene */
                for (SETLOOPER(scene, sce_iter, base)) {
-                       /* Need to check for active layers, too.
-                       Otherwise this check fails if the objects are not on the same layer - DG */
-                       if ((base->lay & self->lay) || (base->lay & scene->lay))
-                               add_collision_object(&objs, &numobj, &maxobj, base->object, self, 0, modifier_type);
+                       if ( base->lay & layer )
+                               add_collision_object(&objs, &numobj, &maxobj, base->object, self, level, modifier_type);
 
                }
        }
@@ -535,6 +534,13 @@ Object **get_collisionobjects(Scene *scene, Object *self, Group *group, unsigned
        return objs;
 }
 
+Object **get_collisionobjects(Scene *scene, Object *self, Group *group, unsigned int *numcollobj, unsigned int modifier_type)
+{
+       /* Need to check for active layers, too.
+          Otherwise this check fails if the objects are not on the same layer - DG */
+       return get_collisionobjects_ext(scene, self, group, self->lay | scene->lay, numcollobj, modifier_type, true);
+}
+
 static void add_collider_cache_object(ListBase **objs, Object *ob, Object *self, int level)
 {
        CollisionModifierData *cmd= NULL;
index 45a23c39910c209d89b1642114c182503c98d677..5f8332dcf0cb7c2f3f5f26292a9ae4f55487f4ac 100644 (file)
 #include "DNA_windowmanager_types.h"
 #include "DNA_movieclip_types.h"
 #include "DNA_mask_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_rigidbody_types.h"
 
 #include "BKE_anim.h"
 #include "BKE_animsys.h"
 #include "BKE_action.h"
 #include "BKE_DerivedMesh.h"
+#include "BKE_collision.h"
 #include "BKE_effect.h"
 #include "BKE_fcurve.h"
 #include "BKE_global.h"
@@ -450,49 +453,51 @@ static void dag_add_lamp_driver_relations(DagForest *dag, DagNode *node, Lamp *l
        la->id.tag &= ~LIB_TAG_DOIT;
 }
 
-static void check_and_create_collision_relation(DagForest *dag, Object *ob, DagNode *node, Object *ob1, int skip_forcefield, bool no_collision)
+static void create_collision_relation(DagForest *dag, DagNode *node, Object *ob1, const char *name)
 {
-       DagNode *node2;
-       if (ob1->pd && (ob1->pd->deflect || ob1->pd->forcefield) && (ob1 != ob)) {
-               if ((skip_forcefield && ob1->pd->forcefield == skip_forcefield) || (no_collision && ob1->pd->forcefield == 0))
-                       return;
-               node2 = dag_get_node(dag, ob1);
-               dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Field Collision");
+       DagNode *node2 = dag_get_node(dag, ob1);
+       dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, name);
+}
+
+void dag_add_collision_relations(DagForest *dag, Scene *scene, Object *ob, DagNode *node, Group *group, int layer, unsigned int modifier_type, DagCollobjFilterFunction fn, bool dupli, const char *name)
+{
+       unsigned int numcollobj;
+       Object **collobjs = get_collisionobjects_ext(scene, ob, group, layer, &numcollobj, modifier_type, dupli);
+
+       for (unsigned int i = 0; i < numcollobj; i++) {
+               Object *ob1 = collobjs[i];
+
+               if (!fn || fn(ob1, modifiers_findByType(ob1, modifier_type))) {
+                       create_collision_relation(dag, node, ob1, name);
+               }
        }
+
+       if (collobjs)
+               MEM_freeN(collobjs);
 }
 
-static void dag_add_collision_field_relation(DagForest *dag, Scene *scene, Object *ob, DagNode *node, int skip_forcefield, bool no_collision)
+void dag_add_forcefield_relations(DagForest *dag, Scene *scene, Object *ob, DagNode *node, EffectorWeights *effector_weights, bool add_absorption, int skip_forcefield, const char *name)
 {
-       Base *base;
-       ParticleSystem *particle_system;
+       ListBase *effectors = pdInitEffectors(scene, ob, NULL, effector_weights, false);
 
-       for (particle_system = ob->particlesystem.first;
-            particle_system;
-            particle_system = particle_system->next)
-       {
-               EffectorWeights *effector_weights = particle_system->part->effector_weights;
-               if (effector_weights->group) {
-                       GroupObject *group_object;
+       if (effectors) {
+               for (EffectorCache *eff = effectors->first; eff; eff = eff->next) {
+                       if (eff->ob != ob && eff->pd->forcefield != skip_forcefield) {
+                               create_collision_relation(dag, node, eff->ob, name);
 
-                       for (group_object = effector_weights->group->gobject.first;
-                            group_object;
-                            group_object = group_object->next)
-                       {
-                               if ((group_object->ob->lay & ob->lay)) {
-                                       check_and_create_collision_relation(dag, ob, node, group_object->ob, skip_forcefield, no_collision);
+                               if (eff->pd->forcefield == PFIELD_SMOKEFLOW && eff->pd->f_source) {
+                                       create_collision_relation(dag, node, eff->pd->f_source, "Smoke Force Domain");
+                               }
+
+                               if (add_absorption && (eff->pd->flag & PFIELD_VISIBILITY)) {
+                                       /* Actual code uses get_collider_cache */
+                                       dag_add_collision_relations(dag, scene, ob, node, NULL, eff->ob->lay, eModifierType_Collision, NULL, true, "Force Absorption");
                                }
                        }
                }
        }
 
-       /* would be nice to have a list of colliders here
-        * so for now walk all objects in scene check 'same layer rule' */
-       for (base = scene->base.first; base; base = base->next) {
-               if ((base->lay & ob->lay)) {
-                       Object *ob1 = base->object;
-                       check_and_create_collision_relation(dag, ob, node, ob1, skip_forcefield, no_collision);
-               }
-       }
+       pdEndEffectors(&effectors);
 }
 
 static void build_dag_object(DagForest *dag, DagNode *scenenode, Main *bmain, Scene *scene, Object *ob, int mask)
@@ -643,23 +648,13 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Main *bmain, Sc
                }
        }
 
-       /* softbody collision  */
+       /* rigidbody force fields  */
        if ((ob->type == OB_MESH) || (ob->type == OB_CURVE) || (ob->type == OB_LATTICE)) {
-               if (ob->particlesystem.first ||
-                   modifiers_isModifierEnabled(ob, eModifierType_Softbody) ||
-                   modifiers_isModifierEnabled(ob, eModifierType_Cloth) ||
-                   modifiers_isModifierEnabled(ob, eModifierType_DynamicPaint))
-               {
-                       dag_add_collision_field_relation(dag, scene, ob, node, 0, false);  /* TODO: use effectorweight->group */
-               }
-               else if (modifiers_isModifierEnabled(ob, eModifierType_Smoke)) {
-                       dag_add_collision_field_relation(dag, scene, ob, node, PFIELD_SMOKEFLOW, false);
-               }
-               else if (ob->rigidbody_object) {
-                       dag_add_collision_field_relation(dag, scene, ob, node, 0, true);
+               if (ob->rigidbody_object && scene->rigidbody_world) {
+                       dag_add_forcefield_relations(dag, scene, ob, node, scene->rigidbody_world->effector_weights, true, 0, "Force Field");
                }
        }
-       
+
        /* object data drivers */
        if (ob->data) {
                AnimData *adt = BKE_animdata_from_id((ID *)ob->data);
@@ -763,8 +758,6 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Main *bmain, Sc
                        BoidRule *rule = NULL;
                        BoidState *state = NULL;
                        ParticleSettings *part = psys->part;
-                       ListBase *effectors = NULL;
-                       EffectorCache *eff;
 
                        if (part->adt) {
                                dag_add_driver_relation(part->adt, dag, node, 1);
@@ -803,18 +796,12 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Main *bmain, Sc
                                }
                        }
 
-                       effectors = pdInitEffectors(scene, ob, psys, part->effector_weights, false);
-
-                       if (effectors) {
-                               for (eff = effectors->first; eff; eff = eff->next) {
-                                       if (eff->psys) {
-                                               node2 = dag_get_node(dag, eff->ob);
-                                               dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Particle Field");
-                                       }
-                               }
+                       if (part->type != PART_HAIR) {
+                               /* Actual code uses get_collider_cache */
+                               dag_add_collision_relations(dag, scene, ob, node, part->collision_group, ob->lay, eModifierType_Collision, NULL, true, "Particle Collision");
                        }
 
-                       pdEndEffectors(&effectors);
+                       dag_add_forcefield_relations(dag, scene, ob, node, part->effector_weights, part->type == PART_HAIR, 0, "Particle Force Field");
 
                        if (part->boids) {
                                for (state = part->boids->states.first; state; state = state->next) {
index 5090e46f1fcf2591ddd6bf3ff5facdabb3fa3f26..7e6897a2858dd12c88968b357aeed55bb5a8d582 100644 (file)
@@ -155,15 +155,20 @@ static EffectorCache *new_effector_cache(Scene *scene, Object *ob, ParticleSyste
        eff->frame = -1;
        return eff;
 }
-static void add_object_to_effectors(ListBase **effectors, Scene *scene, EffectorWeights *weights, Object *ob, Object *ob_src)
+static void add_object_to_effectors(ListBase **effectors, Scene *scene, EffectorWeights *weights, Object *ob, Object *ob_src, bool for_simulation)
 {
        EffectorCache *eff = NULL;
 
-       if ( ob == ob_src || weights->weight[ob->pd->forcefield] == 0.0f )
+       if ( ob == ob_src )
                return;
 
-       if (ob->pd->shape == PFIELD_SHAPE_POINTS && !ob->derivedFinal )
-               return;
+       if (for_simulation) {
+               if (weights->weight[ob->pd->forcefield] == 0.0f )
+                       return;
+
+               if (ob->pd->shape == PFIELD_SHAPE_POINTS && !ob->derivedFinal )
+                       return;
+       }
 
        if (*effectors == NULL)
                *effectors = MEM_callocN(sizeof(ListBase), "effectors list");
@@ -175,7 +180,7 @@ static void add_object_to_effectors(ListBase **effectors, Scene *scene, Effector
 
        BLI_addtail(*effectors, eff);
 }
-static void add_particles_to_effectors(ListBase **effectors, Scene *scene, EffectorWeights *weights, Object *ob, ParticleSystem *psys, ParticleSystem *psys_src)
+static void add_particles_to_effectors(ListBase **effectors, Scene *scene, EffectorWeights *weights, Object *ob, ParticleSystem *psys, ParticleSystem *psys_src, bool for_simulation)
 {
        ParticleSettings *part= psys->part;
 
@@ -185,14 +190,14 @@ static void add_particles_to_effectors(ListBase **effectors, Scene *scene, Effec
        if ( psys == psys_src && (part->flag & PART_SELF_EFFECT) == 0)
                return;
 
-       if ( part->pd && part->pd->forcefield && weights->weight[part->pd->forcefield] != 0.0f) {
+       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");
 
                BLI_addtail(*effectors, new_effector_cache(scene, ob, psys, part->pd));
        }
 
-       if (part->pd2 && part->pd2->forcefield && weights->weight[part->pd2->forcefield] != 0.0f) {
+       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");
 
@@ -202,7 +207,7 @@ static void add_particles_to_effectors(ListBase **effectors, Scene *scene, Effec
 
 /* returns ListBase handle with objects taking part in the effecting */
 ListBase *pdInitEffectors(Scene *scene, Object *ob_src, ParticleSystem *psys_src,
-                          EffectorWeights *weights, bool precalc)
+                          EffectorWeights *weights, bool for_simulation)
 {
        Base *base;
        unsigned int layer= ob_src->lay;
@@ -214,13 +219,13 @@ ListBase *pdInitEffectors(Scene *scene, Object *ob_src, ParticleSystem *psys_src
                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);
+                                       add_object_to_effectors(&effectors, scene, weights, go->ob, ob_src, for_simulation);
 
                                if ( go->ob->particlesystem.first ) {
                                        ParticleSystem *psys= go->ob->particlesystem.first;
 
                                        for ( ; psys; psys=psys->next )
-                                               add_particles_to_effectors(&effectors, scene, weights, go->ob, psys, psys_src);
+                                               add_particles_to_effectors(&effectors, scene, weights, go->ob, psys, psys_src, for_simulation);
                                }
                        }
                }
@@ -229,19 +234,19 @@ ListBase *pdInitEffectors(Scene *scene, Object *ob_src, ParticleSystem *psys_src
                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);
+                                       add_object_to_effectors(&effectors, scene, weights, base->object, ob_src, for_simulation);
 
                                if ( base->object->particlesystem.first ) {
                                        ParticleSystem *psys= base->object->particlesystem.first;
 
                                        for ( ; psys; psys=psys->next )
-                                               add_particles_to_effectors(&effectors, scene, weights, base->object, psys, psys_src);
+                                               add_particles_to_effectors(&effectors, scene, weights, base->object, psys, psys_src, for_simulation);
                                }
                        }
                }
        }
        
-       if (precalc)
+       if (for_simulation)
                pdPrecalculateEffectors(effectors);
        
        return effectors;
index 0209e94debee2fb4de5b645a38e57e6a6af4dfad..0945da439ef3b021adc3657377e3add958016a34 100644 (file)
@@ -42,6 +42,8 @@ struct Depsgraph;
 
 struct Main;
 struct Scene;
+struct Group;
+struct EffectorWeights;
 
 #ifdef __cplusplus
 extern "C" {
@@ -112,6 +114,12 @@ void DEG_add_object_cache_relation(struct DepsNodeHandle *handle, struct CacheFi
 /* TODO(sergey): Remove once all geometry update is granular. */
 void DEG_add_special_eval_flag(struct Depsgraph *graph, struct ID *id, short flag);
 
+/* Utility functions for physics modifiers */
+typedef bool (*DEG_CollobjFilterFunction)(struct Object *obj, struct ModifierData *md);
+
+void DEG_add_collision_relations(struct DepsNodeHandle *handle, struct Scene *scene, Object *ob, struct Group *group, int layer, unsigned int modifier_type, DEG_CollobjFilterFunction fn, bool dupli, const char *name);
+void DEG_add_forcefield_relations(struct DepsNodeHandle *handle, struct Scene *scene, Object *ob, struct EffectorWeights *eff, bool add_absorption, int skip_forcefield, const char *name);
+
 /* ************************************************ */
 
 #ifdef __cplusplus
index 9ab283312491ffebd8c5d9caab79d7211dab8792..2148a3501d8c05111992ae79a22228684b42c0aa 100644 (file)
@@ -65,6 +65,7 @@ extern "C" {
 #include "DNA_scene_types.h"
 #include "DNA_texture_types.h"
 #include "DNA_world_types.h"
+#include "DNA_object_force.h"
 
 #include "BKE_action.h"
 #include "BKE_armature.h"
@@ -72,6 +73,7 @@ extern "C" {
 #include "BKE_constraint.h"
 #include "BKE_curve.h"
 #include "BKE_effect.h"
+#include "BKE_collision.h"
 #include "BKE_fcurve.h"
 #include "BKE_group.h"
 #include "BKE_key.h"
@@ -243,6 +245,69 @@ void DepsgraphRelationBuilder::add_operation_relation(
        }
 }
 
+void DepsgraphRelationBuilder::add_collision_relations(const OperationKey &key, Scene *scene, Object *ob, Group *group, int layer, bool dupli, const char *name)
+{
+       unsigned int numcollobj;
+       Object **collobjs = get_collisionobjects_ext(scene, ob, group, layer, &numcollobj, eModifierType_Collision, dupli);
+
+       for (unsigned int i = 0; i < numcollobj; i++)
+       {
+               Object *ob1 = collobjs[i];
+
+               ComponentKey trf_key(&ob1->id, DEPSNODE_TYPE_TRANSFORM);
+               add_relation(trf_key, key, DEPSREL_TYPE_STANDARD, name);
+
+               ComponentKey coll_key(&ob1->id, DEPSNODE_TYPE_GEOMETRY);
+               add_relation(coll_key, key, DEPSREL_TYPE_STANDARD, name);
+       }
+
+       if (collobjs)
+               MEM_freeN(collobjs);
+}
+
+void DepsgraphRelationBuilder::add_forcefield_relations(const OperationKey &key, Scene *scene, Object *ob, ParticleSystem *psys, EffectorWeights *eff, bool add_absorption, const char *name)
+{
+       ListBase *effectors = pdInitEffectors(scene, ob, psys, eff, false);
+
+       if (effectors) {
+               for (EffectorCache *eff = (EffectorCache *)effectors->first; eff; eff = eff->next) {
+                       if (eff->ob != ob) {
+                               ComponentKey eff_key(&eff->ob->id, DEPSNODE_TYPE_TRANSFORM);
+                               add_relation(eff_key, key, DEPSREL_TYPE_STANDARD, name);
+                       }
+
+                       if (eff->psys) {
+                               if (eff->ob != ob) {
+                                       ComponentKey eff_key(&eff->ob->id, DEPSNODE_TYPE_EVAL_PARTICLES);
+                                       add_relation(eff_key, key, DEPSREL_TYPE_STANDARD, name);
+
+                                       /* TODO: remove this when/if EVAL_PARTICLES is sufficient for up to date particles */
+                                       ComponentKey mod_key(&eff->ob->id, DEPSNODE_TYPE_GEOMETRY);
+                                       add_relation(mod_key, key, DEPSREL_TYPE_STANDARD, name);
+                               }
+                               else if (eff->psys != psys) {
+                                       OperationKey eff_key(&eff->ob->id, DEPSNODE_TYPE_EVAL_PARTICLES, DEG_OPCODE_PSYS_EVAL, eff->psys->name);
+                                       add_relation(eff_key, key, DEPSREL_TYPE_STANDARD, name);
+                               }
+                       }
+
+                       if (eff->pd->forcefield == PFIELD_SMOKEFLOW && eff->pd->f_source) {
+                               ComponentKey trf_key(&eff->pd->f_source->id, DEPSNODE_TYPE_TRANSFORM);
+                               add_relation(trf_key, key, DEPSREL_TYPE_STANDARD, "Smoke Force Domain");
+
+                               ComponentKey eff_key(&eff->pd->f_source->id, DEPSNODE_TYPE_GEOMETRY);
+                               add_relation(eff_key, key, DEPSREL_TYPE_STANDARD, "Smoke Force Domain");
+                       }
+
+                       if (add_absorption && (eff->pd->flag & PFIELD_VISIBILITY)) {
+                               add_collision_relations(key, scene, ob, NULL, eff->ob->lay, true, "Force Absorption");
+                       }
+               }
+       }
+
+       pdEndEffectors(&effectors);
+}
+
 /* **** Functions to build relations between entities  **** */
 
 void DepsgraphRelationBuilder::build_scene(Main *bmain, Scene *scene)
@@ -1137,20 +1202,13 @@ void DepsgraphRelationBuilder::build_particles(Scene *scene, Object *ob)
                }
 #endif
 
-               /* effectors */
-               ListBase *effectors = pdInitEffectors(scene, ob, psys, part->effector_weights, false);
-
-               if (effectors) {
-                       for (EffectorCache *eff = (EffectorCache *)effectors->first; eff; eff = eff->next) {
-                               if (eff->psys) {
-                                       // XXX: DAG_RL_DATA_DATA | DAG_RL_OB_DATA
-                                       ComponentKey eff_key(&eff->ob->id, DEPSNODE_TYPE_GEOMETRY); // xxx: particles instead?
-                                       add_relation(eff_key, psys_key, DEPSREL_TYPE_STANDARD, "Particle Field");
-                               }
-                       }
+               /* collisions */
+               if (part->type != PART_HAIR) {
+                       add_collision_relations(psys_key, scene, ob, part->collision_group, ob->lay, true, "Particle Collision");
                }
 
-               pdEndEffectors(&effectors);
+               /* effectors */
+               add_forcefield_relations(psys_key, scene, ob, psys, part->effector_weights, part->type == PART_HAIR, "Particle Field");
 
                /* boids */
                if (part->boids) {
index ce6d2c961fd3d7e7ba8b3c25812751c29e9a9071..46e65d464a432df4efdeaa63a8715afa86bbf1f7 100644 (file)
@@ -63,6 +63,8 @@ struct bConstraint;
 struct Scene;
 struct Tex;
 struct World;
+struct EffectorWeights;
+struct ParticleSystem;
 
 struct PropertyRNA;
 
@@ -244,6 +246,9 @@ struct DepsgraphRelationBuilder
        void build_compositor(Scene *scene);
        void build_gpencil(ID *owner, bGPdata *gpd);
 
+       void add_collision_relations(const OperationKey &key, Scene *scene, Object *ob, Group *group, int layer, bool dupli, const char *name);
+       void add_forcefield_relations(const OperationKey &key, Scene *scene, Object *ob, ParticleSystem *psys, EffectorWeights *eff, bool add_absorption, const char *name);
+
        template <typename KeyType>
        OperationDepsNode *find_operation_node(const KeyType &key);
 
index ae830da12529b0026359d993dd58cf1b7a9f0865..7a3b19e82c61e8ddf6e6626c5795b4efb82b7169 100644 (file)
@@ -36,11 +36,15 @@ extern "C" {
 #include "DNA_cachefile_types.h"
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
+#include "DNA_object_force.h"
 
 #include "BLI_utildefines.h"
 #include "BLI_ghash.h"
 
 #include "BKE_main.h"
+#include "BKE_collision.h"
+#include "BKE_effect.h"
+#include "BKE_modifier.h"
 
 #include "DEG_depsgraph.h"
 #include "DEG_depsgraph_debug.h"
@@ -304,3 +308,52 @@ void DEG_scene_graph_free(Scene *scene)
                scene->depsgraph = NULL;
        }
 }
+
+void DEG_add_collision_relations(DepsNodeHandle *handle, Scene *scene, Object *ob, Group *group, int layer, unsigned int modifier_type, DEG_CollobjFilterFunction fn, bool dupli, const char *name)
+{
+       unsigned int numcollobj;
+       Object **collobjs = get_collisionobjects_ext(scene, ob, group, layer, &numcollobj, modifier_type, dupli);
+
+       for (unsigned int i = 0; i < numcollobj; i++) {
+               Object *ob1 = collobjs[i];
+
+               if (!fn || fn(ob1, modifiers_findByType(ob1, (ModifierType)modifier_type))) {
+                       DEG_add_object_relation(handle, ob1, DEG_OB_COMP_TRANSFORM, name);
+                       DEG_add_object_relation(handle, ob1, DEG_OB_COMP_GEOMETRY, name);
+               }
+       }
+
+       if (collobjs)
+               MEM_freeN(collobjs);
+}
+
+void DEG_add_forcefield_relations(DepsNodeHandle *handle, Scene *scene, Object *ob, EffectorWeights *effector_weights, bool add_absorption, int skip_forcefield, const char *name)
+{
+       ListBase *effectors = pdInitEffectors(scene, ob, NULL, effector_weights, false);
+
+       if (effectors) {
+               for (EffectorCache *eff = (EffectorCache*)effectors->first; eff; eff = eff->next) {
+                       if (eff->ob != ob && eff->pd->forcefield != skip_forcefield) {
+                               DEG_add_object_relation(handle, eff->ob, DEG_OB_COMP_TRANSFORM, name);
+
+                               if (eff->psys) {
+                                       DEG_add_object_relation(handle, eff->ob, DEG_OB_COMP_EVAL_PARTICLES, name);
+
+                                       /* TODO: remove this when/if EVAL_PARTICLES is sufficient for up to date particles */
+                                       DEG_add_object_relation(handle, eff->ob, DEG_OB_COMP_GEOMETRY, name);
+                               }
+
+                               if (eff->pd->forcefield == PFIELD_SMOKEFLOW && eff->pd->f_source) {
+                                       DEG_add_object_relation(handle, eff->pd->f_source, DEG_OB_COMP_TRANSFORM, "Smoke Force Domain");
+                                       DEG_add_object_relation(handle, eff->pd->f_source, DEG_OB_COMP_GEOMETRY, "Smoke Force Domain");
+                               }
+
+                               if (add_absorption && (eff->pd->flag & PFIELD_VISIBILITY)) {
+                                       DEG_add_collision_relations(handle, scene, ob, NULL, eff->ob->lay, eModifierType_Collision, NULL, true, "Force Absorption");
+                               }
+                       }
+               }
+       }
+
+       pdEndEffectors(&effectors);
+}
index 91cae32d054f96583baff52eaf40e9bad702b4bf..d8bcbc2cc72a51b2462fcdf0fb4234907552e675 100644 (file)
@@ -56,6 +56,12 @@ static void rna_cloth_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerR
        WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob);
 }
 
+static void rna_cloth_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+       DAG_relations_tag_update(bmain);
+       rna_cloth_update(bmain, scene, ptr);
+}
+
 static void rna_cloth_pinning_changed(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
 {
        Object *ob = (Object *)ptr->id.data;
@@ -729,7 +735,7 @@ static void rna_def_cloth_collision_settings(BlenderRNA *brna)
        prop = RNA_def_property(srna, "group", PROP_POINTER, PROP_NONE);
        RNA_def_property_flag(prop, PROP_EDITABLE);
        RNA_def_property_ui_text(prop, "Collision Group", "Limit colliders to this Group");
-       RNA_def_property_update(prop, 0, "rna_cloth_update");
+       RNA_def_property_update(prop, 0, "rna_cloth_dependency_update");
 
        prop = RNA_def_property(srna, "vertex_group_self_collisions", PROP_STRING, PROP_NONE);
        RNA_def_property_string_funcs(prop, "rna_CollSettings_selfcol_vgroup_get", "rna_CollSettings_selfcol_vgroup_length",
index f05813043caf9ac80b3a1f4342cf7849a2245c25..1d89f7535c45c51802bdea5e6013182b282bf838 100644 (file)
@@ -730,6 +730,11 @@ static void rna_softbody_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Point
        WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob);
 }
 
+static void rna_softbody_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+       DAG_relations_tag_update(bmain);
+       rna_softbody_update(bmain, scene, ptr);
+}
 
 static EnumPropertyItem *rna_Effector_shape_itemf(bContext *UNUSED(C), PointerRNA *ptr,
                                                   PropertyRNA *UNUSED(prop), bool *UNUSED(r_free))
@@ -1378,7 +1383,7 @@ static void rna_def_field(BlenderRNA *brna)
        prop = RNA_def_property(srna, "use_absorption", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_VISIBILITY);
        RNA_def_property_ui_text(prop, "Absorption", "Force gets absorbed by collision objects");
-       RNA_def_property_update(prop, 0, "rna_FieldSettings_update");
+       RNA_def_property_update(prop, 0, "rna_FieldSettings_dependency_update");
 
        prop = RNA_def_property(srna, "use_multiple_springs", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_MULTIPLE_SPRINGS);
@@ -1855,7 +1860,7 @@ static void rna_def_softbody(BlenderRNA *brna)
        prop = RNA_def_property(srna, "collision_group", PROP_POINTER, PROP_NONE);
        RNA_def_property_flag(prop, PROP_EDITABLE);
        RNA_def_property_ui_text(prop, "Collision Group", "Limit colliders to this Group");
-       RNA_def_property_update(prop, 0, "rna_softbody_update");
+       RNA_def_property_update(prop, 0, "rna_softbody_dependency_update");
 
        prop = RNA_def_property(srna, "effector_weights", PROP_POINTER, PROP_NONE);
        RNA_def_property_pointer_sdna(prop, NULL, "effector_weights");
index eabf41cb3321ace32fd56a2cd1969f860b0fc081..5e3fa4b467d82de7e5ee554079a7518ce22d98b5 100644 (file)
@@ -630,6 +630,12 @@ static void rna_Particle_reset(Main *bmain, Scene *scene, PointerRNA *ptr)
        particle_recalc(bmain, scene, ptr, PSYS_RECALC_RESET);
 }
 
+static void rna_Particle_reset_dependency(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+       DAG_relations_tag_update(bmain);
+       rna_Particle_reset(bmain, scene, ptr);
+}
+
 static void rna_Particle_change_type(Main *bmain, Scene *scene, PointerRNA *ptr)
 {
        particle_recalc(bmain, scene, ptr, PSYS_RECALC_RESET | PSYS_RECALC_TYPE);
@@ -2744,7 +2750,7 @@ static void rna_def_particle_settings(BlenderRNA *brna)
        prop = RNA_def_property(srna, "collision_group", PROP_POINTER, PROP_NONE);
        RNA_def_property_flag(prop, PROP_EDITABLE);
        RNA_def_property_ui_text(prop, "Collision Group", "Limit colliders to this Group");
-       RNA_def_property_update(prop, 0, "rna_Particle_reset");
+       RNA_def_property_update(prop, 0, "rna_Particle_reset_dependency");
 
        /* global physical properties */
        prop = RNA_def_property(srna, "drag_factor", PROP_FLOAT, PROP_NONE);
index 6cc2f097be8f0f1bef779ca83e5ba1b62ae52088..d15a6fcb1c8020927600b5f4e58122dc33954da5 100644 (file)
@@ -123,19 +123,11 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
 {
        ClothModifierData *clmd = (ClothModifierData *) md;
        
-       Base *base;
-       
        if (clmd) {
-               for (base = scene->base.first; base; base = base->next) {
-                       Object *ob1 = base->object;
-                       if (ob1 != ob) {
-                               CollisionModifierData *coll_clmd = (CollisionModifierData *)modifiers_findByType(ob1, eModifierType_Collision);
-                               if (coll_clmd) {
-                                       DagNode *curNode = dag_get_node(forest, ob1);
-                                       dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Cloth Collision");
-                               }
-                       }
-               }
+               /* Actual code uses get_collisionobjects */
+               dag_add_collision_relations(forest, scene, ob, obNode, clmd->coll_parms->group, ob->lay|scene->lay, eModifierType_Collision, NULL, true, "Cloth Collision");
+
+               dag_add_forcefield_relations(forest, scene, ob, obNode, clmd->sim_parms->effector_weights, true, 0, "Cloth Field");
        }
 }
 
@@ -147,16 +139,10 @@ static void updateDepsgraph(ModifierData *md,
 {
        ClothModifierData *clmd = (ClothModifierData *)md;
        if (clmd != NULL) {
-               Base *base;
-               for (base = scene->base.first; base; base = base->next) {
-                       Object *ob1 = base->object;
-                       if (ob1 != ob) {
-                               CollisionModifierData *coll_clmd = (CollisionModifierData *)modifiers_findByType(ob1, eModifierType_Collision);
-                               if (coll_clmd) {
-                                       DEG_add_object_relation(node, ob1, DEG_OB_COMP_TRANSFORM, "Cloth Modifier");
-                               }
-                       }
-               }
+               /* Actual code uses get_collisionobjects */
+               DEG_add_collision_relations(node, scene, ob, clmd->coll_parms->group, ob->lay|scene->lay, eModifierType_Collision, NULL, true, "Cloth Collision");
+
+               DEG_add_forcefield_relations(node, scene, ob, clmd->sim_parms->effector_weights, true, 0, "Cloth Field");
        }
 }
 
index edf959f42c6dfbd1f10575321d0eef6ac5346195..bde20e56748e3ee3f93dc403743bda5a4362cec6 100644 (file)
@@ -114,6 +114,11 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
        return dm;
 }
 
+static bool is_brush_cb(Object *UNUSED(ob), ModifierData *pmd)
+{
+       return ((DynamicPaintModifierData*)pmd)->brush != NULL;
+}
+
 static void updateDepgraph(ModifierData *md, DagForest *forest,
                            struct Main *UNUSED(bmain),
                            struct Scene *scene,
@@ -124,16 +129,13 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
 
        /* add relation from canvases to all brush objects */
        if (pmd && pmd->canvas) {
-               Base *base = scene->base.first;
-
-               for (; base; base = base->next) {
-                       DynamicPaintModifierData *pmd2 =
-                               (DynamicPaintModifierData *)modifiers_findByType(base->object, eModifierType_DynamicPaint);
-
-                       if (pmd2 && pmd2->brush && ob != base->object) {
-                               DagNode *brushNode = dag_get_node(forest, base->object);
-                               dag_add_relation(forest, brushNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Dynamic Paint Brush");
+               for (DynamicPaintSurface *surface = pmd->canvas->surfaces.first; surface; surface = surface->next) {
+                       if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) {
+                               dag_add_forcefield_relations(forest, scene, ob, obNode, surface->effector_weights, true, 0, "Dynamic Paint Field");
                        }
+
+                       /* Actual code uses custom loop over group/scene without layer checks in dynamicPaint_doStep */
+                       dag_add_collision_relations(forest, scene, ob, obNode, surface->brush_group, -1, eModifierType_DynamicPaint, is_brush_cb, false, "Dynamic Paint Brush");
                }
        }
 }
@@ -147,13 +149,13 @@ static void updateDepsgraph(ModifierData *md,
        DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
        /* Add relation from canvases to all brush objects. */
        if (pmd->canvas != NULL) {
-               Base *base = scene->base.first;
-               for (; base; base = base->next) {
-                       DynamicPaintModifierData *pmd2 =
-                               (DynamicPaintModifierData *)modifiers_findByType(base->object, eModifierType_DynamicPaint);
-                       if (pmd2 && pmd2->brush && ob != base->object) {
-                               DEG_add_object_relation(node, base->object, DEG_OB_COMP_TRANSFORM, "Dynamic Paint Brush");
+               for (DynamicPaintSurface *surface = pmd->canvas->surfaces.first; surface; surface = surface->next) {
+                       if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) {
+                               DEG_add_forcefield_relations(node, scene, ob, surface->effector_weights, true, 0, "Dynamic Paint Field");
                        }
+
+                       /* Actual code uses custom loop over group/scene without layer checks in dynamicPaint_doStep */
+                       DEG_add_collision_relations(node, scene, ob, surface->brush_group, -1, eModifierType_DynamicPaint, is_brush_cb, false, "Dynamic Paint Brush");
                }
        }
 }
index 237d4cc6718527ec2a8e410f588d17987fa1d26f..f04d7432a8f44da9a33995fa0e6e5007c23e16d1 100644 (file)
@@ -117,219 +117,48 @@ static bool dependsOnTime(ModifierData *UNUSED(md))
        return true;
 }
 
-static void update_depsgraph_flow_coll_object(DagForest *forest,
-                                              DagNode *obNode,
-                                              Object *object2)
+static bool is_flow_cb(Object *UNUSED(ob), ModifierData *md)
 {
-       SmokeModifierData *smd;
-       if ((object2->id.tag & LIB_TAG_DOIT) == 0) {
-               return;
-       }
-       object2->id.tag &= ~LIB_TAG_DOIT;
-       smd = (SmokeModifierData *)modifiers_findByType(object2, eModifierType_Smoke);
-       if (smd && (((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow) ||
-                   ((smd->type & MOD_SMOKE_TYPE_COLL) && smd->coll)))
-       {
-               DagNode *curNode = dag_get_node(forest, object2);
-               dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Smoke Flow/Coll");
-       }
-       if ((object2->transflag & OB_DUPLIGROUP) && object2->dup_group) {
-               GroupObject *go;
-               for (go = object2->dup_group->gobject.first;
-                    go != NULL;
-                    go = go->next)
-               {
-                       if (go->ob == NULL) {
-                               continue;
-                       }
-                       update_depsgraph_flow_coll_object(forest, obNode, go->ob);
-               }
-       }
+       SmokeModifierData *smd = (SmokeModifierData *) md;
+       return (smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow;
 }
 
-static void update_depsgraph_field_source_object(DagForest *forest,
-                                                 DagNode *obNode,
-                                                 Object *object,
-                                                 Object *object2)
+static bool is_coll_cb(Object *UNUSED(ob), ModifierData *md)
 {
-       if ((object2->id.tag & LIB_TAG_DOIT) == 0) {
-               return;
-       }
-       object2->id.tag &= ~LIB_TAG_DOIT;
-       if (object2->pd && object2->pd->forcefield == PFIELD_SMOKEFLOW && object2->pd->f_source == object) {
-               DagNode *node2 = dag_get_node(forest, object2);
-               dag_add_relation(forest, obNode, node2, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Field Source Object");
-       }
-       if ((object2->transflag & OB_DUPLIGROUP) && object2->dup_group) {
-               GroupObject *go;
-               for (go = object2->dup_group->gobject.first;
-                    go != NULL;
-                    go = go->next)
-               {
-                       if (go->ob == NULL) {
-                               continue;
-                       }
-                       update_depsgraph_field_source_object(forest, obNode, object, go->ob);
-               }
-       }
+       SmokeModifierData *smd = (SmokeModifierData *) md;
+       return (smd->type & MOD_SMOKE_TYPE_COLL) && smd->coll;
 }
 
 static void updateDepgraph(ModifierData *md, DagForest *forest,
-                           struct Main *bmain,
+                           struct Main *UNUSED(bmain),
                            struct Scene *scene, struct Object *ob,
                            DagNode *obNode)
 {
        SmokeModifierData *smd = (SmokeModifierData *) md;
-       Base *base;
 
        if (smd && (smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) {
-               if (smd->domain->fluid_group || smd->domain->coll_group) {
-                       GroupObject *go = NULL;
-                       
-                       if (smd->domain->fluid_group)
-                               for (go = smd->domain->fluid_group->gobject.first; go; go = go->next) {
-                                       if (go->ob) {
-                                               SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(go->ob, eModifierType_Smoke);
-                                               
-                                               /* check for initialized smoke object */
-                                               if (smd2 && (smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow) {
-                                                       DagNode *curNode = dag_get_node(forest, go->ob);
-                                                       dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Smoke Flow");
-                                               }
-                                       }
-                               }
-
-                       if (smd->domain->coll_group)
-                               for (go = smd->domain->coll_group->gobject.first; go; go = go->next) {
-                                       if (go->ob) {
-                                               SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(go->ob, eModifierType_Smoke);
-                                               
-                                               /* check for initialized smoke object */
-                                               if (smd2 && (smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll) {
-                                                       DagNode *curNode = dag_get_node(forest, go->ob);
-                                                       dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Smoke Coll");
-                                               }
-                                       }
-                               }
-               }
-               else {
-                       BKE_main_id_tag_listbase(&bmain->object, LIB_TAG_DOIT, true);
-                       base = scene->base.first;
-                       for (; base; base = base->next) {
-                               update_depsgraph_flow_coll_object(forest, obNode, base->object);
-                       }
-               }
-               /* add relation to all "smoke flow" force fields */
-               base = scene->base.first;
-               BKE_main_id_tag_listbase(&bmain->object, LIB_TAG_DOIT, true);
-               for (; base; base = base->next) {
-                       update_depsgraph_field_source_object(forest, obNode, ob, base->object);
-               }
-       }
-}
+               /* Actual code uses get_collisionobjects */
+               dag_add_collision_relations(forest, scene, ob, obNode, smd->domain->fluid_group, ob->lay|scene->lay, eModifierType_Smoke, is_flow_cb, true, "Smoke Flow");
+               dag_add_collision_relations(forest, scene, ob, obNode, smd->domain->coll_group, ob->lay|scene->lay, eModifierType_Smoke, is_coll_cb, true, "Smoke Coll");
 
-static void update_depsgraph_flow_coll_object_new(struct DepsNodeHandle *node,
-                                                  Object *object2)
-{
-       SmokeModifierData *smd;
-       if ((object2->id.tag & LIB_TAG_DOIT) == 0) {
-               return;
-       }
-       object2->id.tag &= ~LIB_TAG_DOIT;
-       smd = (SmokeModifierData *)modifiers_findByType(object2, eModifierType_Smoke);
-       if (smd && (((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow) ||
-                   ((smd->type & MOD_SMOKE_TYPE_COLL) && smd->coll)))
-       {
-               DEG_add_object_relation(node, object2, DEG_OB_COMP_TRANSFORM, "Smoke Flow/Coll");
-               DEG_add_object_relation(node, object2, DEG_OB_COMP_GEOMETRY, "Smoke Flow/Coll");
-       }
-       if ((object2->transflag & OB_DUPLIGROUP) && object2->dup_group) {
-               GroupObject *go;
-               for (go = object2->dup_group->gobject.first;
-                    go != NULL;
-                    go = go->next)
-               {
-                       if (go->ob == NULL) {
-                               continue;
-                       }
-                       update_depsgraph_flow_coll_object_new(node, go->ob);
-               }
-       }
-}
-
-static void update_depsgraph_field_source_object_new(struct DepsNodeHandle *node,
-                                                     Object *object,
-                                                     Object *object2)
-{
-       if ((object2->id.tag & LIB_TAG_DOIT) == 0) {
-               return;
-       }
-       object2->id.tag &= ~LIB_TAG_DOIT;
-       if (object2->pd && object2->pd->forcefield == PFIELD_SMOKEFLOW && object2->pd->f_source == object) {
-               DEG_add_object_relation(node, object2, DEG_OB_COMP_TRANSFORM, "Field Source Object");
-               DEG_add_object_relation(node, object2, DEG_OB_COMP_GEOMETRY, "Field Source Object");
-       }
-       if ((object2->transflag & OB_DUPLIGROUP) && object2->dup_group) {
-               GroupObject *go;
-               for (go = object2->dup_group->gobject.first;
-                    go != NULL;
-                    go = go->next)
-               {
-                       if (go->ob == NULL) {
-                               continue;
-                       }
-                       update_depsgraph_field_source_object_new(node, object, go->ob);
-               }
+               dag_add_forcefield_relations(forest, scene, ob, obNode, smd->domain->effector_weights, true, PFIELD_SMOKEFLOW, "Smoke Force Field");
        }
 }
 
 static void updateDepsgraph(ModifierData *md,
-                            struct Main *bmain,
+                            struct Main *UNUSED(bmain),
                             struct Scene *scene,
                             Object *ob,
                             struct DepsNodeHandle *node)
 {
        SmokeModifierData *smd = (SmokeModifierData *)md;
-       Base *base;
+
        if (smd && (smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) {
-               if (smd->domain->fluid_group || smd->domain->coll_group) {
-                       GroupObject *go = NULL;
-                       if (smd->domain->fluid_group != NULL) {
-                               for (go = smd->domain->fluid_group->gobject.first; go; go = go->next) {
-                                       if (go->ob != NULL) {
-                                               SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(go->ob, eModifierType_Smoke);
-                                               /* Check for initialized smoke object. */
-                                               if (smd2 && (smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow) {
-                                                       DEG_add_object_relation(node, go->ob, DEG_OB_COMP_TRANSFORM, "Smoke Flow");
-                                               }
-                                       }
-                               }
-                       }
-                       if (smd->domain->coll_group != NULL) {
-                               for (go = smd->domain->coll_group->gobject.first; go; go = go->next) {
-                                       if (go->ob != NULL) {
-                                               SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(go->ob, eModifierType_Smoke);
-                                               /* Check for initialized smoke object. */
-                                               if (smd2 && (smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll) {
-                                                       DEG_add_object_relation(node, go->ob, DEG_OB_COMP_TRANSFORM, "Smoke Coll");
-                                               }
-                                       }
-                               }
-                       }
-               }
-               else {
-                       BKE_main_id_tag_listbase(&bmain->object, LIB_TAG_DOIT, true);
-                       base = scene->base.first;
-                       for (; base; base = base->next) {
-                               update_depsgraph_flow_coll_object_new(node, base->object);
-                       }
-               }
-               /* add relation to all "smoke flow" force fields */
-               base = scene->base.first;
-               BKE_main_id_tag_listbase(&bmain->object, LIB_TAG_DOIT, true);
-               for (; base; base = base->next) {
-                       update_depsgraph_field_source_object_new(node, ob, base->object);
-               }
+               /* Actual code uses get_collisionobjects */
+               DEG_add_collision_relations(node, scene, ob, smd->domain->fluid_group, ob->lay|scene->lay, eModifierType_Smoke, is_flow_cb, true, "Smoke Flow");
+               DEG_add_collision_relations(node, scene, ob, smd->domain->coll_group, ob->lay|scene->lay, eModifierType_Smoke, is_coll_cb, true, "Smoke Coll");
+
+               DEG_add_forcefield_relations(node, scene, ob, smd->domain->effector_weights, true, PFIELD_SMOKEFLOW, "Smoke Force Field");
        }
 }
 
index 98a1412d0c6907c7e0db738c4890bcc3afa479b0..17adc7f1520a5cd5cb54a1a660f0733c05519b02 100644 (file)
@@ -35,6 +35,7 @@
 #include <stdio.h>
 
 #include "DNA_scene_types.h"
+#include "DNA_object_force.h"
 
 #include "BLI_utildefines.h"
 
@@ -42,6 +43,9 @@
 #include "BKE_particle.h"
 #include "BKE_softbody.h"
 
+#include "depsgraph_private.h"
+#include "DEG_depsgraph_build.h"
+
 #include "MOD_modifiertypes.h"
 
 static void deformVerts(ModifierData *md, Object *ob,
@@ -58,6 +62,31 @@ static bool dependsOnTime(ModifierData *UNUSED(md))
        return true;
 }
 
+static void updateDepgraph(ModifierData *UNUSED(md), DagForest *forest,
+                           struct Main *UNUSED(bmain),
+                           Scene *scene, Object *ob, DagNode *obNode)
+{
+       if (ob->soft) {
+               /* Actual code uses ccd_build_deflector_hash */
+               dag_add_collision_relations(forest, scene, ob, obNode, ob->soft->collision_group, ob->lay, eModifierType_Collision, NULL, false, "Softbody Collision");
+
+               dag_add_forcefield_relations(forest, scene, ob, obNode, ob->soft->effector_weights, true, 0, "Softbody Field");
+       }
+}
+
+static void updateDepsgraph(ModifierData *UNUSED(md),
+                            struct Main *UNUSED(bmain),
+                            struct Scene *scene,
+                            Object *ob,
+                            struct DepsNodeHandle *node)
+{
+       if (ob->soft) {
+               /* Actual code uses ccd_build_deflector_hash */
+               DEG_add_collision_relations(node, scene, ob, ob->soft->collision_group, ob->lay, eModifierType_Collision, NULL, false, "Softbody Collision");
+
+               DEG_add_forcefield_relations(node, scene, ob, ob->soft->effector_weights, true, 0, "Softbody Field");
+       }
+}
 
 ModifierTypeInfo modifierType_Softbody = {
        /* name */              "Softbody",
@@ -80,8 +109,8 @@ ModifierTypeInfo modifierType_Softbody = {
        /* requiredDataMask */  NULL,
        /* freeData */          NULL,
        /* isDisabled */        NULL,
-       /* updateDepgraph */    NULL,
-       /* updateDepsgraph */   NULL,
+       /* updateDepgraph */    updateDepgraph,
+       /* updateDepsgraph */   updateDepsgraph,
        /* dependsOnTime */     dependsOnTime,
        /* dependsOnNormals */  NULL,
        /* foreachObjectLink */ NULL,