diff --git a/release/ui/buttons_particle.py b/release/ui/buttons_particle.py index f35d15bbb80..dae95dfcc00 100644 --- a/release/ui/buttons_particle.py +++ b/release/ui/buttons_particle.py @@ -151,6 +151,13 @@ class PARTICLE_PT_cache(ParticleButtonsPanel): psys = context.particle_system part = psys.settings cache = psys.point_cache + layout.set_context_pointer("PointCache", cache) + + row = layout.row() + row.template_list(cache, "point_cache_list", cache, "active_point_cache_index") + col = row.column(align=True) + col.itemO("ptcache.add_new", icon="ICON_ZOOMIN", text="") + col.itemO("ptcache.remove", icon="ICON_ZOOMOUT", text="") row = layout.row() row.itemL(text="File Name:") @@ -166,37 +173,38 @@ class PARTICLE_PT_cache(ParticleButtonsPanel): layout.itemL(text=cache.info) - split = layout.split() + #split = layout.split() - col = split.column(align=True) - col.itemR(part, "start") - col.itemR(part, "end") + #col = split.column(align=True) + #col.itemR(part, "start") + #col.itemR(part, "end") - col = split.column(align=True) - col.itemR(part, "lifetime") - col.itemR(part, "random_lifetime", slider=True) + #col = split.column(align=True) + #col.itemR(part, "lifetime") + #col.itemR(part, "random_lifetime", slider=True) else: layout.itemR(cache, "name", text="") row = layout.row() if cache.baked == True: - row.itemO("ptcache.free_bake_particle_system", text="Free Bake") + row.itemO("ptcache.free_bake", text="Free Bake") else: - row.item_booleanO("ptcache.cache_particle_system", "bake", True, text="Bake") + row.item_booleanO("ptcache.bake", "bake", True, text="Bake") subrow = row.row() subrow.enabled = (cache.frames_skipped or cache.outdated) and particle_panel_enabled(psys) - subrow.itemO("ptcache.cache_particle_system", text="Calculate to Current Frame") + subrow.itemO("ptcache.bake", "bake", False, text="Calculate to Current Frame") row = layout.row() row.enabled = particle_panel_enabled(psys) - row.itemO("ptcache.bake_from_particles_cache", text="Current Cache to Bake") + row.itemO("ptcache.bake_from_cache", text="Current Cache to Bake") row.itemR(cache, "step"); row = layout.row() - row.enabled = particle_panel_enabled(psys) - row.itemR(cache, "quick_cache") + subrow = row.row() + subrow.enabled = particle_panel_enabled(psys) + subrow.itemR(cache, "quick_cache") row.itemR(cache, "disk_cache") layout.itemL(text=cache.info) @@ -206,7 +214,7 @@ class PARTICLE_PT_cache(ParticleButtonsPanel): row = layout.row() row.item_booleanO("ptcache.bake_all", "bake", True, text="Bake All Dynamics") row.itemO("ptcache.free_bake_all", text="Free All Bakes") - layout.itemO("ptcache.bake_all", text="Update All Dynamics to current frame") + layout.itemO("ptcache.bake_all", "bake", False, text="Update All Dynamics to current frame") # for particles these are figured out automatically #row.itemR(cache, "start_frame") diff --git a/release/ui/buttons_physics_cloth.py b/release/ui/buttons_physics_cloth.py index 1bd1c507ccf..0edf099fa90 100644 --- a/release/ui/buttons_physics_cloth.py +++ b/release/ui/buttons_physics_cloth.py @@ -85,6 +85,13 @@ class PHYSICS_PT_cloth_cache(PhysicButtonsPanel): layout = self.layout cache = context.cloth.point_cache + layout.set_context_pointer("PointCache", cache) + + row = layout.row() + row.template_list(cache, "point_cache_list", cache, "active_point_cache_index") + col = row.column(align=True) + col.itemO("ptcache.add_new", icon="ICON_ZOOMIN", text="") + col.itemO("ptcache.remove", icon="ICON_ZOOMOUT", text="") row = layout.row() row.itemR(cache, "name") @@ -96,17 +103,17 @@ class PHYSICS_PT_cloth_cache(PhysicButtonsPanel): row = layout.row() if cache.baked == True: - row.itemO("ptcache.free_bake_cloth", text="Free Bake") + row.itemO("ptcache.free_bake", text="Free Bake") else: - row.item_booleanO("ptcache.cache_cloth", "bake", True, text="Bake") + row.item_booleanO("ptcache.bake", "bake", True, text="Bake") subrow = row.row() subrow.enabled = cache.frames_skipped or cache.outdated - subrow.itemO("ptcache.cache_cloth", text="Calculate to Current Frame") + subrow.itemO("ptcache.bake", "bake", False, text="Calculate to Current Frame") row = layout.row() #row.enabled = particle_panel_enabled(psys) - row.itemO("ptcache.bake_from_cloth_cache", text="Current Cache to Bake") + row.itemO("ptcache.bake_from_cache", text="Current Cache to Bake") row.itemR(cache, "step"); row = layout.row() @@ -121,7 +128,7 @@ class PHYSICS_PT_cloth_cache(PhysicButtonsPanel): row = layout.row() row.itemO("ptcache.bake_all", "bake", True, text="Bake All Dynamics") row.itemO("ptcache.free_bake_all", text="Free All Bakes") - layout.itemO("ptcache.bake_all", text="Update All Dynamics to current frame") + layout.itemO("ptcache.bake_all", "bake", False, text="Update All Dynamics to current frame") class PHYSICS_PT_cloth_collision(PhysicButtonsPanel): __label__ = "Cloth Collision" diff --git a/release/ui/buttons_physics_softbody.py b/release/ui/buttons_physics_softbody.py index c17d6e3bcf9..d0d3475c11b 100644 --- a/release/ui/buttons_physics_softbody.py +++ b/release/ui/buttons_physics_softbody.py @@ -63,6 +63,13 @@ class PHYSICS_PT_softbody_cache(PhysicButtonsPanel): layout = self.layout cache = context.soft_body.point_cache + layout.set_context_pointer("PointCache", cache) + + row = layout.row() + row.template_list(cache, "point_cache_list", cache, "active_point_cache_index") + col = row.column(align=True) + col.itemO("ptcache.add_new", icon="ICON_ZOOMIN", text="") + col.itemO("ptcache.remove", icon="ICON_ZOOMOUT", text="") row = layout.row() row.itemR(cache, "name") @@ -74,16 +81,16 @@ class PHYSICS_PT_softbody_cache(PhysicButtonsPanel): row = layout.row() if cache.baked == True: - row.itemO("ptcache.free_bake_softbody", text="Free Bake") + row.itemO("ptcache.free_bake", text="Free Bake") else: - row.item_booleanO("ptcache.cache_softbody", "bake", True, text="Bake") + row.item_booleanO("ptcache.bake", "bake", True, text="Bake") sub = row.row() sub.enabled = cache.frames_skipped or cache.outdated - sub.itemO("ptcache.cache_softbody", text="Calculate to Current Frame") + sub.itemO("ptcache.bake", "bake", False, text="Calculate to Current Frame") row = layout.row() - row.itemO("ptcache.bake_from_softbody_cache", text="Current Cache to Bake") + row.itemO("ptcache.bake_from_cache", text="Current Cache to Bake") row.itemR(cache, "step"); row = layout.row() @@ -97,7 +104,7 @@ class PHYSICS_PT_softbody_cache(PhysicButtonsPanel): row = layout.row() row.itemO("ptcache.bake_all", "bake", True, text="Bake All Dynamics") row.itemO("ptcache.free_bake_all", text="Free All Bakes") - layout.itemO("ptcache.bake_all", text="Update All Dynamics to current frame") + layout.itemO("ptcache.bake_all", "bake", False, text="Update All Dynamics to current frame") class PHYSICS_PT_softbody_goal(PhysicButtonsPanel): __label__ = "Soft Body Goal" 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,43 +75,53 @@ 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; + + 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); + + int (*totpoint)(void *calldata); + int (*totwrite)(void *calldata); + + int (*write_header)(PTCacheFile *pf); + int (*read_header)(PTCacheFile *pf); struct PointCache *cache; + struct PointCache **cache_ptr; + struct ListBase *ptcaches; } PTCacheID; -typedef struct PTCacheWriter { - struct PTCacheID *pid; - int cfra; - int totelem; - - void (*set_elem)(int index, void *calldata, float *data); - void *calldata; -} PTCacheWriter; - -typedef struct PTCacheReader { - struct Scene *scene; - struct PTCacheID *pid; - float cfra; - int totelem; - - 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 *old_frame; -} PTCacheReader; - typedef struct PTCacheBaker { struct Scene *scene; int bake; @@ -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; ptime > 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, ×); + 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; ptotpart; 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<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<part->flag & (PART_UNBORN|PART_DIED))==0) + // pid->data_types|= (1<part->phystype == PART_PHYS_BOIDS) + pid->data_types|= (1<part->rotmode || psys->part->avemode) + pid->data_types|= (1<part->flag & PART_ROT_DYN) + pid->data_types|= (1<info_types= (1<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<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,23 +647,181 @@ 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); +} +static int ptcache_file_write(PTCacheFile *pf, void *f, int tot, int size) +{ + return (fwrite(f, size, tot, pf->fp) == tot); +} +static int ptcache_file_read_data(PTCacheFile *pf) +{ + int i; + + for(i=0; idata_types & (1<cur[i], 1, BKE_ptcache_data_size(i))) + return 0; + } + + return 1; +} +static int ptcache_file_write_data(PTCacheFile *pf) +{ + int i; + + for(i=0; idata_types & (1<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; + + 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; } -int BKE_ptcache_file_write_floats(PTCacheFile *pf, float *f, int tot) + +static int ptcache_file_write_header_begin(PTCacheFile *pf) { - return (fwrite(f, sizeof(float), tot, pf->fp) == tot); + char *bphysics = "BPHYSICS"; + + if(fwrite(bphysics, sizeof(char), 8, pf->fp) != 8) + return 0; + + if(!fwrite(&pf->type, sizeof(int), 1, pf->fp)) + return 0; + + return 1; } -static int ptcache_pid_elemsize(PTCacheID *pid) + +/* 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 + memcpy(to, data[type], BKE_ptcache_data_size(type)); + } +} + +static void ptcache_data_from(void **data, int type, void *from) +{ + if(data[type]) + memcpy(data[type], from, BKE_ptcache_data_size(type)); +} + +static void ptcache_file_init_pointers(PTCacheFile *pf) +{ + int data_types = pf->data_types; + + pf->cur[BPHYS_DATA_INDEX] = data_types & (1<data.index : NULL; + pf->cur[BPHYS_DATA_LOCATION] = data_types & (1<data.loc : NULL; + pf->cur[BPHYS_DATA_VELOCITY] = data_types & (1<data.vel : NULL; + pf->cur[BPHYS_DATA_ROTATION] = data_types & (1<data.rot : NULL; + pf->cur[BPHYS_DATA_AVELOCITY] = data_types & (1<data.ave : NULL; + pf->cur[BPHYS_DATA_SIZE] = data_types & (1<data.size : NULL; + pf->cur[BPHYS_DATA_TIMES] = data_types & (1<data.times : NULL; + pf->cur[BPHYS_DATA_BOIDS] = data_types & (1<data.boids : NULL; +} + +static void ptcache_mem_init_pointers(PTCacheMem *pm) +{ + int data_types = pm->data_types; + int i; + + for(i=0; icur[i] = data_types & (1<data[i] : NULL; +} + +static void ptcache_mem_incr_pointers(PTCacheMem *pm) +{ + int i; + + for(i=0; icur[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; + + for(i=0; idata[i] = MEM_callocN(totpoint * BKE_ptcache_data_size(i), "PTCache Data"); + } +} +static void ptcache_free_data(void *data[]) +{ + int i; + + for(i=0; itype==PTCACHE_TYPE_SOFTBODY) return 6 * sizeof(float); @@ -318,109 +832,39 @@ static int ptcache_pid_elemsize(PTCacheID *pid) 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; - } - else if(pid->type==PTCACHE_TYPE_CLOTH) { - ClothModifierData *clmd = pid->data; - return clmd->clothObject->numverts; - } - return 0; -} - -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) - sprintf(cache->info, "%i points read for %i frames", cache->totpoint, totframes); - 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_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); -} /* reads cache from disk or memory */ /* possible to get old or interpolated result */ -int BKE_ptcache_read_cache(PTCacheReader *reader) +int BKE_ptcache_read_cache(PTCacheID *pid, float cfra, float frs_sec) { - PTCacheID *pid = reader->pid; PTCacheFile *pf=NULL, *pf2=NULL; PTCacheMem *pm=NULL, *pm2=NULL; - int totelem = reader->totelem; - float cfra = reader->cfra; + float old_data1[14], old_data2[14]; int cfrai = (int)cfra; - int elemsize = ptcache_pid_elemsize(pid); - int i, incr = elemsize / sizeof(float); - float frs_sec = reader->scene->r.frs_sec; - int cfra1=0, cfra2; - int ret = 0; + int old_elemsize = ptcache_pid_old_elemsize(pid); + int i, incr = old_elemsize / sizeof(float); - if(totelem == 0) + int cfra1 = 0, cfra2 = 0; + int totpoint = 0, totpoint2 = 0; + int *index = &i, *index2 = &i; + int use_old = 0, old_frame; + + int ret = 0, error = 0; + + /* 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; iset_elem(i, reader->calldata, data); - } - else { - reader->set_elem(i, reader->calldata, data); - data += incr; - } - } - - if(pf) { - BKE_ptcache_file_close(pf); - pf = NULL; - MEM_freeN(data); - } - - ret = PTCACHE_READ_EXACT; - } - - if(ret) - ; /* no exact cache frame found so try to find cached frames around cfra */ - else if(pid->cache->flag & PTCACHE_DISK_CACHE) { - pf=NULL; - while(cfrai > pid->cache->startframe && !pf) { - cfrai--; - pf= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai); - cfra1 = cfrai; + if(!pm && !pf) { + if(pid->cache->flag & PTCACHE_DISK_CACHE) { + pf=NULL; + while(cfrai > pid->cache->startframe && !pf) { + cfrai--; + pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai); + cfra1 = cfrai; + } + + old_frame = cfrai; + + cfrai = (int)cfra; + while(cfrai < pid->cache->endframe && !pf2) { + cfrai++; + pf2= ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai); + cfra2 = cfrai; + } + + if(pf && !pf2) { + pf2 = pf; + pf = NULL; + } } + else if(pid->cache->mem_cache.first){ + pm = pid->cache->mem_cache.first; - 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; + if(pm) { + old_frame = pm->frame; + cfra1 = pm->frame; + } - while(pm->next && pm->next->frame < cfra) - pm= pm->next; + pm2 = pid->cache->mem_cache.last; - if(pm) { - if(reader->old_frame) - *(reader->old_frame) = pm->frame; - cfra1 = pm->frame; - } + if(pm2 && pm2->frame < cfra) + pm2 = NULL; + else { + while(pm2->prev && pm2->prev->frame > cfra) + pm2= pm2->prev; - pm2 = pid->cache->mem_cache.last; + if(pm2) + cfra2 = pm2->frame; + } - if(pm2 && pm2->frame < cfra) - pm2 = NULL; - else { - while(pm2->prev && pm2->prev->frame > cfra) - pm2= pm2->prev; - - 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<cur[BPHYS_DATA_INDEX] : &i; + } + if(pm2) { + ptcache_mem_init_pointers(pm2); + totpoint2 = pm2->totpoint; + index2 = pm2->data_types & (1<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; iinterpolate_elem(i, reader->calldata, frs_sec, cfra, (float)cfra1, (float)cfra2, data1, data2); - } - else { - reader->interpolate_elem(i, reader->calldata, frs_sec, cfra, (float)cfra1, (float)cfra2, data1, data2); - data1 += incr; - data2 += incr; - } - } - - if(pf) { - BKE_ptcache_file_close(pf); - pf = NULL; - BKE_ptcache_file_close(pf2); - pf2 = NULL; - MEM_freeN(data1); - MEM_freeN(data2); - } - - ret = PTCACHE_READ_INTERPOLATED; } - else if(pf || pm) { - /* use last valid cache frame */ - float *data; - - /* don't read cache if allready simulated past cached frame */ - if(cfra1 && cfra1 <= pid->cache->simframe) { - if(pf) - BKE_ptcache_file_close(pf); - if(pf2) - BKE_ptcache_file_close(pf2); - - return 0; - } - - if(pm) - data = pm->data; - else - data = MEM_callocN(elemsize, "pointcache read data"); - - for(i=0; iset_elem(i, reader->calldata, data); + 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->set_elem(i, reader->calldata, data); - data += 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; - MEM_freeN(data); + else { + /* fall back to old cache file format */ + use_old = 1; + totpoint2 = pid->totpoint(pid->calldata); } - if(pf2) { - BKE_ptcache_file_close(pf2); - pf = NULL; + } + + /* 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; + + totpoint = MIN2(totpoint, pid->totpoint(pid->calldata)); + totpoint2 = MIN2(totpoint2, pid->totpoint(pid->calldata)); + + if(!error) for(i=0; iread_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) { + ptcache_mem_incr_pointers(pm); + index = pm->data_types & (1<cur[BPHYS_DATA_INDEX] : &i; + } + } + + if(!error) for(i=0; iread_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 + { 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(pm2) { + ptcache_mem_incr_pointers(pm2); + index2 = pm2->data_types & (1<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; itotpoint; 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; itotelem; 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; iwrite_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; + if(add || overwrite) { + if(overwrite) + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, pm2->frame); - for(i=0; itotelem; i++, pmdata+=incr) { - writer->set_elem(i, writer->calldata, temp); - memcpy(pmdata, temp, elemsize); - } - - 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; itotelem; 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; + + ptcache_alloc_data(pm); + ptcache_mem_init_pointers(pm); + + for(i=0; iwrite_elem(i, pid->calldata, pm->cur)) + ptcache_mem_incr_pointers(pm); } + //ptcache_make_index_array(pm, pid->totpoint(pid->calldata)); - pm->frame = writer->cfra; - pm->totpoint = writer->totelem; - + 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,14 +1844,125 @@ 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 cfra, sfra = cache->startframe, efra = cache->endframe; + int i; + + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); + + for(cfra=sfra; cfra <= efra; cfra++) { + pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra); + + 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; + } + + 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"); + + pm->totpoint = pf->totpoint; + pm->data_types = pf->data_types; + pm->frame = cfra; + + ptcache_alloc_data(pm); + ptcache_mem_init_pointers(pm); + ptcache_file_init_pointers(pf); + + for(i=0; itotpoint; i++) { + if(!ptcache_file_read_data(pf)) { + printf("Error reading from disk cache\n"); + + cache->flag |= PTCACHE_DISK_CACHE; + + ptcache_free_data(pm->data); + MEM_freeN(pm); + ptcache_file_close(pf); + + return; + } + ptcache_copy_data(pf->cur, pm->cur); + ptcache_mem_incr_pointers(pm); + } + + //ptcache_make_index_array(pm, pid->totpoint(pid->calldata)); + + BLI_addtail(&pid->cache->mem_cache, pm); + + ptcache_file_close(pf); + } + } + +} +void BKE_ptcache_mem_to_disk(PTCacheID *pid) +{ + PointCache *cache = pid->cache; + PTCacheFile *pf; + PTCacheMem *pm; + int i; + + pm = cache->mem_cache.first; + + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); + + for(; pm; pm=pm->next) { + pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, pm->frame); + + if(pf) { + pf->data_types = pm->data_types; + pf->totpoint = pm->totpoint; + pf->type = pid->type; + + ptcache_mem_init_pointers(pm); + ptcache_file_init_pointers(pf); + + if(!ptcache_file_write_header_begin(pf) || !pid->write_header(pf)) { + printf("Error writing to disk cache\n"); + cache->flag &= ~PTCACHE_DISK_CACHE; + + ptcache_file_close(pf); + return; + } + + for(i=0; itotpoint; 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; + + 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; if (!G.relbase_valid){ @@ -1357,81 +1971,14 @@ void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) { return; } - totelem = ptcache_pid_totelem(pid); - float_count = ptcache_pid_elemsize(pid) / sizeof(float); + if(cache->flag & PTCACHE_DISK_CACHE) + BKE_ptcache_mem_to_disk(pid); + else + BKE_ptcache_disk_to_mem(pid); - if(totelem==0 || float_count==0) - return; - - tot = totelem*float_count; - - /* MEM -> DISK */ - if(cache->flag & PTCACHE_DISK_CACHE) { - pm = cache->mem_cache.first; - - BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); - - for(; pm; pm=pm->next) { - pf = BKE_ptcache_file_open(pid, PTCACHE_FILE_WRITE, pm->frame); - - if(pf) { - if(fwrite(pm->data, sizeof(float), tot, pf->fp) != tot) { - printf("Error writing to disk cache\n"); - - cache->flag &= ~PTCACHE_DISK_CACHE; - - BKE_ptcache_file_close(pf); - return; - } - BKE_ptcache_file_close(pf); - } - 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; - } - /* DISK -> MEM */ - else { - int cfra; - int sfra = cache->startframe; - int efra = cache->endframe; - - BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); - - for(cfra=sfra; cfra <= efra; cfra++) { - pf = BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfra); - - if(pf) { - pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem"); - pm->data = MEM_callocN(sizeof(float)*tot, "Pointcache mem data"); - - if(fread(pm->data, sizeof(float), tot, pf->fp)!= tot) { - printf("Error reading from disk cache\n"); - - cache->flag |= PTCACHE_DISK_CACHE; - - MEM_freeN(pm->data); - MEM_freeN(pm); - BKE_ptcache_file_close(pf); - return; - } - - pm->frame = cfra; - pm->totpoint = totelem; - - BLI_addtail(&pid->cache->mem_cache, pm); - - BKE_ptcache_file_close(pf); - } - } - - cache->flag |= PTCACHE_DISK_CACHE; - BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); - cache->flag &= ~PTCACHE_DISK_CACHE; - } + 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; idata[i] && pm->data_types & (1<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; - if((cache->flag & PTCACHE_DISK_CACHE)==0) { - PTCacheMem *pm = cache->mem_cache.first; + for(; cache; cache=cache->next) { + writestruct(wd, DATA, "PointCache", 1, cache); - 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); + 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(pm->index_array) + writedata(wd, DATA, sizeof(int) * pm->totpoint, pm->index_array); + + for(i=0; idata[i] && pm->data_types & (1<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) +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; - - if(!scene || !ob || ob->id.lib || !sb) - return 0; - - return 1; -} - -static int ptcache_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; + 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) +{ + PointerRNA ptr= CTX_data_pointer_get_type(C, "PointCache", &RNA_PointCache); + PointCache *cache= ptr.data; + + cache->flag |= PTCACHE_BAKED; + + return OPERATOR_FINISHED; +} +void PTCACHE_OT_bake(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Bake Physics"; + ot->idname= "PTCACHE_OT_bake"; + + /* api callbacks */ + ot->exec= ptcache_bake_exec; + ot->poll= ptcache_bake_all_poll; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "bake", 1, "Bake", ""); +} +void PTCACHE_OT_free_bake(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Free Physics Bake"; + ot->idname= "PTCACHE_OT_free_bake"; + + /* api callbacks */ + ot->exec= ptcache_free_bake_exec; + ot->poll= ptcache_bake_all_poll; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} +void PTCACHE_OT_bake_from_cache(wmOperatorType *ot) { /* identifiers */ ot->name= "Bake From Cache"; - ot->idname= "PTCACHE_OT_bake_from_softbody_cache"; + ot->idname= "PTCACHE_OT_bake_from_cache"; /* api callbacks */ - ot->exec= ptcache_bake_from_softbody_cache_exec; - ot->poll= ptcache_bake_softbody_poll; + ot->exec= ptcache_bake_from_cache_exec; + ot->poll= ptcache_bake_all_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } -/**************************** cloth **********************************/ -static int ptcache_bake_cloth_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); - ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + 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 || !clmd) - return 0; + BKE_ptcache_ids_from_object(&pidlist, ob); - return 1; -} + for(pid=pidlist.first; pid; pid=pid->next) { + if(pid->cache == cache) { + *(pid->cache_ptr) = BKE_ptcache_add(pid->ptcaches); + break; + } + } -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); + BLI_freelistN(&pidlist); WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene); return OPERATOR_FINISHED; } -static int ptcache_free_bake_cloth_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); - ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); - 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_cloth(&pid, ob, clmd); - pid.cache->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; + + break; + } + } + + BLI_freelistN(&pidlist); return OPERATOR_FINISHED; } -void PTCACHE_OT_cache_cloth(wmOperatorType *ot) +void PTCACHE_OT_add_new(wmOperatorType *ot) { /* identifiers */ - ot->name= "Bake Cloth"; - ot->idname= "PTCACHE_OT_cache_cloth"; + ot->name= "Add new cache"; + ot->idname= "PTCACHE_OT_add_new"; /* api callbacks */ - ot->exec= ptcache_bake_cloth_exec; - ot->poll= ptcache_bake_cloth_poll; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - RNA_def_boolean(ot->srna, "bake", 0, "Bake", ""); -} -void PTCACHE_OT_free_bake_cloth(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Free Cloth Bake"; - ot->idname= "PTCACHE_OT_free_bake_cloth"; - - /* api callbacks */ - ot->exec= ptcache_free_bake_cloth_exec; - ot->poll= ptcache_bake_cloth_poll; + ot->exec= ptcache_add_new_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_remove(wmOperatorType *ot) { /* identifiers */ - ot->name= "Bake From Cache"; - ot->idname= "PTCACHE_OT_bake_from_cloth_cache"; + ot->name= "Delete current cache"; + ot->idname= "PTCACHE_OT_remove"; /* api callbacks */ - ot->exec= ptcache_bake_from_cloth_cache_exec; - ot->poll= ptcache_bake_cloth_poll; + ot->exec= ptcache_remove_exec; + ot->poll= ptcache_bake_all_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } - -/**************************** particles **********************************/ -static int ptcache_bake_particle_system_poll(bContext *C) -{ - Scene *scene= CTX_data_scene(C); - Object *ob= CTX_data_active_object(C); - - if(!scene || !ob || ob->id.lib) - return 0; - - 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); - - BKE_ptcache_make_cache(&baker); - - 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) -{ - Scene *scene= CTX_data_scene(C); - 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; - - WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene); - - 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; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - RNA_def_boolean(ot->srna, "bake", 0, "Bake", ""); -} -void PTCACHE_OT_free_bake_particle_system(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Free Particles Bake"; - ot->idname= "PTCACHE_OT_free_bake_particle_system"; - - /* api callbacks */ - ot->exec= ptcache_free_bake_particle_system_exec; - ot->poll= ptcache_bake_particle_system_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) -{ - /* identifiers */ - ot->name= "Bake From Cache"; - ot->idname= "PTCACHE_OT_bake_from_particles_cache"; - - /* api callbacks */ - ot->exec= ptcache_bake_from_particles_cache_exec; - ot->poll= ptcache_bake_particle_system_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<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)