New point cache file format:

- HEADER (beginning of each file)
	* general header:
		+ 8 char: "BPHYSICS"
		+ 1 int: simulation type (same as PTCacheID->type)
	* custom header (same for sb, particles and cloth, but can be different for new dynamics)
		+ 1 int: totpoint (number of points)
		+ 1 int: data_types (bit flags for what the stored data is)
- DATA (directly after header)
	*totpoint times the data as specified in data_types flags

- simulation type
	soft body = 0, particles = 1, cloth = 2
- data types (more can be added easily when needed)
	data		flag		contains
	----------------------------------------
	index		(1<<0)		1 int	(index of current point)
	location	(1<<1)		3 float
	velocity	(1<<2)		3 float
	rotation	(1<<3)		4 float	(quaternion)
	avelocity 	(1<<4)		3 float	(used for particles)
	xconst		(1<<4)		3 float	(used for cloth)
	size		(1<<5)		1 float
	times		(1<<6)		3 float (birth, die & lifetime of particle)
	boids		(1<<7)		1 BoidData
	
Notes:
- Every frame is not nescessary since data is interpolated for the inbetween frames.
- For now every point is needed for every cached frame, the "index" data type is reserved for future usage.
- For loading external particle caches only "location" data is necessary, other needed values are determined from the given data.
- Non-dynamic data should be written into an info file if external usage is desired.
	* Info file is named as normal cache files, but with frame number 0;
	* "Non-dynamic" means data such as particle times.
	* Written automatically when baking to disk so basically a library of particle simulations should be possible.
- Old disk cache format is supported for reading, so pre 2.5 files shouldn't break. However old style memory cache (added during 2.5 development) is not supported. To keep memory cached simulations convert the cache to disk cache before svn update and save the blend.
- External sb and cloth caches should be perfectly possible, but due to lack of testing these are not yet enabled in ui.
	
Other changes:
- Multiple point caches per dynamics system.
	* In the future these will hopefully be nla editable etc, but for now things are simple and the current (selected) point cache is used.
	* Changing the amount of cached points (for example particle count) is allowed, but might not give correct results if multiple caches are present.
- Generalization of point cache baking etc operator & rna code.
- Comb brushing particle hair didn't work smoothly.
This commit is contained in:
Janne Karhu 2009-08-12 09:54:29 +00:00
parent 8641833b57
commit b221c0e2e6
21 changed files with 1497 additions and 1112 deletions

@ -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")

@ -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"

@ -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"

@ -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 );

@ -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);

@ -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

@ -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);
}

@ -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;
}
}

@ -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);

