New point cache file format:
authorJanne Karhu <jhkarh@gmail.com>
Wed, 12 Aug 2009 09:54:29 +0000 (09:54 +0000)
committerJanne Karhu <jhkarh@gmail.com>
Wed, 12 Aug 2009 09:54:29 +0000 (09:54 +0000)
- HEADER (beginning of each file)
* general header:
+ 8 char: "BPHYSICS"
+ 1 int: simulation type (same as PTCacheID->type)
* custom header (same for sb, particles and cloth, but can be different for new dynamics)
+ 1 int: totpoint (number of points)
+ 1 int: data_types (bit flags for what the stored data is)
- DATA (directly after header)
*totpoint times the data as specified in data_types flags

- simulation type
soft body = 0, particles = 1, cloth = 2
- data types (more can be added easily when needed)
data flag contains
----------------------------------------
index (1<<0) 1 int (index of current point)
location (1<<1) 3 float
velocity (1<<2) 3 float
rotation (1<<3) 4 float (quaternion)
avelocity  (1<<4) 3 float (used for particles)
xconst (1<<4) 3 float (used for cloth)
size (1<<5) 1 float
times (1<<6) 3 float (birth, die & lifetime of particle)
boids (1<<7) 1 BoidData

Notes:
- Every frame is not nescessary since data is interpolated for the inbetween frames.
- For now every point is needed for every cached frame, the "index" data type is reserved for future usage.
- For loading external particle caches only "location" data is necessary, other needed values are determined from the given data.
- Non-dynamic data should be written into an info file if external usage is desired.
* Info file is named as normal cache files, but with frame number 0;
* "Non-dynamic" means data such as particle times.
* Written automatically when baking to disk so basically a library of particle simulations should be possible.
- Old disk cache format is supported for reading, so pre 2.5 files shouldn't break. However old style memory cache (added during 2.5 development) is not supported. To keep memory cached simulations convert the cache to disk cache before svn update and save the blend.
- External sb and cloth caches should be perfectly possible, but due to lack of testing these are not yet enabled in ui.

Other changes:
- Multiple point caches per dynamics system.
* In the future these will hopefully be nla editable etc, but for now things are simple and the current (selected) point cache is used.
* Changing the amount of cached points (for example particle count) is allowed, but might not give correct results if multiple caches are present.
- Generalization of point cache baking etc operator & rna code.
- Comb brushing particle hair didn't work smoothly.

21 files changed:
release/ui/buttons_particle.py
release/ui/buttons_physics_cloth.py
release/ui/buttons_physics_softbody.py
source/blender/blenkernel/BKE_cloth.h
source/blender/blenkernel/BKE_pointcache.h
source/blender/blenkernel/BKE_softbody.h
source/blender/blenkernel/intern/cloth.c
source/blender/blenkernel/intern/modifier.c
source/blender/blenkernel/intern/particle.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenkernel/intern/pointcache.c
source/blender/blenkernel/intern/softbody.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/editors/mesh/editmesh.c
source/blender/editors/physics/ed_pointcache.c
source/blender/makesdna/DNA_modifier_types.h
source/blender/makesdna/DNA_object_force.h
source/blender/makesdna/DNA_particle_types.h
source/blender/makesrna/intern/rna_fluidsim.c
source/blender/makesrna/intern/rna_object_force.c

index f35d15bbb80ceadf47f7f24088bb776adc1b23eb..dae95dfcc00277460deb63787d08f32877804d6d 100644 (file)
@@ -151,6 +151,13 @@ class PARTICLE_PT_cache(ParticleButtonsPanel):
                psys = context.particle_system
                part = psys.settings
                cache = psys.point_cache
+               layout.set_context_pointer("PointCache", cache)
+               
+               row = layout.row()
+               row.template_list(cache, "point_cache_list", cache, "active_point_cache_index")
+               col = row.column(align=True)
+               col.itemO("ptcache.add_new", icon="ICON_ZOOMIN", text="")
+               col.itemO("ptcache.remove", icon="ICON_ZOOMOUT", text="")
                
                row = layout.row()
                row.itemL(text="File Name:")
@@ -166,37 +173,38 @@ class PARTICLE_PT_cache(ParticleButtonsPanel):
                        
                        layout.itemL(text=cache.info)
                        
-                       split = layout.split()
+                       #split = layout.split()
                        
-                       col = split.column(align=True)
-                       col.itemR(part, "start")
-                       col.itemR(part, "end")
+                       #col = split.column(align=True)
+                       #col.itemR(part, "start")
+                       #col.itemR(part, "end")
 
-                       col = split.column(align=True)
-                       col.itemR(part, "lifetime")
-                       col.itemR(part, "random_lifetime", slider=True)
+                       #col = split.column(align=True)
+                       #col.itemR(part, "lifetime")
+                       #col.itemR(part, "random_lifetime", slider=True)
                else:
                        layout.itemR(cache, "name", text="")
                        
                        row = layout.row()
                
                        if cache.baked == True:
-                               row.itemO("ptcache.free_bake_particle_system", text="Free Bake")
+                               row.itemO("ptcache.free_bake", text="Free Bake")
                        else:
-                               row.item_booleanO("ptcache.cache_particle_system", "bake", True, text="Bake")
+                               row.item_booleanO("ptcache.bake", "bake", True, text="Bake")
                
                        subrow = row.row()
                        subrow.enabled = (cache.frames_skipped or cache.outdated) and particle_panel_enabled(psys)
-                       subrow.itemO("ptcache.cache_particle_system", text="Calculate to Current Frame")
+                       subrow.itemO("ptcache.bake", "bake", False, text="Calculate to Current Frame")
                        
                        row = layout.row()
                        row.enabled = particle_panel_enabled(psys)
-                       row.itemO("ptcache.bake_from_particles_cache", text="Current Cache to Bake")
+                       row.itemO("ptcache.bake_from_cache", text="Current Cache to Bake")
                        row.itemR(cache, "step");
                
                        row = layout.row()
-                       row.enabled = particle_panel_enabled(psys)
-                       row.itemR(cache, "quick_cache")
+                       subrow = row.row()
+                       subrow.enabled = particle_panel_enabled(psys)
+                       subrow.itemR(cache, "quick_cache")
                        row.itemR(cache, "disk_cache")
                
                        layout.itemL(text=cache.info)
@@ -206,7 +214,7 @@ class PARTICLE_PT_cache(ParticleButtonsPanel):
                        row = layout.row()
                        row.item_booleanO("ptcache.bake_all", "bake", True, text="Bake All Dynamics")
                        row.itemO("ptcache.free_bake_all", text="Free All Bakes")
-                       layout.itemO("ptcache.bake_all", text="Update All Dynamics to current frame")
+                       layout.itemO("ptcache.bake_all", "bake", False, text="Update All Dynamics to current frame")
                
                # for particles these are figured out automatically
                #row.itemR(cache, "start_frame")
index 1bd1c507ccf205aaf7868f932100a312e02933b1..0edf099fa9019a3cc1124300dc0a101bff4ef97a 100644 (file)
@@ -85,6 +85,13 @@ class PHYSICS_PT_cloth_cache(PhysicButtonsPanel):
                layout = self.layout
 
                cache = context.cloth.point_cache
+               layout.set_context_pointer("PointCache", cache)
+               
+               row = layout.row()
+               row.template_list(cache, "point_cache_list", cache, "active_point_cache_index")
+               col = row.column(align=True)
+               col.itemO("ptcache.add_new", icon="ICON_ZOOMIN", text="")
+               col.itemO("ptcache.remove", icon="ICON_ZOOMOUT", text="")
                
                row = layout.row()
                row.itemR(cache, "name")
@@ -96,17 +103,17 @@ class PHYSICS_PT_cloth_cache(PhysicButtonsPanel):
                row = layout.row()
                
                if cache.baked == True:
-                       row.itemO("ptcache.free_bake_cloth", text="Free Bake")
+                       row.itemO("ptcache.free_bake", text="Free Bake")
                else:
-                       row.item_booleanO("ptcache.cache_cloth", "bake", True, text="Bake")
+                       row.item_booleanO("ptcache.bake", "bake", True, text="Bake")
                
                subrow = row.row()
                subrow.enabled = cache.frames_skipped or cache.outdated
-               subrow.itemO("ptcache.cache_cloth", text="Calculate to Current Frame")
+               subrow.itemO("ptcache.bake", "bake", False, text="Calculate to Current Frame")
                        
                row = layout.row()
                #row.enabled = particle_panel_enabled(psys)
-               row.itemO("ptcache.bake_from_cloth_cache", text="Current Cache to Bake")
+               row.itemO("ptcache.bake_from_cache", text="Current Cache to Bake")
                row.itemR(cache, "step");
        
                row = layout.row()
@@ -121,7 +128,7 @@ class PHYSICS_PT_cloth_cache(PhysicButtonsPanel):
                row = layout.row()
                row.itemO("ptcache.bake_all", "bake", True, text="Bake All Dynamics")
                row.itemO("ptcache.free_bake_all", text="Free All Bakes")
-               layout.itemO("ptcache.bake_all", text="Update All Dynamics to current frame")
+               layout.itemO("ptcache.bake_all", "bake", False, text="Update All Dynamics to current frame")
                
 class PHYSICS_PT_cloth_collision(PhysicButtonsPanel):
        __label__ = "Cloth Collision"
index c17d6e3bcf9fca7db109c28e6e604ebbef6dea11..d0d3475c11b598329503634dbef4440d1dc411df 100644 (file)
@@ -63,6 +63,13 @@ class PHYSICS_PT_softbody_cache(PhysicButtonsPanel):
                layout = self.layout
 
                cache = context.soft_body.point_cache
+               layout.set_context_pointer("PointCache", cache)
+               
+               row = layout.row()
+               row.template_list(cache, "point_cache_list", cache, "active_point_cache_index")
+               col = row.column(align=True)
+               col.itemO("ptcache.add_new", icon="ICON_ZOOMIN", text="")
+               col.itemO("ptcache.remove", icon="ICON_ZOOMOUT", text="")
                
                row = layout.row()
                row.itemR(cache, "name")
@@ -74,16 +81,16 @@ class PHYSICS_PT_softbody_cache(PhysicButtonsPanel):
                row = layout.row()
                
                if cache.baked == True:
-                       row.itemO("ptcache.free_bake_softbody", text="Free Bake")
+                       row.itemO("ptcache.free_bake", text="Free Bake")
                else:
-                       row.item_booleanO("ptcache.cache_softbody", "bake", True, text="Bake")
+                       row.item_booleanO("ptcache.bake", "bake", True, text="Bake")
                
                sub = row.row()
                sub.enabled = cache.frames_skipped or cache.outdated
-               sub.itemO("ptcache.cache_softbody", text="Calculate to Current Frame")
+               sub.itemO("ptcache.bake", "bake", False, text="Calculate to Current Frame")
                        
                row = layout.row()
-               row.itemO("ptcache.bake_from_softbody_cache", text="Current Cache to Bake")
+               row.itemO("ptcache.bake_from_cache", text="Current Cache to Bake")
                row.itemR(cache, "step");
        
                row = layout.row()
@@ -97,7 +104,7 @@ class PHYSICS_PT_softbody_cache(PhysicButtonsPanel):
                row = layout.row()
                row.itemO("ptcache.bake_all", "bake", True, text="Bake All Dynamics")
                row.itemO("ptcache.free_bake_all", text="Free All Bakes")
-               layout.itemO("ptcache.bake_all", text="Update All Dynamics to current frame")
+               layout.itemO("ptcache.bake_all", "bake", False, text="Update All Dynamics to current frame")
                
 class PHYSICS_PT_softbody_goal(PhysicButtonsPanel):
        __label__ = "Soft Body Goal"
index f3165c959bf1b008b60e9809ee40bf91a9eec41c..bc4585106e6f887a47c0420b2404dd20dd528e0d 100644 (file)
@@ -244,10 +244,6 @@ void cloth_update_normals ( ClothVertex *verts, int nVerts, MFace *face, int tot
 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, 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 8062f807055e0329563a161e3d4cc52ec1748306..a719ab92a80079d2ebe97be980a248309ab79f2a 100644 (file)
@@ -30,6 +30,8 @@
 #define BKE_POINTCACHE_H
 
 #include "DNA_ID.h"
+#include "DNA_object_force.h"
+#include "DNA_boid_types.h"
 
 #include "MEM_guardedalloc.h"
 
@@ -73,42 +75,52 @@ struct ClothModifierData;
 struct PointCache;
 struct ListBase;
 
+/* temp structure for read/write */
+typedef struct PTCacheData {
+       int index;
+       float loc[3];
+       float vel[3];
+       float rot[4];
+       float ave[3];
+       float size;
+       float times[3];
+       struct BoidData boids;
+} PTCacheData;
+
 typedef struct PTCacheFile {
        FILE *fp;
+
+       int totpoint, type;
+       unsigned int data_types;
+
+       struct PTCacheData data;
+       void *cur[BPHYS_TOT_DATA];
 } PTCacheFile;
 
 typedef struct PTCacheID {
        struct PTCacheID *next, *prev;
 
+       struct Scene *scene;
        struct Object *ob;
-       void *data;
+       void *calldata;
        int type;
        int stack_index;
+       unsigned int data_types, info_types;
 
-       struct PointCache *cache;
-} PTCacheID;
-
-typedef struct PTCacheWriter {
-       struct PTCacheID *pid;
-       int cfra;
-       int totelem;
-
-       void (*set_elem)(int index, void *calldata, float *data);
-       void *calldata;
-} PTCacheWriter;
+       int (*write_elem)(int index, void *calldata, void **data);
+       void (*read_elem)(int index, void *calldata, void **data, float frs_sec, float cfra, float *old_data);
+       void (*interpolate_elem)(int index, void *calldata, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data);
 
-typedef struct PTCacheReader {
-       struct Scene *scene;
-       struct PTCacheID *pid;
-       float cfra;
-       int totelem;
+       int (*totpoint)(void *calldata);
+       int (*totwrite)(void *calldata);
 
-       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 (*write_header)(PTCacheFile *pf);
+       int (*read_header)(PTCacheFile *pf);
 
-       int *old_frame;
-} PTCacheReader;
+       struct PointCache *cache;
+       struct PointCache **cache_ptr;
+       struct ListBase *ptcaches;
+} PTCacheID;
 
 typedef struct PTCacheBaker {
        struct Scene *scene;
@@ -123,6 +135,9 @@ typedef struct PTCacheBaker {
        void *progresscontext;
 } PTCacheBaker;
 
+/* Particle functions */
+void BKE_ptcache_make_particle_key(struct ParticleKey *key, int index, void **data, float time);
+
 /* Creating ID's */
 void BKE_ptcache_id_from_softbody(PTCacheID *pid, struct Object *ob, struct SoftBody *sb);
 void BKE_ptcache_id_from_particles(PTCacheID *pid, struct Object *ob, struct ParticleSystem *psys);
@@ -140,30 +155,30 @@ int               BKE_ptcache_id_reset(struct Scene *scene, PTCacheID *id, int mode);
 void   BKE_ptcache_id_time(PTCacheID *pid, struct Scene *scene, float cfra, int *startframe, int *endframe, float *timescale);
 int            BKE_ptcache_object_reset(struct Scene *scene, struct Object *ob, int mode);
 
-/* File reading/writing */
-PTCacheFile    *BKE_ptcache_file_open(PTCacheID *id, int mode, int cfra);
-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);
+int            BKE_ptcache_data_size(int data_type);
+void   BKE_ptcache_data_get(void **data, int type, int index, void *to);
+void   BKE_ptcache_data_set(void **data, int type, void *from);
+int            BKE_ptcache_read_cache(PTCacheID *pid, float cfra, float frs_sec);
+int            BKE_ptcache_write_cache(PTCacheID *pid, int cfra);
 
 /* Continue physics */
 void BKE_ptcache_set_continue_physics(struct Scene *scene, int enable);
 int BKE_ptcache_get_continue_physics(void);
 
 /* Point Cache */
-struct PointCache *BKE_ptcache_add(void);
+struct PointCache *BKE_ptcache_add(struct ListBase *ptcaches);
+void BKE_ptache_free_mem(struct PointCache *cache);
 void BKE_ptcache_free(struct PointCache *cache);
+void BKE_ptcache_free_list(struct ListBase *ptcaches);
 struct PointCache *BKE_ptcache_copy(struct PointCache *cache);
 
 /* Baking */
 void BKE_ptcache_quick_cache_all(struct Scene *scene);
 void BKE_ptcache_make_cache(struct PTCacheBaker* baker);
+void BKE_ptcache_disk_to_mem(struct PTCacheID *pid);
 void BKE_ptcache_toggle_disk_cache(struct PTCacheID *pid);
 
 void BKE_ptcache_load_external(struct PTCacheID *pid);
