Cycles: svn merge -r39870:r40266 https://svn.blender.org/svnroot/bf-blender/trunk...
[blender-staging.git] / source / blender / blenkernel / intern / softbody.c
index 3704792d9d41915b6d3854c9217d835817b4890a..2960d8a41e515c80a9d1e61bc43723a59150b75e 100644 (file)
  * ***** END GPL LICENSE BLOCK *****
  */
 
+/** \file blender/blenkernel/intern/softbody.c
+ *  \ingroup bke
+ */
+
+
 /*
 ******
 variables on the UI for now
@@ -70,6 +75,7 @@ variables on the UI for now
 #include "BKE_curve.h"
 #include "BKE_effect.h"
 #include "BKE_global.h"
+#include "BKE_modifier.h"
 #include "BKE_softbody.h"
 #include "BKE_DerivedMesh.h"
 #include "BKE_pointcache.h"
@@ -161,7 +167,7 @@ typedef struct  SB_thread_context {
 #define BFF_CLOSEVERT   2 /* collider vertex repulses face */
 
 
-float SoftHeunTol = 1.0f; /* humm .. this should be calculated from sb parameters and sizes */
+static float SoftHeunTol = 1.0f; /* humm .. this should be calculated from sb parameters and sizes */
 
 /* local prototypes */
 static void free_softbody_intern(SoftBody *sb);
@@ -261,7 +267,7 @@ float operations still
 /* just an ID here to reduce the prob for killing objects
 ** ob->sumohandle points to we should not kill :)
 */
