Merge branch 'master' into blender2.8
[blender.git] / source / blender / blenkernel / intern / softbody.c
index 602e99360204b6071a90e79c7035882600289e5f..f4986f7dabae3544ad5b77aeecea212069d7fac6 100644 (file)
@@ -63,6 +63,8 @@ variables on the UI for now
 #include "DNA_curve_types.h"
 #include "DNA_mesh_types.h"
 #include "DNA_meshdata_types.h"
+#include "DNA_object_force.h"
+#include "DNA_group_types.h"
 
 #include "BLI_math.h"
 #include "BLI_utildefines.h"
@@ -75,13 +77,11 @@ variables on the UI for now
 #include "BKE_global.h"
 #include "BKE_modifier.h"
 #include "BKE_softbody.h"
-#include "BKE_pointcache.h"
 #include "BKE_deform.h"
 #include "BKE_mesh.h"
 #include "BKE_scene.h"
 
 #include  "PIL_time.h"
-// #include  "ONL_opennl.h" remove linking to ONL for now
 
 /* callbacks for errors and interrupts and some goo */
 static int (*SB_localInterruptCallBack)(void) = NULL;
@@ -497,59 +497,98 @@ static void ccd_mesh_free(ccd_Mesh *ccdm)
        }
 }
 
-static void ccd_build_deflector_hash(Scene *scene, Object *vertexowner, GHash *hash)
+static void ccd_build_deflector_hash_single(GHash *hash, Object *ob)
+{
+       /* only with deflecting set */
+       if (ob->pd && ob->pd->deflect) {
+               void **val_p;
+               if (!BLI_ghash_ensure_p(hash, ob, &val_p)) {
+                       ccd_Mesh *ccdmesh = ccd_mesh_make(ob);
+                       *val_p = ccdmesh;
+               }
+       }
+}
+
+/**
+ * \note group overrides scene when not NULL.
+ */
+static void ccd_build_deflector_hash(Scene *scene, Group *group, Object *vertexowner, GHash *hash)
 {
-       Base *base= scene->base.first;
        Object *ob;
 
        if (!hash) return;
-       while (base) {
-               /*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 */
-                               base = base->next;
+
+       if (group) {
+               /* Explicit collision group */
+               for (GroupObject *go = group->gobject.first; go; go = go->next) {
+                       ob = go->ob;
+
+                       if (ob == vertexowner || ob->type != OB_MESH)
                                continue;
-                       }
 
-                       /*+++ only with deflecting set */
-                       if (ob->pd && ob->pd->deflect && BLI_ghash_lookup(hash, ob) == NULL) {
-                               ccd_Mesh *ccdmesh = ccd_mesh_make(ob);
-                               BLI_ghash_insert(hash, ob, ccdmesh);
-                       }/*--- only with deflecting set */
+                       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;
+                               }
 
-               }/* mesh && layer*/
-               base = base->next;
-       } /* while (base) */
+                               ccd_build_deflector_hash_single(hash, ob);
+                       }
+               }
+       }
+}
+
+static void ccd_update_deflector_hash_single(GHash *hash, Object *ob)
+{
+       if (ob->pd && ob->pd->deflect) {
+               ccd_Mesh *ccdmesh = BLI_ghash_lookup(hash, ob);
+               if (ccdmesh) {
+                       ccd_mesh_update(ob, ccdmesh);
+               }
+       }
 }
 
-static void ccd_update_deflector_hash(Scene *scene, Object *vertexowner, GHash *hash)
+/**
+ * \note group overrides scene when not NULL.
+ */
+static void ccd_update_deflector_hash(Scene *scene, Group *group, Object *vertexowner, GHash *hash)
 {
-       Base *base= scene->base.first;
        Object *ob;
 
        if ((!hash) || (!vertexowner)) return;
-       while (base) {
-               /*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 */
-                               base = base->next;
+
+       if (group) {
+               /* Explicit collision group */
+               for (GroupObject *go = group->gobject.first; go; go = go->next) {
+                       ob = go->ob;
+
+                       if (ob == vertexowner || ob->type != OB_MESH)
                                continue;
-                       }
 
-                       /*+++ only with deflecting set */
-                       if (ob->pd && ob->pd->deflect) {
-                               ccd_Mesh *ccdmesh = BLI_ghash_lookup(hash, ob);
-                               if (ccdmesh)
-                                       ccd_mesh_update(ob, ccdmesh);
-                       }/*--- only with deflecting set */
+                       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;
+                               }
 
-               }/* mesh && layer*/
-               base = base->next;
-       } /* while (base) */
+                               ccd_update_deflector_hash_single(hash, ob);
+                       }
+               }
+       }
 }
 
 