@ -2260,43 +2260,14 @@ void psys_get_reactor_target(Object *ob, ParticleSystem *psys, Object **target_o
void psys_make_temp_pointcache(Object *ob, ParticleSystem *psys)
{
PointCache *cache = psys->pointcache;
PTCacheFile *pf = NULL;
PTCacheMem *pm = NULL;
PTCacheID pid;
int cfra, sfra = cache->startframe, efra = cache->endframe;
int totelem = psys->totpart;
int float_count = sizeof(ParticleKey) / sizeof(float);
int tot = totelem * float_count;
if((cache->flag & PTCACHE_DISK_CACHE)==0 || cache->mem_cache.first)
return;
BKE_ptcache_id_from_particles(&pid, ob, psys);
for(cfra=sfra; cfra <= efra; cfra++) {
pf = BKE_ptcache_file_open(&pid, PTCACHE_FILE_READ, cfra);
if(pf) {
pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache temp mem");
pm->data = MEM_callocN(sizeof(float)*tot, "Pointcache temp mem data");
if(fread(pm->data, sizeof(float), tot, pf->fp)!= tot) {
printf("Error reading from disk cache\n");
MEM_freeN(pm->data);
MEM_freeN(pm);
BKE_ptcache_file_close(pf);
return;
}
pm->frame = cfra;
pm->totpoint = totelem;
BLI_addtail(&cache->mem_cache, pm);
BKE_ptcache_file_close(pf);
}
}
BKE_ptcache_disk_to_mem(&pid);
}
void psys_clear_temp_pointcache(ParticleSystem *psys)
{
@ -2305,11 +2276,7 @@ void psys_clear_temp_pointcache(ParticleSystem *psys)
if((psys->pointcache->flag & PTCACHE_DISK_CACHE)==0)
return;
for(; pm; pm=pm->next) {
MEM_freeN(pm->data);
}
BLI_freelistN(&psys->pointcache->mem_cache);
BKE_ptache_free_mem(psys->pointcache);
}
void psys_get_pointcache_start_end(Scene *scene, ParticleSystem *psys, int *sfra, int *efra)
{
@ -2318,88 +2285,6 @@ void psys_get_pointcache_start_end(Scene *scene, ParticleSystem *psys, int *sfra
*sfra = MAX2(1, (int)part->sta);
*efra = MIN2((int)(part->end + part->lifetime + 1.0), scene->r.efra);
}
static void particle_write_state(int index, void *psys_ptr, float *data)
{
ParticleSystem *psys= psys_ptr;
memcpy(data, (float *)(&(psys->particles+index)->state), sizeof(ParticleKey));
}
static void particle_read_state(int index, void *psys_ptr, float *data)
{
ParticleSystem *psys= psys_ptr;
ParticleData *pa = psys->particles + index;
ParticleKey *key = (ParticleKey *)data;
if(key->time > pa->state.time)
copy_particle_key(&pa->prev_state, &pa->state, 1);
copy_particle_key(&pa->state, key, 1);
}
static void particle_cache_interpolate(int index, void *psys_ptr, float frs_sec, float cfra, float cfra1, float cfra2, float *data1, float *data2)
{
ParticleSystem *psys= psys_ptr;
ParticleData *pa = psys->particles + index;
ParticleKey keys[4];
float dfra;
cfra = MIN2(cfra, pa->dietime);
cfra1 = MIN2(cfra1, pa->dietime);
cfra2 = MIN2(cfra2, pa->dietime);
keys[1] = *((ParticleKey*)data1);
keys[2] = *((ParticleKey*)data2);
if(cfra1 == cfra2) {
copy_particle_key(&pa->state, &keys[1], 1);
return;
}
dfra = cfra2 - cfra1;
VecMulf(keys[1].vel, dfra / frs_sec);
VecMulf(keys[2].vel, dfra / frs_sec);
psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1);
QuatInterpol(pa->state.rot, keys[1].rot,keys[2].rot, (cfra - cfra1) / dfra);
VecMulf(pa->state.vel, frs_sec / dfra);
pa->state.time = cfra;
}
static void write_particles_to_cache(Object *ob, ParticleSystem *psys, int cfra)
{
PTCacheWriter writer;
PTCacheID pid;
BKE_ptcache_id_from_particles(&pid, ob, psys);
writer.calldata = psys;
writer.cfra = cfra;
writer.set_elem = particle_write_state;
writer.pid = &pid;
writer.totelem = psys->totpart;
BKE_ptcache_write_cache(&writer);
}
static int get_particles_from_cache(Scene *scene, Object *ob, ParticleSystem *psys, float cfra, int *old_frame)
{
PTCacheReader reader;
PTCacheID pid;
BKE_ptcache_id_from_particles(&pid, ob, psys);
reader.calldata = psys;
reader.cfra = cfra;
reader.interpolate_elem = particle_cache_interpolate;
reader.old_frame = old_frame;
reader.pid = &pid;
reader.scene = scene;
reader.set_elem = particle_read_state;
reader.totelem = psys->totpart;
return BKE_ptcache_read_cache(&reader);
}
/************************************************/
/* Effectors */
@ -4237,7 +4122,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
int totpart, oldtotpart, totchild, oldtotchild, p;
float disp, *vg_vel= 0, *vg_tan= 0, *vg_rot= 0, *vg_size= 0;
int init= 0, distr= 0, alloc= 0, usecache= 0, only_children_changed= 0;
int framenr, framedelta, startframe, endframe, old_framenr;
int framenr, framedelta, startframe, endframe;
part= psys->part;
cache= psys->pointcache;
@ -4327,8 +4212,10 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
if(alloc) {
realloc_particles(ob, psys, totpart);
if(usecache && !only_children_changed)
if(usecache && !only_children_changed) {
BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0);
BKE_ptcache_id_from_particles(&pid, ob, psys);
}
}
if(!only_children_changed)
@ -4358,7 +4245,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
/* try to read from the cache */
if(usecache) {
int result = get_particles_from_cache(scene, ob, psys, (float)framenr, &old_framenr);
int result = BKE_ptcache_read_cache(&pid, cfra, scene->r.frs_sec);
if(result == PTCACHE_READ_EXACT || result == PTCACHE_READ_INTERPOLATED) {
cached_step(scene, ob, psmd, psys, cfra);
@ -4369,14 +4256,12 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
cache->flag |= PTCACHE_SIMULATION_VALID;
if(result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED)
write_particles_to_cache(ob, psys, cfra);
BKE_ptcache_write_cache(&pid, (int)cfra);
return;
}
else if(result==PTCACHE_READ_OLD) {
/* set old cfra */
psys->cfra = (float)old_framenr;
psys->cfra = (float)cache->simframe;
for(p=0, pa=psys->particles; p<totpart; p++, pa++) {
/* update alive status */
if(pa->time > psys->cfra)
@ -4402,7 +4287,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
/* if on second frame, write cache for first frame */
if(usecache && psys->cfra == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0))
write_particles_to_cache(ob, psys, startframe);
BKE_ptcache_write_cache(&pid, startframe);
if(part->phystype==PART_PHYS_KEYED)
psys_count_keyed_targets(ob,psys);
@ -4448,7 +4333,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
/* only write cache starting from second frame */
if(usecache && framenr != startframe)
write_particles_to_cache(ob, psys, framenr);
BKE_ptcache_write_cache(&pid, (int)cfra);
/* for keyed particles the path is allways known so it can be drawn */
if(part->phystype==PART_PHYS_KEYED) {

File diff suppressed because it is too large Load Diff

@ -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);
}
}

