Pointcache refresh part 2
authorJanne Karhu <jhkarh@gmail.com>
Sat, 27 Jun 2009 15:28:58 +0000 (15:28 +0000)
committerJanne Karhu <jhkarh@gmail.com>
Sat, 27 Jun 2009 15:28:58 +0000 (15:28 +0000)
* Based on what happens during simulation the cache is marked (also in cache panel, this could possibly be extended to 3d view as well) as:
- exact (not marked)
- outdated (simulation is not done completely with current settings)
- non-exact (frames were skipped during simulation)

* The parameter "cache step" effects the number of frames between saved cache frames.
- This can save a lot of memory (or disk space) if absolutely frame accurate simulation is not required.
- Speeds up the "quick caching" very much.
- Frames between cached frames are interpolated from the cached frames.
- Current default value of 10 frames works nicely with up/down-arrows (skip 10 frames forwards/backwards on timeline), but can be changed if wanted.

* The caching can work in normal or "quick" mode:
[Normal cache]
- Basic: Calculate what even happens (settings change, big frame steps etc.) and cache results, if possible try to use "cache step" when saving cache frames.
- Becomes non-exact: After larger than 1 frame steps.
- Becomes outdated: After any change effecting the simulation other than frame steps.
- Pros/cons: Freedom of doing anything and playing with particles, but exact results have to calculated from the beginning.

[Quick cache]
- Basic: Calculate simulation up to current frame automatically on changes with cache step sized jumps in simulation. With multiple "quick cached" simulations the smallest cache step is used.
- Becomes non-exact: Always from frame 1 (unless cache step = 1).
- Becomes outdated: Never.
- Pros/cons: Not very accurate, but super fast!
- Todo: Transform of any animated (non-autokeyed) object is locked! Probably needs some tinkering with anim sys overrides.

* The simulation can be run forwards or backwards even if it's cache is outdated or non-exact, the following rules apply in these situations:
- step forwards (to unknown) -> simulate from last exact frame, store result
- step backwards (to known) -> result is interpolated from existing frames, store result, clear cache forwards if current frame is after last exact frame

* "Calculate to current frame" runs the simulation from start to current frame with a frame steps of 1.
- Baking does the same, but runs the simulation all the way to the end of simulation.
- Rendering does this automatically if the simulation is outdated of non-exact, so all rendered simulations will always be updated and exact.

* Every cache panel also holds buttons to "Bake all dynamics", "Free all dynamics" and "Update all dynamics to current frame".

* Cloth simulation supports the new cache too.

19 files changed:
release/ui/buttons_particle.py
release/ui/buttons_physic_cloth.py
source/blender/blenkernel/BKE_cloth.h
source/blender/blenkernel/BKE_particle.h
source/blender/blenkernel/BKE_pointcache.h
source/blender/blenkernel/intern/cloth.c
source/blender/blenkernel/intern/implicit.c
source/blender/blenkernel/intern/particle.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenkernel/intern/pointcache.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/editors/physics/ed_pointcache.c
source/blender/editors/transform/transform_conversions.c
source/blender/makesdna/DNA_object_force.h
source/blender/makesrna/intern/rna_cloth.c
source/blender/makesrna/intern/rna_object_force.c
source/blender/render/intern/source/pipeline.c
source/blender/windowmanager/intern/wm_event_system.c

index f82324d..378689e 100644 (file)
@@ -130,11 +130,7 @@ class PARTICLE_PT_cache(ParticleButtonsPanel):
                cache = psys.point_cache
                
                row = layout.row()
-               row.itemR(cache, "name", text="")
-               if cache.outdated:
-                       row.itemL(text="Cache is outdated.")
-               else:
-                       row.itemL(text="")
+               row.itemR(cache, "name")
                
                row = layout.row()
                
@@ -142,18 +138,29 @@ class PARTICLE_PT_cache(ParticleButtonsPanel):
                        row.itemO("PTCACHE_OT_free_bake_particle_system", text="Free Bake")
                else:
                        row.item_booleanO("PTCACHE_OT_cache_particle_system", "bake", True, text="Bake")
-                       
+               
+               subrow = row.row()
+               subrow.enabled = (cache.frames_skipped or cache.outdated) and particle_panel_enabled(psys)
+               subrow.itemO("PTCACHE_OT_cache_particle_system", text="Calculate to Current Frame")
+               
                row = layout.row()
                row.enabled = particle_panel_enabled(psys)
                row.itemO("PTCACHE_OT_bake_from_particles_cache", text="Current Cache to Bake")
-               if cache.autocache == 0:
-                       row.itemO("PTCACHE_OT_cache_particle_system", text="Cache to Current Frame")
+               row.itemR(cache, "step");
        
                row = layout.row()
                row.enabled = particle_panel_enabled(psys)
-               #row.itemR(cache, "autocache")
+               row.itemR(cache, "quick_cache")
                row.itemR(cache, "disk_cache")
-               row.itemL(text=cache.info)
+               
+               layout.itemL(text=cache.info)
+               
+               layout.itemS()
+               
+               row = layout.row()
+               row.item_booleanO("PTCACHE_OT_bake_all", "bake", True, text="Bake All Dynamics")
+               row.itemO("PTCACHE_OT_free_bake_all", text="Free All Bakes")
+               layout.itemO("PTCACHE_OT_bake_all", text="Update All Dynamics to current frame")
                
                # for particles these are figured out automatically
                #row.itemR(cache, "start_frame")
