use static functions where possible for some local functions.
[blender.git] / source / blender / blenkernel / intern / cloth.c
index 6eb9f73105647a4131353f22c6a666e74b404cf2..9ee6be903fa7ceb338ffba306bc3a0bf851fcd33 100644 (file)
@@ -33,6 +33,7 @@
 #include "DNA_mesh_types.h"
 #include "DNA_object_force.h"
 #include "DNA_scene_types.h"
+#include "DNA_particle_types.h"
 
 #include "BKE_deform.h"
 #include "BKE_DerivedMesh.h"
 #include "BKE_object.h"
 #include "BKE_modifier.h"
 #include "BKE_utildefines.h"
+#include "BKE_particle.h"
 
 #include "BKE_pointcache.h"
 
 #include "BLI_kdopbvh.h"
 
-#include <time.h>
-
 #ifdef _WIN32
 void tstart ( void )
 {}
@@ -80,40 +80,6 @@ double tval()
 }
 #endif
 
-
-/* Util macros */
-#define TO_STR(a)      #a
-#define JOIN(a,b)      a##b
-
-/* Benchmark macros */
-#if 1
-
-#define BENCH(a)       \
-       do {                    \
-               clock_t _clock_init = clock();  \
-               (a);                                                    \
-               printf("%s: %fms\n", #a, (float)(clock()-_clock_init)*1000/CLOCKS_PER_SEC);     \
-} while(0)
-
-#define BENCH_VAR(name)                clock_t JOIN(_bench_step,name) = 0, JOIN(_bench_total,name) = 0
-#define BENCH_BEGIN(name)      JOIN(_bench_step, name) = clock()
-#define BENCH_END(name)                JOIN(_bench_total,name) += clock() - JOIN(_bench_step,name)
-#define BENCH_RESET(name)      JOIN(_bench_total, name) = 0
-#define BENCH_REPORT(name)     printf("%s: %fms\n", TO_STR(name), JOIN(_bench_total,name)*1000.0f/CLOCKS_PER_SEC)
-
-#else
-
-#define BENCH(a)       (a)
-#define BENCH_VAR(name)
-#define BENCH_BEGIN(name)
-#define BENCH_END(name)
-#define BENCH_RESET(name)
-#define BENCH_REPORT(name)
-
-#endif
-
-
-
 /* Our available solvers. */
 // 255 is the magic reserved number, so NEVER try to put 255 solvers in here!
 // 254 = MAX!
@@ -129,7 +95,7 @@ static CM_SOLVER_DEF solvers [] =
 static void cloth_to_object (Object *ob,  ClothModifierData *clmd, DerivedMesh *dm);
 static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm );
 static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float framenr, int first);
-int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm );
+static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm );
 static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm );
 
 
@@ -168,7 +134,7 @@ void cloth_init ( ClothModifierData *clmd )
        
        clmd->coll_parms->self_friction = 5.0;
        clmd->coll_parms->friction = 5.0;
-       clmd->coll_parms->loop_count = 3;
+       clmd->coll_parms->loop_count = 2;
        clmd->coll_parms->epsilon = 0.015f;
        clmd->coll_parms->flags = CLOTH_COLLSETTINGS_FLAG_ENABLED;
        clmd->coll_parms->collision_list = NULL;
@@ -189,11 +155,52 @@ void cloth_init ( ClothModifierData *clmd )
        clmd->sim_parms->goalfrict = 0.0f;
 }
 