@ -2929,13 +2929,21 @@ static void direct_link_pointcache(FileData *fd, PointCache *cache)
{
if((cache->flag & PTCACHE_DISK_CACHE)==0) {
PTCacheMem *pm;
int i;
link_list(fd, &cache->mem_cache);
pm = cache->mem_cache.first;
for(; pm; pm=pm->next)
pm->data = newdataadr(fd, pm->data);
for(; pm; pm=pm->next) {
if(pm->index_array)
pm->index_array = newdataadr(fd, pm->index_array);
for(i=0; i<BPHYS_TOT_DATA; i++) {
if(pm->data[i] && pm->data_types & (1<<i))
pm->data[i] = newdataadr(fd, pm->data[i]);
}
}
}
else
cache->mem_cache.first = cache->mem_cache.last = NULL;
@ -2944,6 +2952,24 @@ static void direct_link_pointcache(FileData *fd, PointCache *cache)
cache->simframe= 0;
}
static void direct_link_pointcache_list(FileData *fd, ListBase *ptcaches, PointCache **ocache)
{
PointCache *cache;
if(ptcaches->first) {
link_list(fd, ptcaches);
for(cache=ptcaches->first; cache; cache=cache->next)
direct_link_pointcache(fd, cache);
*ocache = newdataadr(fd, *ocache);
}
else if(*ocache) {
/* old "single" caches need to be linked too for do-versions */
*ocache = newdataadr(fd, *ocache);
direct_link_pointcache(fd, *ocache);
}
}
static void lib_link_particlesettings(FileData *fd, Main *main)
{
ParticleSettings *part;
@ -3089,9 +3115,7 @@ static void direct_link_particlesystems(FileData *fd, ListBase *particles)
sb->bspring= NULL;
sb->scratch= NULL;
sb->pointcache= newdataadr(fd, sb->pointcache);
if(sb->pointcache)
direct_link_pointcache(fd, sb->pointcache);
direct_link_pointcache_list(fd, &sb->ptcaches, &sb->pointcache);
}
link_list(fd, &psys->targets);
@ -3104,9 +3128,7 @@ static void direct_link_particlesystems(FileData *fd, ListBase *particles)
psys->childcachebufs.first = psys->childcachebufs.last = 0;
psys->reactevents.first = psys->reactevents.last = 0;
psys->pointcache= newdataadr(fd, psys->pointcache);
if(psys->pointcache)
direct_link_pointcache(fd, psys->pointcache);
direct_link_pointcache_list(fd, &psys->ptcaches, &psys->pointcache);
psys->tree = NULL;
}
@ -3630,8 +3652,7 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
clmd->coll_parms= newdataadr(fd, clmd->coll_parms);
clmd->point_cache= newdataadr(fd, clmd->point_cache);
if(clmd->point_cache)
direct_link_pointcache(fd, clmd->point_cache);
direct_link_pointcache_list(fd, &clmd->ptcaches, &clmd->point_cache);
if(clmd->sim_parms) {
if(clmd->sim_parms->presets > 10)
@ -3888,7 +3909,7 @@ static void direct_link_object(FileData *fd, Object *ob)
sb->pointcache= newdataadr(fd, sb->pointcache);
if(sb->pointcache)
direct_link_pointcache(fd, sb->pointcache);
direct_link_pointcache_list(fd, &sb->ptcaches, &sb->pointcache);
}
ob->bsoft= newdataadr(fd, ob->bsoft);
ob->fluidsimSettings= newdataadr(fd, ob->fluidsimSettings); /* NT */
@ -8301,20 +8322,20 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
/* add point caches */
for(ob=main->object.first; ob; ob=ob->id.next) {
if(ob->soft && !ob->soft->pointcache)
ob->soft->pointcache= BKE_ptcache_add();
ob->soft->pointcache= BKE_ptcache_add(&ob->soft->ptcaches);
for(psys=ob->particlesystem.first; psys; psys=psys->next) {
if(psys->soft && !psys->soft->pointcache)
psys->soft->pointcache= BKE_ptcache_add();
psys->soft->pointcache= BKE_ptcache_add(&psys->soft->ptcaches);
if(!psys->pointcache)
psys->pointcache= BKE_ptcache_add();
psys->pointcache= BKE_ptcache_add(&psys->ptcaches);
}
for(md=ob->modifiers.first; md; md=md->next) {
if(md->type==eModifierType_Cloth) {
ClothModifierData *clmd = (ClothModifierData*) md;
if(!clmd->point_cache)
clmd->point_cache= BKE_ptcache_add();
clmd->point_cache= BKE_ptcache_add(&clmd->ptcaches);
}
}
}
@ -8602,7 +8623,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
/* create new particle system */
psys = MEM_callocN(sizeof(ParticleSystem), "particle_system");
psys->pointcache = BKE_ptcache_add();
psys->pointcache = BKE_ptcache_add(&psys->ptcaches);
part = psys->part = psys_new_settings("ParticleSettings", main);
@ -9344,9 +9365,19 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
Tex *tex;
Scene *sce;
ToolSettings *ts;
PTCacheID *pid;
ListBase pidlist;
int i, a;
for(ob = main->object.first; ob; ob = ob->id.next) {
BKE_ptcache_ids_from_object(&pidlist, ob);
for(pid=pidlist.first; pid; pid=pid->next) {
if(pid->ptcaches->first == NULL)
pid->ptcaches->first = pid->ptcaches->last = pid->cache;
}
BLI_freelistN(&pidlist);
if(ob->type == OB_MESH) {
Mesh *me = newlibadr(fd, lib, ob->data);

@ -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; i<BPHYS_TOT_DATA; i++) {
if(pm->data[i] && pm->data_types & (1<<i))
writedata(wd, DATA, BKE_ptcache_data_size(i) * pm->totpoint, pm->data[i]);
}
}
}
}
}
@ -652,8 +661,8 @@ static void write_particlesystems(WriteData *wd, ListBase *particles)
if(psys->child) writestruct(wd, DATA, "ChildParticle", psys->totchild ,psys->child);
writestruct(wd, DATA, "SoftBody", 1, psys->soft);
if(psys->soft) write_pointcaches(wd, psys->soft->pointcache, PTCACHE_WRITE_PSYS);
write_pointcaches(wd, psys->pointcache, PTCACHE_WRITE_PSYS);
if(psys->soft) write_pointcaches(wd, &psys->soft->ptcaches);
write_pointcaches(wd, &psys->ptcaches);
}
}
@ -1112,7 +1121,7 @@ static void write_modifiers(WriteData *wd, ListBase *modbase, int write_undo)
writestruct(wd, DATA, "ClothSimSettings", 1, clmd->sim_parms);
writestruct(wd, DATA, "ClothCollSettings", 1, clmd->coll_parms);
write_pointcaches(wd, clmd->point_cache, PTCACHE_WRITE_CLOTH);
write_pointcaches(wd, &clmd->ptcaches);
}
else if(md->type==eModifierType_Smoke) {
SmokeModifierData *smd = (SmokeModifierData*) md;

@ -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;

@ -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)

