Fix depsgraph to compute more accurate links for collision & force.
[blender.git] / source / blender / depsgraph / intern / builder / deg_builder_relations.cc
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) {