-BVHTree *bvhtree_build_from_cloth (ClothModifierData *clmd, float epsilon)
+static BVHTree *bvhselftree_build_from_cloth (ClothModifierData *clmd, float epsilon)
 {
-       int i;
+       unsigned int i;
        BVHTree *bvhtree;
-       Cloth *cloth = clmd->clothObject;
+       Cloth *cloth;
+       ClothVertex *verts;
+       MFace *mfaces;
+       float co[12];
+
+       if(!clmd)
+               return NULL;
+
+       cloth = clmd->clothObject;
+
+       if(!cloth)
+               return NULL;
+       
+       verts = cloth->verts;
+       mfaces = cloth->mfaces;
+       
+       // in the moment, return zero if no faces there
+       if(!cloth->numverts)
+               return NULL;
+       
+       // create quadtree with k=26
+       bvhtree = BLI_bvhtree_new(cloth->numverts, epsilon, 4, 6);
+       
+       // fill tree
+       for(i = 0; i < cloth->numverts; i++, verts++)
+       {
+               VECCOPY(&co[0*3], verts->xold);
+               
+               BLI_bvhtree_insert(bvhtree, i, co, 1);
+       }
+       
+       // balance tree
+       BLI_bvhtree_balance(bvhtree);
+       
+       return bvhtree;
+}
+
+static BVHTree *bvhtree_build_from_cloth (ClothModifierData *clmd, float epsilon)
+{
+       unsigned int i;
+       BVHTree *bvhtree;
+       Cloth *cloth;
        ClothVertex *verts;
        MFace *mfaces;
        float co[12];
@@ -214,7 +221,7 @@ BVHTree *bvhtree_build_from_cloth (ClothModifierData *clmd, float epsilon)
                return NULL;
        
        // create quadtree with k=26
-       bvhtree = BLI_bvhtree_new(cloth->numfaces, epsilon, 8, 6);
+       bvhtree = BLI_bvhtree_new(cloth->numfaces, epsilon, 4, 26);
        
        // fill tree
        for(i = 0; i < cloth->numfaces; i++, mfaces++)
@@ -289,42 +296,48 @@ void bvhtree_update_from_cloth(ClothModifierData *clmd, int moving)
        }
 }
 
-int modifiers_indexInObject(Object *ob, ModifierData *md_seek);
-
-int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr)
-{
-       PTCacheID pid;
-       PTCacheFile *pf;
+void bvhselftree_update_from_cloth(ClothModifierData *clmd, int moving)
+{      
+       unsigned int i = 0;
        Cloth *cloth = clmd->clothObject;
-       unsigned int a, ret = 1;
+       BVHTree *bvhtree = cloth->bvhselftree;
+       ClothVertex *verts = cloth->verts;
+       MFace *mfaces;
+       float co[12], co_moving[12];
+       int ret = 0;
        
-       if(!cloth)
-               return 0;
+       if(!bvhtree)
+               return;
        
-       BKE_ptcache_id_from_cloth(&pid, ob, clmd);
-       pf = BKE_ptcache_file_open(&pid, PTCACHE_FILE_READ, framenr);
-       if(pf) {
-               for(a = 0; a < cloth->numverts; a++) {
-                       if(!BKE_ptcache_file_read_floats(pf, cloth->verts[a].x, 3)) {
-                               ret = 0;
-                               break;
+       mfaces = cloth->mfaces;
+       
+       // update vertex position in bvh tree
+       if(verts && mfaces)
+       {
+               for(i = 0; i < cloth->numverts; i++, verts++)
+               {
+                       VECCOPY(&co[0*3], verts->txold);
+                       
+                       // copy new locations into array
+                       if(moving)
+                       {
+                               // update moving positions
+                               VECCOPY(&co_moving[0*3], verts->tx);
+                               
+                               ret = BLI_bvhtree_update_node(bvhtree, i, co, co_moving, 1);
                        }
-                       if(!BKE_ptcache_file_read_floats(pf, cloth->verts[a].xconst, 3)) {
-                               ret = 0;
-                               break;
+                       else
+                       {
+                               ret = BLI_bvhtree_update_node(bvhtree, i, co, NULL, 1);
                        }
-                       if(!BKE_ptcache_file_read_floats(pf, cloth->verts[a].v, 3)) {
-                               ret = 0;
+                       
+                       // check if tree is already full
+                       if(!ret)
                                break;
-                       }
                }
                
-               BKE_ptcache_file_close(pf);
+               BLI_bvhtree_update_tree(bvhtree);
        }
-       else
-               ret = 0;
-       
-       return ret;
 }
 
 void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr)
@@ -334,36 +347,12 @@ void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr)
        BKE_ptcache_id_from_cloth(&pid, ob, clmd);
 
        // don't do anything as long as we're in editmode!
-       if(pid.cache->flag & PTCACHE_BAKE_EDIT_ACTIVE)
+       if(pid.cache->edit && ob->mode & OB_MODE_PARTICLE_EDIT)
                return;
        
        BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_AFTER, framenr);
 }
 
-void cloth_write_cache(Object *ob, ClothModifierData *clmd, float framenr)
-{
-       Cloth *cloth = clmd->clothObject;
-       PTCacheID pid;
-       PTCacheFile *pf;
-       unsigned int a;
-       
-       if(!cloth)
-               return;
-       
-       BKE_ptcache_id_from_cloth(&pid, ob, clmd);
-       pf = BKE_ptcache_file_open(&pid, PTCACHE_FILE_WRITE, framenr);
-       if(!pf)
-               return;
-       
-       for(a = 0; a < cloth->numverts; a++) {
-               BKE_ptcache_file_write_floats(pf, cloth->verts[a].x, 3);
-               BKE_ptcache_file_write_floats(pf, cloth->verts[a].xconst, 3);
-               BKE_ptcache_file_write_floats(pf, cloth->verts[a].v, 3);
-       }
-       
-       BKE_ptcache_file_close(pf);
-}
-
 static int do_init_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *result, int framenr)
 {
        PointCache *cache;
@@ -422,7 +411,7 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul
 
        tend();
 
-       printf ( "Cloth simulation time: %f\n", ( float ) tval() ); 
+       // printf ( "%f\n", ( float ) tval() );
        
        return ret;
 }