-const int CCD_SAVETY = 190561;
+static const int CCD_SAVETY = 190561;
 
 typedef struct ccdf_minmax{
 float minx,miny,minz,maxx,maxy,maxz;
@@ -284,21 +290,24 @@ typedef struct ccd_Mesh {
 
 
 
-static ccd_Mesh *ccd_mesh_make(Object *ob, DerivedMesh *dm)
+static ccd_Mesh *ccd_mesh_make(Object *ob)
 {
+       CollisionModifierData *cmd;
        ccd_Mesh *pccd_M = NULL;
        ccdf_minmax *mima =NULL;
        MFace *mface=NULL;
        float v[3],hull;
        int i;
 
+       cmd =(CollisionModifierData *)modifiers_findByType(ob, eModifierType_Collision);
+
        /* first some paranoia checks */
-       if (!dm) return NULL;
-       if (!dm->getNumVerts(dm) || !dm->getNumFaces(dm)) return NULL;
+       if (!cmd) return NULL;
+       if (!cmd->numverts || !cmd->numfaces) return NULL;
 
        pccd_M = MEM_mallocN(sizeof(ccd_Mesh),"ccd_Mesh");
-       pccd_M->totvert = dm->getNumVerts(dm);
-       pccd_M->totface = dm->getNumFaces(dm);
+       pccd_M->totvert = cmd->numverts;
+       pccd_M->totface = cmd->numfaces;
        pccd_M->savety  = CCD_SAVETY;
        pccd_M->bbmin[0]=pccd_M->bbmin[1]=pccd_M->bbmin[2]=1e30f;
        pccd_M->bbmax[0]=pccd_M->bbmax[1]=pccd_M->bbmax[2]=-1e30f;
@@ -309,12 +318,10 @@ static ccd_Mesh *ccd_mesh_make(Object *ob, DerivedMesh *dm)
        hull = MAX2(ob->pd->pdef_sbift,ob->pd->pdef_sboft);
 
        /* alloc and copy verts*/
-       pccd_M->mvert = dm->dupVertArray(dm);
-       /* ah yeah, put the verices to global coords once */
-       /* and determine the ortho BB on the fly */
+       pccd_M->mvert = MEM_dupallocN(cmd->xnew);
+       /* note that xnew coords are already in global space, */
+       /* determine the ortho BB */
        for(i=0; i < pccd_M->totvert; i++){
-               mul_m4_v3(ob->obmat, pccd_M->mvert[i].co);
-
                /* evaluate limits */
                VECCOPY(v,pccd_M->mvert[i].co);
                pccd_M->bbmin[0] = MIN2(pccd_M->bbmin[0],v[0]-hull);
@@ -327,7 +334,7 @@ static ccd_Mesh *ccd_mesh_make(Object *ob, DerivedMesh *dm)
 
        }
        /* alloc and copy faces*/
-       pccd_M->mface = dm->dupFaceArray(dm);
+       pccd_M->mface = MEM_dupallocN(cmd->mfaces);
 
        /* OBBs for idea1 */
        pccd_M->mima = MEM_mallocN(sizeof(ccdf_minmax)*pccd_M->totface,"ccd_Mesh_Faces_mima");
@@ -381,19 +388,22 @@ static ccd_Mesh *ccd_mesh_make(Object *ob, DerivedMesh *dm)
        }
        return pccd_M;
 }
-static void ccd_mesh_update(Object *ob,ccd_Mesh *pccd_M, DerivedMesh *dm)
+static void ccd_mesh_update(Object *ob,ccd_Mesh *pccd_M)
 {
-        ccdf_minmax *mima =NULL;
+       CollisionModifierData *cmd;
+       ccdf_minmax *mima =NULL;
        MFace *mface=NULL;
        float v[3],hull;
        int i;
 
+       cmd =(CollisionModifierData *)modifiers_findByType(ob, eModifierType_Collision);
+
        /* first some paranoia checks */
-       if (!dm) return ;
-       if (!dm->getNumVerts(dm) || !dm->getNumFaces(dm)) return ;
+       if (!cmd) return ;
+       if (!cmd->numverts || !cmd->numfaces) return ;
 
-       if ((pccd_M->totvert != dm->getNumVerts(dm)) ||
-               (pccd_M->totface != dm->getNumFaces(dm))) return;
+       if ((pccd_M->totvert != cmd->numverts) ||
+               (pccd_M->totface != cmd->numfaces)) return;
 
        pccd_M->bbmin[0]=pccd_M->bbmin[1]=pccd_M->bbmin[2]=1e30f;
        pccd_M->bbmax[0]=pccd_M->bbmax[1]=pccd_M->bbmax[2]=-1e30f;
@@ -406,12 +416,10 @@ static void ccd_mesh_update(Object *ob,ccd_Mesh *pccd_M, DerivedMesh *dm)
        if(pccd_M->mprevvert) MEM_freeN(pccd_M->mprevvert);
        pccd_M->mprevvert = pccd_M->mvert;
        /* alloc and copy verts*/
-       pccd_M->mvert = dm->dupVertArray(dm);
-       /* ah yeah, put the verices to global coords once */
-       /* and determine the ortho BB on the fly */
+       pccd_M->mvert = MEM_dupallocN(cmd->xnew);
+       /* note that xnew coords are already in global space, */
+       /* determine the ortho BB */
        for(i=0; i < pccd_M->totvert; i++){
-               mul_m4_v3(ob->obmat, pccd_M->mvert[i].co);
-
                /* evaluate limits */
                VECCOPY(v,pccd_M->mvert[i].co);
                pccd_M->bbmin[0] = MIN2(pccd_M->bbmin[0],v[0]-hull);
@@ -549,22 +557,9 @@ static void ccd_build_deflector_hash(Scene *scene, Object *vertexowner, GHash *h
                        }
 
                        /*+++ only with deflecting set */
-                       if(ob->pd && ob->pd->deflect && BLI_ghash_lookup(hash, ob) == 0) {
-                               DerivedMesh *dm= NULL;
-
-                               if(ob->softflag & OB_SB_COLLFINAL) /* so maybe someone wants overkill to collide with subsurfed */
-                                       dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
-                               else
-                                       dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
-
-                               if(dm){
-                                       ccd_Mesh *ccdmesh = ccd_mesh_make(ob, dm);
-                                       BLI_ghash_insert(hash, ob, ccdmesh);
-
-                                       /* we did copy & modify all we need so give 'em away again */
-                                       dm->release(dm);
-
-                               }
+                       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 */
 
                }/* mesh && layer*/
@@ -590,21 +585,9 @@ static void ccd_update_deflector_hash(Scene *scene, Object *vertexowner, GHash *
 
                        /*+++ only with deflecting set */
                        if(ob->pd && ob->pd->deflect) {
-                               DerivedMesh *dm= NULL;
-
-                               if(ob->softflag & OB_SB_COLLFINAL) { /* so maybe someone wants overkill to collide with subsurfed */
-                                       dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
-                               } else {
-                                       dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
-                               }
-                               if(dm){
-                                       ccd_Mesh *ccdmesh = BLI_ghash_lookup(hash,ob);
-                                       if (ccdmesh)
-                                               ccd_mesh_update(ob,ccdmesh,dm);
-
-                                       /* we did copy & modify all we need so give 'em away again */
-                                       dm->release(dm);
-                               }
+                               ccd_Mesh *ccdmesh = BLI_ghash_lookup(hash,ob);
+                               if (ccdmesh)
+                                       ccd_mesh_update(ob,ccdmesh);
                        }/*--- only with deflecting set */
 
                }/* mesh && layer*/
@@ -635,7 +618,7 @@ static void add_mesh_quad_diag_springs(Object *ob)
 {
        Mesh *me= ob->data;
        MFace *mface= me->mface;
-       BodyPoint *bp;
+       /*BodyPoint *bp;*/ /*UNUSED*/
        BodySpring *bs, *bs_new;
        int a ;
 
@@ -656,7 +639,7 @@ static void add_mesh_quad_diag_springs(Object *ob)
                        /* fill the tail */
                        a = 0;
                        bs = bs_new+ob->soft->totspring;
-                       bp= ob->soft->bpoint;
+                       /*bp= ob->soft->bpoint; */ /*UNUSED*/
                        if(mface ) {
                                for(a=me->totface; a>0; a--, mface++) {
                                        if(mface->v4) {
@@ -1037,7 +1020,10 @@ static int sb_detect_aabb_collisionCached(       float UNUSED(force[3]), unsigned int
        GHash *hash;
        GHashIterator *ihash;
        float  aabbmin[3],aabbmax[3];
-       int a, deflected=0;
+       int deflected=0;
+#if 0
+       int a;
+#endif
 
        if ((sb == NULL) || (sb->scratch ==NULL)) return 0;
        VECCOPY(aabbmin,sb->scratch->aabbmin);
@@ -1051,17 +1037,20 @@ static int sb_detect_aabb_collisionCached(      float UNUSED(force[3]), unsigned int
                ob             = BLI_ghashIterator_getKey       (ihash);
                        /* only with deflecting set */
                        if(ob->pd && ob->pd->deflect) {
+#if 0                  /* UNUSED */
                                MFace *mface= NULL;
                                MVert *mvert= NULL;
                                MVert *mprevvert= NULL;
                                ccdf_minmax *mima= NULL;
+#endif
                                if(ccdm){
+#if 0                          /* UNUSED */
                                        mface= ccdm->mface;
                                        mvert= ccdm->mvert;
                                        mprevvert= ccdm->mprevvert;
                                        mima= ccdm->mima;
                                        a = ccdm->totface;
-
+#endif
                                        if ((aabbmax[0] < ccdm->bbmin[0]) ||
                                                (aabbmax[1] < ccdm->bbmin[1]) ||
                                                (aabbmax[2] < ccdm->bbmin[2]) ||
@@ -1643,21 +1632,19 @@ 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)
 {
-  SoftBody *sb = ob->soft;
-  ListBase *do_effector = NULL;
-
-  do_effector = pdInitEffectors(scene, ob, NULL, sb->effector_weights);
-  if (sb){
-         _scan_for_ext_spring_forces(scene, ob, timenow, 0, sb->totspring, do_effector);
-  }
-  pdEndEffectors(&do_effector);
+       SoftBody *sb = ob->soft;
+       ListBase *do_effector = NULL;
+
+       do_effector = pdInitEffectors(scene, ob, NULL, sb->effector_weights);
+       _scan_for_ext_spring_forces(scene, ob, timenow, 0, sb->totspring, do_effector);
+       pdEndEffectors(&do_effector);
 }
 
 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);
-       return 0;
+       return NULL;
 }
 
 static void sb_sfesf_threads_run(Scene *scene, struct Object *ob, float timenow,int totsprings,int *UNUSED(ptr_to_break_func(void)))
@@ -2092,19 +2079,25 @@ static void sb_spring_force(Object *ob,int bpi,BodySpring *bs,float iks,float UN
 
        float dir[3],dvel[3];
        float distance,forcefactor,kd,absvel,projvel,kw;
+#if 0  /* UNUSED */
        int ia,ic;
+#endif
        /* prepare depending on which side of the spring we are on */
        if (bpi == bs->v1){
                bp1 = &sb->bpoint[bs->v1];
                bp2 = &sb->bpoint[bs->v2];
+#if 0  /* UNUSED */
                ia =3*bs->v1;
                ic =3*bs->v2;
+#endif
        }
        else if (bpi == bs->v2){
                bp1 = &sb->bpoint[bs->v2];
                bp2 = &sb->bpoint[bs->v1];
+#if 0  /* UNUSED */
                ia =3*bs->v2;
                ic =3*bs->v1;
+#endif
        }
        else{
                /* TODO make this debug option */
@@ -2213,50 +2206,50 @@ static int _softbody_calc_forces_slice_in_a_thread(Scene *scene, Object *ob, flo
                /* naive ball self collision */
                /* needs to be done if goal snaps or not */
                if(do_selfcollision){
-                                int attached;
-                               BodyPoint   *obp;
-                               BodySpring *bs;
-                               int c,b;
-                               float velcenter[3],dvel[3],def[3];
-                               float distance;
-                               float compare;
-                                float bstune = sb->ballstiff;
-
-                               for(c=sb->totpoint, obp= sb->bpoint; c>=ifirst+bb; c--, obp++) {
-                                       compare = (obp->colball + bp->colball);
-                                       sub_v3_v3v3(def, bp->pos, obp->pos);
-                                       /* rather check the AABBoxes before ever calulating the real distance */
-                                       /* mathematically it is completly nuts, but performace is pretty much (3) times faster */
-                                       if ((ABS(def[0]) > compare) || (ABS(def[1]) > compare) || (ABS(def[2]) > compare)) continue;
-                                       distance = normalize_v3(def);
-                                       if (distance < compare ){
-                                               /* exclude body points attached with a spring */
-                                               attached = 0;
-                                               for(b=obp->nofsprings;b>0;b--){
-                                                       bs = sb->bspring + obp->springs[b-1];
-                                                       if (( ilast-bb == bs->v2)  || ( ilast-bb == bs->v1)){
-                                                               attached=1;
-                                                               continue;}
-                                               }
-                                               if (!attached){
-                                                       float f = bstune/(distance) + bstune/(compare*compare)*distance - 2.0f*bstune/compare ;
+                       int attached;
+                       BodyPoint   *obp;
+                       BodySpring *bs;
+                       int c,b;
+                       float velcenter[3],dvel[3],def[3];
+                       float distance;
+                       float compare;
+                       float bstune = sb->ballstiff;
+
+                       for(c=sb->totpoint, obp= sb->bpoint; c>=ifirst+bb; c--, obp++) {
+                               compare = (obp->colball + bp->colball);
+                               sub_v3_v3v3(def, bp->pos, obp->pos);
+                               /* rather check the AABBoxes before ever calulating the real distance */
+                               /* mathematically it is completly nuts, but performace is pretty much (3) times faster */
+                               if ((ABS(def[0]) > compare) || (ABS(def[1]) > compare) || (ABS(def[2]) > compare)) continue;
+                               distance = normalize_v3(def);
+                               if (distance < compare ){
+                                       /* exclude body points attached with a spring */
+                                       attached = 0;
+                                       for(b=obp->nofsprings;b>0;b--){
+                                               bs = sb->bspring + obp->springs[b-1];
+                                               if (( ilast-bb == bs->v2)  || ( ilast-bb == bs->v1)){
+                                                       attached=1;
+                                                       continue;}
+                                       }
+                                       if (!attached){
+                                               float f = bstune/(distance) + bstune/(compare*compare)*distance - 2.0f*bstune/compare ;
 
-                                                       mid_v3_v3v3(velcenter, bp->vec, obp->vec);
-                                                       sub_v3_v3v3(dvel,velcenter,bp->vec);
-                                                       mul_v3_fl(dvel,_final_mass(ob,bp));
+                                               mid_v3_v3v3(velcenter, bp->vec, obp->vec);
+                                               sub_v3_v3v3(dvel,velcenter,bp->vec);
+                                               mul_v3_fl(dvel,_final_mass(ob,bp));
 
-                                                       Vec3PlusStVec(bp->force,f*(1.0f-sb->balldamp),def);
-                                                       Vec3PlusStVec(bp->force,sb->balldamp,dvel);
+                                               Vec3PlusStVec(bp->force,f*(1.0f-sb->balldamp),def);
+                                               Vec3PlusStVec(bp->force,sb->balldamp,dvel);
 
-                                                       /* exploit force(a,b) == -force(b,a) part2/2 */
-                                                       sub_v3_v3v3(dvel,velcenter,obp->vec);
-                                                       mul_v3_fl(dvel,_final_mass(ob,bp));
+                                               /* exploit force(a,b) == -force(b,a) part2/2 */
+                                               sub_v3_v3v3(dvel,velcenter,obp->vec);
+                                               mul_v3_fl(dvel,_final_mass(ob,bp));
 
-                                                       Vec3PlusStVec(obp->force,sb->balldamp,dvel);
-                                                       Vec3PlusStVec(obp->force,-f*(1.0f-sb->balldamp),def);
-                                               }
+                                               Vec3PlusStVec(obp->force,sb->balldamp,dvel);
+                                               Vec3PlusStVec(obp->force,-f*(1.0f-sb->balldamp),def);
                                        }
                                }
+                       }
                }
                /* naive ball self collision done */
 
@@ -2384,7 +2377,7 @@ 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);
-       return 0;
+       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)
@@ -2451,23 +2444,23 @@ static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, fl
  * this will ruin adaptive stepsize AKA heun! (BM)
  */
        SoftBody *sb= ob->soft; /* is supposed to be there */
-       BodyPoint *bproot;
+       /*BodyPoint *bproot;*/ /* UNUSED */
        ListBase *do_effector = NULL;
-       float gravity;
+       /* float gravity; */ /* UNUSED */
        /* float iks; */
        float fieldfactor = -1.0f, windfactor  = 0.25;
-       int   do_deflector,do_selfcollision,do_springcollision,do_aero;
+       int   do_deflector /*,do_selfcollision*/ ,do_springcollision,do_aero;
 
-       gravity = sb->grav * sb_grav_force_scale(ob);
+       /* gravity = sb->grav * sb_grav_force_scale(ob); */ /* UNUSED */
 
        /* check conditions for various options */
        do_deflector= query_external_colliders(scene, ob);
-       do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF));
+       /* 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));
 
        /* iks  = 1.0f/(1.0f-sb->inspring)-1.0f; */ /* inner spring constants function */ /* UNUSED */
-       bproot= sb->bpoint; /* need this for proper spring addressing */
+       /* 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);
@@ -2513,7 +2506,7 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa
                */
                SoftBody *sb= ob->soft; /* is supposed to be there */
                BodyPoint  *bp;
-               BodyPoint *bproot;
+               /* BodyPoint *bproot; */ /* UNUSED */
                BodySpring *bs;
                ListBase *do_effector = NULL;
                float iks, ks, kd, gravity[3] = {0.0f,0.0f,0.0f};
@@ -2544,7 +2537,7 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa
                do_aero=((sb->aeroedge)&& (ob->softflag & OB_SB_EDGES));
 
                iks  = 1.0f/(1.0f-sb->inspring)-1.0f ;/* inner spring constants function */
-               bproot= sb->bpoint; /* need this for proper spring addressing */
+               /* bproot= sb->bpoint; */ /* need this for proper spring addressing */ /* UNUSED */
 
                if (do_springcollision || do_aero)  scan_for_ext_spring_forces(scene, ob, timenow);
                /* after spring scan because it uses Effoctors too */
@@ -2927,7 +2920,7 @@ static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *
 /* now we have individual masses   */
 /* claim a minimum mass for vertex */
                if (_final_mass(ob,bp) > 0.009999f) timeovermass = forcetime/_final_mass(ob,bp);
-                 else timeovermass = forcetime/0.009999f;
+               else timeovermass = forcetime/0.009999f;
 
 
                if(_final_goal(ob,bp) < SOFTGOALSNAP){
@@ -3824,7 +3817,7 @@ void SB_estimate_transform(Object *ob,float lloc[3],float lrot[3][3],float lscal
 {
        BodyPoint *bp;
        ReferenceVert *rp;
-       SoftBody *sb = 0;
+       SoftBody *sb = NULL;
        float (*opos)[3];
        float (*rpos)[3];
        float com[3],rcom[3];