@ -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 {

@ -74,14 +74,36 @@ typedef struct PartDeflect {
int seed; /* wind noise random seed */
} PartDeflect;
/* Point cache file data types:
/* - used as (1<<flag) so poke jahka if you reach the limit of 15
/* - to add new data types update:
/* * BKE_ptcache_data_size()
/* * ptcache_file_init_pointers()
*/
#define BPHYS_DATA_INDEX 0
#define BPHYS_DATA_LOCATION 1
#define BPHYS_DATA_VELOCITY 2
#define BPHYS_DATA_ROTATION 3
#define BPHYS_DATA_AVELOCITY 4 /* used for particles */
#define BPHYS_DATA_XCONST 4 /* used for cloth */
#define BPHYS_DATA_SIZE 5
#define BPHYS_DATA_TIMES 6
#define BPHYS_DATA_BOIDS 7
#define BPHYS_TOT_DATA 8
typedef struct PTCacheMem {
struct PTCacheMem *next, *prev;
int frame, totpoint;
float *data; /* data points */
void *xdata; /* extra data */
unsigned int data_types, rt;
int *index_array; /* quick access to stored points with index */
void *data[8]; /* BPHYS_TOT_DATA */
void *cur[8]; /* BPHYS_TOT_DATA */
} PTCacheMem;
typedef struct PointCache {
struct PointCache *next, *prev;
int flag; /* generic flag */
int step; /* frames between cached frames */
int simframe; /* current frame of simulation (only if SIMULATION_VALID) */
@ -229,6 +251,7 @@ typedef struct SoftBody {
float inpush;
struct PointCache *pointcache;
struct ListBase ptcaches;
} SoftBody;
@ -283,6 +306,7 @@ typedef struct SoftBody {
#define PTCACHE_QUICK_CACHE 128
#define PTCACHE_FRAMES_SKIPPED 256
#define PTCACHE_EXTERNAL 512
#define PTCACHE_READ_INFO 1024
/* PTCACHE_OUTDATED + PTCACHE_FRAMES_SKIPPED */
#define PTCACHE_REDO_NEEDED 258

@ -229,6 +229,7 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in
/* point cache */
struct PointCache *pointcache;
struct ListBase ptcaches;
struct KDTree *tree; /* used for interactions with self and other systems */
}ParticleSystem;

@ -98,7 +98,7 @@ static void rna_FluidSettings_update_type(bContext *C, PointerRNA *ptr)
part->type= PART_FLUID;
psys->part= part;
psys->pointcache= BKE_ptcache_add();
psys->pointcache= BKE_ptcache_add(&psys->ptcaches);
psys->flag |= PSYS_ENABLED;
BLI_addtail(&ob->particlesystem,psys);

@ -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)