index bd65392..a06c644 100644 (file)
@@ -43,7 +43,54 @@ class Physic_PT_cloth(PhysicButtonsPanel):
                        col.itemR(cloth, "goal_spring", text="Stiffness")
                        col.itemR(cloth, "goal_friction", text="Friction")
                """
+
+class PHYSICS_PT_cloth_cache(PhysicButtonsPanel):
+       __idname__= "PHYSICS_PT_cloth_cache"
+       __label__ = "Cache"
+       __default_closed__ = True
+
+       def draw(self, context):
+               layout = self.layout
+
+               cache = context.cloth.point_cache
+               
+               row = layout.row()
+               row.itemR(cache, "name")
+               
+               row = layout.row()
+               row.itemR(cache, "start_frame")
+               row.itemR(cache, "end_frame")
+               
+               row = layout.row()
+               
+               if cache.baked == True:
+                       row.itemO("PTCACHE_OT_free_bake_cloth", text="Free Bake")
+               else:
+                       row.item_booleanO("PTCACHE_OT_cache_cloth", "bake", True, text="Bake")
+               
+               subrow = row.row()
+               subrow.enabled = cache.frames_skipped or cache.outdated
+               subrow.itemO("PTCACHE_OT_cache_cloth", text="Calculate to Current Frame")
+                       
+               row = layout.row()
+               #row.enabled = particle_panel_enabled(psys)
+               row.itemO("PTCACHE_OT_bake_from_cloth_cache", text="Current Cache to Bake")
+               row.itemR(cache, "step");
        
+               row = layout.row()
+               #row.enabled = particle_panel_enabled(psys)
+               row.itemR(cache, "quick_cache")
+               row.itemR(cache, "disk_cache")
+               
+               layout.itemL(text=cache.info)
+               
+               layout.itemS()
+               
+               row = layout.row()
+               row.itemO("PTCACHE_OT_bake_all", "bake", True, text="Bake All Dynamics")
+               row.itemO("PTCACHE_OT_free_bake_all", text="Free All Bakes")
+               layout.itemO("PTCACHE_OT_bake_all", text="Update All Dynamics to current frame")
+               
 class Physic_PT_cloth_collision(PhysicButtonsPanel):
        __idname__ = "Physic_PT_clothcollision"
        __label__ = "Cloth Collision"
@@ -102,5 +149,6 @@ class Physic_PT_cloth_stiffness(PhysicButtonsPanel):
                sub.itemR(cloth, "bending_stiffness_max", text="Max")
                
 bpy.types.register(Physic_PT_cloth)
+bpy.types.register(PHYSICS_PT_cloth_cache)
 bpy.types.register(Physic_PT_cloth_collision)
 bpy.types.register(Physic_PT_cloth_stiffness)
index e09be83..4270c67 100644 (file)
@@ -46,6 +46,7 @@
 #include "DNA_meshdata_types.h"
 #include "DNA_modifier_types.h"
 #include "DNA_object_types.h"
+#include "DNA_scene_types.h"
 
 #include "BKE_collision.h"
 
@@ -245,8 +246,8 @@ void bvhtree_update_from_cloth ( ClothModifierData *clmd, int moving );
 void bvhselftree_update_from_cloth ( ClothModifierData *clmd, int moving );
 
 // needed for editmesh.c
-void cloth_write_cache ( Object *ob, ClothModifierData *clmd, float framenr );
-int cloth_read_cache ( Object *ob, ClothModifierData *clmd, float framenr );
+void cloth_write_cache( Object *ob, ClothModifierData *clmd, int framenr );
+int cloth_read_cache( Scene *scene, Object *ob, ClothModifierData *clmd, float framenr, int *old_framenr );
 
 // needed for button_object.c
 void cloth_clear_cache ( Object *ob, ClothModifierData *clmd, float framenr );
index 0ecd71f..08aa111 100644 (file)
@@ -252,7 +252,6 @@ struct ParticleSystemModifierData *psys_get_modifier(struct Object *ob, struct P
 
 struct ParticleSettings *psys_new_settings(char *name, struct Main *main);
 struct ParticleSettings *psys_copy_settings(struct ParticleSettings *part);
-int psys_count_autocache(struct Scene *scene, struct ParticleSettings *part);
 void psys_flush_particle_settings(struct Scene *scene, struct ParticleSettings *part, int recalc);
 void make_local_particlesettings(struct ParticleSettings *part);
 
index b79357e..3f1c45d 100644 (file)
@@ -93,7 +93,7 @@ typedef struct PTCacheWriter {
        int cfra;
        int totelem;
 
-       float *(*elem_ptr)(int index, void *calldata);
+       void (*set_elem)(int index, void *calldata, float *data);
        void *calldata;
 } PTCacheWriter;
 
@@ -103,12 +103,10 @@ typedef struct PTCacheReader {
        float cfra;
        int totelem;
 
-       void (*set_elem)(int index, void *calldata, float *data);
-       void (*interpolate_elem)(int index, void *calldata, float frs_sec, float cfra, int cfra1, int cfra2, float *data1, float *data2);
+       void (*set_elem)(int elem_index, void *calldata, float *data);
+       void (*interpolate_elem)(int index, void *calldata, float frs_sec, float cfra, float cfra1, float cfra2, float *data1, float *data2);
        void *calldata;
 
-       int allow_interpolate;
-       int allow_old;
        int *old_frame;
 } PTCacheReader;
 
@@ -116,6 +114,7 @@ typedef struct PTCacheBaker {
        struct Scene *scene;
        int bake;
        int render;
+       int quick_step;
        struct PTCacheID *pid;
        int (*break_test)(void *data);
        void *break_data;
@@ -146,6 +145,8 @@ void         BKE_ptcache_file_close(PTCacheFile *pf);
 int          BKE_ptcache_file_read_floats(PTCacheFile *pf, float *f, int tot);
 int          BKE_ptcache_file_write_floats(PTCacheFile *pf, float *f, int tot);
 
+void BKE_ptcache_update_info(PTCacheID *pid);
+
 /* General cache reading/writing */
 int                     BKE_ptcache_read_cache(PTCacheReader *reader);
 int                     BKE_ptcache_write_cache(PTCacheWriter *writer);
@@ -160,7 +161,7 @@ void BKE_ptcache_free(struct PointCache *cache);
 struct PointCache *BKE_ptcache_copy(struct PointCache *cache);
 
 /* Baking */
-void BKE_ptcache_autocache_all(struct Scene *scene);
+void BKE_ptcache_quick_cache_all(struct Scene *scene);
 void BKE_ptcache_make_cache(struct PTCacheBaker* baker);
 void BKE_ptcache_toggle_disk_cache(struct PTCacheID *pid);
 
index e98d7bb..08caea5 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"
@@ -42,6 +43,7 @@
 #include "BKE_object.h"
 #include "BKE_modifier.h"
 #include "BKE_utildefines.h"
+#include "BKE_particle.h"
 
 #include "BKE_pointcache.h"
 
@@ -339,78 +341,99 @@ void bvhselftree_update_from_cloth(ClothModifierData *clmd, int moving)
 }
 
 int modifiers_indexInObject(Object *ob, ModifierData *md_seek);
+static void cloth_write_state(int index, Cloth *cloth, float *data)
+{
+       ClothVertex *vert = cloth->verts + index;
 
-int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr)
+       memcpy(data, vert->x, 3 * sizeof(float));
+       memcpy(data + 3, vert->xconst, 3 * sizeof(float));
+       memcpy(data + 6, vert->v, 3 * sizeof(float));
+}
+static void cloth_read_state(int index, Cloth *cloth, float *data)
 {
-       PTCacheID pid;
-       PTCacheFile *pf;
-       Cloth *cloth = clmd->clothObject;
-       unsigned int a, ret = 1;
+       ClothVertex *vert = cloth->verts + index;
        
-       if(!cloth)
-               return 0;
-       
-       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;
-                       }
-                       if(!BKE_ptcache_file_read_floats(pf, cloth->verts[a].xconst, 3)) {
-                               ret = 0;
-                               break;
-                       }
-                       if(!BKE_ptcache_file_read_floats(pf, cloth->verts[a].v, 3)) {
-                               ret = 0;
-                               break;
-                       }
-               }
-               
-               BKE_ptcache_file_close(pf);
-       }
-       else
-               ret = 0;
-       
-       return ret;
+       memcpy(vert->x, data, 3 * sizeof(float));
+       memcpy(vert->xconst, data + 3, 3 * sizeof(float));
+       memcpy(vert->v, data + 6, 3 * sizeof(float));
 }
+static void cloth_cache_interpolate(int index, Cloth *cloth, float frs_sec, float cfra, float cfra1, float cfra2, float *data1, float *data2)
+{
+       ClothVertex *vert = cloth->verts + index;
+       ParticleKey keys[4];
+       float dfra;
 
-void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr)
+       if(cfra1 == cfra2) {
+               cloth_read_state(index, cloth, data1);
+               return;
+       }
+
+       memcpy(keys[1].co, data1, 3 * sizeof(float));
+       memcpy(keys[1].vel, data1 + 6, 3 * sizeof(float));
+
+       memcpy(keys[2].co, data2, 3 * sizeof(float));
+       memcpy(keys[2].vel, data2 + 6, 3 * sizeof(float));
+
+       dfra = cfra2 - cfra1;
+
+       VecMulf(keys[1].vel, dfra);
+       VecMulf(keys[2].vel, dfra);
+
+       psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1);
+
+       VecMulf(keys->vel, 1.0f / dfra);
+
+       memcpy(vert->x, keys->co, 3 * sizeof(float));
+       memcpy(vert->v, keys->vel, 3 * sizeof(float));
+
+       /* not sure what to do with this - jahka */
+       memcpy(vert->xconst, data1 + 3, 3 * sizeof(float));
+}
+void cloth_write_cache(Object *ob, ClothModifierData *clmd, int cfra)
 {
+       PTCacheWriter writer;
        PTCacheID pid;
-       
+
        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)
-               return;
-       
-       BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_AFTER, framenr);
+       writer.calldata = clmd->clothObject;
+       writer.cfra = cfra;
+       writer.set_elem = cloth_write_state;
+       writer.pid = &pid;
+       writer.totelem = clmd->clothObject->numverts;
+
+       BKE_ptcache_write_cache(&writer);
 }
 
-void cloth_write_cache(Object *ob, ClothModifierData *clmd, float framenr)
+int cloth_read_cache(Scene *scene, Object *ob, ClothModifierData *clmd, float cfra, int *old_framenr)
 {
-       Cloth *cloth = clmd->clothObject;
+       PTCacheReader reader;
        PTCacheID pid;
-       PTCacheFile *pf;
-       unsigned int a;
        
-       if(!cloth)
-               return;
+       BKE_ptcache_id_from_cloth(&pid, ob, clmd);
+
+       reader.calldata = clmd->clothObject;
+       reader.cfra = cfra;
+       reader.interpolate_elem = cloth_cache_interpolate;
+       reader.old_frame = old_framenr;
+       reader.pid = &pid;
+       reader.scene = scene;
+       reader.set_elem = cloth_read_state;
+       reader.totelem = clmd->clothObject->numverts;
+
+       return BKE_ptcache_read_cache(&reader);
+}
+void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr)
+{
+       PTCacheID pid;
        
        BKE_ptcache_id_from_cloth(&pid, ob, clmd);
-       pf = BKE_ptcache_file_open(&pid, PTCACHE_FILE_WRITE, framenr);
-       if(!pf)
+
+       // don't do anything as long as we're in editmode!
+       if(pid.cache->flag & PTCACHE_BAKE_EDIT_ACTIVE)
                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);
+       BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_AFTER, framenr);
 }
 
 static int do_init_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *result, int framenr)
@@ -486,6 +509,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
        PTCacheID pid;
        float timescale;
        int framedelta, framenr, startframe, endframe;
+       int cache_result, old_framenr;
 
        clmd->scene= scene;     /* nice to pass on later :) */
        framenr= (int)scene->r.cfra;
@@ -499,6 +523,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
        if(!result) {
                cache->flag &= ~PTCACHE_SIMULATION_VALID;
                cache->simframe= 0;
+               cache->last_exact= 0;
                return dm;
        }
        
@@ -510,6 +535,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
                if(result->getNumVerts(result) != clmd->clothObject->numverts) {
                        cache->flag &= ~PTCACHE_SIMULATION_VALID;
                        cache->simframe= 0;
+                       cache->last_exact= 0;
                        return result;
                }
        }
@@ -521,6 +547,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
        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))
@@ -536,6 +563,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
        if(framenr < startframe) {
                cache->flag &= ~PTCACHE_SIMULATION_VALID;
                cache->simframe= 0;
+               cache->last_exact= 0;
                return result;
        }
        else if(framenr > endframe) {
@@ -552,7 +580,9 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
                return result;
 
        /* try to read from cache */
-       if(cloth_read_cache(ob, clmd, framenr)) {
+       cache_result = cloth_read_cache(scene, ob, clmd, framenr, &old_framenr);
+
+       if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) {
                cache->flag |= PTCACHE_SIMULATION_VALID;
                cache->simframe= framenr;
 
@@ -561,25 +591,40 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
 
                return result;
        }
+       else if(cache_result==PTCACHE_READ_OLD) {
+               BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_FREE);
+
+               implicit_set_positions(clmd);
+
+               cache->flag |= PTCACHE_SIMULATION_VALID;
+               cache->simframe= old_framenr;
+       }
        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) {
+               if(cache->flag & PTCACHE_REDO_NEEDED) {
+                       BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
+                       do_init_cloth(ob, clmd, result, framenr);
+               }
                cache->flag |= PTCACHE_SIMULATION_VALID;
                cache->simframe= framenr;
 
                /* don't write cache on first frame, but on second frame write
                 * cache for frame 1 and 2 */
        }
-       else if(framedelta == 1) {
+       else {
                /* if on second frame, write cache for first frame */
-               if(framenr == startframe+1)
+               if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0))
                        cloth_write_cache(ob, clmd, startframe);
 
+               clmd->sim_parms->timescale *= framenr - cache->simframe;
+
                /* do simulation */
                cache->flag |= PTCACHE_SIMULATION_VALID;
                cache->simframe= framenr;
@@ -587,16 +632,13 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
                if(!do_step_cloth(ob, clmd, result, framenr)) {
                        cache->flag &= ~PTCACHE_SIMULATION_VALID;
                        cache->simframe= 0;
+                       cache->last_exact= 0;
                }
                else
                        cloth_write_cache(ob, clmd, framenr);
 
                cloth_to_object (ob, clmd, result);
        }
-       else {
-               cache->flag &= ~PTCACHE_SIMULATION_VALID;
-               cache->simframe= 0;
-       }
 
        return result;
 }
index 40c98c1..fc5213d 100644 (file)
@@ -1600,6 +1600,10 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase
                
                if(clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED)
                {
+                       float temp = clmd->sim_parms->stepsPerFrame;
+                       /* not too nice hack, but collisions need this correction -jahka */
+                       clmd->sim_parms->stepsPerFrame /= clmd->sim_parms->timescale;
+
                        // collisions 
                        // itstart();
                        
@@ -1614,7 +1618,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase
                        
                        // call collision function
                        // TODO: check if "step" or "step+dt" is correct - dg
-                       result = cloth_bvh_objcollision(ob, clmd, step, dt);
+                       result = cloth_bvh_objcollision(ob, clmd, step/clmd->sim_parms->timescale, dt/clmd->sim_parms->timescale);
                        
                        // correct velocity again, just to be sure we had to change it due to adaptive collisions
                        for(i = 0; i < numverts; i++)
@@ -1637,6 +1641,9 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase
                                }
                        }
                        
+                       /* restore original stepsPerFrame */
+                       clmd->sim_parms->stepsPerFrame = temp;
+                       
                        // X = Xnew;
                        cp_lfvector(id->X, id->Xnew, numverts);
                        
@@ -1654,7 +1661,6 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase
                                
                                simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt / 2.0f, id->A, id->B, id->dV, id->S, id->z, id->olddV, id->P, id->Pinv, id->M, id->bigI);
                        }
-                       
                }
                else
                {
index 5b3720c..04215b1 100644 (file)
@@ -236,31 +236,6 @@ Object *psys_find_object(Scene *scene, ParticleSystem *psys)
 
        return NULL;
 }
-int psys_count_autocache(Scene *scene, ParticleSettings *part)
-{
-       Base *base = scene->base.first;
-       ParticleSystem *psys;
-       PTCacheID pid;
-       int autocache_count= 0;
-
-       for(base = scene->base.first; base; base = base->next) {
-               for(psys = base->object->particlesystem.first; psys; psys=psys->next) {
-                       if(part && psys->part != part)
-                               continue;
-
-                       BKE_ptcache_id_from_particles(&pid, base->object, psys);
-
-                       if((psys->pointcache->flag & PTCACHE_BAKED)
-                               || (psys->pointcache->flag & PTCACHE_AUTOCACHE)==0)
-                               continue;
-
-                       if((psys->pointcache->flag & PTCACHE_OUTDATED)
-                               || BKE_ptcache_id_exist(&pid, CFRA)==0)
-                               autocache_count++;
-               }
-       }
-       return autocache_count;
-}
 /* change object's active particle system */
 void psys_change_act(void *ob_v, void *act_v)
 {
@@ -3740,6 +3715,8 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy
                        if((pa->alive==PARS_UNBORN && (part->flag & PART_UNBORN)==0)
                                || (pa->alive==PARS_DEAD && (part->flag & PART_DIED)==0))
                                return 0;
+
+               state->time = MIN2(state->time, pa->dietime);
        }
 
        if(psys->flag & PSYS_KEYED){
index 97b1956..591b6ca 100644 (file)
@@ -2205,11 +2205,9 @@ void psys_get_pointcache_start_end(Scene *scene, ParticleSystem *psys, int *sfra
        *sfra = MAX2(1, (int)part->sta);
        *efra = MIN2((int)(part->end + part->lifetime + 1.0), scene->r.efra);
 }
-static float *particle_state_ptr(int index, void *psys_ptr)
+static void particle_write_state(int index, ParticleSystem *psys, float *data)
 {
-       ParticleSystem *psys= psys_ptr;
-
-       return (float *)(&(psys->particles+index)->state);
+       memcpy(data, (float *)(&(psys->particles+index)->state), sizeof(ParticleKey));
 }
 static void particle_read_state(int index, void *psys_ptr, float *data)
 {
@@ -2222,24 +2220,35 @@ static void particle_read_state(int index, void *psys_ptr, float *data)
 
        copy_particle_key(&pa->state, key, 1);
 }
-static void particle_cache_interpolate(int index, void *psys_ptr, float frs_sec, float cfra, int cfra1, int cfra2, float *data1, float *data2)
+static void particle_cache_interpolate(int index, void *psys_ptr, float frs_sec, float cfra, float cfra1, float cfra2, float *data1, float *data2)
 {
        ParticleSystem *psys= psys_ptr;
        ParticleData *pa = psys->particles + index;
        ParticleKey keys[4];
-       float dfra;
+       float dfra, cfra1f = (float)cfra1, cfra2f(float);
+
+       cfra = MIN2(cfra, pa->dietime);
+       cfra1 = MIN2(cfra1, pa->dietime);
+       cfra2 = MIN2(cfra2, pa->dietime);
 
        keys[1] = *((ParticleKey*)data1);
        keys[2] = *((ParticleKey*)data2);
 
-       dfra = keys[2].time - keys[1].time;
+       if(cfra1 == cfra2) {
+               copy_particle_key(&pa->state, &keys[1], 1);
+               return;
+       }
+
+       dfra = cfra2 - cfra1;
 
        VecMulf(keys[1].vel, dfra / frs_sec);
        VecMulf(keys[2].vel, dfra / frs_sec);
 
-       psys_interpolate_particle(-1, keys, (keys[1].time - cfra) / dfra, &pa->state, 1);
+       psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1);
 
        VecMulf(pa->state.vel, frs_sec / dfra);
+
+       pa->state.time = cfra;
 }
 static void write_particles_to_cache(Object *ob, ParticleSystem *psys, int cfra)
 {
@@ -2250,22 +2259,20 @@ static void write_particles_to_cache(Object *ob, ParticleSystem *psys, int cfra)
 
        writer.calldata = psys;
        writer.cfra = cfra;
-       writer.elem_ptr = particle_state_ptr;
+       writer.set_elem = particle_write_state;
        writer.pid = &pid;
        writer.totelem = psys->totpart;
 
        BKE_ptcache_write_cache(&writer);
 }
 
-static int get_particles_from_cache(Scene *scene, Object *ob, ParticleSystem *psys, float cfra, int allow_interpolate, int allow_old, int *old_frame)
+static int get_particles_from_cache(Scene *scene, Object *ob, ParticleSystem *psys, float cfra, int *old_frame)
 {
        PTCacheReader reader;
        PTCacheID pid;
        
        BKE_ptcache_id_from_particles(&pid, ob, psys);
 
-       reader.allow_interpolate = allow_interpolate;
-       reader.allow_old = allow_old;
        reader.calldata = psys;
        reader.cfra = cfra;
        reader.interpolate_elem = particle_cache_interpolate;
@@ -2402,6 +2409,8 @@ static void add_to_effectors(ListBase *lb, Scene *scene, Object *ob, Object *obs
                Object *tob;
 
                for(i=0; epsys; epsys=epsys->next,i++){
+                       if(!psys_check_enabled(ob, epsys))
+                               continue;
                        type=0;
                        if(epsys!=psys || (psys->part->flag & PART_SELF_EFFECT)){
                                epart=epsys->part;
@@ -4366,7 +4375,7 @@ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *ps
                        pa->alive = PARS_UNBORN;
                else if(dietime <= cfra){
                        if(dietime > psys->cfra){
-                               state.time = pa->dietime;
+                               state.time = dietime;
                                psys_get_particle_state(scene, ob,psys,p,&state,1);
                                push_reaction(ob,psys,p,PART_EVENT_DEATH,&state);
                        }
@@ -4668,9 +4677,9 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
 
        /* try to read from the cache */
        if(usecache) {
-               int result = get_particles_from_cache(scene, ob, psys, (float)framenr, 0, 1, &old_framenr);
+               int result = get_particles_from_cache(scene, ob, psys, (float)framenr, &old_framenr);
 
-               if(result == PTCACHE_READ_EXACT) {
+               if(result == PTCACHE_READ_EXACT || result == PTCACHE_READ_INTERPOLATED) {
                        //if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED) {
                        //      psys_count_keyed_targets(ob,psys);
                        //      set_keyed_keys(scene, ob, psys);
@@ -4687,15 +4696,12 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
                        cache->simframe= framenr;
                        cache->flag |= PTCACHE_SIMULATION_VALID;
 
-                       if(cache->flag & PTCACHE_OUTDATED)
-                               BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_FREE);
+                       if(result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED)
+                               write_particles_to_cache(ob, psys, cfra);
 
                        return;
                }
-               else if((cache->flag & PTCACHE_AUTOCACHE)==0 && result==PTCACHE_READ_OLD) {
-                       /* clear cache after current frame */
-                       BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_FREE);
-
+               else if(result==PTCACHE_READ_OLD) {
                        /* set old cfra */
                        psys->cfra = (float)old_framenr;
 
@@ -4715,15 +4721,6 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
                        psys->recalc = 0;
                        return;
                }
-
-               if(framenr != startframe && framedelta != 1 && cache->flag & PTCACHE_AUTOCACHE) {
-                       //psys_reset(psys, PSYS_RESET_CACHE_MISS);
-                       /* make sure cache is recalculated */
-                       BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_FRAME, (int)cfra);
-                       psys->cfra = cfra;
-                       psys->recalc = 0;
-                       return;
-               }
        }
        else {
                cache->flag &= ~PTCACHE_SIMULATION_VALID;
index b514ac0..64473d0 100644 (file)
@@ -303,7 +303,7 @@ static int ptcache_pid_elemsize(PTCacheID *pid)
        else if(pid->type==PTCACHE_TYPE_PARTICLES)
                return sizeof(ParticleKey);
        else if(pid->type==PTCACHE_TYPE_CLOTH)
-               return 0; // TODO
+               return 9 * sizeof(float);
 
        return 0;
 }
@@ -321,10 +321,11 @@ static int ptcache_pid_totelem(PTCacheID *pid)
        return 0;
 }
 
-void ptcache_update_info(PTCacheID *pid)
+void BKE_ptcache_update_info(PTCacheID *pid)
 {
        PointCache *cache = pid->cache;
        int totframes = 0;
+       char mem_info[64];
 
        if(cache->flag & PTCACHE_DISK_CACHE) {
                int cfra = cache->startframe;
@@ -334,7 +335,7 @@ void ptcache_update_info(PTCacheID *pid)
                                totframes++;
                }
 
-               sprintf(cache->info, "%i frames on disk.", totframes);
+               sprintf(mem_info, "%i frames on disk", totframes);
        }
        else {
                PTCacheMem *pm = cache->mem_cache.first;                
@@ -351,11 +352,20 @@ void ptcache_update_info(PTCacheID *pid)
 
                mb = (bytes > 1024.0f * 1024.0f);
 
-               sprintf(cache->info, "%i frames in memory (%.1f %s).",
+               sprintf(mem_info, "%i frames in memory (%.1f %s)",
                        totframes,
                        bytes / (mb ? 1024.0f * 1024.0f : 1024.0f),
                        mb ? "Mb" : "kb");
        }
+
+       if(cache->flag & PTCACHE_OUTDATED) {
+               sprintf(cache->info, "%s, cache is outdated!", mem_info);
+       }
+       else if(cache->flag & PTCACHE_FRAMES_SKIPPED) {
+               sprintf(cache->info, "%s, not exact since frame %i.", mem_info, cache->last_exact);
+       }
+       else
+               sprintf(cache->info, "%s.", mem_info);
 }
 /* reads cache from disk or memory */
 /* possible to get old or interpolated result */
@@ -370,10 +380,13 @@ int BKE_ptcache_read_cache(PTCacheReader *reader)
        int elemsize = ptcache_pid_elemsize(pid);
        int i, incr = elemsize / sizeof(float);
        float frs_sec = reader->scene->r.frs_sec;
+       int cfra1=0, cfra2;
+       int ret = 0;
 
        if(totelem == 0)
                return 0;
 
+
        /* first check if we have the actual frame cached */
        if(cfra == (float)cfrai) {
                if(pid->cache->flag & PTCACHE_DISK_CACHE) {
@@ -419,130 +432,147 @@ int BKE_ptcache_read_cache(PTCacheReader *reader)
                        MEM_freeN(data);
                }
 
-               return PTCACHE_READ_EXACT;
+               ret = PTCACHE_READ_EXACT;
        }
-       /* no exact cache frame found so try to find cached frames around cfra */
-       if(reader->allow_interpolate || reader->allow_old) {
-               int cfra1, cfra2;
 
-               if(pid->cache->flag & PTCACHE_DISK_CACHE) {
-                       pf=NULL;
-                       while(cfrai > pid->cache->startframe && !pf) {
-                               cfrai--;
-                               pf= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
-                               cfra1 = cfrai;
-                       }
+       if(ret)
+               ;
+       /* no exact cache frame found so try to find cached frames around cfra */
+       else if(pid->cache->flag & PTCACHE_DISK_CACHE) {
+               pf=NULL;
+               while(cfrai > pid->cache->startframe && !pf) {
+                       cfrai--;
+                       pf= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
+                       cfra1 = cfrai;
+               }
 
+               if(reader->old_frame)
                        *(reader->old_frame) = cfrai;
 
-                       cfrai = (int)cfra;
-                       while(cfrai < pid->cache->endframe && !pf2) {
-                               cfrai++;
-                               pf2= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
-                               cfra2 = cfrai;
-                       }
+               cfrai = (int)cfra;
+               while(cfrai < pid->cache->endframe && !pf2) {
+                       cfrai++;
+                       pf2= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
+                       cfra2 = cfrai;
                }
-               else if(pid->cache->mem_cache.first){
-                       pm = pid->cache->mem_cache.first;
+       }
+       else if(pid->cache->mem_cache.first){
+               pm = pid->cache->mem_cache.first;
 
-                       while(pm->next && pm->next->frame < cfra)
-                               pm= pm->next;
+               while(pm->next && pm->next->frame < cfra)
+                       pm= pm->next;
 
-                       if(pm) {
+               if(pm) {
+                       if(reader->old_frame)
                                *(reader->old_frame) = pm->frame;
-                               cfra1 = pm->frame;
-                       }
+                       cfra1 = pm->frame;
+               }
 
-                       pm2 = pid->cache->mem_cache.last;
+               pm2 = pid->cache->mem_cache.last;
 
-                       while(pm2->prev && pm2->frame > cfra)
+               if(pm2 && pm2->frame < cfra)
+                       pm2 = NULL;
+               else {
+                       while(pm2->prev && pm2->prev->frame > cfra)
                                pm2= pm2->prev;
 
                        if(pm2)
                                cfra2 = pm2->frame;
                }
+       }
 
-               if(reader->allow_interpolate && ((pf && pf2) || (pm && pm2))) {
-                       /* interpolate from nearest frames */
-                       float *data1, *data2;
+       if(ret)
+               ;
+       else if((pf && pf2) || (pm && pm2)) {
+               /* interpolate from nearest frames if cache isn't outdated */
+               float *data1, *data2;
 
-                       if(pm) {
-                               data1 = pm->data;
-                               data2 = pm2->data;
-                       }
-                       else {
-                               data1 = MEM_callocN(elemsize, "pointcache read data1");
-                               data2 = MEM_callocN(elemsize, "pointcache read data2");
-                       }
+               if(pm) {
+                       data1 = pm->data;
+                       data2 = pm2->data;
+               }
+               else {
+                       data1 = MEM_callocN(elemsize, "pointcache read data1");
+                       data2 = MEM_callocN(elemsize, "pointcache read data2");
+               }
 
-                       for(i=0; i<totelem; i++) {
-                               if(pf && pf2) {
-                                       if(!BKE_ptcache_file_read_floats(pf, data1, incr)) {
-                                               BKE_ptcache_file_close(pf);
-                                               BKE_ptcache_file_close(pf2);
-                                               MEM_freeN(data1);
-                                               MEM_freeN(data2);
-                                               return 0;
-                                       }
-                                       if(!BKE_ptcache_file_read_floats(pf2, data2, incr)) {
-                                               BKE_ptcache_file_close(pf);
-                                               BKE_ptcache_file_close(pf2);
-                                               MEM_freeN(data1);
-                                               MEM_freeN(data2);
-                                               return 0;
-                                       }
-                                       reader->interpolate_elem(i, reader->calldata, frs_sec, cfra, cfra1, cfra2, data1, data2);
+               for(i=0; i<totelem; i++) {
+                       if(pf && pf2) {
+                               if(!BKE_ptcache_file_read_floats(pf, data1, incr)) {
+                                       BKE_ptcache_file_close(pf);
+                                       BKE_ptcache_file_close(pf2);
+                                       MEM_freeN(data1);
+                                       MEM_freeN(data2);
+                                       return 0;
                                }
-                               else {
-                                       reader->interpolate_elem(i, reader->calldata, frs_sec, cfra, cfra1, cfra2, data1, data2);
-                                       data1 += incr;
-                                       data2 += incr;
+                               if(!BKE_ptcache_file_read_floats(pf2, data2, incr)) {
+                                       BKE_ptcache_file_close(pf);
+                                       BKE_ptcache_file_close(pf2);
+                                       MEM_freeN(data1);
+                                       MEM_freeN(data2);
+                                       return 0;
                                }
+                               reader->interpolate_elem(i, reader->calldata, frs_sec, cfra, (float)cfra1, (float)cfra2, data1, data2);
                        }
+                       else {
+                               reader->interpolate_elem(i, reader->calldata, frs_sec, cfra, (float)cfra1, (float)cfra2, data1, data2);
+                               data1 += incr;
+                               data2 += incr;
+                       }
+               }
 
-                       if(pf) {
+               if(pf) {
+                       BKE_ptcache_file_close(pf);
+                       BKE_ptcache_file_close(pf2);
+                       MEM_freeN(data1);
+                       MEM_freeN(data2);
+               }
+
+               ret = PTCACHE_READ_INTERPOLATED;
+       }
+       else if(pf || pm) {
+               /* use last valid cache frame */
+               float *data;
+
+               /* don't read cache if allready simulated past cached frame */
+               if(cfra1 && cfra1 <= pid->cache->simframe) {
+                       if(pf)
                                BKE_ptcache_file_close(pf);
+                       if(pf2)
                                BKE_ptcache_file_close(pf2);
-                               MEM_freeN(data1);
-                               MEM_freeN(data2);
-                       }
 
-                       return PTCACHE_READ_INTERPOLATED;
+                       return 0;
                }
-               else if(reader->allow_old && (pf || pm)) {
-                       /* use last valid cache frame */
-                       float *data;
 
-                       if(pm)
-                               data = pm->data;
-                       else
-                               data = MEM_callocN(elemsize, "pointcache read data");
-
-                       for(i=0; i<totelem; i++) {
-                               if(pf) {
-                                       if(!BKE_ptcache_file_read_floats(pf, data, incr)) {
-                                               BKE_ptcache_file_close(pf);
-                                               if(pf2)
-                                                       BKE_ptcache_file_close(pf2);
-                                               return 0;
-                                       }
-                                       reader->set_elem(i, reader->calldata, data);
-                               }
-                               else {
-                                       reader->set_elem(i, reader->calldata, data);
-                                       data += incr;
-                               }
-                       }
+               if(pm)
+                       data = pm->data;
+               else
+                       data = MEM_callocN(elemsize, "pointcache read data");
 
+               for(i=0; i<totelem; i++) {
                        if(pf) {
-                               BKE_ptcache_file_close(pf);
-                               MEM_freeN(data);
+                               if(!BKE_ptcache_file_read_floats(pf, data, incr)) {
+                                       BKE_ptcache_file_close(pf);
+                                       if(pf2)
+                                               BKE_ptcache_file_close(pf2);
+                                       return 0;
+                               }
+                               reader->set_elem(i, reader->calldata, data);
                        }
-                       if(pf2)
-                               BKE_ptcache_file_close(pf2);
+                       else {
+                               reader->set_elem(i, reader->calldata, data);
+                               data += incr;
+                       }
+               }
 
-                       return PTCACHE_READ_OLD;
+               if(pf) {
+                       BKE_ptcache_file_close(pf);
+                       MEM_freeN(data);
                }
+               if(pf2)
+                       BKE_ptcache_file_close(pf2);
+
+               ret = PTCACHE_READ_OLD;
        }
 
        if(pf)
@@ -550,7 +580,20 @@ int BKE_ptcache_read_cache(PTCacheReader *reader)
        if(pf2)
                BKE_ptcache_file_close(pf2);
 
-       return 0;
+       if((pid->cache->flag & PTCACHE_QUICK_CACHE)==0) {
+               /* clear invalid cache frames so that better stuff can be simulated */
+               if(pid->cache->flag & PTCACHE_OUTDATED) {
+                       BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, cfra);
+               }
+               else if(pid->cache->flag & PTCACHE_FRAMES_SKIPPED) {
+                       if(cfra <= pid->cache->last_exact)
+                               pid->cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
+
+                       BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfra,pid->cache->last_exact));
+               }
+       }
+
+       return ret;
 }
 /* writes cache to disk or memory */
 int BKE_ptcache_write_cache(PTCacheWriter *writer)
@@ -559,57 +602,118 @@ int BKE_ptcache_write_cache(PTCacheWriter *writer)
        PTCacheFile *pf= NULL;
        int elemsize = ptcache_pid_elemsize(writer->pid);
        int i, incr = elemsize / sizeof(float);
+       int add = 0, overwrite = 0, ocfra;
+       float temp[14];
 
        if(writer->totelem == 0 || writer->cfra <= 0)
                return 0;
 
        if(cache->flag & PTCACHE_DISK_CACHE) {
-               pf = BKE_ptcache_file_open(writer->pid, PTCACHE_FILE_WRITE, writer->cfra);
-               if(!pf)
-                       return 0;
+               /* allways start from scratch on the first frame */
+               if(writer->cfra == cache->startframe) {
+                       BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_ALL, writer->cfra);
+                       cache->flag &= ~PTCACHE_REDO_NEEDED;
+                       add = 1;
+               }
+               else {
+                       int cfra = cache->endframe;
+                       /* find last cached frame */
+                       while(cfra > cache->startframe && !BKE_ptcache_id_exist(writer->pid, cfra))
+                               cfra--;
+
+                       /* find second last cached frame */
+                       ocfra = cfra-1;
+                       while(ocfra > cache->startframe && !BKE_ptcache_id_exist(writer->pid, ocfra))
+                               ocfra--;
+
+                       if(writer->cfra > cfra) {
+                               if(ocfra >= cache->startframe && cfra - ocfra < cache->step)
+                                       overwrite = 1;
+                               else
+                                       add = 1;
+                       }
+               }
 
-               for(i=0; i<writer->totelem; i++)
-                       BKE_ptcache_file_write_floats(pf, writer->elem_ptr(i, writer->calldata), incr);
+               if(add || overwrite) {
+                       if(overwrite)
+                               BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_FRAME, ocfra);
+
+                       pf = BKE_ptcache_file_open(writer->pid, PTCACHE_FILE_WRITE, writer->cfra);
+                       if(!pf)
+                               return 0;
+
+                       for(i=0; i<writer->totelem; i++) {
+                               writer->set_elem(i, writer->calldata, &temp);
+                               BKE_ptcache_file_write_floats(pf, &temp, incr);
+                       }
+               }
        }
        else {
-               PTCacheMem *pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
+               PTCacheMem *pm;
                PTCacheMem *pm2;
                float *pmdata;
 
-               pm->data = MEM_callocN(elemsize * writer->totelem, "Pointcache mem data");
-               pmdata = pm->data;
+               pm2 = cache->mem_cache.first;
+               
+               /* allways start from scratch on the first frame */
+               if(writer->cfra == cache->startframe) {
+                       BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_ALL, writer->cfra);
+                       cache->flag &= ~PTCACHE_REDO_NEEDED;
+                       add = 1;
+               }
+               else {
+                       pm2 = cache->mem_cache.last;
+
+                       if(pm2 && writer->cfra > pm2->frame) {
+                               if(pm2 && pm2->prev && pm2->frame - pm2->prev->frame < cache->step)
+                                       overwrite = 1;
+                               else
+                                       add = 1;
+                       }
+               }
 
-               for(i=0; i<writer->totelem; i++, pmdata+=incr)
-                       memcpy(pmdata, writer->elem_ptr(i, writer->calldata), elemsize);
+               if(overwrite) {
+                       pm = cache->mem_cache.last;
+                       pmdata = pm->data;
 
-               pm->frame = writer->cfra;
-               pm->totpoint = writer->totelem;
+                       for(i=0; i<writer->totelem; i++, pmdata+=incr) {
+                               writer->set_elem(i, writer->calldata, &temp);
+                               memcpy(pmdata, &temp, elemsize);
+                       }
 
-               /* find add location */
-               pm2 = cache->mem_cache.first;
-               if(!pm2)
-                       BLI_addtail(&cache->mem_cache, pm);
-               else if(pm2->frame == writer->cfra) {
-                       /* overwrite same frame */
-                       MEM_freeN(pm2->data);
-                       pm2->data = pm->data;
-                       MEM_freeN(pm);
+                       pm->frame = writer->cfra;
                }
-               else {
-                       while(pm2->next && pm2->next->frame < writer->cfra)
-                               pm2 = pm2->next;
+               else if(add) {
+                       pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
+                       pm->data = MEM_callocN(elemsize * writer->totelem, "Pointcache mem data");
+                       pmdata = pm->data;
+
+                       for(i=0; i<writer->totelem; i++, pmdata+=incr) {
+                               writer->set_elem(i, writer->calldata, &temp);
+                               memcpy(pmdata, &temp, elemsize);
+                       }
+
+                       pm->frame = writer->cfra;
+                       pm->totpoint = writer->totelem;
 
-                       BLI_insertlinkafter(&cache->mem_cache, pm2, pm);
+                       BLI_addtail(&cache->mem_cache, pm);
                }
        }
 
-       if(writer->cfra - cache->last_exact == 1)
-               cache->last_exact = writer->cfra;
+       if(add || overwrite) {
+               if(writer->cfra - cache->last_exact == 1
+                       || writer->cfra == cache->startframe) {
+                       cache->last_exact = writer->cfra;
+                       cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
+               }
+               else
+                       cache->flag |= PTCACHE_FRAMES_SKIPPED;
+       }
        
        if(pf)
                BKE_ptcache_file_close(pf);
 
-       ptcache_update_info(writer->pid);
+       BKE_ptcache_update_info(writer->pid);
 
        return 1;
 }
@@ -730,7 +834,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra)
                break;
        }
 
-       ptcache_update_info(pid);
+       BKE_ptcache_update_info(pid);
 }
 
 int BKE_ptcache_id_exist(PTCacheID *pid, int cfra)
@@ -762,6 +866,9 @@ void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startfra
        PointCache *cache;
        float offset, time, nexttime;
 
+       /* TODO: this has to be sorter out once bsystem_time gets redone, */
+       /*       now caches can handle interpolating etc. too - jahka */
+
        /* time handling for point cache:
         * - simulation time is scaled by result of bsystem_time
         * - for offsetting time only time offset is taken into account, since
@@ -798,7 +905,7 @@ void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startfra
 int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
 {
        PointCache *cache;
-       int reset, clear, current, after;
+       int reset, clear, after;
 
        if(!pid->cache)
                return 0;
@@ -806,23 +913,17 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
        cache= pid->cache;
        reset= 0;
        clear= 0;
-       current= 0;
        after= 0;
 
        if(mode == PTCACHE_RESET_DEPSGRAPH) {
                if(!(cache->flag & PTCACHE_BAKED) && !BKE_ptcache_get_continue_physics()) {
-                       if(cache->flag & PTCACHE_AUTOCACHE) {
-                               reset= 1;
+                       if(cache->flag & PTCACHE_QUICK_CACHE)
                                clear= 1;
-                       }
-                       else {
-                               current= 1;
-                               after= 1;
-                               cache->flag |= PTCACHE_OUTDATED;
-                       }
+
+                       after= 1;
                }
-               else
-                       cache->flag |= PTCACHE_OUTDATED;
+
+               cache->flag |= PTCACHE_OUTDATED;
        }
        else if(mode == PTCACHE_RESET_BAKED) {
                if(!BKE_ptcache_get_continue_physics()) {
@@ -839,17 +940,9 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
                        if(!(cache->flag & PTCACHE_BAKED))
                                clear= 1;
        }
-       else if(mode == PTCACHE_RESET_FREE) {
-               if(!(cache->flag & PTCACHE_BAKED) && !BKE_ptcache_get_continue_physics()) {
-                       if((cache->flag & PTCACHE_AUTOCACHE)==0) {
-                               current= 1;
-                               after= 1;
-                       }
-               }
-       }
 
        if(reset) {
-               cache->flag &= ~(PTCACHE_OUTDATED|PTCACHE_SIMULATION_VALID);
+               cache->flag &= ~(PTCACHE_REDO_NEEDED|PTCACHE_SIMULATION_VALID);
                cache->simframe= 0;
                cache->last_exact= 0;
 
@@ -862,12 +955,10 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
        }
        if(clear)
                BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
-       if(after)
+       else if(after)
                BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, CFRA);
-       if(current)
-               BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, CFRA);
 
-       return (reset || clear || current || after);
+       return (reset || clear || after);
 }
 
 int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode)
@@ -987,6 +1078,7 @@ PointCache *BKE_ptcache_add()
        cache= MEM_callocN(sizeof(PointCache), "PointCache");
        cache->startframe= 1;
        cache->endframe= 250;
+       cache->step= 10;
 
        return cache;
 }
@@ -1019,7 +1111,39 @@ PointCache *BKE_ptcache_copy(PointCache *cache)
 
 
 /* Baking */
-void BKE_ptcache_autocache_all(Scene *scene)
+static int count_quick_cache(Scene *scene, int *quick_step)
+{
+       Base *base = scene->base.first;
+       PTCacheID *pid;
+       ListBase pidlist;
+       int autocache_count= 0;
+
+       for(base = scene->base.first; base; base = base->next) {
+               if(base->object) {
+                       BKE_ptcache_ids_from_object(&pidlist, base->object);
+
+                       for(pid=pidlist.first; pid; pid=pid->next) {
+                               if((pid->cache->flag & PTCACHE_BAKED)
+                                       || (pid->cache->flag & PTCACHE_QUICK_CACHE)==0)
+                                       continue;
+
+                               if(pid->cache->flag & PTCACHE_OUTDATED || (pid->cache->flag & PTCACHE_SIMULATION_VALID)==0) {
+                                       if(!autocache_count)
+                                               *quick_step = pid->cache->step;
+                                       else
+                                               *quick_step = MIN2(*quick_step, pid->cache->step);
+
+                                       autocache_count++;
+                               }
+                       }
+
+                       BLI_freelistN(&pidlist);
+               }
+       }
+
+       return autocache_count;
+}
+void BKE_ptcache_quick_cache_all(Scene *scene)
 {
        PTCacheBaker baker;
 
@@ -1032,7 +1156,7 @@ void BKE_ptcache_autocache_all(Scene *scene)
        baker.render=0;
        baker.scene=scene;
 
-       if(psys_count_autocache(scene, NULL))
+       if(count_quick_cache(scene, &baker.quick_step))
                BKE_ptcache_make_cache(&baker);
 }
 
@@ -1050,11 +1174,10 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
        int endframe = CFRA;
        int bake = baker->bake;
        int render = baker->render;
+       int step = baker->quick_step;
 
        G.afbreek = 0;
 
-       //printf("Caching physics...");
-
        /* set caches to baking mode and figure out start frame */
        if(pid) {
                /* cache/bake a single object */
@@ -1063,7 +1186,7 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
                        if(pid->type==PTCACHE_TYPE_PARTICLES)
                                psys_get_pointcache_start_end(scene, pid->data, &cache->startframe, &cache->endframe);
 
-                       if(bake || cache->flag & PTCACHE_OUTDATED)
+                       if(bake || cache->flag & PTCACHE_REDO_NEEDED)
                                BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
 
                        startframe = MAX2(cache->last_exact, cache->startframe);
@@ -1072,8 +1195,9 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
                                endframe = cache->endframe;
                                cache->flag |= PTCACHE_BAKING;
                        }
-                       else
+                       else {
                                endframe = MIN2(endframe, cache->endframe);
+                       }
 
                        cache->flag &= ~PTCACHE_BAKED;
                }
@@ -1088,31 +1212,30 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
                                if(pid->type==PTCACHE_TYPE_PARTICLES)
                                        psys_get_pointcache_start_end(scene, pid->data, &cache->startframe, &cache->endframe);
 
-                               if(cache->flag & PTCACHE_OUTDATED)
+                               if((cache->flag & PTCACHE_REDO_NEEDED || (cache->flag & PTCACHE_SIMULATION_VALID)==0)
+                                       && ((cache->flag & PTCACHE_QUICK_CACHE)==0 || render || bake))
                                        BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
 
                                startframe = MIN2(startframe, cache->startframe);
 
-                               if(bake) {
-                                       endframe = MAX2(endframe, cache->endframe);
+                               if(bake || render) {
                                        cache->flag |= PTCACHE_BAKING;
+
+                                       if(bake)
+                                               endframe = MAX2(endframe, cache->endframe);
                                }
-                               else if(render)
-                                       cache->flag |= PTCACHE_BAKING;
 
                                cache->flag &= ~PTCACHE_BAKED;
 
                        }
                }
-
                BLI_freelistN(&pidlist);
        }
 
        CFRA= startframe;
        scene->r.framelen = 1.0;
-       scene_update_for_newframe(scene, scene->lay);
 
-       for(; CFRA <= endframe; CFRA++) {
+       for(; CFRA <= endframe; CFRA+=step) {
                float prog;
 
                if(bake)
@@ -1133,7 +1256,8 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
 
        /* clear baking flag */
        if(pid) {
-               cache->flag &= ~(PTCACHE_BAKING|PTCACHE_OUTDATED);
+               cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED);
+               cache->flag |= PTCACHE_SIMULATION_VALID;
                if(bake)
                        cache->flag |= PTCACHE_BAKED;
        }
@@ -1141,17 +1265,26 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
                BKE_ptcache_ids_from_object(&pidlist, base->object);
 
                for(pid=pidlist.first; pid; pid=pid->next) {
-                       cache->flag &= ~(PTCACHE_BAKING|PTCACHE_OUTDATED);
+                       cache = pid->cache;
+
+                       if(step > 1)
+                               cache->flag &= ~(PTCACHE_BAKING|PTCACHE_OUTDATED);
+                       else
+                               cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED);
+
+                       cache->flag |= PTCACHE_SIMULATION_VALID;
+
                        if(bake)
                                cache->flag |= PTCACHE_BAKED;
                }
+               BLI_freelistN(&pidlist);
        }
-       
-       //printf("done!\n");
 
        scene->r.framelen = frameleno;
        CFRA = cfrao;
        scene_update_for_newframe(scene, scene->lay);
+
+       /* TODO: call redraw all windows somehow */
 }
 
 void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) {
@@ -1161,6 +1294,7 @@ void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) {
        int totelem=0;
        int float_count=0;
        int tot;
+       int last_exact = cache->last_exact;
 
        if (!G.relbase_valid){
                cache->flag &= ~PTCACHE_DISK_CACHE;
@@ -1230,6 +1364,7 @@ void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) {
                                }
 
                                pm->frame = cfra;
+                               pm->totpoint = totelem;
 
                                BLI_addtail(&pid->cache->mem_cache, pm);
 
@@ -1241,4 +1376,8 @@ void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) {
                BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
                cache->flag &= ~PTCACHE_DISK_CACHE;
        }
+       
+       cache->last_exact = last_exact;
+
+       BKE_ptcache_update_info(pid);
 }
index 7921740..441e8af 100644 (file)
@@ -9013,6 +9013,8 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                Tex *tx;
                ParticleSettings *part;
                Object *ob;
+               PTCacheID *pid;
+               ListBase pidlist;
                
                for(screen= main->screen.first; screen; screen= screen->id.next) {
                        do_versions_windowmanager_2_50(screen);
@@ -9073,14 +9075,13 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                }
                /* set old pointcaches to have disk cache flag */
                for(ob = main->object.first; ob; ob= ob->id.next) {
-                       ParticleSystem *psys = ob->particlesystem.first;
 
-                       for(; psys; psys=psys->next) {
-                               if(psys->pointcache)
-                                       psys->pointcache->flag |= PTCACHE_DISK_CACHE;
-                       }
+                       BKE_ptcache_ids_from_object(&pidlist, ob);
+
+                       for(pid=pidlist.first; pid; pid=pid->next)
+                               pid->cache->flag |= PTCACHE_DISK_CACHE;
 
-                       /* TODO: softbody & cloth caches */
+                       BLI_freelistN(&pidlist);
                }
        }
 
index ef1e7d7..c433232 100644 (file)
@@ -552,6 +552,7 @@ static void write_userdef(WriteData *wd)
 
 /* TODO: replace *cache with *cachelist once it's coded */
 #define PTCACHE_WRITE_PSYS     0
+#define PTCACHE_WRITE_CLOTH    1
 static void write_pointcaches(WriteData *wd, PointCache *cache, int type)
 {
        writestruct(wd, DATA, "PointCache", 1, cache);
@@ -563,6 +564,8 @@ static void write_pointcaches(WriteData *wd, PointCache *cache, int type)
                        writestruct(wd, DATA, "PTCacheMem", 1, pm);
                        if(type==PTCACHE_WRITE_PSYS)
                                writestruct(wd, DATA, "ParticleKey", pm->totpoint, pm->data);
+                       else if(type==PTCACHE_WRITE_CLOTH)
+                               writedata(wd, DATA, 9 * sizeof(float) * pm->totpoint, pm->data);
                }
        }
 }
@@ -1025,7 +1028,7 @@ static void write_modifiers(WriteData *wd, ListBase *modbase, int write_undo)
                        
                        writestruct(wd, DATA, "ClothSimSettings", 1, clmd->sim_parms);
                        writestruct(wd, DATA, "ClothCollSettings", 1, clmd->coll_parms);
-                       writestruct(wd, DATA, "PointCache", 1, clmd->point_cache);
+                       write_pointcaches(wd, clmd->point_cache, PTCACHE_WRITE_CLOTH);
                } 
                else if(md->type==eModifierType_Fluidsim) {
                        FluidsimModifierData *fluidmd = (FluidsimModifierData*) md;
index 3374e05..893c59a 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "DNA_scene_types.h"
 #include "DNA_object_force.h"
+#include "DNA_modifier_types.h"
 
 #include "BKE_context.h"
 #include "BKE_particle.h"
@@ -39,7 +40,7 @@
 #include "BKE_utildefines.h" 
 #include "BKE_pointcache.h"
 #include "BKE_global.h"
-#include "BKE_multires.h"
+#include "BKE_modifier.h"
 
 #include "BLI_blenlib.h"
 
@@ -81,6 +82,7 @@ static int ptcache_bake_all_exec(bContext *C, wmOperator *op)
        baker.pid = NULL;
        baker.bake = RNA_boolean_get(op->ptr, "bake");
        baker.render = 0;
+       baker.quick_step = 1;
        baker.break_test = cache_break_test;
        baker.break_data = NULL;
        baker.progressbar = (void (*)(void *, int))WM_timecursor;
@@ -104,12 +106,11 @@ static int ptcache_free_bake_all_exec(bContext *C, wmOperator *op)
 
                for(pid=pidlist.first; pid; pid=pid->next) {
                        pid->cache->flag &= ~PTCACHE_BAKED;
-                       BKE_ptcache_id_reset(scene, pid, PTCACHE_RESET_OUTDATED);
                }
+               
+               BLI_freelistN(&pidlist);
        }
 
-       BLI_freelistN(&pidlist);
-
        WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
 
        return OPERATOR_FINISHED;
@@ -127,6 +128,8 @@ void PTCACHE_OT_bake_all(wmOperatorType *ot)
 
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+       RNA_def_boolean(ot->srna, "bake", 0, "Bake", "");
 }
 void PTCACHE_OT_free_bake_all(wmOperatorType *ot)
 {
@@ -142,6 +145,112 @@ void PTCACHE_OT_free_bake_all(wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
+/**************************** cloth **********************************/
+static int ptcache_bake_cloth_poll(bContext *C)
+{
+       Scene *scene= CTX_data_scene(C);
+       Object *ob= CTX_data_active_object(C);
+       ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
+
+       if(!scene || !ob || ob->id.lib || !clmd)
+               return 0;
+       
+       return 1;
+}
+
+static int ptcache_bake_cloth_exec(bContext *C, wmOperator *op)
+{
+       Scene *scene= CTX_data_scene(C);
+       Object *ob= CTX_data_active_object(C);
+       ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
+       PTCacheID pid;
+       PTCacheBaker baker;
+
+       BKE_ptcache_id_from_cloth(&pid, ob, clmd);
+
+       baker.scene = scene;
+       baker.pid = &pid;
+       baker.bake = RNA_boolean_get(op->ptr, "bake");
+       baker.render = 0;
+       baker.quick_step = 1;
+       baker.break_test = cache_break_test;
+       baker.break_data = NULL;
+       baker.progressbar = WM_timecursor;
+       baker.progresscontext = CTX_wm_window(C);
+
+       BKE_ptcache_make_cache(&baker);
+
+       WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
+
+       return OPERATOR_FINISHED;
+}
+static int ptcache_free_bake_cloth_exec(bContext *C, wmOperator *op)
+{
+       Scene *scene= CTX_data_scene(C);
+       Object *ob= CTX_data_active_object(C);
+       ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
+       PTCacheID pid;
+
+       BKE_ptcache_id_from_cloth(&pid, ob, clmd);
+       pid.cache->flag &= ~PTCACHE_BAKED;
+
+       WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
+
+       return OPERATOR_FINISHED;
+}
+void PTCACHE_OT_cache_cloth(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Bake Cloth";
+       ot->idname= "PTCACHE_OT_cache_cloth";
+       
+       /* api callbacks */
+       ot->exec= ptcache_bake_cloth_exec;
+       ot->poll= ptcache_bake_cloth_poll;
+
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+       RNA_def_boolean(ot->srna, "bake", 0, "Bake", "");
+}
+void PTCACHE_OT_free_bake_cloth(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Free Cloth Bake";
+       ot->idname= "PTCACHE_OT_free_bake_cloth";
+       
+       /* api callbacks */
+       ot->exec= ptcache_free_bake_cloth_exec;
+       ot->poll= ptcache_bake_cloth_poll;
+
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+static int ptcache_bake_from_cloth_cache_exec(bContext *C, wmOperator *op)
+{
+       Object *ob= CTX_data_active_object(C);
+       ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
+       PTCacheID pid;
+
+       BKE_ptcache_id_from_cloth(&pid, ob, clmd);
+       pid.cache->flag |= PTCACHE_BAKED;
+
+       return OPERATOR_FINISHED;
+}
+void PTCACHE_OT_bake_from_cloth_cache(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Bake From Cache";
+       ot->idname= "PTCACHE_OT_bake_from_cloth_cache";
+       
+       /* api callbacks */
+       ot->exec= ptcache_bake_from_cloth_cache_exec;
+       ot->poll= ptcache_bake_cloth_poll;
+
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
 /**************************** particles **********************************/
 static int ptcache_bake_particle_system_poll(bContext *C)
 {
@@ -168,6 +277,7 @@ static int ptcache_bake_particle_system_exec(bContext *C, wmOperator *op)
        baker.pid = &pid;
        baker.bake = RNA_boolean_get(op->ptr, "bake");
        baker.render = 0;
+       baker.quick_step = 1;
        baker.break_test = cache_break_test;
        baker.break_data = NULL;
        baker.progressbar = (void (*)(void *, int))WM_timecursor;
@@ -188,7 +298,6 @@ static int ptcache_free_bake_particle_system_exec(bContext *C, wmOperator *op)
 
        BKE_ptcache_id_from_particles(&pid, ob, psys);
        psys->pointcache->flag &= ~PTCACHE_BAKED;
-       BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
 
        WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
 
@@ -256,6 +365,9 @@ void ED_operatortypes_pointcache(void)
        WM_operatortype_append(PTCACHE_OT_cache_particle_system);
        WM_operatortype_append(PTCACHE_OT_free_bake_particle_system);
        WM_operatortype_append(PTCACHE_OT_bake_from_particles_cache);
+       WM_operatortype_append(PTCACHE_OT_cache_cloth);
+       WM_operatortype_append(PTCACHE_OT_free_bake_cloth);
+       WM_operatortype_append(PTCACHE_OT_bake_from_cloth_cache);
 }
 
 //void ED_keymap_pointcache(wmWindowManager *wm)
index bb1f09e..490ce82 100644 (file)
@@ -4674,6 +4674,12 @@ void special_aftertrans_update(TransInfo *t)
                                /* pointcache refresh */
                                if (BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH))
                                        ob->recalc |= OB_RECALC_DATA;
+
+                               /* Needed for proper updating of "quick cached" dynamics. */
+                               /* Creates troubles for moving animated objects without */
+                               /* autokey though, probably needed is an anim sys override? */
+                               /* Please remove if some other solution is found. -jahka */
+                               DAG_object_flush_update(scene, ob, OB_RECALC_OB);
                                
                                /* Set autokey if necessary */
                                if (!cancelled)
index a8d402f..88d9894 100644 (file)
@@ -82,7 +82,8 @@ typedef struct PTCacheMem {
 } PTCacheMem;
 
 typedef struct PointCache {
-       int flag, rt;           /* generic flag */
+       int flag;               /* generic flag */
+       int step;               /* frames between cached frames */
        int simframe;   /* current frame of simulation (only if SIMULATION_VALID) */
        int startframe; /* simulation start frame */
        int endframe;   /* simulation end frame */
@@ -263,7 +264,11 @@ typedef struct SoftBody {
 #define PTCACHE_BAKE_EDIT                      16
 #define PTCACHE_BAKE_EDIT_ACTIVE       32
 #define PTCACHE_DISK_CACHE                     64
-#define PTCACHE_AUTOCACHE                      128
+#define PTCACHE_QUICK_CACHE                    128
+#define PTCACHE_FRAMES_SKIPPED         256
+
+/* PTCACHE_OUTDATED + PTCACHE_FRAMES_SKIPPED */
+#define PTCACHE_REDO_NEEDED                    258
 
 /* ob->softflag */
 #define OB_SB_ENABLE   1
index 361c1b6..cefd231 100644 (file)
 #include "BKE_modifier.h"
 
 #include "DNA_cloth_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "WM_types.h"
 
 #ifdef RNA_RUNTIME
 
+#include "BKE_context.h"
+#include "BKE_depsgraph.h"
+
+static void rna_cloth_update(bContext *C, PointerRNA *ptr)
+{
+       Scene *scene = CTX_data_scene(C);
+       Object *ob = ptr->id.data;
+
+       DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+}
+
 static void rna_ClothSettings_max_bend_set(struct PointerRNA *ptr, float value)
 {
        ClothSimSettings *settings = (ClothSimSettings*)ptr->data;
@@ -165,42 +180,50 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
        RNA_def_property_float_sdna(prop, NULL, "mingoal");
        RNA_def_property_range(prop, 0.0f, 1.0f);
        RNA_def_property_ui_text(prop, "Goal Minimum", "Goal minimum, vertex group weights are scaled to match this range.");
+       RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
        prop= RNA_def_property(srna, "goal_max", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "maxgoal");
        RNA_def_property_range(prop, 0.0f, 1.0f);
        RNA_def_property_ui_text(prop, "Goal Maximum", "Goal maximum, vertex group weights are scaled to match this range.");
+       RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
        prop= RNA_def_property(srna, "goal_default", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "defgoal");
        RNA_def_property_range(prop, 0.0f, 1.0f);
        RNA_def_property_ui_text(prop, "Goal Default", "Default Goal (vertex target position) value, when no Vertex Group used.");
+       RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
        
        prop= RNA_def_property(srna, "goal_spring", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "goalspring");
        RNA_def_property_range(prop, 0.0f, 0.999f);
        RNA_def_property_ui_text(prop, "Goal Stiffness", "Goal (vertex target position) spring stiffness.");
+       RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
        
        prop= RNA_def_property(srna, "goal_friction", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "goalfrict");
        RNA_def_property_range(prop, 0.0f, 50.0f);
        RNA_def_property_ui_text(prop, "Goal Damping", "Goal (vertex target position) friction.");
+       RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
        /* mass */
 
        prop= RNA_def_property(srna, "mass", PROP_FLOAT, PROP_NONE);
        RNA_def_property_range(prop, 0.0f, 10.0f);
        RNA_def_property_ui_text(prop, "Mass", "Mass of cloth material.");
+       RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
        prop= RNA_def_property(srna, "mass_vertex_group", PROP_STRING, PROP_NONE);
        RNA_def_property_string_funcs(prop, "rna_ClothSettings_mass_vgroup_get", "rna_ClothSettings_mass_vgroup_length", "rna_ClothSettings_mass_vgroup_set");
        RNA_def_property_ui_text(prop, "Mass Vertex Group", "Vertex group for fine control over mass distribution.");
+       RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
        
        prop= RNA_def_property(srna, "gravity", PROP_FLOAT, PROP_VECTOR);
        RNA_def_property_array(prop, 3);
        RNA_def_property_range(prop, -100.0, 100.0);
        RNA_def_property_float_funcs(prop, "rna_ClothSettings_gravity_get", "rna_ClothSettings_gravity_set", NULL);
        RNA_def_property_ui_text(prop, "Gravity", "Gravity or external force vector.");
+       RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
        /* various */
 
@@ -208,61 +231,73 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
        RNA_def_property_float_sdna(prop, NULL, "Cvi");
        RNA_def_property_range(prop, 0.0f, 10.0f);
        RNA_def_property_ui_text(prop, "Air Damping", "Air has normally some thickness which slows falling things down.");
+       RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
        prop= RNA_def_property(srna, "pin_cloth", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_SIMSETTINGS_FLAG_GOAL);
        RNA_def_property_ui_text(prop, "Pin Cloth", "Define forces for vertices to stick to animated position.");
+       RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
        prop= RNA_def_property(srna, "pin_stiffness", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "goalspring");
        RNA_def_property_range(prop, 0.0f, 50.0);
        RNA_def_property_ui_text(prop, "Pin Stiffness", "Pin (vertex target position) spring stiffness.");
+       RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
        prop= RNA_def_property(srna, "quality", PROP_INT, PROP_NONE);
        RNA_def_property_int_sdna(prop, NULL, "stepsPerFrame");
        RNA_def_property_range(prop, 4, 80);
        RNA_def_property_ui_text(prop, "Quality", "Quality of the simulation in steps per frame (higher is better quality but slower).");
+       RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
        /* springs */
 
        prop= RNA_def_property(srna, "stiffness_scaling", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_SIMSETTINGS_FLAG_SCALING);
        RNA_def_property_ui_text(prop, "Stiffness Scaling", "If enabled, stiffness can be scaled along a weight painted vertex group.");
+       RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
        
        prop= RNA_def_property(srna, "spring_damping", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "Cdis");
        RNA_def_property_range(prop, 0.0f, 50.0f);
        RNA_def_property_ui_text(prop, "Spring Damping", "Damping of cloth velocity (higher = more smooth, less jiggling)");
+       RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
        
        prop= RNA_def_property(srna, "structural_stiffness", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "structural");
        RNA_def_property_range(prop, 1.0f, 10000.0f);
        RNA_def_property_ui_text(prop, "Structural Stiffness", "Overall stiffness of structure.");
+       RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
        prop= RNA_def_property(srna, "structural_stiffness_max", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "max_struct");
        RNA_def_property_range(prop, 0.0f, 10000.0f);
        RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_max_struct_set", NULL);
        RNA_def_property_ui_text(prop, "Structural Stiffness Maximum", "Maximum structural stiffness value.");
+       RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
        prop= RNA_def_property(srna, "structural_stiffness_vertex_group", PROP_STRING, PROP_NONE);
        RNA_def_property_string_funcs(prop, "rna_ClothSettings_struct_vgroup_get", "rna_ClothSettings_struct_vgroup_length", "rna_ClothSettings_struct_vgroup_set");
        RNA_def_property_ui_text(prop, "Structural Stiffness Vertex Group", "Vertex group for fine control over structural stiffness.");
+       RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
        prop= RNA_def_property(srna, "bending_stiffness", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "bending");
        RNA_def_property_range(prop, 0.0f, 10000.0f);
        RNA_def_property_ui_text(prop, "Bending Stiffness", "Wrinkle coefficient (higher = less smaller but more big wrinkles).");
+       RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
        prop= RNA_def_property(srna, "bending_stiffness_max", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "max_bend");
        RNA_def_property_range(prop, 0.0f, 10000.0f);
        RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_max_bend_set", NULL);
        RNA_def_property_ui_text(prop, "Bending Stiffness Maximum", "Maximum bending stiffness value.");
+       RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
        prop= RNA_def_property(srna, "bending_vertex_group", PROP_STRING, PROP_NONE);
        RNA_def_property_string_funcs(prop, "rna_ClothSettings_bend_vgroup_get", "rna_ClothSettings_bend_vgroup_length", "rna_ClothSettings_bend_vgroup_set");
        RNA_def_property_ui_text(prop, "Bending Stiffness Vertex Group", "Vertex group for fine control over bending stiffness.");
+       RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
        /* unused */
 
@@ -323,40 +358,48 @@ static void rna_def_cloth_collision_settings(BlenderRNA *brna)
        prop= RNA_def_property(srna, "enable_collision", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_COLLSETTINGS_FLAG_ENABLED);
        RNA_def_property_ui_text(prop, "Enable Collision", "Enable collisions with other objects.");
+       RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
        
        prop= RNA_def_property(srna, "min_distance", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "epsilon");
        RNA_def_property_range(prop, 0.001f, 1.0f);
        RNA_def_property_ui_text(prop, "Minimum Distance", "Minimum distance between collision objects before collision response takes in, can be changed for each frame.");
+       RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
        prop= RNA_def_property(srna, "friction", PROP_FLOAT, PROP_NONE);
        RNA_def_property_range(prop, 0.0f, 80.0f);
        RNA_def_property_ui_text(prop, "Friction", "Friction force if a collision happened (0=movement not changed, 100=no movement left)");
+       RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
        prop= RNA_def_property(srna, "collision_quality", PROP_INT, PROP_NONE);
        RNA_def_property_int_sdna(prop, NULL, "loop_count");
        RNA_def_property_range(prop, 1, 20);
        RNA_def_property_ui_text(prop, "Collision Quality", "How many collision iterations should be done. (higher is better quality but slower)");
+       RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
        /* self collision */
 
        prop= RNA_def_property(srna, "enable_self_collision", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_COLLSETTINGS_FLAG_SELF);
        RNA_def_property_ui_text(prop, "Enable Self Collision", "Enable self collisions.");
+       RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
        
        prop= RNA_def_property(srna, "self_min_distance", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "selfepsilon");
        RNA_def_property_range(prop, 0.5f, 1.0f);
        RNA_def_property_ui_text(prop, "Self Minimum Distance", "0.5 means no distance at all, 1.0 is maximum distance");
+       RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
        
        prop= RNA_def_property(srna, "self_friction", PROP_FLOAT, PROP_NONE);
        RNA_def_property_range(prop, 0.0f, 80.0f);
        RNA_def_property_ui_text(prop, "Self Friction", "Friction/damping with self contact.");
+       RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
        prop= RNA_def_property(srna, "self_collision_quality", PROP_INT, PROP_NONE);
        RNA_def_property_int_sdna(prop, NULL, "self_loop_count");
        RNA_def_property_range(prop, 1, 10);
        RNA_def_property_ui_text(prop, "Self Collision Quality", "How many self collision iterations should be done. (higher is better quality but slower), can be changed for each frame.");
+       RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 }
 
 void RNA_def_cloth(BlenderRNA *brna)
index 07408c5..4d8c728 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "DNA_object_types.h"
 #include "DNA_object_force.h"
+#include "DNA_scene_types.h"
 
 #include "WM_types.h"
 
 
 #include "BKE_context.h"
 #include "BKE_pointcache.h"
+#include "BKE_depsgraph.h"
 
 #include "BLI_blenlib.h"
 
+static void rna_Cache_change(bContext *C, PointerRNA *ptr)
+{
+       Scene *scene = CTX_data_scene(C);
+       Object *ob = CTX_data_active_object(C);
+       PointCache *cache = (PointCache*)ptr->data;
+       PTCacheID *pid = NULL;
+       ListBase pidlist;
+
+       if(!ob)
+               return;
+
+       cache->flag |= PTCACHE_OUTDATED;
+
+       BKE_ptcache_ids_from_object(&pidlist, ob);
+
+       DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+
+       for(pid=pidlist.first; pid; pid=pid->next) {
+               if(pid->cache==cache)
+                       break;
+       }
+
+       if(pid)
+               BKE_ptcache_update_info(pid);
+
+       BLI_freelistN(&pidlist);
+}
+
 static void rna_Cache_toggle_disk_cache(bContext *C, PointerRNA *ptr)
 {
        Object *ob = CTX_data_active_object(C);
@@ -240,6 +270,12 @@ static void rna_def_pointcache(BlenderRNA *brna)
        RNA_def_property_range(prop, 1, 300000);
        RNA_def_property_ui_text(prop, "End", "Frame on which the simulation stops.");
 
+       prop= RNA_def_property(srna, "step", PROP_INT, PROP_NONE);
+       RNA_def_property_int_sdna(prop, NULL, "step");
+       RNA_def_property_range(prop, 1, 20);
+       RNA_def_property_ui_text(prop, "Cache Step", "Number of frames between cached frames.");
+       RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_change");
+
        /* flags */
        prop= RNA_def_property(srna, "baked", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_BAKED);
@@ -257,21 +293,24 @@ static void rna_def_pointcache(BlenderRNA *brna)
        RNA_def_property_clear_flag(prop, PROP_EDITABLE);
        RNA_def_property_ui_text(prop, "Cache is outdated", "");
 
+       prop= RNA_def_property(srna, "frames_skipped", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_FRAMES_SKIPPED);
+       RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
        prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
        RNA_def_property_string_sdna(prop, NULL, "name");
        RNA_def_property_ui_text(prop, "Name", "Cache name");
        RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_idname_change");
 
-       prop= RNA_def_property(srna, "autocache", PROP_BOOLEAN, PROP_NONE);
-       RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_AUTOCACHE);
-       RNA_def_property_ui_text(prop, "Auto Cache", "Cache changes automatically");
-       //RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_toggle_autocache");
+       prop= RNA_def_property(srna, "quick_cache", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_QUICK_CACHE);
+       RNA_def_property_ui_text(prop, "Quick Cache", "Update simulation with cache steps");
+       RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_change");
 
        prop= RNA_def_property(srna, "info", PROP_STRING, PROP_NONE);
        RNA_def_property_string_sdna(prop, NULL, "info");
        RNA_def_property_clear_flag(prop, PROP_EDITABLE);
        RNA_def_property_ui_text(prop, "Cache Info", "Info on current cache status.");
-
 }
 
 static void rna_def_collision(BlenderRNA *brna)
index 5eec13e..ccc793e 100644 (file)
@@ -2421,6 +2421,7 @@ static void update_physics_cache(Render *re, Scene *scene)
        baker.pid = NULL;
        baker.bake = 0;
        baker.render = 1;
+       baker.quick_step = 1;
        baker.break_test = re->test_break;
        baker.break_data = re->tbh;
        baker.progressbar = NULL;
index ea6a658..286d121 100644 (file)
@@ -49,6 +49,7 @@
 #include "BKE_report.h"
 #include "BKE_scene.h"
 #include "BKE_utildefines.h"
+#include "BKE_pointcache.h"
 
 #include "ED_fileselect.h"
 #include "ED_screen.h"
@@ -234,6 +235,8 @@ void wm_event_do_notifiers(bContext *C)
                        for(base= scene->base.first; base; base= base->next) {
                                object_handle_update(scene, base->object);
                        }
+
+                       BKE_ptcache_quick_cache_all(scene);
                }               
        }
        CTX_wm_window_set(C, NULL);