index 0d9682cf84241f21a6666f56a857881009071e16..d8053281cebad639501f7c550d623514c3a92c55 100644 (file)
@@ -68,8 +68,5 @@ extern void                           sbObjectToSoftbody(struct Object *ob);
 /* pass NULL to unlink again */
 extern void             sbSetInterruptCallBack(int (*f)(void));
 
-/* writing to cache for bake editing */
-extern void                    softbody_write_cache(struct Object *ob, struct SoftBody *soft, int cfra);
-
 #endif
 
index 089dafeb8c798866d4d1433799c585f639a70f1c..3acaaecb1e87fc95a3beb287fdd7d2b198f0e35b 100644 (file)
@@ -340,92 +340,6 @@ void bvhselftree_update_from_cloth(ClothModifierData *clmd, int moving)
        }
 }
 
-int modifiers_indexInObject(Object *ob, ModifierData *md_seek);
-static void cloth_write_state(int index, void *cloth_v, float *data)
-{
-       Cloth *cloth= cloth_v;
-       ClothVertex *vert = cloth->verts + index;
-
-       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, void *cloth_v, float *data)
-{
-       Cloth *cloth= cloth_v;
-       ClothVertex *vert = cloth->verts + index;
-       
-       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, void *cloth_v, float frs_sec, float cfra, float cfra1, float cfra2, float *data1, float *data2)
-{
-       Cloth *cloth= cloth_v;
-       ClothVertex *vert = cloth->verts + index;
-       ParticleKey keys[4];
-       float dfra;
-
-       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);
-
-       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);
-}
-
-int cloth_read_cache(Scene *scene, Object *ob, ClothModifierData *clmd, float cfra, int *old_framenr)
-{
-       PTCacheReader reader;
-       PTCacheID pid;
-       
-       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;
@@ -512,7 +426,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
        PTCacheID pid;
        float timescale;
        int framedelta, framenr, startframe, endframe;
-       int cache_result, old_framenr;
+       int cache_result;
 
        clmd->scene= scene;     /* nice to pass on later :) */
        framenr= (int)scene->r.cfra;
@@ -583,7 +497,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
                return result;
 
        /* try to read from cache */
-       cache_result = cloth_read_cache(scene, ob, clmd, framenr, &old_framenr);
+       cache_result = BKE_ptcache_read_cache(&pid, (float)framenr, scene->r.frs_sec);
 
        if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) {
                cache->flag |= PTCACHE_SIMULATION_VALID;
@@ -600,7 +514,6 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
                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 */
@@ -624,7 +537,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
        else {
                /* if on second frame, write cache for first frame */
                if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0))
-                       cloth_write_cache(ob, clmd, startframe);
+                       BKE_ptcache_write_cache(&pid, startframe);
 
                clmd->sim_parms->timescale *= framenr - cache->simframe;
 
@@ -638,7 +551,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
                        cache->last_exact= 0;
                }
                else
-                       cloth_write_cache(ob, clmd, framenr);
+                       BKE_ptcache_write_cache(&pid, framenr);
 
                cloth_to_object (ob, clmd, result);
        }
index f8795edc87828b7c1c5407bf2a79de4e6f0c6be9..0c975a10c0ae4edd05ee481b2afec1cdb104cafc 100644 (file)
@@ -5893,7 +5893,7 @@ static void clothModifier_initData(ModifierData *md)
        
        clmd->sim_parms = MEM_callocN(sizeof(ClothSimSettings), "cloth sim parms");
        clmd->coll_parms = MEM_callocN(sizeof(ClothCollSettings), "cloth coll parms");
-       clmd->point_cache = BKE_ptcache_add();
+       clmd->point_cache = BKE_ptcache_add(&clmd->ptcaches);
        
        /* check for alloc failing */
        if(!clmd->sim_parms || !clmd->coll_parms || !clmd->point_cache)
@@ -5972,8 +5972,9 @@ static void clothModifier_copyData(ModifierData *md, ModifierData *target)
                MEM_freeN(tclmd->sim_parms);
        if(tclmd->coll_parms)
                MEM_freeN(tclmd->coll_parms);
-       if(tclmd->point_cache)
-               BKE_ptcache_free(tclmd->point_cache);
+       
+       BKE_ptcache_free_list(&tclmd->ptcaches);
+       tclmd->point_cache = NULL;
        
        tclmd->sim_parms = MEM_dupallocN(clmd->sim_parms);
        tclmd->coll_parms = MEM_dupallocN(clmd->coll_parms);
@@ -6001,8 +6002,9 @@ static void clothModifier_freeData(ModifierData *md)
                        MEM_freeN(clmd->sim_parms);
                if(clmd->coll_parms)
                        MEM_freeN(clmd->coll_parms);    
-               if(clmd->point_cache)
-                       BKE_ptcache_free(clmd->point_cache);
+               
+               BKE_ptcache_free_list(&clmd->ptcaches);
+               clmd->point_cache = NULL;
        }
 }
 
index e4f8a484061057e91851ae8ccc1befed1203bb2d..c8aa440e2da1ea9845d0451b95a407280a1afbb3 100644 (file)
@@ -484,8 +484,8 @@ void psys_free(Object *ob, ParticleSystem * psys)
                if(psys->reactevents.first)
                        BLI_freelistN(&psys->reactevents);
 
-               if(psys->pointcache)
-                       BKE_ptcache_free(psys->pointcache);
+               BKE_ptcache_free_list(&psys->ptcaches);
+               psys->pointcache = NULL;
                
                if(psys->targets.first)
                        BLI_freelistN(&psys->targets);
@@ -980,13 +980,13 @@ static void get_pointcache_keys_for_time(Object *ob, ParticleSystem *psys, int i
                        while(pm && pm->next && (float)pm->frame < t)
                                pm = pm->next;
 
-                       copy_particle_key(key2, ((ParticleKey *)pm->data) + index, 1);
-                       copy_particle_key(key1, ((ParticleKey *)(pm->prev)->data) + index, 1);
+                       BKE_ptcache_make_particle_key(key2, pm->index_array ? pm->index_array[index] : index, pm->data, (float)pm->frame);
+                       BKE_ptcache_make_particle_key(key1, pm->prev->index_array ? pm->prev->index_array[index] : index, pm->prev->data, (float)pm->prev->frame);
                }
                else if(cache->mem_cache.first) {
                        PTCacheMem *pm2 = cache->mem_cache.first;
-                       copy_particle_key(key2, ((ParticleKey *)pm2->data) + index, 1);
-                       copy_particle_key(key1, ((ParticleKey *)pm2->data) + index, 1);
+                       BKE_ptcache_make_particle_key(key2, pm2->index_array ? pm2->index_array[index] : index, pm2->data, (float)pm2->frame);
+                       copy_particle_key(key1, key2, 1);
                }
        }
 }
@@ -3038,7 +3038,7 @@ void object_add_particle_system(Scene *scene, Object *ob)
                psys->flag &= ~PSYS_CURRENT;
 
        psys = MEM_callocN(sizeof(ParticleSystem), "particle_system");
-       psys->pointcache = BKE_ptcache_add();
+       psys->pointcache = BKE_ptcache_add(&psys->ptcaches);
        BLI_addtail(&ob->particlesystem, psys);
 
        psys->part = psys_new_settings("ParticleSettings", NULL);
index b5d58e9db8c69c4412bd2a03acd7c2fd3384a699..2f4a5c28385cbaac26e1e9b7eade750fd25371fd 100644 (file)
@@ -2260,43 +2260,14 @@ void psys_get_reactor_target(Object *ob, ParticleSystem *psys, Object **target_o
 void psys_make_temp_pointcache(Object *ob, ParticleSystem *psys)
 {
        PointCache *cache = psys->pointcache;
-       PTCacheFile *pf = NULL;
-       PTCacheMem *pm = NULL;
        PTCacheID pid;
-       int cfra, sfra = cache->startframe, efra = cache->endframe;
-       int totelem = psys->totpart;
-       int float_count = sizeof(ParticleKey) / sizeof(float);
-       int tot = totelem * float_count;
 
        if((cache->flag & PTCACHE_DISK_CACHE)==0 || cache->mem_cache.first)
                return;
 
        BKE_ptcache_id_from_particles(&pid, ob, psys);
 
-       for(cfra=sfra; cfra <= efra; cfra++) {
-               pf = BKE_ptcache_file_open(&pid, PTCACHE_FILE_READ, cfra);
-
-               if(pf) {
-                       pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache temp mem");
-                       pm->data = MEM_callocN(sizeof(float)*tot, "Pointcache temp mem data");
-
-                       if(fread(pm->data, sizeof(float), tot, pf->fp)!= tot) {
-                               printf("Error reading from disk cache\n");
-
-                               MEM_freeN(pm->data);
-                               MEM_freeN(pm);
-                               BKE_ptcache_file_close(pf);
-                               return;
-                       }
-
-                       pm->frame = cfra;
-                       pm->totpoint = totelem;
-
-                       BLI_addtail(&cache->mem_cache, pm);
-
-                       BKE_ptcache_file_close(pf);
-               }
-       }
+       BKE_ptcache_disk_to_mem(&pid);
 }
 void psys_clear_temp_pointcache(ParticleSystem *psys)
 {
@@ -2305,11 +2276,7 @@ void psys_clear_temp_pointcache(ParticleSystem *psys)
        if((psys->pointcache->flag & PTCACHE_DISK_CACHE)==0)
                return;
 
-       for(; pm; pm=pm->next) {
-               MEM_freeN(pm->data);
-       }
-
-       BLI_freelistN(&psys->pointcache->mem_cache);
+       BKE_ptache_free_mem(psys->pointcache);
 }
 void psys_get_pointcache_start_end(Scene *scene, ParticleSystem *psys, int *sfra, int *efra)
 {
@@ -2318,88 +2285,6 @@ 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 void particle_write_state(int index, void *psys_ptr, float *data)
-{
-       ParticleSystem *psys= psys_ptr;
-       
-       memcpy(data, (float *)(&(psys->particles+index)->state), sizeof(ParticleKey));
-}
-static void particle_read_state(int index, void *psys_ptr, float *data)
-{
-       ParticleSystem *psys= psys_ptr;
-       ParticleData *pa = psys->particles + index;
-       ParticleKey *key = (ParticleKey *)data;
-
-       if(key->time > pa->state.time)
-               copy_particle_key(&pa->prev_state, &pa->state, 1);
-
-       copy_particle_key(&pa->state, key, 1);
-}
-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;
-
-       cfra = MIN2(cfra, pa->dietime);
-       cfra1 = MIN2(cfra1, pa->dietime);
-       cfra2 = MIN2(cfra2, pa->dietime);
-
-       keys[1] = *((ParticleKey*)data1);
-       keys[2] = *((ParticleKey*)data2);
-
-       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, (cfra - cfra1) / dfra, &pa->state, 1);
-       QuatInterpol(pa->state.rot, keys[1].rot,keys[2].rot, (cfra - cfra1) / dfra);
-
-       VecMulf(pa->state.vel, frs_sec / dfra);
-
-       pa->state.time = cfra;
-}
-static void write_particles_to_cache(Object *ob, ParticleSystem *psys, int cfra)
-{
-       PTCacheWriter writer;
-       PTCacheID pid;
-
-       BKE_ptcache_id_from_particles(&pid, ob, psys);
-
-       writer.calldata = psys;
-       writer.cfra = cfra;
-       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 *old_frame)
-{
-       PTCacheReader reader;
-       PTCacheID pid;
-       
-       BKE_ptcache_id_from_particles(&pid, ob, psys);
-
-       reader.calldata = psys;
-       reader.cfra = cfra;
-       reader.interpolate_elem = particle_cache_interpolate;
-       reader.old_frame = old_frame;
-       reader.pid = &pid;
-       reader.scene = scene;
-       reader.set_elem = particle_read_state;
-       reader.totelem = psys->totpart;
-
-       return BKE_ptcache_read_cache(&reader);
-}
 
 /************************************************/
 /*                     Effectors                                                       */
@@ -4237,7 +4122,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
        int totpart, oldtotpart, totchild, oldtotchild, p;
        float disp, *vg_vel= 0, *vg_tan= 0, *vg_rot= 0, *vg_size= 0;
        int init= 0, distr= 0, alloc= 0, usecache= 0, only_children_changed= 0;
-       int framenr, framedelta, startframe, endframe, old_framenr;
+       int framenr, framedelta, startframe, endframe;
 
        part= psys->part;
        cache= psys->pointcache;
@@ -4327,8 +4212,10 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
                        if(alloc) {
                                realloc_particles(ob, psys, totpart);
 
-                               if(usecache && !only_children_changed)
+                               if(usecache && !only_children_changed) {
                                        BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0);
+                                       BKE_ptcache_id_from_particles(&pid, ob, psys);
+                               }
                        }
 
                        if(!only_children_changed)
