Merge branch 'master' into blender2.8
[blender.git] / source / blender / blenkernel / intern / softbody.c
index 9bcff23e134e9cc5c4bb446d4d0b1cd37e45c8df..2707e4eebd7d0079d1803318f2a0c8d71a2d55f2 100644 (file)
 #include "MEM_guardedalloc.h"
 
 /* types */
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_lattice_types.h"
+#include "DNA_collection_types.h"
 #include "DNA_curve_types.h"
-#include "DNA_mesh_types.h"
+#include "DNA_lattice_types.h"
 #include "DNA_meshdata_types.h"
-#include "DNA_group_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
 
 #include "BLI_math.h"
 #include "BLI_utildefines.h"
 #include "BLI_ghash.h"
 #include "BLI_threads.h"
 
+#include "BKE_collection.h"
+#include "BKE_collision.h"
 #include "BKE_curve.h"
 #include "BKE_effect.h"
 #include "BKE_global.h"
+#include "BKE_layer.h"
 #include "BKE_modifier.h"
 #include "BKE_softbody.h"
 #include "BKE_pointcache.h"
@@ -79,6 +82,9 @@
 #include "BKE_mesh.h"
 #include "BKE_scene.h"
 
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
 #include  "PIL_time.h"
 
 /* callbacks for errors and interrupts and some goo */
@@ -132,7 +138,7 @@ typedef struct  SB_thread_context {
                float timenow;
                int ifirst;
                int ilast;
-               ListBase *do_effector;
+               ListBase *effectors;
                int do_deflector;
                float fieldfactor;
                float windfactor;
@@ -508,39 +514,24 @@ static void ccd_build_deflector_hash_single(GHash *hash, Object *ob)
 }
 
 /**
- * \note group overrides scene when not NULL.
+ * \note collection overrides scene when not NULL.
  */