@@ -430,25 +419,28 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul
 /************************************************
  * clothModifier_do - main simulation function
 ************************************************/
-DerivedMesh *clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc)
+DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc)
 {
        DerivedMesh *result;
        PointCache *cache;
        PTCacheID pid;
        float timescale;
        int framedelta, framenr, startframe, endframe;
+       int cache_result;
 
-       framenr= (int)G.scene->r.cfra;
+       clmd->scene= scene;     /* nice to pass on later :) */
+       framenr= (int)scene->r.cfra;
        cache= clmd->point_cache;
        result = CDDM_copy(dm);
 
        BKE_ptcache_id_from_cloth(&pid, ob, clmd);
-       BKE_ptcache_id_time(&pid, framenr, &startframe, &endframe, &timescale);
+       BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, &timescale);
        clmd->sim_parms->timescale= timescale;
 
        if(!result) {
                cache->flag &= ~PTCACHE_SIMULATION_VALID;
                cache->simframe= 0;
+               cache->last_exact= 0;
                return dm;
        }
        
@@ -460,6 +452,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *
                if(result->getNumVerts(result) != clmd->clothObject->numverts) {
                        cache->flag &= ~PTCACHE_SIMULATION_VALID;
                        cache->simframe= 0;
+                       cache->last_exact= 0;
                        return result;
                }
        }