@@ -935,22 +974,32 @@ static void free_softbody_intern(SoftBody *sb)
 
 /* +++ dependency information functions*/
 
-static int are_there_deflectors(Scene *scene, unsigned int layer)
+/**
+ * \note group overrides scene when not NULL.
+ */
+static bool are_there_deflectors(Scene *scene, Group *group, unsigned int layer)
 {
-       Base *base;
-
-       for (base = scene->base.first; base; base= base->next) {
-               if ( (base->lay & layer) && base->object->pd) {
-                       if (base->object->pd->deflect)
+       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;
+                       }
+               }
+       }
+
        return 0;
 }
 
-static int query_external_colliders(Scene *scene, Object *me)
+static int query_external_colliders(Scene *scene, Group *group, Object *me)
 {
-       return(are_there_deflectors(scene, me->lay));
+       return(are_there_deflectors(scene, group, me->lay));
 }
 /* --- dependency information functions*/
 
@@ -1214,9 +1263,9 @@ static int sb_detect_face_collisionCached(float face_v1[3], float face_v2[3], fl
                                        sub_v3_v3v3(edge2, nv3, nv2);
                                        cross_v3_v3v3(d_nvect, edge2, edge1);
                                        normalize_v3(d_nvect);
-                                       if (isect_line_tri_v3(nv1, nv2, face_v1, face_v2, face_v3, &t, NULL) ||
-                                           isect_line_tri_v3(nv2, nv3, face_v1, face_v2, face_v3, &t, NULL) ||
-                                           isect_line_tri_v3(nv3, nv1, face_v1, face_v2, face_v3, &t, NULL) )
+                                       if (isect_line_segment_tri_v3(nv1, nv2, face_v1, face_v2, face_v3, &t, NULL) ||
+                                           isect_line_segment_tri_v3(nv2, nv3, face_v1, face_v2, face_v3, &t, NULL) ||
+                                           isect_line_segment_tri_v3(nv3, nv1, face_v1, face_v2, face_v3, &t, NULL) )
                                        {
                                                madd_v3_v3fl(force, d_nvect, -0.5f);
                                                *damp=tune*ob->pd->pdef_sbdamp;
@@ -1397,7 +1446,7 @@ static int sb_detect_edge_collisionCached(float edge_v1[3], float edge_v2[3], fl
 
                                        cross_v3_v3v3(d_nvect, edge2, edge1);
                                        normalize_v3(d_nvect);
-                                       if ( isect_line_tri_v3(edge_v1, edge_v2, nv1, nv2, nv3, &t, NULL)) {
+                                       if (isect_line_segment_tri_v3(edge_v1, edge_v2, nv1, nv2, nv3, &t, NULL)) {
                                                float v1[3], v2[3];
                                                float intrusiondepth, i1, i2;
                                                sub_v3_v3v3(v1, edge_v1, nv2);
@@ -1500,7 +1549,7 @@ static void scan_for_ext_spring_forces(Scene *scene, Object *ob, float timenow)
        SoftBody *sb = ob->soft;
        ListBase *do_effector = NULL;
 
-       do_effector = pdInitEffectors(scene, ob, NULL, sb->effector_weights, true);
+       do_effector = pdInitEffectors(scene, ob, sb->effector_weights, true);
        _scan_for_ext_spring_forces(scene, ob, timenow, 0, sb->totspring, do_effector);
        pdEndEffectors(&do_effector);
 }
@@ -1520,7 +1569,7 @@ static void sb_sfesf_threads_run(Scene *scene, struct Object *ob, float timenow,
        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);
+       do_effector= pdInitEffectors(scene, ob, ob->soft->effector_weights, true);
 
        /* figure the number of threads while preventing pretty pointless threading overhead */
        totthread= BKE_scene_num_threads(scene);
@@ -1811,14 +1860,14 @@ static void dfdx_spring(int ia, int ic, int op, float dir[3], float L, float len
                        for (j=0;j<3;j++) {
                                delta_ij = (i==j ? (1.0f): (0.0f));
                                m=factor*(dir[i]*dir[j] + (1-L/len)*(delta_ij - dir[i]*dir[j]));
-                               nlMatrixAdd(ia+i, op+ic+j, m);
+                               EIG_linear_solver_matrix_add(ia+i, op+ic+j, m);
                        }
        }
        else {
                for (i=0;i<3;i++)
                        for (j=0;j<3;j++) {
                                m=factor*dir[i]*dir[j];
-                               nlMatrixAdd(ia+i, op+ic+j, m);
+                               EIG_linear_solver_matrix_add(ia+i, op+ic+j, m);
                        }
        }
 }
@@ -1827,13 +1876,13 @@ static void dfdx_spring(int ia, int ic, int op, float dir[3], float L, float len
 static void dfdx_goal(int ia, int ic, int op, float factor)
 {
        int i;
-       for (i=0;i<3;i++) nlMatrixAdd(ia+i, op+ic+i, factor);
+       for (i=0;i<3;i++) EIG_linear_solver_matrix_add(ia+i, op+ic+i, factor);
 }
 
 static void dfdv_goal(int ia, int ic, float factor)
 {
        int i;
-       for (i=0;i<3;i++) nlMatrixAdd(ia+i, ic+i, factor);
+       for (i=0;i<3;i++) EIG_linear_solver_matrix_add(ia+i, ic+i, factor);
 }
 */
 static void sb_spring_force(Object *ob, int bpi, BodySpring *bs, float iks, float UNUSED(forcetime))
@@ -2198,7 +2247,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, ob);
+       do_deflector= query_external_colliders(scene, sb->collision_group, ob);
        /* 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));
@@ -2210,7 +2259,7 @@ static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, fl
                sb_sfesf_threads_run(scene, ob, timenow, sb->totspring, NULL);
 
        /* after spring scan because it uses Effoctors too */
-       do_effector= pdInitEffectors(scene, ob, NULL, sb->effector_weights, true);
+       do_effector= pdInitEffectors(scene, ob, sb->effector_weights, true);
 
        if (do_deflector) {
                float defforce[3];
@@ -2244,7 +2293,7 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa
                .. keeping G.debug_value==17 0x11 option for old files 'needing' the bug*/
 
                /* rule we never alter free variables :bp->vec bp->pos in here !
-               * this will ruin adaptive stepsize AKA heun! (BM)
+                * this will ruin adaptive stepsize AKA heun! (BM)
                */
                SoftBody *sb= ob->soft; /* is supposed to be there */
                BodyPoint  *bp;
@@ -2254,7 +2303,7 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa
                float iks, ks, kd, gravity[3] = {0.0f, 0.0f, 0.0f};
                float fieldfactor = -1.0f, windfactor  = 0.25f;
                float tune = sb->ballstiff;
-               int a, b,  do_deflector, do_selfcollision, do_springcollision, do_aero;
+               int do_deflector, do_selfcollision, do_springcollision, do_aero;
 
                if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) {
                        copy_v3_v3(gravity, scene->physics_settings.gravity);
@@ -2262,7 +2311,7 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa
                }
 
                /* check conditions for various options */
-               do_deflector= query_external_colliders(scene, ob);
+               do_deflector= query_external_colliders(scene, sb->collision_group, ob);
                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));
@@ -2272,14 +2321,15 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa
 
                if (do_springcollision || do_aero)  scan_for_ext_spring_forces(scene, ob, timenow);
                /* after spring scan because it uses Effoctors too */
-               do_effector= pdInitEffectors(scene, ob, NULL, ob->soft->effector_weights, true);
+               do_effector= pdInitEffectors(scene, ob, ob->soft->effector_weights, true);
 
                if (do_deflector) {
                        float defforce[3];
                        do_deflector = sb_detect_aabb_collisionCached(defforce, ob->lay, ob, timenow);
                }
 
-               for (a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
+               bp = sb->bpoint;
+               for (int a = sb->totpoint; a > 0; a--, bp++) {
                        /* clear forces  accumulator */
                        bp->force[0] = bp->force[1] = bp->force[2] = 0.0;
 
@@ -2451,7 +2501,7 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa
                                /* +++springs */
                                if (ob->softflag & OB_SB_EDGES) {
                                        if (sb->bspring) { /* spring list exists at all ? */
-                                               for (b=bp->nofsprings;b>0;b--) {
+                                               for (int b = bp->nofsprings; b > 0; b--) {
                                                        bs = sb->bspring + bp->springs[b-1];
                                                        if (do_springcollision || do_aero) {
                                                                add_v3_v3(bp->force, bs->ext_force);
@@ -3273,8 +3323,6 @@ SoftBody *sbNew(Scene *scene)
        sb->shearstiff = 1.0f;
        sb->solverflags |= SBSO_OLDERR;
 
-       sb->pointcache = BKE_ptcache_add(&sb->ptcaches);
-
        if (!sb->effector_weights)
                sb->effector_weights = BKE_add_effector_weights(NULL);
 
@@ -3287,8 +3335,6 @@ SoftBody *sbNew(Scene *scene)
 void sbFree(SoftBody *sb)
 {
        free_softbody_intern(sb);
-       BKE_ptcache_free_list(&sb->ptcaches);
-       sb->pointcache = NULL;
        if (sb->effector_weights)
                MEM_freeN(sb->effector_weights);
        MEM_freeN(sb);
@@ -3472,11 +3518,11 @@ static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime)
         */
        if (dtime < 0 || dtime > 10.5f) return;
 
-       ccd_update_deflector_hash(scene, ob, sb->scratch->colliderhash);
+       ccd_update_deflector_hash(scene, sb->collision_group, ob, sb->scratch->colliderhash);
 
        if (sb->scratch->needstobuildcollider) {
-               if (query_external_colliders(scene, ob)) {
-                       ccd_build_deflector_hash(scene, ob, sb->scratch->colliderhash);
+               if (query_external_colliders(scene, sb->collision_group, ob)) {
+                       ccd_build_deflector_hash(scene, sb->collision_group, ob, sb->scratch->colliderhash);
                }
                sb->scratch->needstobuildcollider=0;
        }
@@ -3595,30 +3641,17 @@ static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime)
 void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], int numVerts)
 {
        SoftBody *sb= ob->soft;
-       PointCache *cache;
-       PTCacheID pid;
-       float dtime, timescale;
-       int framedelta, framenr, startframe, endframe;
-       int cache_result;
-
-       cache= sb->pointcache;
-
-       framenr= (int)cfra;
-       framedelta= framenr - cache->simframe;
-
-       BKE_ptcache_id_from_softbody(&pid, ob, sb);
-       BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, &timescale);
+       float dtime, timescale = 1.0f;
+       int framedelta = 1, framenr = (int)cfra, startframe = scene->r.sfra, endframe = scene->r.efra;
 
        /* check for changes in mesh, should only happen in case the mesh
         * structure changes during an animation */
        if (sb->bpoint && numVerts != sb->totpoint) {
-               BKE_ptcache_invalidate(cache);
                return;
        }
 
        /* clamp frame ranges */
        if (framenr < startframe) {
-               BKE_ptcache_invalidate(cache);
                return;
        }
        else if (framenr > endframe) {
@@ -3655,50 +3688,17 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
                return;
        }
        if (framenr == startframe) {
-               BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
-
                /* first frame, no simulation to do, just set the positions */
                softbody_update_positions(ob, sb, vertexCos, numVerts);
 
-               BKE_ptcache_validate(cache, framenr);
-               cache->flag &= ~PTCACHE_REDO_NEEDED;
-
                sb->last_frame = framenr;
 
                return;
        }
 
-       /* try to read from cache */
-       cache_result = BKE_ptcache_read(&pid, (float)framenr+scene->r.subframe);
-
-       if (cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) {
-               softbody_to_object(ob, vertexCos, numVerts, sb->local);
-
-               BKE_ptcache_validate(cache, framenr);
-
-               if (cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED)
-                       BKE_ptcache_write(&pid, framenr);
-
-               sb->last_frame = framenr;
-
-               return;
-       }
-       else if (cache_result==PTCACHE_READ_OLD) {
-               ; /* do nothing */
-       }
-       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);
-               return;
-       }
-
        if (framenr!=sb->last_frame+1)
                return;
 
-       /* if on second frame, write cache for first frame */
-       if (cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0))
-               BKE_ptcache_write(&pid, startframe);
-
        softbody_update_positions(ob, sb, vertexCos, numVerts);
 
        /* checking time: */
@@ -3709,9 +3709,6 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
 
        softbody_to_object(ob, vertexCos, numVerts, 0);
 
-       BKE_ptcache_validate(cache, framenr);
-       BKE_ptcache_write(&pid, framenr);
-
        sb->last_frame = framenr;
 }