-static void ccd_build_deflector_hash(Scene *scene, Group *group, Object *vertexowner, GHash *hash)
+static void ccd_build_deflector_hash(Depsgraph *depsgraph, Collection *collection, Object *vertexowner, GHash *hash)
 {
-       Object *ob;
-
        if (!hash) return;
 
-       if (group) {
-               /* Explicit collision group */
-               for (GroupObject *go = group->gobject.first; go; go = go->next) {
-                       ob = go->ob;
+       unsigned int numobjects;
+       Object **objects = BKE_collision_objects_create(depsgraph, vertexowner, collection, &numobjects, eModifierType_Collision);
 
-                       if (ob == vertexowner || ob->type != OB_MESH)
-                               continue;
+       for (int i = 0; i < numobjects; i++) {
+               Object *ob = objects[i];
 
+               if (ob->type == OB_MESH) {
                        ccd_build_deflector_hash_single(hash, ob);
                }
        }
-       else {
-               for (Base *base = scene->base.first; base; base = base->next) {
-                       /*Only proceed for mesh object in same layer */
-                       if (base->object->type == OB_MESH && (base->lay & vertexowner->lay)) {
-                               ob= base->object;
-                               if ((vertexowner) && (ob == vertexowner)) {
-                                       /* if vertexowner is given  we don't want to check collision with owner object */
-                                       continue;
-                               }
 
-                               ccd_build_deflector_hash_single(hash, ob);
-                       }
-               }
-       }
+       BKE_collision_objects_free(objects);
 }
 
 static void ccd_update_deflector_hash_single(GHash *hash, Object *ob)
@@ -554,42 +545,26 @@ static void ccd_update_deflector_hash_single(GHash *hash, Object *ob)
 }
 
 /**
- * \note group overrides scene when not NULL.
+ * \note collection overrides scene when not NULL.
  */
-static void ccd_update_deflector_hash(Scene *scene, Group *group, Object *vertexowner, GHash *hash)
+static void ccd_update_deflector_hash(Depsgraph *depsgraph, Collection *collection, Object *vertexowner, GHash *hash)
 {
-       Object *ob;
-
        if ((!hash) || (!vertexowner)) return;
 
-       if (group) {
-               /* Explicit collision group */
-               for (GroupObject *go = group->gobject.first; go; go = go->next) {
-                       ob = go->ob;
+       unsigned int numobjects;
+       Object **objects = BKE_collision_objects_create(depsgraph, vertexowner, collection, &numobjects, eModifierType_Collision);
 
-                       if (ob == vertexowner || ob->type != OB_MESH)
-                               continue;
+       for (int i = 0; i < numobjects; i++) {
+               Object *ob = objects[i];
 
+               if (ob->type == OB_MESH) {
                        ccd_update_deflector_hash_single(hash, ob);
                }
        }
-       else {
-               for (Base *base = scene->base.first; base; base = base->next) {
-                       /*Only proceed for mesh object in same layer */
-                       if (base->object->type == OB_MESH && (base->lay & vertexowner->lay)) {
-                               ob= base->object;
-                               if (ob == vertexowner) {
-                                       /* if vertexowner is given  we don't want to check collision with owner object */
-                                       continue;
-                               }
 
-                               ccd_update_deflector_hash_single(hash, ob);
-                       }
-               }
-       }
+       BKE_collision_objects_free(objects);
 }
 
-
 /*--- collider caching and dicing ---*/
 
 
@@ -975,37 +950,21 @@ static void free_softbody_intern(SoftBody *sb)
 /* +++ dependency information functions*/
 
 /**
- * \note group overrides scene when not NULL.
+ * \note collection overrides scene when not NULL.
  */
-static bool are_there_deflectors(Scene *scene, Group *group, unsigned int layer)
+static int query_external_colliders(Depsgraph *depsgraph, Collection *collection)
 {
-       if (group) {
-               for (GroupObject *go = group->gobject.first; go; go = go->next) {
-                       if (go->ob->pd && go->ob->pd->deflect)
-                               return 1;
-               }
-       }
-       else {
-               for (Base *base = scene->base.first; base; base= base->next) {
-                       if ( (base->lay & layer) && base->object->pd) {
-                               if (base->object->pd->deflect)
-                                       return 1;
-                       }
-               }
-       }
+       unsigned int numobjects;
+       Object **objects = BKE_collision_objects_create(depsgraph, NULL, collection, &numobjects, eModifierType_Collision);
+       BKE_collision_objects_free(objects);
 
-       return 0;
-}
-
-static int query_external_colliders(Scene *scene, Group *group, Object *me)
-{
-       return(are_there_deflectors(scene, group, me->lay));
+       return (numobjects != 0);
 }
 /* --- dependency information functions*/
 
 
 /* +++ the aabb "force" section*/
-static int sb_detect_aabb_collisionCached(float UNUSED(force[3]), unsigned int UNUSED(par_layer), struct Object *vertexowner, float UNUSED(time))
+static int sb_detect_aabb_collisionCached(float UNUSED(force[3]), struct Object *vertexowner, float UNUSED(time))
 {
        Object *ob;
        SoftBody *sb=vertexowner->soft;
@@ -1066,7 +1025,7 @@ static int sb_detect_aabb_collisionCached(float UNUSED(force[3]), unsigned int U
 
 /* +++ the face external section*/
 static int sb_detect_face_pointCached(float face_v1[3], float face_v2[3], float face_v3[3], float *damp,
-                                      float force[3], unsigned int UNUSED(par_layer), struct Object *vertexowner, float time)
+                                      float force[3], struct Object *vertexowner, float time)
 {
        Object *ob;
        GHash *hash;
@@ -1167,7 +1126,7 @@ static int sb_detect_face_pointCached(float face_v1[3], float face_v2[3], float
 
 
 static int sb_detect_face_collisionCached(float face_v1[3], float face_v2[3], float face_v3[3], float *damp,
-                                          float force[3], unsigned int UNUSED(par_layer), struct Object *vertexowner, float time)
+                                          float force[3], struct Object *vertexowner, float time)
 {
        Object *ob;
        GHash *hash;
@@ -1304,7 +1263,7 @@ static void scan_for_ext_face_forces(Object *ob, float timenow)
                        zero_v3(feedback);
                        if (sb_detect_face_collisionCached(
                                sb->bpoint[bf->v1].pos, sb->bpoint[bf->v2].pos, sb->bpoint[bf->v3].pos,
-                               &damp, feedback, ob->lay, ob, timenow))
+                               &damp, feedback, ob, timenow))
                        {
                                madd_v3_v3fl(sb->bpoint[bf->v1].force, feedback, tune);
                                madd_v3_v3fl(sb->bpoint[bf->v2].force, feedback, tune);
@@ -1322,7 +1281,7 @@ static void scan_for_ext_face_forces(Object *ob, float timenow)
                                zero_v3(feedback);
                                if (sb_detect_face_pointCached(
                                        sb->bpoint[bf->v1].pos, sb->bpoint[bf->v2].pos, sb->bpoint[bf->v3].pos,
-                                       &damp,  feedback, ob->lay, ob, timenow))
+                                       &damp,  feedback, ob, timenow))
                                {
                                        madd_v3_v3fl(sb->bpoint[bf->v1].force, feedback, tune);
                                        madd_v3_v3fl(sb->bpoint[bf->v2].force, feedback, tune);
@@ -1351,7 +1310,7 @@ static void scan_for_ext_face_forces(Object *ob, float timenow)
 /* +++ the spring external section*/
 
 static int sb_detect_edge_collisionCached(float edge_v1[3], float edge_v2[3], float *damp,
-                                                                  float force[3], unsigned int UNUSED(par_layer), struct Object *vertexowner, float time)
+                                                                  float force[3], struct Object *vertexowner, float time)
 {
        Object *ob;
        GHash *hash;
@@ -1470,7 +1429,7 @@ static int sb_detect_edge_collisionCached(float edge_v1[3], float edge_v2[3], fl
        return deflected;
 }
 
-static void _scan_for_ext_spring_forces(Scene *scene, Object *ob, float timenow, int ifirst, int ilast, struct ListBase *do_effector)
+static void _scan_for_ext_spring_forces(Scene *scene, Object *ob, float timenow, int ifirst, int ilast, struct ListBase *effectors)
 {
        SoftBody *sb = ob->soft;
        int a;
@@ -1488,7 +1447,7 @@ static void _scan_for_ext_spring_forces(Scene *scene, Object *ob, float timenow,
                                /* +++ springs colliding */
                                if (ob->softflag & OB_SB_EDGECOLL) {
                                        if ( sb_detect_edge_collisionCached (sb->bpoint[bs->v1].pos, sb->bpoint[bs->v2].pos,
-                                               &damp, feedback, ob->lay, ob, timenow)) {
+                                               &damp, feedback, ob, timenow)) {
                                                        add_v3_v3(bs->ext_force, feedback);
                                                        bs->flag |= BSF_INTERSECT;
                                                        //bs->cf=damp;
@@ -1504,14 +1463,14 @@ static void _scan_for_ext_spring_forces(Scene *scene, Object *ob, float timenow,
                                        float vel[3], sp[3], pr[3], force[3];
                                        float f, windfactor  = 0.25f;
                                        /*see if we have wind*/
-                                       if (do_effector) {
+                                       if (effectors) {
                                                EffectedPoint epoint;
                                                float speed[3] = {0.0f, 0.0f, 0.0f};
                                                float pos[3];
                                                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);
-                                               pdDoEffectors(do_effector, NULL, sb->effector_weights, &epoint, force, speed);
+                                               BKE_effectors_apply(effectors, NULL, sb->effector_weights, &epoint, force, speed);
 
                                                mul_v3_fl(speed, windfactor);
                                                add_v3_v3(vel, speed);
@@ -1544,32 +1503,30 @@ static void _scan_for_ext_spring_forces(Scene *scene, Object *ob, float timenow,
 }
 
 
-static void scan_for_ext_spring_forces(Scene *scene, Object *ob, float timenow)
+static void scan_for_ext_spring_forces(struct Depsgraph *depsgraph, Scene *scene, Object *ob, float timenow)
 {
        SoftBody *sb = ob->soft;
-       ListBase *do_effector = NULL;
 
-       do_effector = pdInitEffectors(scene, ob, NULL, sb->effector_weights, true);
-       _scan_for_ext_spring_forces(scene, ob, timenow, 0, sb->totspring, do_effector);
-       pdEndEffectors(&do_effector);
+       ListBase *effectors = BKE_effectors_create(depsgraph, ob, NULL, sb->effector_weights);
+       _scan_for_ext_spring_forces(scene, ob, timenow, 0, sb->totspring, effectors);
+       BKE_effectors_free(effectors);
 }
 
 static void *exec_scan_for_ext_spring_forces(void *data)
 {
        SB_thread_context *pctx = (SB_thread_context*)data;
-       _scan_for_ext_spring_forces(pctx->scene, pctx->ob, pctx->timenow, pctx->ifirst, pctx->ilast, pctx->do_effector);
+       _scan_for_ext_spring_forces(pctx->scene, pctx->ob, pctx->timenow, pctx->ifirst, pctx->ilast, pctx->effectors);
        return NULL;
 }
 
-static void sb_sfesf_threads_run(Scene *scene, struct Object *ob, float timenow, int totsprings, int *UNUSED(ptr_to_break_func(void)))
+static void sb_sfesf_threads_run(struct Depsgraph *depsgraph, Scene *scene, struct Object *ob, float timenow, int totsprings, int *UNUSED(ptr_to_break_func(void)))
 {
-       ListBase *do_effector = NULL;
        ListBase threads;
        SB_thread_context *sb_threads;
        int i, totthread, left, dec;
        int lowsprings =100; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */
 
-       do_effector= pdInitEffectors(scene, ob, NULL, ob->soft->effector_weights, true);
+       ListBase *effectors = BKE_effectors_create(depsgraph, ob, NULL, ob->soft->effector_weights);
 
        /* figure the number of threads while preventing pretty pointless threading overhead */
        totthread= BKE_scene_num_threads(scene);
@@ -1594,7 +1551,7 @@ static void sb_sfesf_threads_run(Scene *scene, struct Object *ob, float timenow,
                }
                else
                        sb_threads[i].ifirst  = 0;
-               sb_threads[i].do_effector = do_effector;
+               sb_threads[i].effectors = effectors;
                sb_threads[i].do_deflector = false;// not used here
                sb_threads[i].fieldfactor = 0.0f;// not used here
                sb_threads[i].windfactor  = 0.0f;// not used here
@@ -1614,7 +1571,7 @@ static void sb_sfesf_threads_run(Scene *scene, struct Object *ob, float timenow,
        /* clean up */
        MEM_freeN(sb_threads);
 
-       pdEndEffectors(&do_effector);
+       BKE_effectors_free(effectors);
 }
 
 
@@ -1649,7 +1606,7 @@ static int choose_winner(float*w, float* pos, float*a, float*b, float*c, float*c
 
 static int sb_detect_vertex_collisionCached(
         float opco[3], float facenormal[3], float *damp,
-        float force[3], unsigned int UNUSED(par_layer), struct Object *vertexowner,
+        float force[3], struct Object *vertexowner,
         float time, float vel[3], float *intrusion)
 {
        Object *ob= NULL;
@@ -1845,8 +1802,8 @@ static int sb_deflect_face(Object *ob, float *actpos, float *facenormal, float *
        float s_actpos[3];
        int deflected;
        copy_v3_v3(s_actpos, actpos);
-       deflected= sb_detect_vertex_collisionCached(s_actpos, facenormal, cf, force, ob->lay, ob, time, vel, intrusion);
-       //deflected= sb_detect_vertex_collisionCachedEx(s_actpos, facenormal, cf, force, ob->lay, ob, time, vel, intrusion);
+       deflected= sb_detect_vertex_collisionCached(s_actpos, facenormal, cf, force, ob, time, vel, intrusion);
+       //deflected= sb_detect_vertex_collisionCachedEx(s_actpos, facenormal, cf, force, ob, time, vel, intrusion);
        return(deflected);
 }
 
@@ -1969,7 +1926,7 @@ static void sb_spring_force(Object *ob, int bpi, BodySpring *bs, float iks, floa
 /* since this is definitely the most CPU consuming task here .. try to spread it */
 /* core function _softbody_calc_forces_slice_in_a_thread */
 /* result is int to be able to flag user break */
-static int _softbody_calc_forces_slice_in_a_thread(Scene *scene, Object *ob, float forcetime, float timenow, int ifirst, int ilast, int *UNUSED(ptr_to_break_func(void)), ListBase *do_effector, int do_deflector, float fieldfactor, float windfactor)
+static int _softbody_calc_forces_slice_in_a_thread(Scene *scene, Object *ob, float forcetime, float timenow, int ifirst, int ilast, int *UNUSED(ptr_to_break_func(void)), ListBase *effectors, int do_deflector, float fieldfactor, float windfactor)
 {
        float iks;
        int bb, do_selfcollision, do_springcollision, do_aero;
@@ -2088,14 +2045,14 @@ static int _softbody_calc_forces_slice_in_a_thread(Scene *scene, Object *ob, flo
                        }
 
                        /* particle field & vortex */
-                       if (do_effector) {
+                       if (effectors) {
                                EffectedPoint epoint;
                                float kd;
                                float force[3] = {0.0f, 0.0f, 0.0f};
                                float speed[3] = {0.0f, 0.0f, 0.0f};
                                float eval_sb_fric_force_scale = sb_fric_force_scale(ob); /* just for calling function once */
                                pd_point_from_soft(scene, bp->pos, bp->vec, sb->bpoint-bp, &epoint);
-                               pdDoEffectors(do_effector, NULL, sb->effector_weights, &epoint, force, speed);
+                               BKE_effectors_apply(effectors, NULL, sb->effector_weights, &epoint, force, speed);
 
                                /* apply forcefield*/
                                mul_v3_fl(force, fieldfactor* eval_sb_fric_force_scale);
@@ -2170,11 +2127,11 @@ static int _softbody_calc_forces_slice_in_a_thread(Scene *scene, Object *ob, flo
 static void *exec_softbody_calc_forces(void *data)
 {
        SB_thread_context *pctx = (SB_thread_context*)data;
-       _softbody_calc_forces_slice_in_a_thread(pctx->scene, pctx->ob, pctx->forcetime, pctx->timenow, pctx->ifirst, pctx->ilast, NULL, pctx->do_effector, pctx->do_deflector, pctx->fieldfactor, pctx->windfactor);
+       _softbody_calc_forces_slice_in_a_thread(pctx->scene, pctx->ob, pctx->forcetime, pctx->timenow, pctx->ifirst, pctx->ilast, NULL, pctx->effectors, pctx->do_deflector, pctx->fieldfactor, pctx->windfactor);
        return NULL;
 }
 
-static void sb_cf_threads_run(Scene *scene, Object *ob, float forcetime, float timenow, int totpoint, int *UNUSED(ptr_to_break_func(void)), struct ListBase *do_effector, int do_deflector, float fieldfactor, float windfactor)
+static void sb_cf_threads_run(Scene *scene, Object *ob, float forcetime, float timenow, int totpoint, int *UNUSED(ptr_to_break_func(void)), struct ListBase *effectors, int do_deflector, float fieldfactor, float windfactor)
 {
        ListBase threads;
        SB_thread_context *sb_threads;
@@ -2206,7 +2163,7 @@ static void sb_cf_threads_run(Scene *scene, Object *ob, float forcetime, float t
                }
                else
                        sb_threads[i].ifirst  = 0;
-               sb_threads[i].do_effector = do_effector;
+               sb_threads[i].effectors = effectors;
                sb_threads[i].do_deflector = do_deflector;
                sb_threads[i].fieldfactor = fieldfactor;
                sb_threads[i].windfactor  = windfactor;
@@ -2229,14 +2186,13 @@ static void sb_cf_threads_run(Scene *scene, Object *ob, float forcetime, float t
        MEM_freeN(sb_threads);
 }
 
-static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, float timenow)
+static void softbody_calc_forcesEx(struct Depsgraph *depsgraph, Scene *scene, Object *ob, float forcetime, float timenow)
 {
        /* rule we never alter free variables :bp->vec bp->pos in here !
         * this will ruin adaptive stepsize AKA heun! (BM)
         */
        SoftBody *sb= ob->soft; /* is supposed to be there */
        /*BodyPoint *bproot;*/ /* UNUSED */
-       ListBase *do_effector = NULL;
        /* float gravity; */ /* UNUSED */
        /* float iks; */
        float fieldfactor = -1.0f, windfactor  = 0.25;
@@ -2245,7 +2201,7 @@ static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, fl
        /* gravity = sb->grav * sb_grav_force_scale(ob); */ /* UNUSED */
 
        /* check conditions for various options */
-       do_deflector= query_external_colliders(scene, sb->collision_group, ob);
+       do_deflector= query_external_colliders(depsgraph, sb->collision_group);
        /* do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF)); */ /* UNUSED */
        do_springcollision=do_deflector && (ob->softflag & OB_SB_EDGES) &&(ob->softflag & OB_SB_EDGECOLL);
        do_aero=((sb->aeroedge)&& (ob->softflag & OB_SB_EDGES));
@@ -2254,31 +2210,31 @@ static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, fl
        /* bproot= sb->bpoint; */ /* need this for proper spring addressing */ /* UNUSED */
 
        if (do_springcollision || do_aero)
-               sb_sfesf_threads_run(scene, ob, timenow, sb->totspring, NULL);
+               sb_sfesf_threads_run(depsgraph, scene, ob, timenow, sb->totspring, NULL);
 
        /* after spring scan because it uses Effoctors too */
-       do_effector= pdInitEffectors(scene, ob, NULL, sb->effector_weights, true);
+       ListBase *effectors = BKE_effectors_create(depsgraph, ob, NULL, sb->effector_weights);
 
        if (do_deflector) {
                float defforce[3];
-               do_deflector = sb_detect_aabb_collisionCached(defforce, ob->lay, ob, timenow);
+               do_deflector = sb_detect_aabb_collisionCached(defforce, ob, timenow);
        }
 
-       sb_cf_threads_run(scene, ob, forcetime, timenow, sb->totpoint, NULL, do_effector, do_deflector, fieldfactor, windfactor);
+       sb_cf_threads_run(scene, ob, forcetime, timenow, sb->totpoint, NULL, effectors, do_deflector, fieldfactor, windfactor);
 
        /* finally add forces caused by face collision */
        if (ob->softflag & OB_SB_FACECOLL) scan_for_ext_face_forces(ob, timenow);
 
        /* finish matrix and solve */
-       pdEndEffectors(&do_effector);
+       BKE_effectors_free(effectors);
 }
 
 
-static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, float timenow)
+static void softbody_calc_forces(struct Depsgraph *depsgraph, Scene *scene, Object *ob, float forcetime, float timenow)
 {
        /* redirection to the new threaded Version */
        if (!(G.debug_value & 0x10)) { // 16
-               softbody_calc_forcesEx(scene, ob, forcetime, timenow);
+               softbody_calc_forcesEx(depsgraph, scene, ob, forcetime, timenow);
                return;
        }
        else {
@@ -2297,7 +2253,6 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa
                BodyPoint  *bp;
                /* BodyPoint *bproot; */ /* UNUSED */
                BodySpring *bs;
-               ListBase *do_effector = NULL;
                float iks, ks, kd, gravity[3] = {0.0f, 0.0f, 0.0f};
                float fieldfactor = -1.0f, windfactor  = 0.25f;
                float tune = sb->ballstiff;
@@ -2309,7 +2264,7 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa
                }
 
                /* check conditions for various options */
-               do_deflector= query_external_colliders(scene, sb->collision_group, ob);
+               do_deflector= query_external_colliders(depsgraph, sb->collision_group);
                do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF));
                do_springcollision=do_deflector && (ob->softflag & OB_SB_EDGES) &&(ob->softflag & OB_SB_EDGECOLL);
                do_aero=((sb->aeroedge)&& (ob->softflag & OB_SB_EDGES));
@@ -2317,13 +2272,13 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa
                iks  = 1.0f/(1.0f-sb->inspring)-1.0f ;/* inner spring constants function */
                /* bproot= sb->bpoint; */ /* need this for proper spring addressing */ /* UNUSED */
 
-               if (do_springcollision || do_aero)  scan_for_ext_spring_forces(scene, ob, timenow);
+               if (do_springcollision || do_aero)  scan_for_ext_spring_forces(depsgraph, scene, ob, timenow);
                /* after spring scan because it uses Effoctors too */
-               do_effector= pdInitEffectors(scene, ob, NULL, ob->soft->effector_weights, true);
+               ListBase *effectors = BKE_effectors_create(depsgraph, ob, NULL, ob->soft->effector_weights);
 
                if (do_deflector) {
                        float defforce[3];
-                       do_deflector = sb_detect_aabb_collisionCached(defforce, ob->lay, ob, timenow);
+                       do_deflector = sb_detect_aabb_collisionCached(defforce, ob, timenow);
                }
 
                bp = sb->bpoint;
@@ -2422,13 +2377,13 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa
 
 
                                /* particle field & vortex */
-                               if (do_effector) {
+                               if (effectors) {
                                        EffectedPoint epoint;
                                        float force[3] = {0.0f, 0.0f, 0.0f};
                                        float speed[3] = {0.0f, 0.0f, 0.0f};
                                        float eval_sb_fric_force_scale = sb_fric_force_scale(ob); /* just for calling function once */
                                        pd_point_from_soft(scene, bp->pos, bp->vec, sb->bpoint-bp, &epoint);
-                                       pdDoEffectors(do_effector, NULL, sb->effector_weights, &epoint, force, speed);
+                                       BKE_effectors_apply(effectors, NULL, sb->effector_weights, &epoint, force, speed);
 
                                        /* apply forcefield*/
                                        mul_v3_fl(force, fieldfactor* eval_sb_fric_force_scale);
@@ -2520,7 +2475,7 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa
 
                /* finally add forces caused by face collision */
                if (ob->softflag & OB_SB_FACECOLL) scan_for_ext_face_forces(ob, timenow);
-               pdEndEffectors(&do_effector);
+               BKE_effectors_free(effectors);
        }
 }
 
@@ -3321,7 +3276,8 @@ SoftBody *sbNew(Scene *scene)
        sb->shearstiff = 1.0f;
        sb->solverflags |= SBSO_OLDERR;
 
-       sb->pointcache = BKE_ptcache_add(&sb->ptcaches);
+       sb->shared = MEM_callocN(sizeof(*sb->shared), "SoftBody_Shared");
+       sb->shared->pointcache = BKE_ptcache_add(&sb->shared->ptcaches);
 
        if (!sb->effector_weights)
                sb->effector_weights = BKE_effector_add_weights(NULL);
@@ -3332,14 +3288,26 @@ SoftBody *sbNew(Scene *scene)
 }
 
 /* frees all */
-void sbFree(SoftBody *sb)
+void sbFree(Object *ob)
 {
+       SoftBody *sb = ob->soft;
+       if (sb == NULL) {
+               return;
+       }
+
        free_softbody_intern(sb);
-       BKE_ptcache_free_list(&sb->ptcaches);
-       sb->pointcache = NULL;
+
+       if ((ob->id.tag & LIB_TAG_COPIED_ON_WRITE) == 0) {
+               /* Only free shared data on non-CoW copies */
+               BKE_ptcache_free_list(&sb->shared->ptcaches);
+               sb->shared->pointcache = NULL;
+               MEM_freeN(sb->shared);
+       }
        if (sb->effector_weights)
                MEM_freeN(sb->effector_weights);
        MEM_freeN(sb);
+
+       ob->soft = NULL;
 }
 
 void sbFreeSimulation(SoftBody *sb)
@@ -3506,7 +3474,7 @@ static void softbody_reset(Object *ob, SoftBody *sb, float (*vertexCos)[3], int
        }
 }
 
-static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime)
+static void softbody_step(struct Depsgraph *depsgraph, Scene *scene, Object *ob, SoftBody *sb, float dtime)
 {
        /* the simulator */
        float forcetime;
@@ -3520,12 +3488,10 @@ static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime)
         */
        if (dtime < 0 || dtime > 10.5f) return;
 
-       ccd_update_deflector_hash(scene, sb->collision_group, ob, sb->scratch->colliderhash);
+       ccd_update_deflector_hash(depsgraph, sb->collision_group, ob, sb->scratch->colliderhash);
 
        if (sb->scratch->needstobuildcollider) {
-               if (query_external_colliders(scene, sb->collision_group, ob)) {
-                       ccd_build_deflector_hash(scene, sb->collision_group, ob, sb->scratch->colliderhash);
-               }
+               ccd_build_deflector_hash(depsgraph, sb->collision_group, ob, sb->scratch->colliderhash);
                sb->scratch->needstobuildcollider=0;
        }
 
@@ -3554,12 +3520,12 @@ static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime)
 
                        sb->scratch->flag &= ~SBF_DOFUZZY;
                        /* do predictive euler step */
-                       softbody_calc_forces(scene, ob, forcetime, timedone/dtime);
+                       softbody_calc_forces(depsgraph, scene, ob, forcetime, timedone/dtime);
 
                        softbody_apply_forces(ob, forcetime, 1, NULL, mid_flags);
 
                        /* crop new slope values to do averaged slope step */
-                       softbody_calc_forces(scene, ob, forcetime, timedone/dtime);
+                       softbody_calc_forces(depsgraph, scene, ob, forcetime, timedone/dtime);
 
                        softbody_apply_forces(ob, forcetime, 2, &err, mid_flags);
                        softbody_apply_goalsnap(ob);
@@ -3640,7 +3606,7 @@ static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime)
 }
 
 /* simulates one step. framenr is in frames */
-void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], int numVerts)
+void sbObjectStep(struct Depsgraph *depsgraph, Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], int numVerts)
 {
        SoftBody *sb= ob->soft;
        PointCache *cache;
@@ -3648,8 +3614,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
        float dtime, timescale;
        int framedelta, framenr, startframe, endframe;
        int cache_result;
-
-       cache= sb->pointcache;
+       cache= sb->shared->pointcache;
 
        framenr= (int)cfra;
        framedelta= framenr - cache->simframe;
@@ -3717,7 +3682,8 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
        }
 
        /* try to read from cache */
-       bool can_simulate = (framenr == sb->last_frame+1) && !(cache->flag & PTCACHE_BAKED);
+       bool can_write_cache = DEG_is_active(depsgraph);
+       bool can_simulate = (framenr == sb->last_frame + 1) && !(cache->flag & PTCACHE_BAKED) && can_write_cache;
 
        cache_result = BKE_ptcache_read(&pid, (float)framenr+scene->r.subframe, can_simulate);
 
@@ -3728,7 +3694,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
 
                BKE_ptcache_validate(cache, framenr);
 
-               if (cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED)
+               if (cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED && can_write_cache)
                        BKE_ptcache_write(&pid, framenr);
 
                sb->last_frame = framenr;
@@ -3740,7 +3706,9 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
        }
        else if (/*ob->id.lib || */(cache->flag & PTCACHE_BAKED)) { /* "library linking & pointcaches" has to be solved properly at some point */
                /* if baked and nothing in cache, do nothing */
-               BKE_ptcache_invalidate(cache);
+               if (can_write_cache) {
+                       BKE_ptcache_invalidate(cache);
+               }
                return;
        }
 
@@ -3757,7 +3725,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
        dtime = framedelta*timescale;
 
        /* do simulation */
-       softbody_step(scene, ob, sb, dtime);
+       softbody_step(depsgraph, scene, ob, sb, dtime);
 
        softbody_to_object(ob, vertexCos, numVerts, 0);