@@ -471,6 +464,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *
        if(BKE_ptcache_get_continue_physics()) {
                cache->flag &= ~PTCACHE_SIMULATION_VALID;
                cache->simframe= 0;
+               cache->last_exact= 0;
 
                /* do simulation */
                if(!do_init_cloth(ob, clmd, result, framenr))
@@ -486,6 +480,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *
        if(framenr < startframe) {
                cache->flag &= ~PTCACHE_SIMULATION_VALID;
                cache->simframe= 0;
+               cache->last_exact= 0;
                return result;
        }
        else if(framenr > endframe) {
@@ -501,52 +496,61 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *
        if(!do_init_cloth(ob, clmd, result, framenr))
                return result;
 
-       /* try to read from cache */
-       if(cloth_read_cache(ob, clmd, framenr)) {
-               cache->flag |= PTCACHE_SIMULATION_VALID;
+       if(framenr == startframe) {
+               BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
+               do_init_cloth(ob, clmd, result, framenr);
                cache->simframe= framenr;
+               cache->flag |= PTCACHE_SIMULATION_VALID;
+               cache->flag &= ~PTCACHE_REDO_NEEDED;
+               return result;
+       }
 
+       /* try to read from cache */
+       cache_result = BKE_ptcache_read_cache(&pid, (float)framenr, scene->r.frs_sec);
+
+       if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) {
                implicit_set_positions(clmd);
                cloth_to_object (ob, clmd, result);
 
+               cache->simframe= framenr;
+               cache->flag |= PTCACHE_SIMULATION_VALID;
+
+               if(cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED)
+                       BKE_ptcache_write_cache(&pid, framenr);
+
                return result;
        }
+       else if(cache_result==PTCACHE_READ_OLD) {
+               implicit_set_positions(clmd);
+               cache->flag |= PTCACHE_SIMULATION_VALID;
+       }
        else if(ob->id.lib || (cache->flag & PTCACHE_BAKED)) {
                /* if baked and nothing in cache, do nothing */
                cache->flag &= ~PTCACHE_SIMULATION_VALID;
                cache->simframe= 0;
+               cache->last_exact= 0;
                return result;
        }
 
-       if(framenr == startframe) {
-               cache->flag |= PTCACHE_SIMULATION_VALID;
-               cache->simframe= framenr;
+       /* if on second frame, write cache for first frame */
+       if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0))
+               BKE_ptcache_write_cache(&pid, startframe);
 
-               /* don't write cache on first frame, but on second frame write
-                * cache for frame 1 and 2 */
-       }
-       else if(framedelta == 1) {
-               /* if on second frame, write cache for first frame */
-               if(framenr == startframe+1)
-                       cloth_write_cache(ob, clmd, startframe);
+       clmd->sim_parms->timescale *= framenr - cache->simframe;
 
-               /* do simulation */
-               cache->flag |= PTCACHE_SIMULATION_VALID;
-               cache->simframe= framenr;
+       /* do simulation */
+       cache->flag |= PTCACHE_SIMULATION_VALID;
+       cache->simframe= framenr;
 
-               if(!do_step_cloth(ob, clmd, result, framenr)) {
-                       cache->flag &= ~PTCACHE_SIMULATION_VALID;
-                       cache->simframe= 0;
-               }
-               else
-                       cloth_write_cache(ob, clmd, framenr);
-
-               cloth_to_object (ob, clmd, result);
-       }
-       else {
+       if(!do_step_cloth(ob, clmd, result, framenr)) {
                cache->flag &= ~PTCACHE_SIMULATION_VALID;
                cache->simframe= 0;
+               cache->last_exact= 0;
        }
+       else
+               BKE_ptcache_write_cache(&pid, framenr);
+
+       cloth_to_object (ob, clmd, result);
 
        return result;
 }
@@ -599,6 +603,9 @@ void cloth_free_modifier ( Object *ob, ClothModifierData *clmd )
                // free BVH collision tree
                if ( cloth->bvhtree )
                        BLI_bvhtree_free ( cloth->bvhtree );
+               
+               if ( cloth->bvhselftree )
+                       BLI_bvhtree_free ( cloth->bvhselftree );
 
                // we save our faces for collision objects
                if ( cloth->mfaces )
@@ -669,6 +676,9 @@ void cloth_free_modifier_extern ( ClothModifierData *clmd )
                // free BVH collision tree
                if ( cloth->bvhtree )
                        BLI_bvhtree_free ( cloth->bvhtree );
+               
+               if ( cloth->bvhselftree )
+                       BLI_bvhtree_free ( cloth->bvhselftree );
 
                // we save our faces for collision objects
                if ( cloth->mfaces )