@@ -4358,7 +4245,7 @@ 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, &old_framenr);
+               int result = BKE_ptcache_read_cache(&pid, cfra, scene->r.frs_sec);
 
                if(result == PTCACHE_READ_EXACT || result == PTCACHE_READ_INTERPOLATED) {
                        cached_step(scene, ob, psmd, psys, cfra);
@@ -4369,14 +4256,12 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
                        cache->flag |= PTCACHE_SIMULATION_VALID;
 
                        if(result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED)
-                               write_particles_to_cache(ob, psys, cfra);
+                               BKE_ptcache_write_cache(&pid, (int)cfra);
 
                        return;
                }
                else if(result==PTCACHE_READ_OLD) {
-                       /* set old cfra */
-                       psys->cfra = (float)old_framenr;
-
+                       psys->cfra = (float)cache->simframe;
                        for(p=0, pa=psys->particles; p<totpart; p++, pa++) {
                                /* update alive status */
                                if(pa->time > psys->cfra)
@@ -4402,7 +4287,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
 
        /* if on second frame, write cache for first frame */
        if(usecache && psys->cfra == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0))
-               write_particles_to_cache(ob, psys, startframe);
+               BKE_ptcache_write_cache(&pid, startframe);
 
        if(part->phystype==PART_PHYS_KEYED)
                psys_count_keyed_targets(ob,psys);
@@ -4448,7 +4333,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
 
        /* only write cache starting from second frame */
        if(usecache && framenr != startframe)
-               write_particles_to_cache(ob, psys, framenr);
+               BKE_ptcache_write_cache(&pid, (int)cfra);
 
        /* for keyed particles the path is allways known so it can be drawn */
        if(part->phystype==PART_PHYS_KEYED) {
index beb72c2c13fa556b27cc1b844346fe67bf63b9a0..7aa01de71d0785436c84f11e38c3eb78e5bfa262 100644 (file)
 #endif
 #endif
 
-/* Creating ID's */
+static void ptcache_data_to(void **data, int type, int index, void *to);
+static void ptcache_data_from(void **data, int type, void *from);
+
+/* Common functions */
+static int ptcache_read_basic_header(PTCacheFile *pf)
+{
+       int error=0;
+
+       /* Custom functions should read these basic elements too! */
+       if(!error && !fread(&pf->totpoint, sizeof(int), 1, pf->fp))
+               error = 1;
+       
+       if(!error && !fread(&pf->data_types, sizeof(int), 1, pf->fp))
+               error = 1;
+
+       return !error;
+}
+static int ptcache_write_basic_header(PTCacheFile *pf)
+{
+       /* Custom functions should write these basic elements too! */
+       if(!fwrite(&pf->totpoint, sizeof(int), 1, pf->fp))
+               return 0;
+       
+       if(!fwrite(&pf->data_types, sizeof(int), 1, pf->fp))
+               return 0;
+
+       return 1;
+}
+/* Softbody functions */
+static int ptcache_write_softbody(int index, void *soft_v, void **data)
+{
+       SoftBody *soft= soft_v;
+       BodyPoint *bp = soft->bpoint + index;
+
+       ptcache_data_from(data, BPHYS_DATA_LOCATION, bp->pos);
+       ptcache_data_from(data, BPHYS_DATA_VELOCITY, bp->vec);
+
+       return 1;
+}
+static void ptcache_read_softbody(int index, void *soft_v, void **data, float frs_sec, float cfra, float *old_data)
+{
+       SoftBody *soft= soft_v;
+       BodyPoint *bp = soft->bpoint + index;
+
+       if(old_data) {
+               memcpy(bp->pos, data, 3 * sizeof(float));
+               memcpy(bp->vec, data + 3, 3 * sizeof(float));
+       }
+       else {
+               ptcache_data_to(data, BPHYS_DATA_LOCATION, 0, bp->pos);
+               ptcache_data_to(data, BPHYS_DATA_VELOCITY, 0, bp->vec);
+       }
+}
+static void ptcache_interpolate_softbody(int index, void *soft_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data)
+{
+       SoftBody *soft= soft_v;
+       BodyPoint *bp = soft->bpoint + index;
+       ParticleKey keys[4];
+       float dfra;
+
+       if(cfra1 == cfra2)
+               return;
+
+       VECCOPY(keys[1].co, bp->pos);
+       VECCOPY(keys[1].vel, bp->vec);
+
+       if(old_data) {
+               memcpy(keys[2].co, old_data, 3 * sizeof(float));
+               memcpy(keys[2].vel, old_data + 3, 3 * sizeof(float));
+       }
+       else
+               BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
+
+       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);
+
+       VECCOPY(bp->pos, keys->co);
+       VECCOPY(bp->vec, keys->vel);
+}
+static int ptcache_totpoint_softbody(void *soft_v)
+{
+       SoftBody *soft= soft_v;
+       return soft->totpoint;
+}
+/* Particle functions */
+static int ptcache_write_particle(int index, void *psys_v, void **data)
+{
+       ParticleSystem *psys= psys_v;
+       ParticleData *pa = psys->particles + index;
+       float times[3] = {pa->time, pa->dietime, pa->lifetime};
+
+       if(data[BPHYS_DATA_INDEX]) {
+               int step = psys->pointcache->step;
+               /* No need to store unborn or died particles */
+               if(pa->time - step > pa->state.time || pa->dietime + step < pa->state.time)
+                       return 0;
+       }
+       
+       ptcache_data_from(data, BPHYS_DATA_INDEX, &index);
+       ptcache_data_from(data, BPHYS_DATA_LOCATION, pa->state.co);
+       ptcache_data_from(data, BPHYS_DATA_VELOCITY, pa->state.vel);
+       ptcache_data_from(data, BPHYS_DATA_ROTATION, pa->state.rot);
+       ptcache_data_from(data, BPHYS_DATA_AVELOCITY, pa->state.ave);
+       ptcache_data_from(data, BPHYS_DATA_SIZE, &pa->size);
+       ptcache_data_from(data, BPHYS_DATA_TIMES, times);
+
+       if(pa->boid)
+               ptcache_data_from(data, BPHYS_DATA_TIMES, &pa->boid);
+
+       return 1;
+}
+void BKE_ptcache_make_particle_key(ParticleKey *key, int index, void **data, float time)
+{
+       ptcache_data_to(data, BPHYS_DATA_LOCATION, index, key->co);
+       ptcache_data_to(data, BPHYS_DATA_VELOCITY, index, key->vel);
+       ptcache_data_to(data, BPHYS_DATA_ROTATION, index, key->rot);
+       ptcache_data_to(data, BPHYS_DATA_AVELOCITY, index, key->ave);
+       key->time = time;
+}
+static void ptcache_read_particle(int index, void *psys_v, void **data, float frs_sec, float cfra, float *old_data)
+{
+       ParticleSystem *psys= psys_v;
+       ParticleData *pa = psys->particles + index;
+
+       if(cfra > pa->state.time)
+               memcpy(&pa->prev_state, &pa->state, sizeof(ParticleKey));
+
+       if(old_data){
+               /* old format cache */
+               memcpy(&pa->state, old_data, sizeof(ParticleKey));
+               return;
+       }
+
+       BKE_ptcache_make_particle_key(&pa->state, 0, data, cfra);
+
+       if(data[BPHYS_DATA_SIZE])
+               ptcache_data_to(data, BPHYS_DATA_SIZE, 0, &pa->size);
+       
+       if(data[BPHYS_DATA_TIMES]) {
+               float times[3];
+               ptcache_data_to(data, BPHYS_DATA_TIMES, 0, &times);
+               pa->time = times[0];
+               pa->dietime = times[1];
+               pa->lifetime = times[2];
+       }
+
+       if(pa->boid)
+               ptcache_data_to(data, BPHYS_DATA_BOIDS, 0, &pa->boid);
+
+       /* determine velocity from previous location */
+       if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) {
+               if(cfra > pa->prev_state.time) {
+                       VecSubf(pa->state.vel, pa->state.co, pa->prev_state.co);
+                       VecMulf(pa->state.vel, (cfra - pa->prev_state.time) / frs_sec);
+               }
+               else {
+                       VecSubf(pa->state.vel, pa->prev_state.co, pa->state.co);
+                       VecMulf(pa->state.vel, (pa->prev_state.time - cfra) / frs_sec);
+               }
+       }
+
+       /* determine rotation from velocity */
+       if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) {
+               vectoquat(pa->state.vel, OB_POSX, OB_POSZ, pa->state.rot);
+       }
+}
+static void ptcache_interpolate_particle(int index, void *psys_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data)
+{
+       ParticleSystem *psys= psys_v;
+       ParticleData *pa = psys->particles + index;
+       ParticleKey keys[4];
+       float dfra;
 
+       cfra = MIN2(cfra, pa->dietime);
+       cfra1 = MIN2(cfra1, pa->dietime);
+       cfra2 = MIN2(cfra2, pa->dietime);
+
+       if(cfra1 == cfra2)
+               return;
+
+       memcpy(keys+1, &pa->state, sizeof(ParticleKey));
+       if(old_data)
+               memcpy(keys+2, old_data, sizeof(ParticleKey));
+       else
+               BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
+
+       dfra = cfra2 - cfra1;
+
+       VecMulf(keys[1].vel, dfra / frs_sec);
+       VecMulf(keys[2].vel, dfra / frs_sec);
+
+       psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1);
+       QuatInterpol(pa->state.rot, keys[1].rot,keys[2].rot, (cfra - cfra1) / dfra);
+
+       VecMulf(pa->state.vel, frs_sec / dfra);
+
+       pa->state.time = cfra;
+}
+
+static int ptcache_totpoint_particle(void *psys_v)
+{
+       ParticleSystem *psys = psys_v;
+       return psys->totpart;
+}
+static int ptcache_totwrite_particle(void *psys_v)
+{
+       ParticleSystem *psys = psys_v;
+       int totwrite = 0;
+
+       /* TODO for later */
+       //if((psys->part->flag & (PART_UNBORN|PART_DIED))==0) {
+       //      ParticleData *pa= psys->particles;
+       //      int p, step = psys->pointcache->step;
+
+       //      for(p=0; p<psys->totpart; p++,pa++)
+       //              totwrite += (pa->time - step > pa->state.time || pa->dietime + step > pa->state.time);
+       //}
+       //else
+               totwrite= psys->totpart;
+
+       return totwrite;
+}
+/* Cloth functions */
+static int ptcache_write_cloth(int index, void *cloth_v, void **data)
+{
+       ClothModifierData *clmd= cloth_v;
+       Cloth *cloth= clmd->clothObject;
+       ClothVertex *vert = cloth->verts + index;
+
+       ptcache_data_from(data, BPHYS_DATA_LOCATION, vert->x);
+       ptcache_data_from(data, BPHYS_DATA_VELOCITY, vert->v);
+       ptcache_data_from(data, BPHYS_DATA_XCONST, vert->xconst);
+
+       return 1;
+}
+static void ptcache_read_cloth(int index, void *cloth_v, void **data, float frs_sec, float cfra, float *old_data)
+{
+       ClothModifierData *clmd= cloth_v;
+       Cloth *cloth= clmd->clothObject;
+       ClothVertex *vert = cloth->verts + index;
+       
+       if(old_data) {
+               memcpy(vert->x, data, 3 * sizeof(float));
+               memcpy(vert->xconst, data + 3, 3 * sizeof(float));
+               memcpy(vert->v, data + 6, 3 * sizeof(float));
+       }
+       else {
+               ptcache_data_to(data, BPHYS_DATA_LOCATION, 0, vert->x);
+               ptcache_data_to(data, BPHYS_DATA_VELOCITY, 0, vert->v);
+               ptcache_data_to(data, BPHYS_DATA_XCONST, 0, vert->xconst);
+       }
+}
+static void ptcache_interpolate_cloth(int index, void *cloth_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data)
+{
+       ClothModifierData *clmd= cloth_v;
+       Cloth *cloth= clmd->clothObject;
+       ClothVertex *vert = cloth->verts + index;
+       ParticleKey keys[4];
+       float dfra;
+
+       if(cfra1 == cfra2)
+               return;
+
+       VECCOPY(keys[1].co, vert->x);
+       VECCOPY(keys[1].vel, vert->v);
+
+       if(old_data) {
+               memcpy(keys[2].co, old_data, 3 * sizeof(float));
+               memcpy(keys[2].vel, old_data + 6, 3 * sizeof(float));
+       }
+       else
+               BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
+
+       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);
+
+       VECCOPY(vert->x, keys->co);
+       VECCOPY(vert->v, keys->vel);
+
+       /* should vert->xconst be interpolated somehow too? - jahka */
+}
+
+static int ptcache_totpoint_cloth(void *cloth_v)
+{
+       ClothModifierData *clmd= cloth_v;
+       return clmd->clothObject->numverts;
+}
+/* Creating ID's */
 void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb)
 {
        ParticleSystemModifierData *psmd;
@@ -88,9 +386,22 @@ void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb)
        memset(pid, 0, sizeof(PTCacheID));
 
        pid->ob= ob;
-       pid->data= sb;
+       pid->calldata= sb;
        pid->type= PTCACHE_TYPE_SOFTBODY;
        pid->cache= sb->pointcache;
+       pid->cache_ptr= &sb->pointcache;
+       pid->ptcaches= &sb->ptcaches;
+       pid->totpoint= pid->totwrite= ptcache_totpoint_softbody;
+
+       pid->write_elem= ptcache_write_softbody;
+       pid->read_elem= ptcache_read_softbody;
+       pid->interpolate_elem= ptcache_interpolate_softbody;
+
+       pid->write_header= ptcache_write_basic_header;
+       pid->read_header= ptcache_read_basic_header;
+
+       pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY);
+       pid->info_types= 0;
 
        if(sb->particles) {
                psmd= psys_get_modifier(ob, sb->particles);
@@ -113,10 +424,39 @@ void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *p
        memset(pid, 0, sizeof(PTCacheID));
 
        pid->ob= ob;
-       pid->data= psys;
+       pid->calldata= psys;
        pid->type= PTCACHE_TYPE_PARTICLES;
        pid->stack_index= modifiers_indexInObject(ob, (ModifierData *)psmd);
        pid->cache= psys->pointcache;
+       pid->cache_ptr= &psys->pointcache;
+       pid->ptcaches= &psys->ptcaches;
+
+       pid->write_elem= ptcache_write_particle;
+       pid->read_elem= ptcache_read_particle;
+       pid->interpolate_elem= ptcache_interpolate_particle;
+
+       pid->totpoint= ptcache_totpoint_particle;
+       pid->totwrite= ptcache_totwrite_particle;
+
+       pid->write_header= ptcache_write_basic_header;
+       pid->read_header= ptcache_read_basic_header;
+
+       pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY);
+
+       /* TODO for later */
+       //if((psys->part->flag & (PART_UNBORN|PART_DIED))==0)
+       //      pid->data_types|= (1<<BPHYS_DATA_INDEX);
+
+       if(psys->part->phystype == PART_PHYS_BOIDS)
+               pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION) | (1<<BPHYS_DATA_BOIDS);
+
+       if(psys->part->rotmode || psys->part->avemode)
+               pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION);
+
+       if(psys->part->flag & PART_ROT_DYN)
+               pid->data_types|= (1<<BPHYS_DATA_ROTATION);
+
+       pid->info_types= (1<<BPHYS_DATA_TIMES);
 }
 
 void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *clmd)
@@ -124,10 +464,23 @@ void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *cl
        memset(pid, 0, sizeof(PTCacheID));
 
        pid->ob= ob;
-       pid->data= clmd;
+       pid->calldata= clmd;
        pid->type= PTCACHE_TYPE_CLOTH;
        pid->stack_index= modifiers_indexInObject(ob, (ModifierData *)clmd);
        pid->cache= clmd->point_cache;
+       pid->cache_ptr= &clmd->point_cache;
+       pid->ptcaches= &clmd->ptcaches;
+       pid->totpoint= pid->totwrite= ptcache_totpoint_cloth;
+
+       pid->write_elem= ptcache_write_cloth;
+       pid->read_elem= ptcache_read_cloth;
+       pid->interpolate_elem= ptcache_interpolate_cloth;
+
+       pid->write_header= ptcache_write_basic_header;
+       pid->read_header= ptcache_read_basic_header;
+
+       pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_XCONST);
+       pid->info_types= 0;
 }
 
 void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob)
@@ -165,6 +518,9 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob)
        }
 }
 
+
+/* File handling */
+
 /*     Takes an Object ID and returns a unique name
        - id: object id
        - cfra: frame for the cache, can be negative
@@ -258,7 +614,7 @@ static int BKE_ptcache_id_filename(PTCacheID *pid, char *filename, int cfra, sho
 }
 
 /* youll need to close yourself after! */
-PTCacheFile *BKE_ptcache_file_open(PTCacheID *pid, int mode, int cfra)
+static PTCacheFile *ptcache_file_open(PTCacheID *pid, int mode, int cfra)
 {
        PTCacheFile *pf;
        FILE *fp = NULL;
@@ -291,381 +647,490 @@ PTCacheFile *BKE_ptcache_file_open(PTCacheID *pid, int mode, int cfra)
        return pf;
 }
 
-void BKE_ptcache_file_close(PTCacheFile *pf)
+static void ptcache_file_close(PTCacheFile *pf)
 {
        fclose(pf->fp);
        MEM_freeN(pf);
 }
 
-int BKE_ptcache_file_read_floats(PTCacheFile *pf, float *f, int tot)
+static int ptcache_file_read(PTCacheFile *pf, void *f, int tot, int size)
 {
-       return (fread(f, sizeof(float), tot, pf->fp) == tot);
+       return (fread(f, size, tot, pf->fp) == tot);
 }
-
-int BKE_ptcache_file_write_floats(PTCacheFile *pf, float *f, int tot)
+static int ptcache_file_write(PTCacheFile *pf, void *f, int tot, int size)
 {
-       return (fwrite(f, sizeof(float), tot, pf->fp) == tot);
+       return (fwrite(f, size, tot, pf->fp) == tot);
 }
