Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorJanne Karhu <jhkarh@gmail.com>2009-08-12 13:54:29 +0400
committerJanne Karhu <jhkarh@gmail.com>2009-08-12 13:54:29 +0400
commitb221c0e2e6f390f3ed810b7f520b0ad60511ba36 (patch)
tree09b3b18e14773ee015959b214284cc5010f6fdc4 /source
parent8641833b57606a2ac21f7c83b53ea5fc55664815 (diff)
New point cache file format:
- 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.
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_cloth.h4
-rw-r--r--source/blender/blenkernel/BKE_pointcache.h77
-rw-r--r--source/blender/blenkernel/BKE_softbody.h3
-rw-r--r--source/blender/blenkernel/intern/cloth.c95
-rw-r--r--source/blender/blenkernel/intern/modifier.c12
-rw-r--r--source/blender/blenkernel/intern/particle.c14
-rw-r--r--source/blender/blenkernel/intern/particle_system.c137
-rw-r--r--source/blender/blenkernel/intern/pointcache.c1394
-rw-r--r--source/blender/blenkernel/intern/softbody.c95
-rw-r--r--source/blender/blenloader/intern/readfile.c63
-rw-r--r--source/blender/blenloader/intern/writefile.c35
-rw-r--r--source/blender/editors/mesh/editmesh.c16
-rw-r--r--source/blender/editors/physics/ed_pointcache.c332
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h1
-rw-r--r--source/blender/makesdna/DNA_object_force.h28
-rw-r--r--source/blender/makesdna/DNA_particle_types.h1
-rw-r--r--source/blender/makesrna/intern/rna_fluidsim.c2
-rw-r--r--source/blender/makesrna/intern/rna_object_force.c94
18 files changed, 1383 insertions, 1020 deletions
diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h
index f3165c959bf..bc4585106e6 100644
--- a/source/blender/blenkernel/BKE_cloth.h
+++ b/source/blender/blenkernel/BKE_cloth.h
@@ -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 );
diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h
index 8062f807055..a719ab92a80 100644
--- a/source/blender/blenkernel/BKE_pointcache.h
+++ b/source/blender/blenkernel/BKE_pointcache.h
@@ -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);
diff --git a/source/blender/blenkernel/BKE_softbody.h b/source/blender/blenkernel/BKE_softbody.h
index 0d9682cf842..d8053281ceb 100644
--- a/source/blender/blenkernel/BKE_softbody.h
+++ b/source/blender/blenkernel/BKE_softbody.h
@@ -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
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index 089dafeb8c7..3acaaecb1e8 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -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);
}
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index f8795edc878..0c975a10c0a 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -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;
}
}
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index e4f8a484061..c8aa440e2da 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -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);
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index b5d58e9db8c..2f4a5c28385 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -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) {
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index beb72c2c13f..7aa01de71d0 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -77,8 +77,306 @@
#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,136 +647,224 @@ 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);
+
+ int cfra1 = 0, cfra2 = 0;
+ int totpoint = 0, totpoint2 = 0;
+ int *index = &i, *index2 = &i;
+ int use_old = 0, old_frame;
- if(totelem == 0)
+ int ret = 0, error = 0;
+
+ /* nothing to read to */
+ if(pid->totpoint(pid->calldata) == 0)
return 0;
+ if(pid->cache->flag & PTCACHE_READ_INFO) {
+ pid->cache->flag &= ~PTCACHE_READ_INFO;
+ BKE_ptcache_read_cache(pid, 0, frs_sec);
+ }
+
/* 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);
+ pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
}
else {
pm = pid->cache->mem_cache.first;
@@ -432,240 +876,261 @@ int BKE_ptcache_read_cache(PTCacheReader *reader)
}
}
- /* 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;
+ /* no exact cache frame found so try to find cached frames around cfra */
+ 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(pf) {
- BKE_ptcache_file_close(pf);
- pf = NULL;
- MEM_freeN(data);
- }
+ old_frame = cfrai;
- ret = PTCACHE_READ_EXACT;
- }
+ cfrai = (int)cfra;
+ while(cfrai < pid->cache->endframe && !pf2) {
+ cfrai++;
+ pf2= ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
+ cfra2 = cfrai;
+ }
- if(ret)
- ;
- /* no exact cache frame found so try to find cached frames around cfra */
- else if(pid->cache->flag & PTCACHE_DISK_CACHE) {
- pf=NULL;
- while(cfrai > pid->cache->startframe && !pf) {
- cfrai--;
- pf= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
- cfra1 = cfrai;
+ if(pf && !pf2) {
+ pf2 = pf;
+ pf = NULL;
+ }
}
+ else if(pid->cache->mem_cache.first){
+ pm = pid->cache->mem_cache.first;
- if(reader->old_frame)
- *(reader->old_frame) = cfrai;
+ while(pm->next && pm->next->frame < cfra)
+ pm= pm->next;
- cfrai = (int)cfra;
- while(cfrai < pid->cache->endframe && !pf2) {
- cfrai++;
- pf2= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
- cfra2 = cfrai;
- }
- }
- else if(pid->cache->mem_cache.first){
- pm = pid->cache->mem_cache.first;
-
- while(pm->next && pm->next->frame < cfra)
- pm= pm->next;
+ if(pm) {
+ old_frame = pm->frame;
+ cfra1 = pm->frame;
+ }
- if(pm) {
- if(reader->old_frame)
- *(reader->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
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 0a1963c84f2..68f918b0c68 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -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);
}
}
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 2b6c372861a..c937dfd88a4 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -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);
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index cf636cc2b94..d8841962e7b 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -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;
diff --git a/source/blender/editors/mesh/editmesh.c b/source/blender/editors/mesh/editmesh.c
index e32dd0e8ac7..0d4e926f3b5 100644
--- a/source/blender/editors/mesh/editmesh.c
+++ b/source/blender/editors/mesh/editmesh.c
@@ -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;
diff --git a/source/blender/editors/physics/ed_pointcache.c b/source/blender/editors/physics/ed_pointcache.c
index 5d0a6d21fac..a256fd97686 100644
--- a/source/blender/editors/physics/ed_pointcache.c
+++ b/source/blender/editors/physics/ed_pointcache.c
@@ -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)
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 3f504848d77..9d1707599b9 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -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 {
diff --git a/source/blender/makesdna/DNA_object_force.h b/source/blender/makesdna/DNA_object_force.h
index b5b33610bfe..d7ef3d73ecf 100644
--- a/source/blender/makesdna/DNA_object_force.h
+++ b/source/blender/makesdna/DNA_object_force.h
@@ -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
diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h
index b71d390db5a..925fd31328d 100644
--- a/source/blender/makesdna/DNA_particle_types.h
+++ b/source/blender/makesdna/DNA_particle_types.h
@@ -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;
diff --git a/source/blender/makesrna/intern/rna_fluidsim.c b/source/blender/makesrna/intern/rna_fluidsim.c
index b7084a0b26d..936e1700ed7 100644
--- a/source/blender/makesrna/intern/rna_fluidsim.c
+++ b/source/blender/makesrna/intern/rna_fluidsim.c
@@ -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);
diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c
index f04001d8a64..93274a01cc5 100644
--- a/source/blender/makesrna/intern/rna_object_force.c
+++ b/source/blender/makesrna/intern/rna_object_force.c
@@ -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)