@@ -727,19 +737,18 @@ static void cloth_to_object (Object *ob,  ClothModifierData *clmd, DerivedMesh *
 /* can be optimized to do all groups in one loop */
 static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm )
 {
-       unsigned int i = 0;
-       unsigned int j = 0;
+       int i = 0;
+       int j = 0;
        MDeformVert *dvert = NULL;
        Cloth *clothObj = NULL;
-       unsigned int numverts = dm->getNumVerts ( dm );
+       int numverts;
        float goalfac = 0;
        ClothVertex *verts = NULL;
 
+       if (!clmd || !dm) return;
+
        clothObj = clmd->clothObject;
 
-       if ( !dm )
-               return;
-       
        numverts = dm->getNumVerts ( dm );
 
        verts = clothObj->verts;
@@ -802,11 +811,12 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm )
 
 static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float framenr, int first)
 {
-       unsigned int i = 0;
+       int i = 0;
        MVert *mvert = NULL;
        ClothVertex *verts = NULL;
        float tnull[3] = {0,0,0};
        Cloth *cloth = NULL;
+       float maxdist = 0;
 
        // If we have a clothObject, free it. 
        if ( clmd->clothObject != NULL )
@@ -876,8 +886,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d
        // apply / set vertex groups
        // has to be happen before springs are build!
        cloth_apply_vgroup (clmd, dm);
-       
-       
+
        if ( !cloth_build_springs ( clmd, dm ) )
        {
                cloth_free_modifier ( ob, clmd );
@@ -902,8 +911,15 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d
        if(!first)
                implicit_set_positions(clmd);
 
-       BENCH(clmd->clothObject->bvhtree = bvhtree_build_from_cloth ( clmd, clmd->coll_parms->epsilon ));
+       clmd->clothObject->bvhtree = bvhtree_build_from_cloth ( clmd, clmd->coll_parms->epsilon );
+       
+       for(i = 0; i < dm->getNumVerts(dm); i++)
+       {
+               maxdist = MAX2(maxdist, clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len*2.0));
+       }
        
+       clmd->clothObject->bvhselftree = bvhselftree_build_from_cloth ( clmd, maxdist );
+
        return 1;
 }
 
@@ -982,7 +998,7 @@ int cloth_add_spring ( ClothModifierData *clmd, unsigned int indexA, unsigned in
        return 0;
 }
 
-void cloth_free_errorsprings(Cloth *cloth, EdgeHash *edgehash, LinkNode **edgelist)
+static void cloth_free_errorsprings(Cloth *cloth, EdgeHash *edgehash, LinkNode **edgelist)
 {
        unsigned int i = 0;
        
@@ -1015,18 +1031,18 @@ void cloth_free_errorsprings(Cloth *cloth, EdgeHash *edgehash, LinkNode **edgeli
                BLI_edgehash_free ( cloth->edgehash, NULL );
 }
 
-int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm )
+static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm )
 {
        Cloth *cloth = clmd->clothObject;
        ClothSpring *spring = NULL, *tspring = NULL, *tspring2 = NULL;
        unsigned int struct_springs = 0, shear_springs=0, bend_springs = 0;
-       unsigned int i = 0;
-       unsigned int numverts = dm->getNumVerts ( dm );
-       unsigned int numedges = dm->getNumEdges ( dm );
-       unsigned int numfaces = dm->getNumFaces ( dm );
+       int i = 0;
+       int numverts = dm->getNumVerts ( dm );
+       int numedges = dm->getNumEdges ( dm );
+       int numfaces = dm->getNumFaces ( dm );
        MEdge *medge = CDDM_get_edges ( dm );
        MFace *mface = CDDM_get_faces ( dm );
-       unsigned int index2 = 0; // our second vertex index
+       int index2 = 0; // our second vertex index
        LinkNode **edgelist = NULL;
        EdgeHash *edgehash = NULL;
        LinkNode *search = NULL, *search2 = NULL;