-
-static int ptcache_pid_elemsize(PTCacheID *pid)
+static int ptcache_file_read_data(PTCacheFile *pf)
 {
-       if(pid->type==PTCACHE_TYPE_SOFTBODY)
-               return 6 * sizeof(float);
-       else if(pid->type==PTCACHE_TYPE_PARTICLES)
-               return sizeof(ParticleKey);
-       else if(pid->type==PTCACHE_TYPE_CLOTH)
-               return 9 * sizeof(float);
+       int i;
 
-       return 0;
-}
-static int ptcache_pid_totelem(PTCacheID *pid)
-{
-       if(pid->type==PTCACHE_TYPE_SOFTBODY) {
-               SoftBody *soft = pid->data;
-               return soft->totpoint;
-       }
-       else if(pid->type==PTCACHE_TYPE_PARTICLES) {
-               ParticleSystem *psys = pid->data;
-               return psys->totpart;
+       for(i=0; i<BPHYS_TOT_DATA; i++) {
+               if(pf->data_types & (1<<i) && !ptcache_file_read(pf, pf->cur[i], 1, BKE_ptcache_data_size(i)))
+                       return 0;
        }
-       else if(pid->type==PTCACHE_TYPE_CLOTH) {
-               ClothModifierData *clmd = pid->data;
-               return clmd->clothObject->numverts;
+       
+       return 1;
+}
+static int ptcache_file_write_data(PTCacheFile *pf)
+{              
+       int i;
+
+       for(i=0; i<BPHYS_TOT_DATA; i++) {
+               if(pf->data_types & (1<<i) && !ptcache_file_write(pf, pf->cur[i], 1, BKE_ptcache_data_size(i)))
+                       return 0;
        }
+       
+       return 1;
+}
+static int ptcache_file_read_header_begin(PTCacheFile *pf)
+{
+       int error=0;
+       char bphysics[8];
+       
+       pf->data_types = 0;
+       
+       if(fread(bphysics, sizeof(char), 8, pf->fp) != 8)
+               error = 1;
+       
+       if(!error && strncmp(bphysics, "BPHYSICS", 8))
+               error = 1;
 
-       return 0;
+       if(!error && !fread(&pf->type, sizeof(int), 1, pf->fp))
+               error = 1;
+       
+       /* if there was an error set file as it was */
+       if(error)
+               fseek(pf->fp, 0, SEEK_SET);
+
+       return !error;
 }
 
-void BKE_ptcache_update_info(PTCacheID *pid)
+
+static int ptcache_file_write_header_begin(PTCacheFile *pf)
 {
-       PointCache *cache = pid->cache;
-       int totframes = 0;
-       char mem_info[64];
+       char *bphysics = "BPHYSICS";
+       
+       if(fwrite(bphysics, sizeof(char), 8, pf->fp) != 8)
+               return 0;
 
-       if(cache->flag & PTCACHE_EXTERNAL) {
-               int cfra = cache->startframe;
+       if(!fwrite(&pf->type, sizeof(int), 1, pf->fp))
+               return 0;
+       
+       return 1;
+}
 
-               for(; cfra<=cache->endframe; cfra++) {
-                       if(BKE_ptcache_id_exist(pid, cfra))
-                               totframes++;
-               }
 
-               if(totframes)
-                       sprintf(cache->info, "%i points read for %i frames", cache->totpoint, totframes);
+/* Data pointer handling */
+int BKE_ptcache_data_size(int data_type)
+{
+       switch(data_type) {
+               case BPHYS_DATA_INDEX:
+                       return sizeof(int);
+               case BPHYS_DATA_LOCATION:
+               case BPHYS_DATA_VELOCITY:
+               case BPHYS_DATA_AVELOCITY: /* also BPHYS_DATA_XCONST */
+               case BPHYS_DATA_TIMES:
+                       return 3 * sizeof(float);
+               case BPHYS_DATA_ROTATION:
+                       return 4 * sizeof(float);
+               case BPHYS_DATA_SIZE:
+                       return sizeof(float);
+               case BPHYS_DATA_BOIDS:
+                       return sizeof(BoidData);
+               default:
+                       return 0;
+       }
+}
+static void ptcache_data_to(void **data, int type, int index, void *to)
+{
+       if(data[type]) {
+               if(index)
+                       memcpy(to, (char*)data[type] + index * BKE_ptcache_data_size(type), BKE_ptcache_data_size(type));
                else
-                       sprintf(cache->info, "No valid data to read!");
-               return;
+                       memcpy(to, data[type], BKE_ptcache_data_size(type));
        }
+}
 
-       if(cache->flag & PTCACHE_DISK_CACHE) {
-               int cfra = cache->startframe;
+static void ptcache_data_from(void **data, int type, void *from)
+{
+       if(data[type])
+               memcpy(data[type], from, BKE_ptcache_data_size(type));
+}
 
-               for(; cfra<=cache->endframe; cfra++) {
-                       if(BKE_ptcache_id_exist(pid, cfra))
-                               totframes++;
-               }
+static void ptcache_file_init_pointers(PTCacheFile *pf)
+{
+       int data_types = pf->data_types;
+
+       pf->cur[BPHYS_DATA_INDEX] =             data_types & (1<<BPHYS_DATA_INDEX) ?            &pf->data.index : NULL;
+       pf->cur[BPHYS_DATA_LOCATION] =  data_types & (1<<BPHYS_DATA_LOCATION) ?         &pf->data.loc   : NULL;
+       pf->cur[BPHYS_DATA_VELOCITY] =  data_types & (1<<BPHYS_DATA_VELOCITY) ?         &pf->data.vel   : NULL;
+       pf->cur[BPHYS_DATA_ROTATION] =  data_types & (1<<BPHYS_DATA_ROTATION) ?         &pf->data.rot   : NULL;
+       pf->cur[BPHYS_DATA_AVELOCITY] = data_types & (1<<BPHYS_DATA_AVELOCITY) ?        &pf->data.ave   : NULL;
+       pf->cur[BPHYS_DATA_SIZE] =              data_types & (1<<BPHYS_DATA_SIZE)       ?               &pf->data.size  : NULL;
+       pf->cur[BPHYS_DATA_TIMES] =             data_types & (1<<BPHYS_DATA_TIMES) ?            &pf->data.times : NULL;
+       pf->cur[BPHYS_DATA_BOIDS] =             data_types & (1<<BPHYS_DATA_BOIDS) ?            &pf->data.boids : NULL;
+}
 
-               sprintf(mem_info, "%i frames on disk", totframes);
-       }
-       else {
-               PTCacheMem *pm = cache->mem_cache.first;                
-               float framesize = 0.0f, bytes = 0.0f;
-               int mb;
+static void ptcache_mem_init_pointers(PTCacheMem *pm)
+{
+       int data_types = pm->data_types;
+       int i;
 
-               if(pm)
-                       framesize = (float)ptcache_pid_elemsize(pid) * (float)pm->totpoint;
-               
-               for(; pm; pm=pm->next)
-                       totframes++;
+       for(i=0; i<BPHYS_TOT_DATA; i++)
+               pm->cur[i] = data_types & (1<<i) ? pm->data[i] : NULL;
+}
 
-               bytes = totframes * framesize;
+static void ptcache_mem_incr_pointers(PTCacheMem *pm)
+{
+       int i;
 
-               mb = (bytes > 1024.0f * 1024.0f);
+       for(i=0; i<BPHYS_TOT_DATA; i++) {
+               if(pm->cur[i])
+                       pm->cur[i] = (char*)pm->cur[i] + BKE_ptcache_data_size(i);
+       }
+}
+static void ptcache_alloc_data(PTCacheMem *pm)
+{
+       int data_types = pm->data_types;
+       int totpoint = pm->totpoint;
+       int i;
 
-               sprintf(mem_info, "%i frames in memory (%.1f %s)",
-                       totframes,
-                       bytes / (mb ? 1024.0f * 1024.0f : 1024.0f),
-                       mb ? "Mb" : "kb");
+       for(i=0; i<BPHYS_TOT_DATA; i++) {
+               if(data_types & (1<<i))
+                       pm->data[i] = MEM_callocN(totpoint * BKE_ptcache_data_size(i), "PTCache Data");
        }
+}
+static void ptcache_free_data(void *data[])
+{
+       int i;
 
-       if(cache->flag & PTCACHE_OUTDATED) {
-               sprintf(cache->info, "%s, cache is outdated!", mem_info);
+       for(i=0; i<BPHYS_TOT_DATA; i++) {
+               if(data[i])
+                       MEM_freeN(data[i]);
        }
-       else if(cache->flag & PTCACHE_FRAMES_SKIPPED) {
-               sprintf(cache->info, "%s, not exact since frame %i.", mem_info, cache->last_exact);
+}
+static void ptcache_copy_data(void *from[], void *to[])
+{
+       int i;
+       for(i=0; i<BPHYS_TOT_DATA; i++) {
+               if(from[i])
+                       memcpy(to[i], from[i], BKE_ptcache_data_size(i));
        }
-       else
-               sprintf(cache->info, "%s.", mem_info);
 }
+
+
+
+static int ptcache_pid_old_elemsize(PTCacheID *pid)
+{
+       if(pid->type==PTCACHE_TYPE_SOFTBODY)
+               return 6 * sizeof(float);
+       else if(pid->type==PTCACHE_TYPE_PARTICLES)
+               return sizeof(ParticleKey);
+       else if(pid->type==PTCACHE_TYPE_CLOTH)
+               return 9 * sizeof(float);
+
+       return 0;
+}
+
 /* reads cache from disk or memory */
 /* possible to get old or interpolated result */
-int BKE_ptcache_read_cache(PTCacheReader *reader)
+int BKE_ptcache_read_cache(PTCacheID *pid, float cfra, float frs_sec)
 {
-       PTCacheID *pid = reader->pid;
        PTCacheFile *pf=NULL, *pf2=NULL;
        PTCacheMem *pm=NULL, *pm2=NULL;
-       int totelem = reader->totelem;
-       float cfra = reader->cfra;
+       float old_data1[14], old_data2[14];
        int cfrai = (int)cfra;
-       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;
+       int old_elemsize = ptcache_pid_old_elemsize(pid);
+       int i, incr = old_elemsize / sizeof(float);
 
-       if(totelem == 0)
-               return 0;
+       int cfra1 = 0, cfra2 = 0;
+       int totpoint = 0, totpoint2 = 0;
+       int *index = &i, *index2 = &i;
+       int use_old = 0, old_frame;
 
+       int ret = 0, error = 0;
 
-       /* first check if we have the actual frame cached */
-       if(cfra == (float)cfrai) {
-               if(pid->cache->flag & PTCACHE_DISK_CACHE) {
-                       pf= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
-               }
-               else {
-                       pm = pid->cache->mem_cache.first;
+       /* nothing to read to */
+       if(pid->totpoint(pid->calldata) == 0)
+               return 0;
 
-                       for(; pm; pm=pm->next) {
-                               if(pm->frame == cfrai)
-                                       break;
-                       }
-               }
+       if(pid->cache->flag & PTCACHE_READ_INFO) {
+               pid->cache->flag &= ~PTCACHE_READ_INFO;
+               BKE_ptcache_read_cache(pid, 0, frs_sec);
        }
 
-       /* if found, use exact frame */
-       if(pf || pm) {
-               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);
-                                       MEM_freeN(data);
-                                       return 0;
-                               }
-
-                               reader->set_elem(i, reader->calldata, data);
-                       }
-                       else {
-                               reader->set_elem(i, reader->calldata, data);
-                               data += incr;
-                       }
+       /* first check if we have the actual frame cached */
+       if(cfra == (float)cfrai) {
+               if(pid->cache->flag & PTCACHE_DISK_CACHE) {
+                       pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
                }
+               else {
+                       pm = pid->cache->mem_cache.first;
 
-               if(pf) {
-                       BKE_ptcache_file_close(pf);
-                       pf = NULL;
-                       MEM_freeN(data);
+                       for(; pm; pm=pm->next) {
+                               if(pm->frame == cfrai)
+                                       break;
+                       }
                }
-
-               ret = PTCACHE_READ_EXACT;
        }
 
-       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(!pm && !pf) {
+               if(pid->cache->flag & PTCACHE_DISK_CACHE) {
+                       pf=NULL;
+                       while(cfrai > pid->cache->startframe && !pf) {
+                               cfrai--;
+                               pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
+                               cfra1 = cfrai;
+                       }
 
-               if(reader->old_frame)
-                       *(reader->old_frame) = cfrai;
+                       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= ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
+                               cfra2 = cfrai;
+                       }
+
+                       if(pf && !pf2) {
+                               pf2 = pf;
+                               pf = NULL;
+                       }
                }
-       }
-       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(reader->old_frame)
-                               *(reader->old_frame) = pm->frame;
-                       cfra1 = pm->frame;
-               }
+                       if(pm) {
+                               old_frame = pm->frame;
+                               cfra1 = pm->frame;
+                       }
 
-               pm2 = pid->cache->mem_cache.last;
+                       pm2 = pid->cache->mem_cache.last;
 
-               if(pm2 && pm2->frame < cfra)
-                       pm2 = NULL;
-               else {
-                       while(pm2->prev && pm2->prev->frame > cfra)
-                               pm2= pm2->prev;
+                       if(pm2 && pm2->frame < cfra)
+                               pm2 = NULL;
+                       else {
+                               while(pm2->prev && pm2->prev->frame > cfra)
+                                       pm2= pm2->prev;
+
+                               if(pm2)
+                                       cfra2 = pm2->frame;
+                       }
 
-                       if(pm2)
-                               cfra2 = pm2->frame;
+                       if(pm && !pm2) {
+                               pm2 = pm;
+                               pm = NULL;
+                       }
                }
        }
 
-       if(ret)
-               ;
-       else if((pf && pf2) || (pm && pm2)) {
-               /* interpolate from nearest frames if cache isn't outdated */
-               float *data1, *data2;
+       if(!pm && !pm2 && !pf && !pf2)
+               return 0;
 
-               if(pm) {
-                       data1 = pm->data;
-                       data2 = pm2->data;
+       if(pm) {
+               ptcache_mem_init_pointers(pm);
+               totpoint = pm->totpoint;
+               index = pm->data_types & (1<<BPHYS_DATA_INDEX) ? pm->cur[BPHYS_DATA_INDEX] : &i;
+       }
+       if(pm2) {
+               ptcache_mem_init_pointers(pm2);
+               totpoint2 = pm2->totpoint;
+               index2 = pm2->data_types & (1<<BPHYS_DATA_INDEX) ? pm2->cur[BPHYS_DATA_INDEX] : &i;
+       }
+       if(pf) {
+               if(ptcache_file_read_header_begin(pf)) {
+                       if(pf->type != pid->type) {
+                               /* todo report error */
+                               ptcache_file_close(pf);
+                               pf = NULL;
+                       }
+                       else if(pid->read_header(pf)) {
+                               ptcache_file_init_pointers(pf);
+                               totpoint = pf->totpoint;
+                               index = pf->data_types & BPHYS_DATA_INDEX ? &pf->data.index : &i;
+                       }
                }
                else {
-                       data1 = MEM_callocN(elemsize, "pointcache read data1");
-                       data2 = MEM_callocN(elemsize, "pointcache read data2");
+                       /* fall back to old cache file format */
+                       use_old = 1;
+                       totpoint = pid->totpoint(pid->calldata);
                }
-
-               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, (float)cfra1, (float)cfra2, data1, data2);
+       }
+       if(pf2) {
+               if(ptcache_file_read_header_begin(pf2)) {
+                       if(pf2->type != pid->type) {
+                               /* todo report error */
+                               ptcache_file_close(pf2);
+                               pf2 = NULL;
                        }
-                       else {
-                               reader->interpolate_elem(i, reader->calldata, frs_sec, cfra, (float)cfra1, (float)cfra2, data1, data2);
-                               data1 += incr;
-                               data2 += incr;
+                       else if(pid->read_header(pf2)) {
+                               ptcache_file_init_pointers(pf2);
+                               totpoint2 = pf2->totpoint;
+                               index2 = pf->data_types & BPHYS_DATA_INDEX ? &pf2->data.index : &i;
                        }
                }
-
-               if(pf) {
-                       BKE_ptcache_file_close(pf);
-                       pf = NULL;
-                       BKE_ptcache_file_close(pf2);
-                       pf2 = NULL;
-                       MEM_freeN(data1);
-                       MEM_freeN(data2);
+               else {
+                       /* fall back to old cache file format */
+                       use_old = 1;
+                       totpoint2 = pid->totpoint(pid->calldata);
                }
-
-               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);
+       /* don't read old cache if allready simulated past cached frame */
+       if(!pm && !pf && cfra1 && cfra1 <= pid->cache->simframe)
+               error = 1;
+       if(cfra1 && cfra1==cfra2)
+               error = 1;
 
-                       return 0;
+       totpoint = MIN2(totpoint, pid->totpoint(pid->calldata));
+       totpoint2 = MIN2(totpoint2, pid->totpoint(pid->calldata));
+
+       if(!error) for(i=0; i<totpoint; i++) {
+               /* read old cache file format */
+               if(use_old) {
+                       if(ptcache_file_read(pf, (void*)old_data1, 1, old_elemsize))
+                               pid->read_elem(i, pid->calldata, NULL, frs_sec, cfra, old_data1);
+                       else
+                               { error = 1; break; }
+               }
+               else {
+                       if(pm || ptcache_file_read_data(pf))
+                               pid->read_elem(*index, pid->calldata, pm ? pm->cur : pf->cur, frs_sec, cfra1 ? (float)cfra1 : (float)cfrai, NULL);
+                       else
+                               { error = 1; break; }
                }
 
-               if(pm)
-                       data = pm->data;
-               else
-                       data = MEM_callocN(elemsize, "pointcache read data");
+               if(pm) {
+                       ptcache_mem_incr_pointers(pm);
+                       index = pm->data_types & (1<<BPHYS_DATA_INDEX) ? pm->cur[BPHYS_DATA_INDEX] : &i;
+               }
+       }
 
-               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);
+       if(!error) for(i=0; i<totpoint2; i++) {
+               /* read old cache file format */
+               if(use_old) {
+                       if(ptcache_file_read(pf2, (void*)old_data2, 1, old_elemsize)) {
+                               if(!pf && pf2)
+                                       pid->read_elem(i, pid->calldata, NULL, frs_sec, (float)cfra2, old_data2);
+                               else
+                                       pid->interpolate_elem(i, pid->calldata, NULL, frs_sec, cfra, (float)cfra1, (float)cfra2, old_data2);
                        }
-                       else {
-                               reader->set_elem(i, reader->calldata, data);
-                               data += incr;
+                       else
+                               { error = 1; break; }
+               }
+               else {
+                       if(pm2 || ptcache_file_read_data(pf2)) {
+                               if((!pf && pf2) || (!pm && pm2))
+                                       pid->read_elem(*index2, pid->calldata, pm2 ? pm2->cur : pf2->cur, frs_sec, (float)cfra2, NULL);
+                               else
+                                       pid->interpolate_elem(*index2, pid->calldata, pm2 ? pm2->cur : pf2->cur, frs_sec, cfra, (float)cfra1, (float)cfra2, NULL);
                        }
+                       else
+                               { error = 1; break; }
                }
 
-               if(pf) {
-                       BKE_ptcache_file_close(pf);
-                       pf = NULL;
-                       MEM_freeN(data);
-               }
-               if(pf2) {
-                       BKE_ptcache_file_close(pf2);
-                       pf = NULL;
+               if(pm2) {
+                       ptcache_mem_incr_pointers(pm2);
+                       index2 = pm2->data_types & (1<<BPHYS_DATA_INDEX) ? pm2->cur[BPHYS_DATA_INDEX] : &i;
                }
+       }
 
+       if(pm || pf)
+               ret = (pm2 || pf2) ? PTCACHE_READ_INTERPOLATED : PTCACHE_READ_EXACT;
+       else if(pm2 || pf2) {
                ret = PTCACHE_READ_OLD;
+               pid->cache->simframe = old_frame;
        }
 
-       if(pf)
-               BKE_ptcache_file_close(pf);
-       if(pf2)
-               BKE_ptcache_file_close(pf2);
+       if(pf) {
+               ptcache_file_close(pf);
+               pf = NULL;
+       }
+
+       if(pf2) {
+               ptcache_file_close(pf2);
+               pf = NULL;
+       }
 
        if((pid->cache->flag & PTCACHE_QUICK_CACHE)==0) {
+               cfrai = (int)cfra;
                /* 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);
+                       BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, cfrai);
                }
                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));
+                       BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfrai,pid->cache->last_exact));
                }
        }
 
-       return ret;
+       return (error ? 0 : ret);
 }
+/* TODO for later */
+//static void ptcache_make_index_array(PTCacheMem *pm, int totpoint)
+//{
+//     int i, *index;
+//
+//     if(pm->index_array) {
+//             MEM_freeN(pm->index_array);
+//             pm->index_array = NULL;
+//     }
+//
+//     if(!pm->data[BPHYS_DATA_INDEX])
+//             return;
+//
+//     pm->index_array = MEM_callocN(totpoint * sizeof(int), "PTCacheMem index_array");
+//     index = pm->data[BPHYS_DATA_INDEX];
+//
+//     for(i=0; i<pm->totpoint; i++, index++)
+//             pm->index_array[*index] = i;
+//}
 /* writes cache to disk or memory */
-int BKE_ptcache_write_cache(PTCacheWriter *writer)
+int BKE_ptcache_write_cache(PTCacheID *pid, int cfra)
 {
-       PointCache *cache = writer->pid->cache;
+       PointCache *cache = pid->cache;
        PTCacheFile *pf= NULL;
-       int elemsize = ptcache_pid_elemsize(writer->pid);
+       int elemsize = ptcache_pid_old_elemsize(pid);
        int i, incr = elemsize / sizeof(float);
+       int totpoint = pid->totpoint(pid->calldata);
        int add = 0, overwrite = 0;
-       float temp[14];
 
-       if(writer->totelem == 0 || writer->cfra <= 0)
+       if(totpoint == 0 || cfra < 0
+               || (cfra ? pid->data_types == 0 : pid->info_types == 0))
                return 0;
 
        if(cache->flag & PTCACHE_DISK_CACHE) {
-               int cfra = cache->endframe;
+               int efra = cache->endframe;
 
+               if(cfra==0)
+                       add = 1;
                /* allways start from scratch on the first frame */
-               if(writer->cfra == cache->startframe) {
-                       BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_ALL, writer->cfra);
+               else if(cfra == cache->startframe) {
+                       BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, cfra);
                        cache->flag &= ~PTCACHE_REDO_NEEDED;
                        add = 1;
                }
                else {
-                       int ocfra;
+                       int ofra;
                        /* find last cached frame */
-                       while(cfra > cache->startframe && !BKE_ptcache_id_exist(writer->pid, cfra))
-                               cfra--;
+                       while(efra > cache->startframe && !BKE_ptcache_id_exist(pid, efra))
+                               efra--;
 
                        /* find second last cached frame */
-                       ocfra = cfra-1;
-                       while(ocfra > cache->startframe && !BKE_ptcache_id_exist(writer->pid, ocfra))
-                               ocfra--;
+                       ofra = efra-1;
+                       while(ofra > cache->startframe && !BKE_ptcache_id_exist(pid, ofra))
+                               ofra--;
 
-                       if(cfra >= cache->startframe && writer->cfra > cfra) {
-                               if(ocfra >= cache->startframe && cfra - ocfra < cache->step)
+                       if(efra >= cache->startframe && cfra > efra) {
+                               if(ofra >= cache->startframe && efra - ofra < cache->step)
                                        overwrite = 1;
                                else
                                        add = 1;
@@ -674,74 +1139,87 @@ int BKE_ptcache_write_cache(PTCacheWriter *writer)
 
                if(add || overwrite) {
                        if(overwrite)
-                               BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_FRAME, cfra);
+                               BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, efra);
 
-                       pf = BKE_ptcache_file_open(writer->pid, PTCACHE_FILE_WRITE, writer->cfra);
+                       pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, 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);
+                       pf->type = pid->type;
+                       pf->totpoint = cfra ? totpoint : pid->totwrite(pid->calldata);
+                       pf->data_types = cfra ? pid->data_types : pid->info_types;
+
+                       if(!ptcache_file_write_header_begin(pf) || !pid->write_header(pf)) {
+                               ptcache_file_close(pf);
+                               return 0;
+                       }
+
+                       ptcache_file_init_pointers(pf);
+
+                       for(i=0; i<totpoint; i++) {
+                               if(pid->write_elem(i, pid->calldata, pf->cur))
+                                       if(!ptcache_file_write_data(pf)) {
+                                               ptcache_file_close(pf);
+                                               return 0;
+                                       }
                        }
                }
        }
        else {
                PTCacheMem *pm;
                PTCacheMem *pm2;
-               float *pmdata;
 
                pm2 = cache->mem_cache.first;
                
+               /* don't write info file in memory */
+               if(cfra==0)
+                       return 1;
                /* allways start from scratch on the first frame */
-               if(writer->cfra == cache->startframe) {
-                       BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_ALL, writer->cfra);
+               if(cfra == cache->startframe) {
+                       BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, cfra);
                        cache->flag &= ~PTCACHE_REDO_NEEDED;
                        add = 1;
                }
-               else {
+               else if (cache->mem_cache.last) {
                        pm2 = cache->mem_cache.last;
 
-                       if(pm2 && writer->cfra > pm2->frame) {
+                       if(pm2 && cfra > pm2->frame) {
                                if(pm2->prev && pm2->frame - pm2->prev->frame < cache->step)
                                        overwrite = 1;
                                else
                                        add = 1;
                        }
                }
+               else
+                       add = 1;
 
-               if(overwrite) {
-                       pm = cache->mem_cache.last;
-                       pmdata = pm->data;
-
-                       for(i=0; i<writer->totelem; i++, pmdata+=incr) {
-                               writer->set_elem(i, writer->calldata, temp);
-                               memcpy(pmdata, temp, elemsize);
-                       }
+               if(add || overwrite) {
+                       if(overwrite)
+                               BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, pm2->frame);
 
-                       pm->frame = writer->cfra;
-               }
-               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->totpoint = pid->totwrite(pid->calldata);
+                       pm->data_types = cfra ? pid->data_types : pid->info_types;
 
-                       pm->frame = writer->cfra;
-                       pm->totpoint = writer->totelem;
+                       ptcache_alloc_data(pm);
+                       ptcache_mem_init_pointers(pm);
 
+                       for(i=0; i<totpoint; i++) {
+                               if(pid->write_elem(i, pid->calldata, pm->cur))
+                                       ptcache_mem_incr_pointers(pm);
+                       }
+                       //ptcache_make_index_array(pm, pid->totpoint(pid->calldata));
+
+                       pm->frame = cfra;
                        BLI_addtail(&cache->mem_cache, pm);
                }
        }
 
        if(add || overwrite) {
-               if(writer->cfra - cache->last_exact == 1
-                       || writer->cfra == cache->startframe) {
-                       cache->last_exact = writer->cfra;
+               if(cfra - cache->last_exact == 1
+                       || cfra == cache->startframe) {
+                       cache->last_exact = cfra;
                        cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
                }
                else
@@ -749,9 +1227,9 @@ int BKE_ptcache_write_cache(PTCacheWriter *writer)
        }
        
        if(pf)
-               BKE_ptcache_file_close(pf);
+               ptcache_file_close(pf);
 
-       BKE_ptcache_update_info(writer->pid);
+       BKE_ptcache_update_info(pid);
 
        return 1;
 }
@@ -759,7 +1237,7 @@ int BKE_ptcache_write_cache(PTCacheWriter *writer)
  * mode - PTCACHE_CLEAR_ALL, 
 
 */
-
+/* Clears & resets */
 void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra)
 {
        int len; /* store the length of the string */
@@ -833,7 +1311,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra)
                        if(mode == PTCACHE_CLEAR_ALL) {
                                pid->cache->last_exact = 0;
                                for(; pm; pm=pm->next)
-                                       MEM_freeN(pm->data);
+                                       ptcache_free_data(pm->data);
                                BLI_freelistN(&pid->cache->mem_cache);
                        } else {
                                while(pm) {
@@ -841,7 +1319,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra)
                                        (mode==PTCACHE_CLEAR_AFTER && pm->frame > cfra) ) {
                                                link = pm;
                                                pm = pm->next;
-                                               MEM_freeN(link->data);
+                                               ptcache_free_data(link->data);
                                                BLI_freelinkN(&pid->cache->mem_cache, link);
                                        }
                                        else
@@ -863,7 +1341,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra)
 
                        for(; pm; pm=pm->next) {
                                if(pm->frame == cfra) {
-                                       MEM_freeN(pm->data);
+                                       ptcache_free_data(pm->data);
                                        BLI_freelinkN(&pid->cache->mem_cache, pm);
                                        break;
                                }
@@ -985,11 +1463,11 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
                cache->last_exact= 0;
 
                if(pid->type == PTCACHE_TYPE_CLOTH)
-                       cloth_free_modifier(pid->ob, pid->data);
+                       cloth_free_modifier(pid->ob, pid->calldata);
                else if(pid->type == PTCACHE_TYPE_SOFTBODY)
-                       sbFreeSimulation(pid->data);
+                       sbFreeSimulation(pid->calldata);
                else if(pid->type == PTCACHE_TYPE_PARTICLES)
-                       psys_reset(pid->data, PSYS_RESET_DEPSGRAPH);
+                       psys_reset(pid->calldata, PSYS_RESET_DEPSGRAPH);
        }
        if(clear)
                BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
@@ -1107,9 +1585,9 @@ int BKE_ptcache_get_continue_physics()
        return CONTINUE_PHYSICS;
 }
 
-/* Point Cache */
+/* Point Cache handling */
 
-PointCache *BKE_ptcache_add()
+PointCache *BKE_ptcache_add(ListBase *ptcaches)
 {
        PointCache *cache;
 
@@ -1118,21 +1596,39 @@ PointCache *BKE_ptcache_add()
        cache->endframe= 250;
        cache->step= 10;
 
+       BLI_addtail(ptcaches, cache);
+
        return cache;
 }
 
-void BKE_ptcache_free(PointCache *cache)
+void BKE_ptache_free_mem(PointCache *cache)
 {
        PTCacheMem *pm = cache->mem_cache.first;
+
        if(pm) {
-               for(; pm; pm=pm->next)
-                       MEM_freeN(pm->data);
+               for(; pm; pm=pm->next) {
+                       ptcache_free_data(pm->data);
+                       if(pm->index_array)
+                               MEM_freeN(pm->index_array);
+               }
 
                BLI_freelistN(&cache->mem_cache);
        }
-
+}
+void BKE_ptcache_free(PointCache *cache)
+{
+       BKE_ptache_free_mem(cache);
        MEM_freeN(cache);
 }
+void BKE_ptcache_free_list(ListBase *ptcaches)
+{
+       PointCache *cache = ptcaches->first;
+
+       for(; cache; cache=cache->next)
+               BKE_ptache_free_mem(cache);
+
+       BLI_freelistN(ptcaches);
+}
 
 PointCache *BKE_ptcache_copy(PointCache *cache)
 {
@@ -1227,7 +1723,7 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
                cache = pid->cache;
                if((cache->flag & PTCACHE_BAKED)==0) {
                        if(pid->type==PTCACHE_TYPE_PARTICLES)
-                               psys_get_pointcache_start_end(scene, pid->data, &cache->startframe, &cache->endframe);
+                               psys_get_pointcache_start_end(scene, pid->calldata, &cache->startframe, &cache->endframe);
 
                        if(bake || cache->flag & PTCACHE_REDO_NEEDED)
                                BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
@@ -1253,12 +1749,12 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
                        cache = pid->cache;
                        if((cache->flag & PTCACHE_BAKED)==0) {
                                if(pid->type==PTCACHE_TYPE_PARTICLES) {
-                                       ParticleSystem *psys = (ParticleSystem*)pid->data;
+                                       ParticleSystem *psys = (ParticleSystem*)pid->calldata;
                                        /* skip hair & keyed particles */
                                        if(psys->part->type == PART_HAIR || psys->part->phystype == PART_PHYS_KEYED)
                                                continue;
 
-                                       psys_get_pointcache_start_end(scene, pid->data, &cache->startframe, &cache->endframe);
+                                       psys_get_pointcache_start_end(scene, pid->calldata, &cache->startframe, &cache->endframe);
                                }
 
                                if((cache->flag & PTCACHE_REDO_NEEDED || (cache->flag & PTCACHE_SIMULATION_VALID)==0)
@@ -1285,10 +1781,10 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
        scene->r.framelen = 1.0;
 
        for(; CFRA <= endframe; CFRA+=step) {
-               float prog;
+               int prog;
 
                if(bake)
-                       prog = (int)(100.0 * (float)(CFRA - startframe)/(float)(endframe-startframe));
+                       prog = (int)(100.0f * (float)(CFRA - startframe)/(float)(endframe-startframe));
                else
                        prog = CFRA;
 
@@ -1307,15 +1803,19 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
        if(pid) {
                cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED);
                cache->flag |= PTCACHE_SIMULATION_VALID;
-               if(bake)
+               if(bake) {
                        cache->flag |= PTCACHE_BAKED;
+                       /* write info file */
+                       if(cache->flag & PTCACHE_DISK_CACHE)
+                               BKE_ptcache_write_cache(pid, 0);
+               }
        }
        else for(base=scene->base.first; base; base= base->next) {
                BKE_ptcache_ids_from_object(&pidlist, base->object);
 
                for(pid=pidlist.first; pid; pid=pid->next) {
                        /* skip hair particles */
-                       if(pid->type==PTCACHE_TYPE_PARTICLES && ((ParticleSystem*)pid->data)->part->type == PART_HAIR)
+                       if(pid->type==PTCACHE_TYPE_PARTICLES && ((ParticleSystem*)pid->calldata)->part->type == PART_HAIR)
                                continue;
                
                        cache = pid->cache;
@@ -1327,8 +1827,11 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
 
                        cache->flag |= PTCACHE_SIMULATION_VALID;
 
-                       if(bake)
+                       if(bake) {
                                cache->flag |= PTCACHE_BAKED;
+                               if(cache->flag & PTCACHE_DISK_CACHE)
+                                       BKE_ptcache_write_cache(pid, 0);
+                       }
                }
                BLI_freelistN(&pidlist);
        }
@@ -1341,97 +1844,141 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
 
        /* TODO: call redraw all windows somehow */
 }
-
-void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) {
+/* Helpers */
+void BKE_ptcache_disk_to_mem(PTCacheID *pid)
+{
        PointCache *cache = pid->cache;
        PTCacheFile *pf;
        PTCacheMem *pm;
-       int totelem=0;
-       int float_count=0;
-       int tot;
-       int last_exact = cache->last_exact;
 
-       if (!G.relbase_valid){
-               cache->flag &= ~PTCACHE_DISK_CACHE;
-               printf("File must be saved before using disk cache!\n");
-               return;
-       }
+       int cfra, sfra = cache->startframe, efra = cache->endframe;
+       int i;
 
-       totelem = ptcache_pid_totelem(pid);
-       float_count = ptcache_pid_elemsize(pid) / sizeof(float);
+       BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
 
-       if(totelem==0 || float_count==0)
-               return;
+       for(cfra=sfra; cfra <= efra; cfra++) {
+               pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra);
 
-       tot = totelem*float_count;
+               if(pf) {
+                       if(!ptcache_file_read_header_begin(pf)) {
+                               printf("Can't yet convert old cache format\n");
+                               cache->flag |= PTCACHE_DISK_CACHE;
+                               ptcache_file_close(pf);
+                               return;
+                       }
 
-       /* MEM -> DISK */
-       if(cache->flag & PTCACHE_DISK_CACHE) {
-               pm = cache->mem_cache.first;
+                       if(pf->type != pid->type || !pid->read_header(pf)) {
+                               cache->flag |= PTCACHE_DISK_CACHE;
+                               ptcache_file_close(pf);
+                               return;
+                       }
+                       
+                       pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
 
-               BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
+                       pm->totpoint = pf->totpoint;
+                       pm->data_types = pf->data_types;
+                       pm->frame = cfra;
 
-               for(; pm; pm=pm->next) {
-                       pf = BKE_ptcache_file_open(pid, PTCACHE_FILE_WRITE, pm->frame);
+                       ptcache_alloc_data(pm);
+                       ptcache_mem_init_pointers(pm);
+                       ptcache_file_init_pointers(pf);
 
-                       if(pf) {
-                               if(fwrite(pm->data, sizeof(float), tot, pf->fp) != tot) {
-                                       printf("Error writing to disk cache\n");
+                       for(i=0; i<pm->totpoint; i++) {
+                               if(!ptcache_file_read_data(pf)) {
+                                       printf("Error reading from disk cache\n");
                                        
-                                       cache->flag &= ~PTCACHE_DISK_CACHE;
+                                       cache->flag |= PTCACHE_DISK_CACHE;
+                                       
+                                       ptcache_free_data(pm->data);
+                                       MEM_freeN(pm);
+                                       ptcache_file_close(pf);
 
-                                       BKE_ptcache_file_close(pf);
                                        return;
                                }
-                               BKE_ptcache_file_close(pf);
+                               ptcache_copy_data(pf->cur, pm->cur);
+                               ptcache_mem_incr_pointers(pm);
                        }
-                       else
-                               printf("Error creating disk cache file\n");
-               }
 
-               cache->flag &= ~PTCACHE_DISK_CACHE;
-               BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
-               cache->flag |= PTCACHE_DISK_CACHE;
+                       //ptcache_make_index_array(pm, pid->totpoint(pid->calldata));
+
+                       BLI_addtail(&pid->cache->mem_cache, pm);
+
+                       ptcache_file_close(pf);
+               }
        }
-       /* DISK -> MEM */
-       else {
-               int cfra;
-               int sfra = cache->startframe;
-               int efra = cache->endframe;
 
-               BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
+}
+void BKE_ptcache_mem_to_disk(PTCacheID *pid)
+{
+       PointCache *cache = pid->cache;
+       PTCacheFile *pf;
+       PTCacheMem *pm;
+       int i;
 
-               for(cfra=sfra; cfra <= efra; cfra++) {
-                       pf = BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfra);
+       pm = cache->mem_cache.first;
 
-                       if(pf) {
-                               pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
-                               pm->data = MEM_callocN(sizeof(float)*tot, "Pointcache mem data");
+       BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
 
-                               if(fread(pm->data, sizeof(float), tot, pf->fp)!= tot) {
-                                       printf("Error reading from disk cache\n");
+       for(; pm; pm=pm->next) {
+               pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, pm->frame);
 
-                                       cache->flag |= PTCACHE_DISK_CACHE;
+               if(pf) {
+                       pf->data_types = pm->data_types;
+                       pf->totpoint = pm->totpoint;
+                       pf->type = pid->type;
 
-                                       MEM_freeN(pm->data);
-                                       MEM_freeN(pm);
-                                       BKE_ptcache_file_close(pf);
-                                       return;
-                               }
+                       ptcache_mem_init_pointers(pm);
+                       ptcache_file_init_pointers(pf);
 
-                               pm->frame = cfra;
-                               pm->totpoint = totelem;
+                       if(!ptcache_file_write_header_begin(pf) || !pid->write_header(pf)) {
+                               printf("Error writing to disk cache\n");
+                               cache->flag &= ~PTCACHE_DISK_CACHE;
 
-                               BLI_addtail(&pid->cache->mem_cache, pm);
+                               ptcache_file_close(pf);
+                               return;
+                       }
+
+                       for(i=0; i<pm->totpoint; i++) {
+                               ptcache_copy_data(pm->cur, pf->cur);
+                               if(!ptcache_file_write_data(pf)) {
+                                       printf("Error writing to disk cache\n");
+                                       cache->flag &= ~PTCACHE_DISK_CACHE;
 
-                               BKE_ptcache_file_close(pf);
+                                       ptcache_file_close(pf);
+                                       return;
+                               }
+                               ptcache_mem_incr_pointers(pm);
                        }
+
+                       ptcache_file_close(pf);
+
+                       /* write info file */
+                       if(cache->flag & PTCACHE_BAKED)
+                               BKE_ptcache_write_cache(pid, 0);
                }
+               else
+                       printf("Error creating disk cache file\n");
+       }
+}
+void BKE_ptcache_toggle_disk_cache(PTCacheID *pid)
+{
+       PointCache *cache = pid->cache;
+       int last_exact = cache->last_exact;
 
-               cache->flag |= PTCACHE_DISK_CACHE;
-               BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
+       if (!G.relbase_valid){
                cache->flag &= ~PTCACHE_DISK_CACHE;
+               printf("File must be saved before using disk cache!\n");
+               return;
        }
+
+       if(cache->flag & PTCACHE_DISK_CACHE)
+               BKE_ptcache_mem_to_disk(pid);
+       else
+               BKE_ptcache_disk_to_mem(pid);
+
+       cache->flag ^= PTCACHE_DISK_CACHE;
+       BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
+       cache->flag ^= PTCACHE_DISK_CACHE;
        
        cache->last_exact = last_exact;
 
@@ -1440,15 +1987,16 @@ void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) {
 
 void BKE_ptcache_load_external(PTCacheID *pid)
 {
+       /*todo*/
        PointCache *cache = pid->cache;
        int len; /* store the length of the string */
+       int info = 0;
 
        /* mode is same as fopen's modes */
        DIR *dir; 
        struct dirent *de;
        char path[MAX_PTCACHE_PATH];
        char filename[MAX_PTCACHE_FILE];
-       char path_full[MAX_PTCACHE_FILE];
        char ext[MAX_PTCACHE_PATH];
 
        if(!cache)
@@ -1482,8 +2030,12 @@ void BKE_ptcache_load_external(PTCacheID *pid)
                                        BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
                                        frame = atoi(num);
 
-                                       cache->startframe = MIN2(cache->startframe, frame);
-                                       cache->endframe = MAX2(cache->endframe, frame);
+                                       if(frame) {
+                                               cache->startframe = MIN2(cache->startframe, frame);
+                                               cache->endframe = MAX2(cache->endframe, frame);
+                                       }
+                                       else
+                                               info = 1;
                                }
                        }
                }
@@ -1492,18 +2044,36 @@ void BKE_ptcache_load_external(PTCacheID *pid)
 
        if(cache->startframe != MAXFRAME) {
                PTCacheFile *pf;
-               int elemsize = ptcache_pid_elemsize(pid);
-               int     incr = elemsize / sizeof(float);
-               float *data = NULL;
-               pf= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cache->startframe);
 
-               if(pf) {
-                       data = MEM_callocN(elemsize, "pointcache read data");
-                       while(BKE_ptcache_file_read_floats(pf, data, incr))
-                               cache->totpoint++;
-                       
-                       BKE_ptcache_file_close(pf);
-                       MEM_freeN(data);
+               /* read totpoint from info file (frame 0) */
+               if(info) {
+                       pf= ptcache_file_open(pid, PTCACHE_FILE_READ, 0);
+
+                       if(pf) {
+                               if(ptcache_file_read_header_begin(pf)) {
+                                       if(pf->type == pid->type && pid->read_header(pf)) {
+                                               cache->totpoint = pf->totpoint;
+                                               cache->flag |= PTCACHE_READ_INFO;
+                                       }
+                                       else {
+                                               cache->totpoint = 0;
+                                       }
+                               }
+                               ptcache_file_close(pf);
+                       }
+               }
+               /* or from any old format cache file */
+               else {
+                       float old_data[14];
+                       int elemsize = ptcache_pid_old_elemsize(pid);
+                       pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cache->startframe);
+
+                       if(pf) {
+                               while(ptcache_file_read(pf, old_data, 1, elemsize))
+                                       cache->totpoint++;
+                               
+                               ptcache_file_close(pf);
+                       }
                }
        }
 
@@ -1511,3 +2081,65 @@ void BKE_ptcache_load_external(PTCacheID *pid)
 
        BKE_ptcache_update_info(pid);
 }
+
+void BKE_ptcache_update_info(PTCacheID *pid)
+{
+       PointCache *cache = pid->cache;
+       int totframes = 0;
+       char mem_info[64];
+
+       if(cache->flag & PTCACHE_EXTERNAL) {
+               int cfra = cache->startframe;
+
+               for(; cfra<=cache->endframe; cfra++) {
+                       if(BKE_ptcache_id_exist(pid, cfra))
+                               totframes++;
+               }
+
+               if(totframes && cache->totpoint)
+                       sprintf(cache->info, "%i points found!", cache->totpoint);
+               else
+                       sprintf(cache->info, "No valid data to read!");
+               return;
+       }
+
+       if(cache->flag & PTCACHE_DISK_CACHE) {
+               int cfra = cache->startframe;
+
+               for(; cfra<=cache->endframe; cfra++) {
+                       if(BKE_ptcache_id_exist(pid, cfra))
+                               totframes++;
+               }
+
+               sprintf(mem_info, "%i frames on disk", totframes);
+       }
+       else {
+               PTCacheMem *pm = cache->mem_cache.first;                
+               float framesize = 0.0f, bytes = 0.0f;
+               int mb;
+
+               if(pm)
+                       framesize = (float)ptcache_pid_old_elemsize(pid) * (float)pm->totpoint;
+               
+               for(; pm; pm=pm->next)
+                       totframes++;
+
+               bytes = totframes * framesize;
+
+               mb = (bytes > 1024.0f * 1024.0f);
+
+               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);
+}
\ No newline at end of file
index 0a1963c84f2a649ed27f4fff46337faf394f1c40..68f918b0c68a5065e4b3a9d6fd2eec14793ebc7b 100644 (file)
@@ -3687,87 +3687,6 @@ static void softbody_to_object(Object *ob, float (*vertexCos)[3], int numVerts,
        }
 }
 
-static void softbody_write_state(int index, void *soft_v, float *data)
-{
-       SoftBody *soft= soft_v;
-       BodyPoint *bp = soft->bpoint + index;
-
-       memcpy(data, bp->pos, 3 * sizeof(float));
-       memcpy(data + 3, bp->vec, 3 * sizeof(float));
-}
-static void softbody_read_state(int index, void *soft_v, float *data)
-{
-       SoftBody *soft= soft_v;
-       BodyPoint *bp = soft->bpoint + index;
-       
-       memcpy(bp->pos, data, 3 * sizeof(float));
-       memcpy(bp->vec, data + 3, 3 * sizeof(float));
-}
-static void softbody_cache_interpolate(int index, void *soft_v, float frs_sec, float cfra, float cfra1, float cfra2, float *data1, float *data2)
-{
-       SoftBody *soft= soft_v;
-       BodyPoint *bp = soft->bpoint + index;
-       ParticleKey keys[4];
-       float dfra;
-
-       if(cfra1 == cfra2) {
-               softbody_read_state(index, soft, data1);
-               return;
-       }
-
-       memcpy(keys[1].co, data1, 3 * sizeof(float));
-       memcpy(keys[1].vel, data1 + 3, 3 * sizeof(float));
-
-       memcpy(keys[2].co, data2, 3 * sizeof(float));
-       memcpy(keys[2].vel, data2 + 3, 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(bp->pos, keys->co, 3 * sizeof(float));
-       memcpy(bp->vec, keys->vel, 3 * sizeof(float));
-}
-void softbody_write_cache(Object *ob, SoftBody *soft, int cfra)
-{
-       PTCacheWriter writer;
-       PTCacheID pid;
-
-       BKE_ptcache_id_from_softbody(&pid, ob, soft);
-
-       writer.calldata = soft;
-       writer.cfra = cfra;
-       writer.set_elem = softbody_write_state;
-       writer.pid = &pid;
-       writer.totelem = soft->totpoint;
-
-       BKE_ptcache_write_cache(&writer);
-}
-
-int softbody_read_cache(Scene *scene, Object *ob, SoftBody *soft, float cfra, int *old_framenr)
-{
-       PTCacheReader reader;
-       PTCacheID pid;
-       
-       BKE_ptcache_id_from_softbody(&pid, ob, soft);
-
-       reader.calldata = soft;
-       reader.cfra = cfra;
-       reader.interpolate_elem = softbody_cache_interpolate;
-       reader.old_frame = old_framenr;
-       reader.pid = &pid;
-       reader.scene = scene;
-       reader.set_elem = softbody_read_state;
-       reader.totelem = soft->totpoint;
-
-       return BKE_ptcache_read_cache(&reader);
-}
-
 /* +++ ************ maintaining scratch *************** */
 static void sb_new_scratch(SoftBody *sb)
 {
@@ -3827,7 +3746,7 @@ SoftBody *sbNew(Scene *scene)
        sb->shearstiff = 1.0f;
        sb->solverflags |= SBSO_OLDERR;
 
-       sb->pointcache = BKE_ptcache_add();
+       sb->pointcache = BKE_ptcache_add(&sb->ptcaches);
 
        return sb;
 }
@@ -3836,7 +3755,8 @@ SoftBody *sbNew(Scene *scene)
 void sbFree(SoftBody *sb)
 {
        free_softbody_intern(sb);
-       BKE_ptcache_free(sb->pointcache);
+       BKE_ptcache_free_list(&sb->ptcaches);
+       sb->pointcache = NULL;
        MEM_freeN(sb);
 }
 
@@ -4135,7 +4055,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
        PTCacheID pid;
        float dtime, timescale;
        int framedelta, framenr, startframe, endframe;
-       int cache_result, old_framenr;
+       int cache_result;
 
        cache= sb->pointcache;
 
@@ -4221,7 +4141,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
        }
 
        /* try to read from cache */
-       cache_result = softbody_read_cache(scene, ob, sb, framenr, &old_framenr);
+       cache_result = BKE_ptcache_read_cache(&pid, framenr, scene->r.frs_sec);
 
        if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) {
                cache->flag |= PTCACHE_SIMULATION_VALID;
@@ -4235,7 +4155,6 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
        else if(cache_result==PTCACHE_READ_OLD) {
                BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_FREE);
                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 */
@@ -4263,7 +4182,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
        else {
                /* if on second frame, write cache for first frame */
                if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0))
-                       softbody_write_cache(ob, sb, startframe);
+                       BKE_ptcache_write_cache(&pid, startframe);
 
                softbody_update_positions(ob, sb, vertexCos, numVerts);
 
@@ -4279,7 +4198,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
                if(sb->particles==0)
                        softbody_to_object(ob, vertexCos, numVerts, 0);
 
-               softbody_write_cache(ob, sb, framenr);
+               BKE_ptcache_write_cache(&pid, framenr);
        }
 }
 
index 2b6c372861ac0951078b08ad67c753c1985e1d10..c937dfd88a4e9fb52e60a6757db315e274b22864 100644 (file)
@@ -2929,13 +2929,21 @@ static void direct_link_pointcache(FileData *fd, PointCache *cache)
 {
        if((cache->flag & PTCACHE_DISK_CACHE)==0) {
                PTCacheMem *pm;
+               int i;
 
                link_list(fd, &cache->mem_cache);
 
                pm = cache->mem_cache.first;
 
-               for(; pm; pm=pm->next)
-                       pm->data = newdataadr(fd, pm->data);
+               for(; pm; pm=pm->next) {
+                       if(pm->index_array)
+                               pm->index_array = newdataadr(fd, pm->index_array);
+                       
+                       for(i=0; i<BPHYS_TOT_DATA; i++) {
+                               if(pm->data[i] && pm->data_types & (1<<i))
+                                       pm->data[i] = newdataadr(fd, pm->data[i]);
+                       }
+               }
        }
        else
                cache->mem_cache.first = cache->mem_cache.last = NULL;
@@ -2944,6 +2952,24 @@ static void direct_link_pointcache(FileData *fd, PointCache *cache)
        cache->simframe= 0;
 }
 
+static void direct_link_pointcache_list(FileData *fd, ListBase *ptcaches, PointCache **ocache)
+{
+       PointCache *cache;
+
+       if(ptcaches->first) {
+               link_list(fd, ptcaches);
+               for(cache=ptcaches->first; cache; cache=cache->next)
+                       direct_link_pointcache(fd, cache);
+
+               *ocache = newdataadr(fd, *ocache);
+       }
+       else if(*ocache) {
+               /* old "single" caches need to be linked too for do-versions */
+               *ocache = newdataadr(fd, *ocache);
+               direct_link_pointcache(fd, *ocache);
+       }
+}
+
 static void lib_link_particlesettings(FileData *fd, Main *main)
 {
        ParticleSettings *part;
@@ -3089,9 +3115,7 @@ static void direct_link_particlesystems(FileData *fd, ListBase *particles)
                        sb->bspring= NULL;
                        sb->scratch= NULL;
 
-                       sb->pointcache= newdataadr(fd, sb->pointcache);
-                       if(sb->pointcache)
-                               direct_link_pointcache(fd, sb->pointcache);
+                       direct_link_pointcache_list(fd, &sb->ptcaches, &sb->pointcache);
                }
 
                link_list(fd, &psys->targets);
@@ -3104,9 +3128,7 @@ static void direct_link_particlesystems(FileData *fd, ListBase *particles)
                psys->childcachebufs.first = psys->childcachebufs.last = 0;
                psys->reactevents.first = psys->reactevents.last = 0;
 
-               psys->pointcache= newdataadr(fd, psys->pointcache);
-               if(psys->pointcache)
-                       direct_link_pointcache(fd, psys->pointcache);
+               direct_link_pointcache_list(fd, &psys->ptcaches, &psys->pointcache);
 
                psys->tree = NULL;
        }
@@ -3630,8 +3652,7 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
                        clmd->coll_parms= newdataadr(fd, clmd->coll_parms);
                        clmd->point_cache= newdataadr(fd, clmd->point_cache);
 
-                       if(clmd->point_cache)
-                               direct_link_pointcache(fd, clmd->point_cache);
+                       direct_link_pointcache_list(fd, &clmd->ptcaches, &clmd->point_cache);
                        
                        if(clmd->sim_parms) {
                                if(clmd->sim_parms->presets > 10)
@@ -3888,7 +3909,7 @@ static void direct_link_object(FileData *fd, Object *ob)
 
                sb->pointcache= newdataadr(fd, sb->pointcache);
                if(sb->pointcache)
-                       direct_link_pointcache(fd, sb->pointcache);
+                       direct_link_pointcache_list(fd, &sb->ptcaches, &sb->pointcache);
        }
        ob->bsoft= newdataadr(fd, ob->bsoft);
        ob->fluidsimSettings= newdataadr(fd, ob->fluidsimSettings); /* NT */
@@ -8301,20 +8322,20 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                /* add point caches */
                for(ob=main->object.first; ob; ob=ob->id.next) {
                        if(ob->soft && !ob->soft->pointcache)
-                               ob->soft->pointcache= BKE_ptcache_add();
+                               ob->soft->pointcache= BKE_ptcache_add(&ob->soft->ptcaches);
 
                        for(psys=ob->particlesystem.first; psys; psys=psys->next) {
                                if(psys->soft && !psys->soft->pointcache)
-                                       psys->soft->pointcache= BKE_ptcache_add();
+                                       psys->soft->pointcache= BKE_ptcache_add(&psys->soft->ptcaches);
                                if(!psys->pointcache)
-                                       psys->pointcache= BKE_ptcache_add();
+                                       psys->pointcache= BKE_ptcache_add(&psys->ptcaches);
                        }
 
                        for(md=ob->modifiers.first; md; md=md->next) {
                                if(md->type==eModifierType_Cloth) {
                                        ClothModifierData *clmd = (ClothModifierData*) md;
                                        if(!clmd->point_cache)
-                                               clmd->point_cache= BKE_ptcache_add();
+                                               clmd->point_cache= BKE_ptcache_add(&clmd->ptcaches);
                                }
                        }
                }
@@ -8602,7 +8623,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
 
                                /* create new particle system */
                                psys = MEM_callocN(sizeof(ParticleSystem), "particle_system");
-                               psys->pointcache = BKE_ptcache_add();
+                               psys->pointcache = BKE_ptcache_add(&psys->ptcaches);
 
                                part = psys->part = psys_new_settings("ParticleSettings", main);
                                
@@ -9344,9 +9365,19 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                Tex *tex;
                Scene *sce;
                ToolSettings *ts;
+               PTCacheID *pid;
+               ListBase pidlist;
                int i, a;
 
                for(ob = main->object.first; ob; ob = ob->id.next) {
+                       BKE_ptcache_ids_from_object(&pidlist, ob);
+
+                       for(pid=pidlist.first; pid; pid=pid->next) {
+                               if(pid->ptcaches->first == NULL)
+                                       pid->ptcaches->first = pid->ptcaches->last = pid->cache;
+                       }
+
+                       BLI_freelistN(&pidlist);
 
                        if(ob->type == OB_MESH) {
                                Mesh *me = newlibadr(fd, lib, ob->data);
index cf636cc2b94468b577df4e2464a87627293a1d89..d8841962e7b51d5e86e27a2f30186acb9b596d76 100644 (file)
@@ -157,6 +157,7 @@ Any case: direct data is ALWAYS after the lib block
 #include "BKE_main.h"
 #include "BKE_node.h"
 #include "BKE_packedFile.h" // for packAll
+#include "BKE_pointcache.h"
 #include "BKE_report.h"
 #include "BKE_screen.h" // for waitcursor
 #include "BKE_sequence.h"
@@ -582,19 +583,27 @@ static void write_boid_state(WriteData *wd, BoidState *state)
 /* 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)
+static void write_pointcaches(WriteData *wd, ListBase *ptcaches)
 {
-       writestruct(wd, DATA, "PointCache", 1, cache);
+       PointCache *cache = ptcaches->first;
+       int i;
+
+       for(; cache; cache=cache->next) {
+               writestruct(wd, DATA, "PointCache", 1, cache);
 
-       if((cache->flag & PTCACHE_DISK_CACHE)==0) {
-               PTCacheMem *pm = cache->mem_cache.first;
+               if((cache->flag & PTCACHE_DISK_CACHE)==0) {
+                       PTCacheMem *pm = cache->mem_cache.first;
 
-               for(; pm; pm=pm->next) {
-                       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);
+                       for(; pm; pm=pm->next) {
+                               writestruct(wd, DATA, "PTCacheMem", 1, pm);
+                               if(pm->index_array)
+                                       writedata(wd, DATA, sizeof(int) * pm->totpoint, pm->index_array);
+                               
+                               for(i=0; i<BPHYS_TOT_DATA; i++) {
+                                       if(pm->data[i] && pm->data_types & (1<<i))
+                                               writedata(wd, DATA, BKE_ptcache_data_size(i) * pm->totpoint, pm->data[i]);
+                               }
+                       }
                }
        }
 }
@@ -652,8 +661,8 @@ static void write_particlesystems(WriteData *wd, ListBase *particles)
 
                if(psys->child) writestruct(wd, DATA, "ChildParticle", psys->totchild ,psys->child);
                writestruct(wd, DATA, "SoftBody", 1, psys->soft);
-               if(psys->soft) write_pointcaches(wd, psys->soft->pointcache, PTCACHE_WRITE_PSYS);
-               write_pointcaches(wd, psys->pointcache, PTCACHE_WRITE_PSYS);
+               if(psys->soft) write_pointcaches(wd, &psys->soft->ptcaches);
+               write_pointcaches(wd, &psys->ptcaches);
        }
 }
 
@@ -1112,7 +1121,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);
-                       write_pointcaches(wd, clmd->point_cache, PTCACHE_WRITE_CLOTH);
+                       write_pointcaches(wd, &clmd->ptcaches);
                } 
                else if(md->type==eModifierType_Smoke) {
                        SmokeModifierData *smd = (SmokeModifierData*) md;
index e32dd0e8ac70f8aabec4ad362e7ca13de141b58d..0d4e926f3b5b271cf0c56a54975e39593f365ce9 100644 (file)
@@ -873,11 +873,11 @@ void make_editMesh(Scene *scene, Object *ob)
                
                if(cacheedit) {
                        if(pid.type == PTCACHE_TYPE_CLOTH) {
-                               cloth= ((ClothModifierData*)pid.data)->clothObject;
+                               cloth= ((ClothModifierData*)pid.calldata)->clothObject;
                                VECCOPY(cacheco, cloth->verts[a].x)
                        }
                        else if(pid.type == PTCACHE_TYPE_SOFTBODY) {
-                               sb= (SoftBody*)pid.data;
+                               sb= (SoftBody*)pid.calldata;
                                VECCOPY(cacheco, sb->bpoint[a].pos)
                        }
 
@@ -1095,7 +1095,7 @@ void load_editMesh(Scene *scene, Object *ob)
        while(eve) {
                if(cacheedit) {
                        if(pid.type == PTCACHE_TYPE_CLOTH) {
-                               clmd= (ClothModifierData*)pid.data;
+                               clmd= (ClothModifierData*)pid.calldata;
                                cloth= clmd->clothObject;
 
                                /* assign position */
@@ -1110,7 +1110,7 @@ void load_editMesh(Scene *scene, Object *ob)
                                VECADD(cloth->verts[a].v, cloth->verts[a].v, cacheco);
                        }
                        else if(pid.type == PTCACHE_TYPE_SOFTBODY) {
-                               sb= (SoftBody*)pid.data;
+                               sb= (SoftBody*)pid.calldata;
 
                                /* assign position */
                                VECCOPY(cacheco, sb->bpoint[a].pos)
@@ -1156,12 +1156,8 @@ void load_editMesh(Scene *scene, Object *ob)
        }
        
        /* write changes to cache */
-       if(cacheedit) {
-               if(pid.type == PTCACHE_TYPE_CLOTH)
-                       cloth_write_cache(ob, pid.data, pid.cache->editframe);
-               else if(pid.type == PTCACHE_TYPE_SOFTBODY)
-                       softbody_write_cache(ob, pid.data, pid.cache->editframe);
-       }
+       if(cacheedit)
+               BKE_ptcache_write_cache(&pid, pid.cache->editframe);
 
        /* the edges */
        a= 0;
index 5d0a6d21fac8d6afe17942ecae1a4156ca40bdde..a256fd9768612edef29e5d6899dbc8b262614008 100644 (file)
@@ -61,7 +61,6 @@
 static int cache_break_test(void *cbd) {
        return G.afbreek==1;
 }
-/**************************** general **********************************/
 static int ptcache_bake_all_poll(bContext *C)
 {
        Scene *scene= CTX_data_scene(C);
@@ -130,7 +129,7 @@ void PTCACHE_OT_bake_all(wmOperatorType *ot)
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 
-       RNA_def_boolean(ot->srna, "bake", 0, "Bake", "");
+       RNA_def_boolean(ot->srna, "bake", 1, "Bake", "");
 }
 void PTCACHE_OT_free_bake_all(wmOperatorType *ot)
 {
@@ -145,32 +144,25 @@ void PTCACHE_OT_free_bake_all(wmOperatorType *ot)
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
-
-/**************************** softbody **********************************/
-static int ptcache_bake_softbody_poll(bContext *C)
-{
-       Scene *scene= CTX_data_scene(C);
-       Object *ob= CTX_data_active_object(C);
-       SoftBody *sb = ob->soft;
-
-       if(!scene || !ob || ob->id.lib || !sb)
-               return 0;
-       
-       return 1;
-}
-
-static int ptcache_bake_softbody_exec(bContext *C, wmOperator *op)
+static int ptcache_bake_exec(bContext *C, wmOperator *op)
 {
-       Scene *scene= CTX_data_scene(C);
-       Object *ob= CTX_data_active_object(C);
-       SoftBody *sb = ob->soft;
-       PTCacheID pid;
+       Scene *scene = CTX_data_scene(C);
+       PointerRNA ptr= CTX_data_pointer_get_type(C, "PointCache", &RNA_PointCache);
+       Object *ob= ptr.id.data;
+       PointCache *cache= ptr.data;
        PTCacheBaker baker;
+       PTCacheID *pid;
+       ListBase pidlist;
 
-       BKE_ptcache_id_from_softbody(&pid, ob, sb);
+       BKE_ptcache_ids_from_object(&pidlist, ob);
+       
+       for(pid=pidlist.first; pid; pid=pid->next) {
+               if(pid->cache == cache)
+                       break;
+       }
 
        baker.scene = scene;
-       baker.pid = &pid;
+       baker.pid = pid;
        baker.bake = RNA_boolean_get(op->ptr, "bake");
        baker.render = 0;
        baker.anim_init = 0;
@@ -182,305 +174,161 @@ static int ptcache_bake_softbody_exec(bContext *C, wmOperator *op)
 
        BKE_ptcache_make_cache(&baker);
 
-       WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
-
-       return OPERATOR_FINISHED;
-}
-static int ptcache_free_bake_softbody_exec(bContext *C, wmOperator *op)
-{
-       Scene *scene= CTX_data_scene(C);
-       Object *ob= CTX_data_active_object(C);
-       SoftBody *sb = ob->soft;
-       PTCacheID pid;
-
-       BKE_ptcache_id_from_softbody(&pid, ob, sb);
-       pid.cache->flag &= ~PTCACHE_BAKED;
+       BLI_freelistN(&pidlist);
 
        WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
 
        return OPERATOR_FINISHED;
 }
-void PTCACHE_OT_cache_softbody(wmOperatorType *ot)
+static int ptcache_free_bake_exec(bContext *C, wmOperator *op)
 {
-       /* identifiers */
-       ot->name= "Bake Softbody";
-       ot->idname= "PTCACHE_OT_cache_softbody";
+       PointerRNA ptr= CTX_data_pointer_get_type(C, "PointCache", &RNA_PointCache);
+       PointCache *cache= ptr.data;
        
-       /* api callbacks */
-       ot->exec= ptcache_bake_softbody_exec;
-       ot->poll= ptcache_bake_softbody_poll;
-
-       /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
-       RNA_def_boolean(ot->srna, "bake", 0, "Bake", "");
-}
-void PTCACHE_OT_free_bake_softbody(wmOperatorType *ot)
-{
-       /* identifiers */
-       ot->name= "Free SoftBody Bake";
-       ot->idname= "PTCACHE_OT_free_bake_softbody";
-       
-       /* api callbacks */
-       ot->exec= ptcache_free_bake_softbody_exec;
-       ot->poll= ptcache_bake_softbody_poll;
-
-       /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-static int ptcache_bake_from_softbody_cache_exec(bContext *C, wmOperator *op)
-{
-       Object *ob= CTX_data_active_object(C);
-       SoftBody *sb = ob->soft;
-       PTCacheID pid;
-
-       BKE_ptcache_id_from_softbody(&pid, ob, sb);
-       pid.cache->flag |= PTCACHE_BAKED;
+       cache->flag &= ~PTCACHE_BAKED;
 
        return OPERATOR_FINISHED;
 }
-void PTCACHE_OT_bake_from_softbody_cache(wmOperatorType *ot)
+static int ptcache_bake_from_cache_exec(bContext *C, wmOperator *op)
 {
-       /* identifiers */
-       ot->name= "Bake From Cache";
-       ot->idname= "PTCACHE_OT_bake_from_softbody_cache";
-       
-       /* api callbacks */
-       ot->exec= ptcache_bake_from_softbody_cache_exec;
-       ot->poll= ptcache_bake_softbody_poll;
-
-       /* flags */
-       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;
+       PointerRNA ptr= CTX_data_pointer_get_type(C, "PointCache", &RNA_PointCache);
+       PointCache *cache= ptr.data;
        
-       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.anim_init = 0;
-       baker.quick_step = 1;
-       baker.break_test = cache_break_test;
-       baker.break_data = NULL;
-       baker.progressbar = (void (*)(void *, int))WM_timecursor;
-       baker.progresscontext = CTX_wm_window(C);
-
-       BKE_ptcache_make_cache(&baker);
-
-       WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
+       cache->flag |= PTCACHE_BAKED;
 
        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)
+void PTCACHE_OT_bake(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Bake Cloth";
-       ot->idname= "PTCACHE_OT_cache_cloth";
+       ot->name= "Bake Physics";
+       ot->idname= "PTCACHE_OT_bake";
        
        /* api callbacks */
-       ot->exec= ptcache_bake_cloth_exec;
-       ot->poll= ptcache_bake_cloth_poll;
+       ot->exec= ptcache_bake_exec;
+       ot->poll= ptcache_bake_all_poll;
 
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 
-       RNA_def_boolean(ot->srna, "bake", 0, "Bake", "");
+       RNA_def_boolean(ot->srna, "bake", 1, "Bake", "");
 }
-void PTCACHE_OT_free_bake_cloth(wmOperatorType *ot)
+void PTCACHE_OT_free_bake(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Free Cloth Bake";
-       ot->idname= "PTCACHE_OT_free_bake_cloth";
+       ot->name= "Free Physics Bake";
+       ot->idname= "PTCACHE_OT_free_bake";
        
        /* api callbacks */
-       ot->exec= ptcache_free_bake_cloth_exec;
-       ot->poll= ptcache_bake_cloth_poll;
+       ot->exec= ptcache_free_bake_exec;
+       ot->poll= ptcache_bake_all_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)
+void PTCACHE_OT_bake_from_cache(wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Bake From Cache";
-       ot->idname= "PTCACHE_OT_bake_from_cloth_cache";
+       ot->idname= "PTCACHE_OT_bake_from_cache";
        
        /* api callbacks */
-       ot->exec= ptcache_bake_from_cloth_cache_exec;
-       ot->poll= ptcache_bake_cloth_poll;
+       ot->exec= ptcache_bake_from_cache_exec;
+       ot->poll= ptcache_bake_all_poll;
 
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
-/**************************** particles **********************************/
-static int ptcache_bake_particle_system_poll(bContext *C)
+static int ptcache_add_new_exec(bContext *C, wmOperator *op)
 {
-       Scene *scene= CTX_data_scene(C);
-       Object *ob= CTX_data_active_object(C);
+       Scene *scene = CTX_data_scene(C);
+       PointerRNA ptr= CTX_data_pointer_get_type(C, "PointCache", &RNA_PointCache);
+       Object *ob= ptr.id.data;
+       PointCache *cache= ptr.data;
+       PTCacheID *pid;
+       ListBase pidlist;
 
-       if(!scene || !ob || ob->id.lib)
-               return 0;
+       BKE_ptcache_ids_from_object(&pidlist, ob);
        
-       return (ob->particlesystem.first != NULL);
-}
-
-static int ptcache_bake_particle_system_exec(bContext *C, wmOperator *op)
-{
-       Scene *scene= CTX_data_scene(C);
-       Object *ob= CTX_data_active_object(C);
-       ParticleSystem *psys =psys_get_current(ob);
-       PTCacheID pid;
-       PTCacheBaker baker;
-
-       BKE_ptcache_id_from_particles(&pid, ob, psys);
-
-       baker.scene = scene;
-       baker.pid = &pid;
-       baker.bake = RNA_boolean_get(op->ptr, "bake");
-       baker.render = 0;
-       baker.anim_init = 0;
-       baker.quick_step = 1;
-       baker.break_test = cache_break_test;
-       baker.break_data = NULL;
-       baker.progressbar = (void (*)(void *, int))WM_timecursor;
-       baker.progresscontext = CTX_wm_window(C);
+       for(pid=pidlist.first; pid; pid=pid->next) {
+               if(pid->cache == cache) {
+                       *(pid->cache_ptr) = BKE_ptcache_add(pid->ptcaches);
+                       break;
+               }
+       }
 
-       BKE_ptcache_make_cache(&baker);
+       BLI_freelistN(&pidlist);
 
        WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
 
        return OPERATOR_FINISHED;
 }
-static int ptcache_free_bake_particle_system_exec(bContext *C, wmOperator *op)
+static int ptcache_remove_exec(bContext *C, wmOperator *op)
 {
-       Scene *scene= CTX_data_scene(C);
-       Object *ob= CTX_data_active_object(C);
-       ParticleSystem *psys= psys_get_current(ob);
-       PTCacheID pid;
+       Scene *scene = CTX_data_scene(C);
+       PointerRNA ptr= CTX_data_pointer_get_type(C, "PointCache", &RNA_PointCache);
+       Object *ob= ptr.id.data;
+       PointCache *cache= ptr.data;
+       PTCacheID *pid;
+       ListBase pidlist;
 
-       BKE_ptcache_id_from_particles(&pid, ob, psys);
-       psys->pointcache->flag &= ~PTCACHE_BAKED;
+       BKE_ptcache_ids_from_object(&pidlist, ob);
+       
+       for(pid=pidlist.first; pid; pid=pid->next) {
+               if(pid->cache == cache) {
+                       if(pid->ptcaches->first == pid->ptcaches->last)
+                               continue; /* don't delete last cache */
 
-       WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
+                       BLI_remlink(pid->ptcaches, pid->cache);
+                       BKE_ptcache_free(pid->cache);
+                       *(pid->cache_ptr) = pid->ptcaches->first;
 
-       return OPERATOR_FINISHED;
-}
-void PTCACHE_OT_cache_particle_system(wmOperatorType *ot)
-{
-       /* identifiers */
-       ot->name= "Bake Particles";
-       ot->idname= "PTCACHE_OT_cache_particle_system";
-       
-       /* api callbacks */
-       ot->exec= ptcache_bake_particle_system_exec;
-       ot->poll= ptcache_bake_particle_system_poll;
+                       break;
+               }
+       }
 
-       /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       BLI_freelistN(&pidlist);
 
-       RNA_def_boolean(ot->srna, "bake", 0, "Bake", "");
+       return OPERATOR_FINISHED;
 }
-void PTCACHE_OT_free_bake_particle_system(wmOperatorType *ot)
+void PTCACHE_OT_add_new(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Free Particles Bake";
-       ot->idname= "PTCACHE_OT_free_bake_particle_system";
+       ot->name= "Add new cache";
+       ot->idname= "PTCACHE_OT_add_new";
        
        /* api callbacks */
-       ot->exec= ptcache_free_bake_particle_system_exec;
-       ot->poll= ptcache_bake_particle_system_poll;
+       ot->exec= ptcache_add_new_exec;
+       ot->poll= ptcache_bake_all_poll;
 
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
-static int ptcache_bake_from_particles_cache_exec(bContext *C, wmOperator *op)
-{
-       Object *ob= CTX_data_active_object(C);
-       ParticleSystem *psys= psys_get_current(ob);
-       PTCacheID pid;
-
-       BKE_ptcache_id_from_particles(&pid, ob, psys);
-       psys->pointcache->flag |= PTCACHE_BAKED;
-
-       return OPERATOR_FINISHED;
-}
-void PTCACHE_OT_bake_from_particles_cache(wmOperatorType *ot)
+void PTCACHE_OT_remove(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Bake From Cache";
-       ot->idname= "PTCACHE_OT_bake_from_particles_cache";
+       ot->name= "Delete current cache";
+       ot->idname= "PTCACHE_OT_remove";
        
        /* api callbacks */
-       ot->exec= ptcache_bake_from_particles_cache_exec;
-       ot->poll= ptcache_bake_particle_system_poll;
+       ot->exec= ptcache_remove_exec;
+       ot->poll= ptcache_bake_all_poll;
 
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
-
 /**************************** registration **********************************/
 
 void ED_operatortypes_pointcache(void)
 {
        WM_operatortype_append(PTCACHE_OT_bake_all);
        WM_operatortype_append(PTCACHE_OT_free_bake_all);
-       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);
-       WM_operatortype_append(PTCACHE_OT_cache_softbody);
-       WM_operatortype_append(PTCACHE_OT_free_bake_softbody);
-       WM_operatortype_append(PTCACHE_OT_bake_from_softbody_cache);
+       WM_operatortype_append(PTCACHE_OT_bake);
+       WM_operatortype_append(PTCACHE_OT_free_bake);
+       WM_operatortype_append(PTCACHE_OT_bake_from_cache);
+       WM_operatortype_append(PTCACHE_OT_add_new);
+       WM_operatortype_append(PTCACHE_OT_remove);
 }
 
 //void ED_keymap_pointcache(wmWindowManager *wm)
index 3f504848d778bf41fa627d8189a76dde47e00c4f..9d1707599b9e4ed217cb3d5c837f35bfa94b8f80 100644 (file)
@@ -420,6 +420,7 @@ typedef struct ClothModifierData {
        struct ClothSimSettings *sim_parms; /* definition is in DNA_cloth_types.h */
        struct ClothCollSettings *coll_parms; /* definition is in DNA_cloth_types.h */
        struct PointCache *point_cache; /* definition is in DNA_object_force.h */
+       struct ListBase ptcaches;
 } ClothModifierData;
 
 typedef struct CollisionModifierData {
index b5b33610bfe3e2b77826a1fb744f724af5da3533..d7ef3d73ecff318f0d8d43730bfc0b9d93d3bb30 100644 (file)
@@ -74,14 +74,36 @@ typedef struct PartDeflect {
        int seed; /* wind noise random seed */
 } PartDeflect;
 
+/* Point cache file data types:
+/* - used as (1<<flag) so poke jahka if you reach the limit of 15
+/* - to add new data types update:
+/*             * BKE_ptcache_data_size()
+/*             * ptcache_file_init_pointers()
+*/
+#define BPHYS_DATA_INDEX               0
+#define BPHYS_DATA_LOCATION            1
+#define BPHYS_DATA_VELOCITY            2
+#define BPHYS_DATA_ROTATION            3
+#define BPHYS_DATA_AVELOCITY   4       /* used for particles */
+#define BPHYS_DATA_XCONST              4       /* used for cloth */
+#define BPHYS_DATA_SIZE                        5
+#define BPHYS_DATA_TIMES               6
+#define BPHYS_DATA_BOIDS               7
+
+#define BPHYS_TOT_DATA                 8
+
 typedef struct PTCacheMem {
        struct PTCacheMem *next, *prev;
        int frame, totpoint;
-       float *data;    /* data points */
-       void *xdata;    /* extra data */
+       unsigned int data_types, rt;
+       int *index_array; /* quick access to stored points with index */
+
+       void *data[8]; /* BPHYS_TOT_DATA */
+       void *cur[8]; /* BPHYS_TOT_DATA */
 } PTCacheMem;
 
 typedef struct PointCache {
+       struct PointCache *next, *prev;
        int flag;               /* generic flag */
        int step;               /* frames between cached frames */
        int simframe;   /* current frame of simulation (only if SIMULATION_VALID) */
@@ -229,6 +251,7 @@ typedef struct SoftBody {
        float inpush;
 
        struct PointCache *pointcache;
+       struct ListBase ptcaches;
 
 } SoftBody;
 
@@ -283,6 +306,7 @@ typedef struct SoftBody {
 #define PTCACHE_QUICK_CACHE                    128
 #define PTCACHE_FRAMES_SKIPPED         256
 #define PTCACHE_EXTERNAL                       512
+#define PTCACHE_READ_INFO                      1024
 
 /* PTCACHE_OUTDATED + PTCACHE_FRAMES_SKIPPED */
 #define PTCACHE_REDO_NEEDED                    258
index b71d390db5a89b79cf45a144127b56efd275bc37..925fd31328d9f5dacda3374eefaeb52e73ea0183 100644 (file)
@@ -229,6 +229,7 @@ typedef struct ParticleSystem{                              /* note, make sure all (runtime) are NULL's in
 
        /* point cache */
        struct PointCache *pointcache;
+       struct ListBase ptcaches;
 
        struct KDTree *tree;                                    /* used for interactions with self and other systems */
 }ParticleSystem;
index b7084a0b26d716b8d48aa8e343029dc7d4b3f57c..936e1700ed746f6197214aa3f2ef8ade698a7cc0 100644 (file)
@@ -98,7 +98,7 @@ static void rna_FluidSettings_update_type(bContext *C, PointerRNA *ptr)
 
                        part->type= PART_FLUID;
                        psys->part= part;
-                       psys->pointcache= BKE_ptcache_add();
+                       psys->pointcache= BKE_ptcache_add(&psys->ptcaches);
                        psys->flag |= PSYS_ENABLED;
                        BLI_addtail(&ob->particlesystem,psys);
 
index f04001d8a642d425181b6bea65845e9c1c2a4669..93274a01cc50b9aeca4e33847b39cedba502f7ae 100644 (file)
@@ -148,6 +148,7 @@ static void rna_Cache_idname_change(bContext *C, PointerRNA *ptr)
 
                if(new_name) {
                        if(pid2 && cache->flag & PTCACHE_DISK_CACHE) {
+                               /* TODO: change to simple file rename */
                                strcpy(name, cache->name);
                                strcpy(cache->name, cache->prev_name);
 
@@ -169,6 +170,87 @@ static void rna_Cache_idname_change(bContext *C, PointerRNA *ptr)
        BLI_freelistN(&pidlist);
 }
 
+static void rna_Cache_list_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+       Object *ob = ptr->id.data;
+       PointCache *cache= ptr->data;
+       PTCacheID *pid;
+       ListBase pidlist;
+
+       BKE_ptcache_ids_from_object(&pidlist, ob);
+
+       for(pid=pidlist.first; pid; pid=pid->next) {
+               if(pid->cache == cache) {
+                       rna_iterator_listbase_begin(iter, pid->ptcaches, NULL);
+                       break;
+               }
+       }
+
+       BLI_freelistN(&pidlist);
+}
+static void rna_Cache_active_point_cache_index_range(PointerRNA *ptr, int *min, int *max)
+{
+       Object *ob = ptr->id.data;
+       PointCache *cache= ptr->data;
+       PTCacheID *pid;
+       ListBase pidlist;
+
+       BKE_ptcache_ids_from_object(&pidlist, ob);
+       
+       *min= 0;
+       *max= 0;
+
+       for(pid=pidlist.first; pid; pid=pid->next) {
+               if(pid->cache == cache) {
+                       *max= BLI_countlist(pid->ptcaches)-1;
+                       *max= MAX2(0, *max);
+                       break;
+               }
+       }
+
+       BLI_freelistN(&pidlist);
+}
+
+static int rna_Cache_active_point_cache_index_get(PointerRNA *ptr)
+{
+       Object *ob = ptr->id.data;
+       PointCache *cache= ptr->data;
+       PTCacheID *pid;
+       ListBase pidlist;
+       int num = 0;
+
+       BKE_ptcache_ids_from_object(&pidlist, ob);
+       
+       for(pid=pidlist.first; pid; pid=pid->next) {
+               if(pid->cache == cache) {
+                       num = BLI_findindex(pid->ptcaches, cache);
+                       break;
+               }
+       }
+
+       BLI_freelistN(&pidlist);
+
+       return num;
+}
+
+static void rna_Cache_active_point_cache_index_set(struct PointerRNA *ptr, int value)
+{
+       Object *ob = ptr->id.data;
+       PointCache *cache= ptr->data;
+       PTCacheID *pid;
+       ListBase pidlist;
+
+       BKE_ptcache_ids_from_object(&pidlist, ob);
+       
+       for(pid=pidlist.first; pid; pid=pid->next) {
+               if(pid->cache == cache) {
+                       *(pid->cache_ptr) = BLI_findlink(pid->ptcaches, value);
+                       break;
+               }
+       }
+
+       BLI_freelistN(&pidlist);
+}
 static int rna_SoftBodySettings_use_edges_get(PointerRNA *ptr)
 {
        Object *data= (Object*)(ptr->id.data);
@@ -371,6 +453,7 @@ static void rna_def_pointcache(BlenderRNA *brna)
 
        srna= RNA_def_struct(brna, "PointCache", NULL);
        RNA_def_struct_ui_text(srna, "Point Cache", "Point cache for physics simulations.");
+       RNA_def_struct_ui_icon(srna, ICON_PHYSICS);
        
        prop= RNA_def_property(srna, "start_frame", PROP_INT, PROP_TIME);
        RNA_def_property_int_sdna(prop, NULL, "startframe");
@@ -420,6 +503,7 @@ static void rna_def_pointcache(BlenderRNA *brna)
        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");
+       RNA_def_struct_name_property(srna, prop);
 
        prop= RNA_def_property(srna, "filepath", PROP_STRING, PROP_DIRPATH);
        RNA_def_property_string_sdna(prop, NULL, "path");
@@ -440,6 +524,16 @@ static void rna_def_pointcache(BlenderRNA *brna)
        RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_EXTERNAL);
        RNA_def_property_ui_text(prop, "External", "Read cache from an external location");
        RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_idname_change");
+
+       prop= RNA_def_property(srna, "point_cache_list", PROP_COLLECTION, PROP_NONE);
+       RNA_def_property_collection_funcs(prop, "rna_Cache_list_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", 0, 0, 0, 0, 0);
+       RNA_def_property_struct_type(prop, "PointCache");
+       RNA_def_property_ui_text(prop, "Point Cache List", "Point cache list");
+
+       prop= RNA_def_property(srna, "active_point_cache_index", PROP_INT, PROP_UNSIGNED);
+       RNA_def_property_int_funcs(prop, "rna_Cache_active_point_cache_index_get", "rna_Cache_active_point_cache_index_set", "rna_Cache_active_point_cache_index_range");
+       RNA_def_property_ui_text(prop, "Active Point Cache Index", "");
+       RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_change");
 }
 
 static void rna_def_collision(BlenderRNA *brna)