diff options
Diffstat (limited to 'source/blender/blenkernel/intern/pointcache.c')
-rw-r--r-- | source/blender/blenkernel/intern/pointcache.c | 2326 |
1 files changed, 1248 insertions, 1078 deletions
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 741580048cf..84331e1b318 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -44,6 +44,7 @@ #include "BLI_blenlib.h" #include "BLI_threads.h" #include "BLI_math.h" +#include "BLI_utildefines.h" #include "PIL_time.h" @@ -63,6 +64,7 @@ #include "BKE_smoke.h" #include "BKE_softbody.h" #include "BKE_utildefines.h" + #include "BIK_api.h" /* both in intern */ @@ -95,44 +97,55 @@ /* could be made into a pointcache option */ #define DURIAN_POINTCACHE_LIB_OK 1 -int ptcache_data_size[] = { - sizeof(int), // BPHYS_DATA_INDEX - 3 * sizeof(float), // BPHYS_DATA_LOCATION: - 3 * sizeof(float), // BPHYS_DATA_VELOCITY: - 4 * sizeof(float), // BPHYS_DATA_ROTATION: - 3 * sizeof(float), // BPHYS_DATA_AVELOCITY: /* also BPHYS_DATA_XCONST */ - sizeof(float), // BPHYS_DATA_SIZE: - 3 * sizeof(float), // BPHYS_DATA_TIMES: - sizeof(BoidData) // case BPHYS_DATA_BOIDS: +static int ptcache_data_size[] = { + sizeof(unsigned int), // BPHYS_DATA_INDEX + 3 * sizeof(float), // BPHYS_DATA_LOCATION + 3 * sizeof(float), // BPHYS_DATA_VELOCITY + 4 * sizeof(float), // BPHYS_DATA_ROTATION + 3 * sizeof(float), // BPHYS_DATA_AVELOCITY / BPHYS_DATA_XCONST + sizeof(float), // BPHYS_DATA_SIZE + 3 * sizeof(float), // BPHYS_DATA_TIMES + sizeof(BoidData) // case BPHYS_DATA_BOIDS +}; + +static int ptcache_extra_datasize[] = { + 0, + sizeof(ParticleSpring) }; +/* forward declerations */ +static int ptcache_file_compressed_read(PTCacheFile *pf, unsigned char *result, unsigned int len); +static int ptcache_file_compressed_write(PTCacheFile *pf, unsigned char *in, unsigned int in_len, unsigned char *out, int mode); +static int ptcache_file_write(PTCacheFile *pf, void *f, unsigned int tot, unsigned int size); +static int ptcache_file_read(PTCacheFile *pf, void *f, unsigned int tot, unsigned int size); + /* Common functions */ -static int ptcache_read_basic_header(PTCacheFile *pf) +static int ptcache_basic_header_read(PTCacheFile *pf) { int error=0; /* Custom functions should read these basic elements too! */ - if(!error && !fread(&pf->totpoint, sizeof(int), 1, pf->fp)) + if(!error && !fread(&pf->totpoint, sizeof(unsigned int), 1, pf->fp)) error = 1; - if(!error && !fread(&pf->data_types, sizeof(int), 1, pf->fp)) + if(!error && !fread(&pf->data_types, sizeof(unsigned int), 1, pf->fp)) error = 1; return !error; } -static int ptcache_write_basic_header(PTCacheFile *pf) +static int ptcache_basic_header_write(PTCacheFile *pf) { /* Custom functions should write these basic elements too! */ - if(!fwrite(&pf->totpoint, sizeof(int), 1, pf->fp)) + if(!fwrite(&pf->totpoint, sizeof(unsigned int), 1, pf->fp)) return 0; - if(!fwrite(&pf->data_types, sizeof(int), 1, pf->fp)) + if(!fwrite(&pf->data_types, sizeof(unsigned int), 1, pf->fp)) return 0; return 1; } /* Softbody functions */ -static int ptcache_write_softbody(int index, void *soft_v, void **data, int cfra) +static int ptcache_softbody_write(int index, void *soft_v, void **data, int UNUSED(cfra)) { SoftBody *soft= soft_v; BodyPoint *bp = soft->bpoint + index; @@ -142,7 +155,7 @@ static int ptcache_write_softbody(int index, void *soft_v, void **data, int cfra return 1; } -static void ptcache_read_softbody(int index, void *soft_v, void **data, float frs_sec, float cfra, float *old_data) +static void ptcache_softbody_read(int index, void *soft_v, void **data, float UNUSED(cfra), float *old_data) { SoftBody *soft= soft_v; BodyPoint *bp = soft->bpoint + index; @@ -156,7 +169,7 @@ static void ptcache_read_softbody(int index, void *soft_v, void **data, float fr 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) +static void ptcache_softbody_interpolate(int index, void *soft_v, void **data, float cfra, float cfra1, float cfra2, float *old_data) { SoftBody *soft= soft_v; BodyPoint *bp = soft->bpoint + index; @@ -188,24 +201,44 @@ static void ptcache_interpolate_softbody(int index, void *soft_v, void **data, f VECCOPY(bp->pos, keys->co); VECCOPY(bp->vec, keys->vel); } -static int ptcache_totpoint_softbody(void *soft_v, int cfra) +static int ptcache_softbody_totpoint(void *soft_v, int UNUSED(cfra)) { SoftBody *soft= soft_v; return soft->totpoint; } /* Particle functions */ -static int ptcache_write_particle(int index, void *psys_v, void **data, int cfra) +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); + + /* no rotation info, so make something nice up */ + if(data[BPHYS_DATA_ROTATION]==NULL) { + vec_to_quat( key->rot, key->vel, OB_NEGX, OB_POSZ); + } + else { + PTCACHE_DATA_TO(data, BPHYS_DATA_ROTATION, index, key->rot); + } + + PTCACHE_DATA_TO(data, BPHYS_DATA_AVELOCITY, index, key->ave); + key->time = time; +} +static int ptcache_particle_write(int index, void *psys_v, void **data, int cfra) { ParticleSystem *psys= psys_v; ParticleData *pa = psys->particles + index; BoidParticle *boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL; - float times[3] = {pa->time, pa->dietime, pa->lifetime}; + float times[3]; int step = psys->pointcache->step; /* No need to store unborn or died particles outside cache step bounds */ if(data[BPHYS_DATA_INDEX] && (cfra < pa->time - step || cfra > pa->dietime + step)) return 0; - + + times[0]= pa->time; + times[1]= pa->dietime; + times[2]= pa->lifetime; + 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); @@ -220,19 +253,12 @@ static int ptcache_write_particle(int index, void *psys_v, void **data, int cfra /* return flag 1+1=2 for newly born particles to copy exact birth location to previously cached frame */ return 1 + (pa->state.time >= pa->time && pa->prev_state.time <= pa->time); } -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) +static void ptcache_particle_read(int index, void *psys_v, void **data, float cfra, float *old_data) { ParticleSystem *psys= psys_v; ParticleData *pa; BoidParticle *boid; + float timestep = 0.04f*psys->part->timetweak; if(index >= psys->totpart) return; @@ -273,11 +299,11 @@ static void ptcache_read_particle(int index, void *psys_v, void **data, float fr if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) { if(cfra > pa->prev_state.time) { sub_v3_v3v3(pa->state.vel, pa->state.co, pa->prev_state.co); - mul_v3_fl(pa->state.vel, (cfra - pa->prev_state.time) / frs_sec); + mul_v3_fl(pa->state.vel, (cfra - pa->prev_state.time) * timestep); } else { sub_v3_v3v3(pa->state.vel, pa->prev_state.co, pa->state.co); - mul_v3_fl(pa->state.vel, (pa->prev_state.time - cfra) / frs_sec); + mul_v3_fl(pa->state.vel, (pa->prev_state.time - cfra) * timestep); } } @@ -286,12 +312,12 @@ static void ptcache_read_particle(int index, void *psys_v, void **data, float fr vec_to_quat( pa->state.rot,pa->state.vel, OB_NEGX, OB_POSZ); } } -static void ptcache_interpolate_particle(int index, void *psys_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data) +static void ptcache_particle_interpolate(int index, void *psys_v, void **data, float cfra, float cfra1, float cfra2, float *old_data) { ParticleSystem *psys= psys_v; ParticleData *pa; ParticleKey keys[4]; - float dfra; + float dfra, timestep = 0.04f*psys->part->timetweak; if(index >= psys->totpart) return; @@ -319,11 +345,11 @@ static void ptcache_interpolate_particle(int index, void *psys_v, void **data, f if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) { if(keys[1].time > keys[2].time) { sub_v3_v3v3(keys[2].vel, keys[1].co, keys[2].co); - mul_v3_fl(keys[2].vel, (keys[1].time - keys[2].time) / frs_sec); + mul_v3_fl(keys[2].vel, (keys[1].time - keys[2].time) * timestep); } else { sub_v3_v3v3(keys[2].vel, keys[2].co, keys[1].co); - mul_v3_fl(keys[2].vel, (keys[2].time - keys[1].time) / frs_sec); + mul_v3_fl(keys[2].vel, (keys[2].time - keys[1].time) * timestep); } } @@ -337,163 +363,81 @@ static void ptcache_interpolate_particle(int index, void *psys_v, void **data, f dfra = cfra2 - cfra1; - mul_v3_fl(keys[1].vel, dfra / frs_sec); - mul_v3_fl(keys[2].vel, dfra / frs_sec); + mul_v3_fl(keys[1].vel, dfra * timestep); + mul_v3_fl(keys[2].vel, dfra * timestep); psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1); interp_qt_qtqt(pa->state.rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra); - mul_v3_fl(pa->state.vel, frs_sec / dfra); + mul_v3_fl(pa->state.vel, 1.f / (dfra * timestep)); pa->state.time = cfra; } -static int ptcache_totpoint_particle(void *psys_v, int cfra) +static int ptcache_particle_totpoint(void *psys_v, int UNUSED(cfra)) { ParticleSystem *psys = psys_v; return psys->totpart; } -static int ptcache_totwrite_particle(void *psys_v, int cfra) +static int ptcache_particle_totwrite(void *psys_v, int cfra) { ParticleSystem *psys = psys_v; ParticleData *pa= psys->particles; int p, step = psys->pointcache->step; int totwrite = 0; + if(cfra == 0) + return psys->totpart; + for(p=0; p<psys->totpart; p++,pa++) totwrite += (cfra >= pa->time - step && cfra <= pa->dietime + step); return totwrite; } -//static int ptcache_write_particle_stream(PTCacheFile *pf, PTCacheMem *pm, void *psys_v) -//{ -// ParticleSystem *psys= psys_v; -// ParticleData *pa = psys->particles; -// BoidParticle *boid = NULL; -// float times[3]; -// int i = 0; -// -// if(!pf && !pm) -// return 0; -// -// for(i=0; i<psys->totpart; i++, pa++) { -// -// 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) -// continue; -// } -// -// times[0] = pa->time; -// times[1] = pa->dietime; -// times[2] = pa->lifetime; -// -// 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); -// -// boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL; -// if(boid) -// PTCACHE_DATA_FROM(data, BPHYS_DATA_BOIDS, &boid->data); -// -// if(pf && !ptcache_file_write_data(pf)) -// return 0; -// -// if(pm) -// BKE_ptcache_mem_incr_pointers(pm); -// } -// -// return 1; -//} -//static void ptcache_read_particle_stream(PTCacheFile *pf, PTCacheMem *pm, void *psys_v, void **data, float frs_sec, float cfra, float *old_data) -//{ -// ParticleSystem *psys= psys_v; -// ParticleData *pa = psys->particles + index; -// BoidParticle *boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL; -// -// 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(boid) -// PTCACHE_DATA_TO(data, BPHYS_DATA_BOIDS, 0, &boid->data); -// -// /* determine velocity from previous location */ -// if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) { -// if(cfra > pa->prev_state.time) { -// sub_v3_v3v3(pa->state.vel, pa->state.co, pa->prev_state.co); -// mul_v3_fl(pa->state.vel, (cfra - pa->prev_state.time) / frs_sec); -// } -// else { -// sub_v3_v3v3(pa->state.vel, pa->prev_state.co, pa->state.co); -// mul_v3_fl(pa->state.vel, (pa->prev_state.time - cfra) / frs_sec); -// } -// } -// -// /* determine rotation from velocity */ -// if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) { -// vec_to_quat( pa->state.rot,pa->state.vel, OB_POSX, OB_POSZ); -// } -//} -//static void ptcache_interpolate_particle_stream(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; -// -// mul_v3_fl(keys[1].vel, dfra / frs_sec); -// mul_v3_fl(keys[2].vel, dfra / frs_sec); -// -// psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1); -// interp_qt_qtqt(pa->state.rot, keys[1].rot,keys[2].rot, (cfra - cfra1) / dfra); -// -// mul_v3_fl(pa->state.vel, frs_sec / dfra); -// -// pa->state.time = cfra; -//} -// +static void ptcache_particle_extra_write(void *psys_v, PTCacheMem *pm, int UNUSED(cfra)) +{ + ParticleSystem *psys = psys_v; + PTCacheExtra *extra = NULL; + + if(psys->part->phystype == PART_PHYS_FLUID && + psys->part->fluid && psys->part->fluid->flag & SPH_VISCOELASTIC_SPRINGS && + psys->tot_fluidsprings && psys->fluid_springs) { + + extra = MEM_callocN(sizeof(PTCacheExtra), "Point cache: fluid extra data"); + + extra->type = BPHYS_EXTRA_FLUID_SPRINGS; + extra->totdata = psys->tot_fluidsprings; + + extra->data = MEM_callocN(extra->totdata * ptcache_extra_datasize[extra->type], "Point cache: extra data"); + memcpy(extra->data, psys->fluid_springs, extra->totdata * ptcache_extra_datasize[extra->type]); + + BLI_addtail(&pm->extradata, extra); + } +} + +static void ptcache_particle_extra_read(void *psys_v, PTCacheMem *pm, float UNUSED(cfra)) +{ + ParticleSystem *psys = psys_v; + PTCacheExtra *extra = pm->extradata.first; + + for(; extra; extra=extra->next) { + switch(extra->type) { + case BPHYS_EXTRA_FLUID_SPRINGS: + { + if(psys->fluid_springs) + MEM_freeN(psys->fluid_springs); + + psys->fluid_springs = MEM_dupallocN(extra->data); + psys->tot_fluidsprings = psys->alloc_fluidsprings = extra->totdata; + break; + } + } + } +} + /* Cloth functions */ -static int ptcache_write_cloth(int index, void *cloth_v, void **data, int cfra) +static int ptcache_cloth_write(int index, void *cloth_v, void **data, int UNUSED(cfra)) { ClothModifierData *clmd= cloth_v; Cloth *cloth= clmd->clothObject; @@ -505,7 +449,7 @@ static int ptcache_write_cloth(int index, void *cloth_v, void **data, int cfra) return 1; } -static void ptcache_read_cloth(int index, void *cloth_v, void **data, float frs_sec, float cfra, float *old_data) +static void ptcache_cloth_read(int index, void *cloth_v, void **data, float UNUSED(cfra), float *old_data) { ClothModifierData *clmd= cloth_v; Cloth *cloth= clmd->clothObject; @@ -522,7 +466,7 @@ static void ptcache_read_cloth(int index, void *cloth_v, void **data, float frs_ 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) +static void ptcache_cloth_interpolate(int index, void *cloth_v, void **data, float cfra, float cfra1, float cfra2, float *old_data) { ClothModifierData *clmd= cloth_v; Cloth *cloth= clmd->clothObject; @@ -558,84 +502,14 @@ static void ptcache_interpolate_cloth(int index, void *cloth_v, void **data, flo /* should vert->xconst be interpolated somehow too? - jahka */ } -static int ptcache_totpoint_cloth(void *cloth_v, int cfra) +static int ptcache_cloth_totpoint(void *cloth_v, int UNUSED(cfra)) { ClothModifierData *clmd= cloth_v; return clmd->clothObject ? clmd->clothObject->numverts : 0; } -/* Creating ID's */ -void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb) -{ - memset(pid, 0, sizeof(PTCacheID)); - - pid->ob= ob; - 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->write_stream = NULL; - pid->read_stream = NULL; - pid->read_elem= ptcache_read_softbody; - pid->interpolate_elem= ptcache_interpolate_softbody; - - pid->write_header= ptcache_write_basic_header; - pid->read_header= ptcache_read_basic_header; - - pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY); - pid->info_types= 0; - - pid->stack_index = pid->cache->index; -} - -void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *psys) -{ - memset(pid, 0, sizeof(PTCacheID)); - - pid->ob= ob; - pid->calldata= psys; - pid->type= PTCACHE_TYPE_PARTICLES; - pid->stack_index= psys->pointcache->index; - pid->cache= psys->pointcache; - pid->cache_ptr= &psys->pointcache; - pid->ptcaches= &psys->ptcaches; - - if(psys->part->type != PART_HAIR) - pid->flag |= PTCACHE_VEL_PER_SEC; - - pid->write_elem= ptcache_write_particle; - pid->write_stream = NULL; - pid->read_stream = NULL; - pid->read_elem= ptcache_read_particle; - pid->interpolate_elem= ptcache_interpolate_particle; - - pid->totpoint= ptcache_totpoint_particle; - pid->totwrite= ptcache_totwrite_particle; - - pid->write_header= ptcache_write_basic_header; - pid->read_header= ptcache_read_basic_header; - - pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_INDEX); - - if(psys->part->phystype == PART_PHYS_BOIDS) - pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION) | (1<<BPHYS_DATA_BOIDS); - - if(psys->part->rotmode!=PART_ROT_VEL - || psys->part->avemode!=PART_AVE_SPIN || psys->part->avefac!=0.0f) - pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION); - - if(psys->part->flag & PART_ROT_DYN) - pid->data_types|= (1<<BPHYS_DATA_ROTATION); - - pid->info_types= (1<<BPHYS_DATA_TIMES); -} - /* Smoke functions */ -static int ptcache_totpoint_smoke(void *smoke_v, int cfra) +static int ptcache_smoke_totpoint(void *smoke_v, int UNUSED(cfra)) { SmokeModifierData *smd= (SmokeModifierData *)smoke_v; SmokeDomainSettings *sds = smd->domain; @@ -646,79 +520,11 @@ static int ptcache_totpoint_smoke(void *smoke_v, int cfra) else return 0; } - -/* Smoke functions */ -static int ptcache_totpoint_smoke_turbulence(void *smoke_v, int cfra) -{ - SmokeModifierData *smd= (SmokeModifierData *)smoke_v; - SmokeDomainSettings *sds = smd->domain; - - if(sds->wt) { - return sds->res_wt[0]*sds->res_wt[1]*sds->res_wt[2]; - } - else - return 0; -} - -// forward decleration -static int ptcache_file_write(PTCacheFile *pf, void *f, size_t tot, int size); - -static int ptcache_compress_write(PTCacheFile *pf, unsigned char *in, unsigned int in_len, unsigned char *out, int mode) -{ - int r = 0; - unsigned char compressed = 0; - unsigned int out_len= 0; - unsigned char *props = MEM_callocN(16*sizeof(char), "tmp"); - size_t sizeOfIt = 5; - -#ifdef WITH_LZO - out_len= LZO_OUT_LEN(in_len); - if(mode == 1) { - LZO_HEAP_ALLOC(wrkmem, LZO1X_MEM_COMPRESS); - - r = lzo1x_1_compress(in, (lzo_uint)in_len, out, (lzo_uint *)&out_len, wrkmem); - if (!(r == LZO_E_OK) || (out_len >= in_len)) - compressed = 0; - else - compressed = 1; - } -#endif -#ifdef WITH_LZMA - if(mode == 2) { - - r = LzmaCompress(out, (size_t *)&out_len, in, in_len,//assume sizeof(char)==1.... - props, &sizeOfIt, 5, 1 << 24, 3, 0, 2, 32, 2); - - if(!(r == SZ_OK) || (out_len >= in_len)) - compressed = 0; - else - compressed = 2; - } -#endif - - ptcache_file_write(pf, &compressed, 1, sizeof(unsigned char)); - if(compressed) { - ptcache_file_write(pf, &out_len, 1, sizeof(unsigned int)); - ptcache_file_write(pf, out, out_len, sizeof(unsigned char)); - } - else - ptcache_file_write(pf, in, in_len, sizeof(unsigned char)); - - if(compressed == 2) - { - ptcache_file_write(pf, &sizeOfIt, 1, sizeof(unsigned int)); - ptcache_file_write(pf, props, sizeOfIt, sizeof(unsigned char)); - } - - MEM_freeN(props); - - return r; -} - -static int ptcache_write_smoke(PTCacheFile *pf, void *smoke_v) +static int ptcache_smoke_write(PTCacheFile *pf, void *smoke_v) { SmokeModifierData *smd= (SmokeModifierData *)smoke_v; SmokeDomainSettings *sds = smd->domain; + int ret = 0; if(sds->fluid) { size_t res = sds->res[0]*sds->res[1]*sds->res[2]; @@ -732,33 +538,26 @@ static int ptcache_write_smoke(PTCacheFile *pf, void *smoke_v) smoke_export(sds->fluid, &dt, &dx, &dens, &densold, &heat, &heatold, &vx, &vy, &vz, &vxold, &vyold, &vzold, &obstacles); - ptcache_compress_write(pf, (unsigned char *)sds->shadow, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)dens, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)densold, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)heat, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)heatold, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)vx, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)vy, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)vz, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)vxold, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)vyold, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)vzold, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)obstacles, (unsigned int)res, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)sds->shadow, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)dens, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)densold, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)heat, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)heatold, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)vx, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)vy, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)vz, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)vxold, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)vyold, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)vzold, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)obstacles, (unsigned int)res, out, mode); ptcache_file_write(pf, &dt, 1, sizeof(float)); ptcache_file_write(pf, &dx, 1, sizeof(float)); MEM_freeN(out); - return 1; + ret = 1; } - return 0; -} -static int ptcache_write_smoke_turbulence(PTCacheFile *pf, void *smoke_v) -{ - SmokeModifierData *smd= (SmokeModifierData *)smoke_v; - SmokeDomainSettings *sds = smd->domain; - if(sds->wt) { int res_big_array[3]; int res_big; @@ -780,71 +579,22 @@ static int ptcache_write_smoke_turbulence(PTCacheFile *pf, void *smoke_v) smoke_turbulence_export(sds->wt, &dens, &densold, &tcu, &tcv, &tcw); out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len_big), "pointcache_lzo_buffer"); - ptcache_compress_write(pf, (unsigned char *)dens, in_len_big, out, mode); - ptcache_compress_write(pf, (unsigned char *)densold, in_len_big, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)dens, in_len_big, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)densold, in_len_big, out, mode); MEM_freeN(out); out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len), "pointcache_lzo_buffer"); - ptcache_compress_write(pf, (unsigned char *)tcu, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)tcv, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)tcw, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)tcu, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)tcv, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)tcw, in_len, out, mode); MEM_freeN(out); - return 1; + ret = 1; } - return 0; -} -// forward decleration -static int ptcache_file_read(PTCacheFile *pf, void *f, size_t tot, int size); - -static int ptcache_compress_read(PTCacheFile *pf, unsigned char *result, unsigned int len) -{ - int r = 0; - unsigned char compressed = 0; - unsigned int in_len; -#ifdef WITH_LZO - unsigned int out_len = len; - size_t sizeOfIt = 5; -#endif - unsigned char *in; - unsigned char *props = MEM_callocN(16*sizeof(char), "tmp"); - - ptcache_file_read(pf, &compressed, 1, sizeof(unsigned char)); - if(compressed) { - ptcache_file_read(pf, &in_len, 1, sizeof(unsigned int)); - if(in_len==0) { - /* do nothing */ - } - else { - in = (unsigned char *)MEM_callocN(sizeof(unsigned char)*in_len, "pointcache_compressed_buffer"); - ptcache_file_read(pf, in, in_len, sizeof(unsigned char)); -#ifdef WITH_LZO - if(compressed == 1) - r = lzo1x_decompress_safe(in, (lzo_uint)in_len, result, (lzo_uint *)&out_len, NULL); -#endif -#ifdef WITH_LZMA - if(compressed == 2) - { - size_t leni = in_len, leno = out_len; - ptcache_file_read(pf, &sizeOfIt, 1, sizeof(unsigned int)); - ptcache_file_read(pf, props, sizeOfIt, sizeof(unsigned char)); - r = LzmaUncompress(result, &leno, in, &leni, props, sizeOfIt); - } -#endif - MEM_freeN(in); - } - } - else { - ptcache_file_read(pf, result, len, sizeof(unsigned char)); - } - - MEM_freeN(props); - - return r; + return ret; } - -static void ptcache_read_smoke(PTCacheFile *pf, void *smoke_v) +static void ptcache_smoke_read(PTCacheFile *pf, void *smoke_v) { SmokeModifierData *smd= (SmokeModifierData *)smoke_v; SmokeDomainSettings *sds = smd->domain; @@ -857,116 +607,126 @@ static void ptcache_read_smoke(PTCacheFile *pf, void *smoke_v) smoke_export(sds->fluid, &dt, &dx, &dens, &densold, &heat, &heatold, &vx, &vy, &vz, &vxold, &vyold, &vzold, &obstacles); - ptcache_compress_read(pf, (unsigned char *)sds->shadow, out_len); - ptcache_compress_read(pf, (unsigned char*)dens, out_len); - ptcache_compress_read(pf, (unsigned char*)densold, out_len); - ptcache_compress_read(pf, (unsigned char*)heat, out_len); - ptcache_compress_read(pf, (unsigned char*)heatold, out_len); - ptcache_compress_read(pf, (unsigned char*)vx, out_len); - ptcache_compress_read(pf, (unsigned char*)vy, out_len); - ptcache_compress_read(pf, (unsigned char*)vz, out_len); - ptcache_compress_read(pf, (unsigned char*)vxold, out_len); - ptcache_compress_read(pf, (unsigned char*)vyold, out_len); - ptcache_compress_read(pf, (unsigned char*)vzold, out_len); - ptcache_compress_read(pf, (unsigned char*)obstacles, (unsigned int)res); + ptcache_file_compressed_read(pf, (unsigned char *)sds->shadow, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)dens, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)densold, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)heat, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)heatold, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)vx, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)vy, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)vz, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)vxold, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)vyold, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)vzold, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)obstacles, (unsigned int)res); ptcache_file_read(pf, &dt, 1, sizeof(float)); ptcache_file_read(pf, &dx, 1, sizeof(float)); - } -} -static void ptcache_read_smoke_turbulence(PTCacheFile *pf, void *smoke_v) -{ - SmokeModifierData *smd= (SmokeModifierData *)smoke_v; - SmokeDomainSettings *sds = smd->domain; - - if(sds->fluid) { - int res = sds->res[0]*sds->res[1]*sds->res[2]; - int res_big, res_big_array[3]; - float *dens, *densold, *tcu, *tcv, *tcw; - unsigned int out_len = sizeof(float)*(unsigned int)res; - unsigned int out_len_big; + if(pf->data_types & (1<<BPHYS_DATA_SMOKE_HIGH) && sds->wt) { + int res = sds->res[0]*sds->res[1]*sds->res[2]; + int res_big, res_big_array[3]; + float *dens, *densold, *tcu, *tcv, *tcw; + unsigned int out_len = sizeof(float)*(unsigned int)res; + unsigned int out_len_big; - smoke_turbulence_get_res(sds->wt, res_big_array); - res_big = res_big_array[0]*res_big_array[1]*res_big_array[2]; - out_len_big = sizeof(float) * (unsigned int)res_big; + smoke_turbulence_get_res(sds->wt, res_big_array); + res_big = res_big_array[0]*res_big_array[1]*res_big_array[2]; + out_len_big = sizeof(float) * (unsigned int)res_big; - smoke_turbulence_export(sds->wt, &dens, &densold, &tcu, &tcv, &tcw); + smoke_turbulence_export(sds->wt, &dens, &densold, &tcu, &tcv, &tcw); - ptcache_compress_read(pf, (unsigned char*)dens, out_len_big); - ptcache_compress_read(pf, (unsigned char*)densold, out_len_big); + ptcache_file_compressed_read(pf, (unsigned char*)dens, out_len_big); + ptcache_file_compressed_read(pf, (unsigned char*)densold, out_len_big); - ptcache_compress_read(pf, (unsigned char*)tcu, out_len); - ptcache_compress_read(pf, (unsigned char*)tcv, out_len); - ptcache_compress_read(pf, (unsigned char*)tcw, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)tcu, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)tcv, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)tcw, out_len); + } } } -void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd) +/* Creating ID's */ +void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb) { - SmokeDomainSettings *sds = smd->domain; - memset(pid, 0, sizeof(PTCacheID)); pid->ob= ob; - pid->calldata= smd; - - pid->type= PTCACHE_TYPE_SMOKE_DOMAIN; - pid->stack_index= sds->point_cache[0]->index; - - pid->cache= sds->point_cache[0]; - pid->cache_ptr= &(sds->point_cache[0]); - pid->ptcaches= &(sds->ptcaches[0]); + 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_softbody_totpoint; - pid->totpoint= pid->totwrite= ptcache_totpoint_smoke; + pid->write_point = ptcache_softbody_write; + pid->read_point = ptcache_softbody_read; + pid->interpolate_point = ptcache_softbody_interpolate; - pid->write_elem= NULL; - pid->read_elem= NULL; + pid->write_stream = NULL; + pid->read_stream = NULL; - pid->read_stream = ptcache_read_smoke; - pid->write_stream = ptcache_write_smoke; - - pid->interpolate_elem= NULL; + pid->write_extra_data = NULL; + pid->read_extra_data = NULL; + pid->interpolate_extra_data = NULL; - pid->write_header= ptcache_write_basic_header; - pid->read_header= ptcache_read_basic_header; + pid->write_header = ptcache_basic_header_write; + pid->read_header = ptcache_basic_header_read; - pid->data_types= (1<<BPHYS_DATA_LOCATION); // bogus values to make pointcache happy + pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY); pid->info_types= 0; -} -void BKE_ptcache_id_from_smoke_turbulence(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd) + pid->stack_index = pid->cache->index; +} +void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *psys) { - SmokeDomainSettings *sds = smd->domain; - memset(pid, 0, sizeof(PTCacheID)); pid->ob= ob; - pid->calldata= smd; - - pid->type= PTCACHE_TYPE_SMOKE_HIGHRES; - pid->stack_index= sds->point_cache[1]->index; + pid->calldata= psys; + pid->type= PTCACHE_TYPE_PARTICLES; + pid->stack_index= psys->pointcache->index; + pid->cache= psys->pointcache; + pid->cache_ptr= &psys->pointcache; + pid->ptcaches= &psys->ptcaches; - pid->cache= sds->point_cache[1]; - pid->cache_ptr= &sds->point_cache[1]; - pid->ptcaches= &sds->ptcaches[1]; + if(psys->part->type != PART_HAIR) + pid->flag |= PTCACHE_VEL_PER_SEC; - pid->totpoint= pid->totwrite= ptcache_totpoint_smoke_turbulence; + pid->totpoint = ptcache_particle_totpoint; + pid->totwrite = ptcache_particle_totwrite; - pid->write_elem= NULL; - pid->read_elem= NULL; + pid->write_point = ptcache_particle_write; + pid->read_point = ptcache_particle_read; + pid->interpolate_point = ptcache_particle_interpolate; - pid->read_stream = ptcache_read_smoke_turbulence; - pid->write_stream = ptcache_write_smoke_turbulence; - - pid->interpolate_elem= NULL; + pid->write_stream = NULL; + pid->read_stream = NULL; - pid->write_header= ptcache_write_basic_header; - pid->read_header= ptcache_read_basic_header; + pid->write_extra_data = NULL; + pid->read_extra_data = NULL; + pid->interpolate_extra_data = NULL; - pid->data_types= (1<<BPHYS_DATA_LOCATION); // bogus values tot make pointcache happy - pid->info_types= 0; -} + pid->write_header = ptcache_basic_header_write; + pid->read_header = ptcache_basic_header_read; + + pid->data_types = (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_INDEX); + + if(psys->part->phystype == PART_PHYS_BOIDS) + pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION) | (1<<BPHYS_DATA_BOIDS); + else if(psys->part->phystype == PART_PHYS_FLUID && psys->part->fluid && psys->part->fluid->flag & SPH_VISCOELASTIC_SPRINGS) { + pid->write_extra_data = ptcache_particle_extra_write; + pid->read_extra_data = ptcache_particle_extra_read; + } + if(psys->part->rotmode!=PART_ROT_VEL + || psys->part->avemode!=PART_AVE_SPIN || psys->part->avefac!=0.0f) + pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION); + + if(psys->part->flag & PART_ROT_DYN) + pid->data_types|= (1<<BPHYS_DATA_ROTATION); + + pid->info_types= (1<<BPHYS_DATA_TIMES); +} void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *clmd) { memset(pid, 0, sizeof(PTCacheID)); @@ -978,21 +738,65 @@ void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *cl pid->cache= clmd->point_cache; pid->cache_ptr= &clmd->point_cache; pid->ptcaches= &clmd->ptcaches; - pid->totpoint= pid->totwrite= ptcache_totpoint_cloth; + pid->totpoint= pid->totwrite= ptcache_cloth_totpoint; + + pid->write_point = ptcache_cloth_write; + pid->read_point = ptcache_cloth_read; + pid->interpolate_point = ptcache_cloth_interpolate; + + pid->write_stream = NULL; + pid->read_stream = NULL; - pid->write_elem= ptcache_write_cloth; - pid->write_stream = NULL; - pid->read_stream = NULL; - pid->read_elem= ptcache_read_cloth; - pid->interpolate_elem= ptcache_interpolate_cloth; + pid->write_extra_data = NULL; + pid->read_extra_data = NULL; + pid->interpolate_extra_data = NULL; - pid->write_header= ptcache_write_basic_header; - pid->read_header= ptcache_read_basic_header; + pid->write_header = ptcache_basic_header_write; + pid->read_header = ptcache_basic_header_read; pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_XCONST); pid->info_types= 0; } +void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd) +{ + SmokeDomainSettings *sds = smd->domain; + + memset(pid, 0, sizeof(PTCacheID)); + + pid->ob= ob; + pid->calldata= smd; + + pid->type= PTCACHE_TYPE_SMOKE_DOMAIN; + pid->stack_index= sds->point_cache[0]->index; + + pid->cache= sds->point_cache[0]; + pid->cache_ptr= &(sds->point_cache[0]); + pid->ptcaches= &(sds->ptcaches[0]); + + pid->totpoint= pid->totwrite= ptcache_smoke_totpoint; + pid->write_point = NULL; + pid->read_point = NULL; + pid->interpolate_point = NULL; + + pid->read_stream = ptcache_smoke_read; + pid->write_stream = ptcache_smoke_write; + + pid->write_extra_data = NULL; + pid->read_extra_data = NULL; + pid->interpolate_extra_data = NULL; + + pid->write_header = ptcache_basic_header_write; + pid->read_header = ptcache_basic_header_read; + + pid->data_types= 0; + pid->info_types= 0; + + if(sds->fluid) + pid->data_types |= (1<<BPHYS_DATA_SMOKE_LOW); + if(sds->wt) + pid->data_types |= (1<<BPHYS_DATA_SMOKE_HIGH); +} void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int duplis) { PTCacheID *pid; @@ -1008,11 +812,23 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup } for(psys=ob->particlesystem.first; psys; psys=psys->next) { - if(psys->part) { - pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); - BKE_ptcache_id_from_particles(pid, ob, psys); - BLI_addtail(lb, pid); - } + if(psys->part==NULL) + continue; + + /* check to make sure point cache is actually used by the particles */ + if(ELEM(psys->part->phystype, PART_PHYS_NO, PART_PHYS_KEYED)) + continue; + + /* hair needs to be included in id-list for cache edit mode to work */ + /* if(psys->part->type == PART_HAIR && (psys->flag & PSYS_HAIR_DYNAMICS)==0) */ + /* continue; */ + + if(psys->part->type == PART_FLUID) + continue; + + pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); + BKE_ptcache_id_from_particles(pid, ob, psys); + BLI_addtail(lb, pid); } for(md=ob->modifiers.first; md; md=md->next) { @@ -1028,10 +844,6 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); BKE_ptcache_id_from_smoke(pid, ob, (SmokeModifierData*)md); BLI_addtail(lb, pid); - - pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); - BKE_ptcache_id_from_smoke_turbulence(pid, ob, (SmokeModifierData*)md); - BLI_addtail(lb, pid); } } } @@ -1045,7 +857,7 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup if(dob->ob != ob) { /* avoids recursive loops with dupliframes: bug 22988 */ ListBase lb_dupli_pid; BKE_ptcache_ids_from_object(&lb_dupli_pid, dob->ob, scene, duplis); - addlisttolist(lb, &lb_dupli_pid); + BLI_movelisttolist(lb, &lb_dupli_pid); if(lb_dupli_pid.first) printf("Adding Dupli\n"); } @@ -1056,7 +868,6 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup } } - /* File handling */ /* Takes an Object ID and returns a unique name @@ -1070,8 +881,8 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup static int ptcache_path(PTCacheID *pid, char *filename) { - Library *lib= (pid)? pid->ob->id.lib: NULL; - const char *blendfilename= (lib && (pid->cache->flag & PTCACHE_IGNORE_LIBPATH)==0) ? lib->filepath: G.sce; + Library *lib= (pid->ob)? pid->ob->id.lib: NULL; + const char *blendfilename= (lib && (pid->cache->flag & PTCACHE_IGNORE_LIBPATH)==0) ? lib->filepath: G.main->name; size_t i; if(pid->cache->flag & PTCACHE_EXTERNAL) { @@ -1104,7 +915,7 @@ static int ptcache_path(PTCacheID *pid, char *filename) return BLI_add_slash(filename); /* new strlen() */ } -static int BKE_ptcache_id_filename(PTCacheID *pid, char *filename, int cfra, short do_path, short do_ext) +static int ptcache_filename(PTCacheID *pid, char *filename, int cfra, short do_path, short do_ext) { int len=0; char *idname; @@ -1169,7 +980,7 @@ static PTCacheFile *ptcache_file_open(PTCacheID *pid, int mode, int cfra) #endif if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0) return NULL; /* save blend file before using disk pointcache */ - BKE_ptcache_id_filename(pid, filename, cfra, 1, 1); + ptcache_filename(pid, filename, cfra, 1, 1); if (mode==PTCACHE_FILE_READ) { if (!BLI_exists(filename)) { @@ -1189,48 +1000,155 @@ static PTCacheFile *ptcache_file_open(PTCacheID *pid, int mode, int cfra) pf= MEM_mallocN(sizeof(PTCacheFile), "PTCacheFile"); pf->fp= fp; + pf->old_format = 0; + pf->frame = cfra; return pf; } - static void ptcache_file_close(PTCacheFile *pf) { - fclose(pf->fp); - MEM_freeN(pf); + if(pf) { + fclose(pf->fp); + MEM_freeN(pf); + } +} + +static int ptcache_file_compressed_read(PTCacheFile *pf, unsigned char *result, unsigned int len) +{ + int r = 0; + unsigned char compressed = 0; + size_t in_len; +#ifdef WITH_LZO + size_t out_len = len; + size_t sizeOfIt = 5; +#endif + unsigned char *in; + unsigned char *props = MEM_callocN(16*sizeof(char), "tmp"); + + ptcache_file_read(pf, &compressed, 1, sizeof(unsigned char)); + if(compressed) { + unsigned int size; + ptcache_file_read(pf, &size, 1, sizeof(unsigned int)); + in_len = (size_t)size; + if(in_len==0) { + /* do nothing */ + } + else { + in = (unsigned char *)MEM_callocN(sizeof(unsigned char)*in_len, "pointcache_compressed_buffer"); + ptcache_file_read(pf, in, in_len, sizeof(unsigned char)); +#ifdef WITH_LZO + if(compressed == 1) + r = lzo1x_decompress_safe(in, (lzo_uint)in_len, result, (lzo_uint *)&out_len, NULL); +#endif +#ifdef WITH_LZMA + if(compressed == 2) + { + size_t leni = in_len, leno = out_len; + ptcache_file_read(pf, &size, 1, sizeof(unsigned int)); + sizeOfIt = (size_t)size; + ptcache_file_read(pf, props, sizeOfIt, sizeof(unsigned char)); + r = LzmaUncompress(result, &leno, in, &leni, props, sizeOfIt); + } +#endif + MEM_freeN(in); + } + } + else { + ptcache_file_read(pf, result, len, sizeof(unsigned char)); + } + + MEM_freeN(props); + + return r; } +static int ptcache_file_compressed_write(PTCacheFile *pf, unsigned char *in, unsigned int in_len, unsigned char *out, int mode) +{ + int r = 0; + unsigned char compressed = 0; + size_t out_len= 0; + unsigned char *props = MEM_callocN(16*sizeof(char), "tmp"); + size_t sizeOfIt = 5; -static int ptcache_file_read(PTCacheFile *pf, void *f, size_t tot, int size) + (void)mode; /* unused when building w/o compression */ + +#ifdef WITH_LZO + out_len= LZO_OUT_LEN(in_len); + if(mode == 1) { + LZO_HEAP_ALLOC(wrkmem, LZO1X_MEM_COMPRESS); + + r = lzo1x_1_compress(in, (lzo_uint)in_len, out, (lzo_uint *)&out_len, wrkmem); + if (!(r == LZO_E_OK) || (out_len >= in_len)) + compressed = 0; + else + compressed = 1; + } +#endif +#ifdef WITH_LZMA + if(mode == 2) { + + r = LzmaCompress(out, &out_len, in, in_len,//assume sizeof(char)==1.... + props, &sizeOfIt, 5, 1 << 24, 3, 0, 2, 32, 2); + + if(!(r == SZ_OK) || (out_len >= in_len)) + compressed = 0; + else + compressed = 2; + } +#endif + + ptcache_file_write(pf, &compressed, 1, sizeof(unsigned char)); + if(compressed) { + unsigned int size = out_len; + ptcache_file_write(pf, &size, 1, sizeof(unsigned int)); + ptcache_file_write(pf, out, out_len, sizeof(unsigned char)); + } + else + ptcache_file_write(pf, in, in_len, sizeof(unsigned char)); + + if(compressed == 2) + { + unsigned int size = sizeOfIt; + ptcache_file_write(pf, &sizeOfIt, 1, sizeof(unsigned int)); + ptcache_file_write(pf, props, size, sizeof(unsigned char)); + } + + MEM_freeN(props); + + return r; +} +static int ptcache_file_read(PTCacheFile *pf, void *f, unsigned int tot, unsigned int size) { return (fread(f, size, tot, pf->fp) == tot); } -static int ptcache_file_write(PTCacheFile *pf, void *f, size_t tot, int size) +static int ptcache_file_write(PTCacheFile *pf, void *f, unsigned int tot, unsigned int size) { return (fwrite(f, size, tot, pf->fp) == tot); } -static int ptcache_file_read_data(PTCacheFile *pf) +static int ptcache_file_data_read(PTCacheFile *pf) { int i; for(i=0; i<BPHYS_TOT_DATA; i++) { - if(pf->data_types & (1<<i) && !ptcache_file_read(pf, pf->cur[i], 1, ptcache_data_size[i])) + if((pf->data_types & (1<<i)) && !ptcache_file_read(pf, pf->cur[i], 1, ptcache_data_size[i])) return 0; } return 1; } -static int ptcache_file_write_data(PTCacheFile *pf) +static int ptcache_file_data_write(PTCacheFile *pf) { int i; for(i=0; i<BPHYS_TOT_DATA; i++) { - if(pf->data_types & (1<<i) && !ptcache_file_write(pf, pf->cur[i], 1, ptcache_data_size[i])) + if((pf->data_types & (1<<i)) && !ptcache_file_write(pf, pf->cur[i], 1, ptcache_data_size[i])) return 0; } return 1; } -static int ptcache_file_read_header_begin(PTCacheFile *pf) +static int ptcache_file_header_begin_read(PTCacheFile *pf) { + unsigned int typeflag=0; int error=0; char bphysics[8]; @@ -1242,8 +1160,11 @@ static int ptcache_file_read_header_begin(PTCacheFile *pf) if(!error && strncmp(bphysics, "BPHYSICS", 8)) error = 1; - if(!error && !fread(&pf->type, sizeof(int), 1, pf->fp)) + if(!error && !fread(&typeflag, sizeof(unsigned int), 1, pf->fp)) error = 1; + + pf->type = (typeflag & PTCACHE_TYPEFLAG_TYPEMASK); + pf->flag = (typeflag & PTCACHE_TYPEFLAG_FLAGMASK); /* if there was an error set file as it was */ if(error) @@ -1251,84 +1172,82 @@ static int ptcache_file_read_header_begin(PTCacheFile *pf) return !error; } - - -static int ptcache_file_write_header_begin(PTCacheFile *pf) +static int ptcache_file_header_begin_write(PTCacheFile *pf) { - char *bphysics = "BPHYSICS"; + const char *bphysics = "BPHYSICS"; + unsigned int typeflag = pf->type + pf->flag; if(fwrite(bphysics, sizeof(char), 8, pf->fp) != 8) return 0; - if(!fwrite(&pf->type, sizeof(int), 1, pf->fp)) + if(!fwrite(&typeflag, sizeof(unsigned int), 1, pf->fp)) return 0; return 1; } - /* Data pointer handling */ int BKE_ptcache_data_size(int data_type) { return ptcache_data_size[data_type]; } -static void ptcache_file_init_pointers(PTCacheFile *pf) +static void ptcache_file_pointers_init(PTCacheFile *pf) { int data_types = pf->data_types; - pf->cur[BPHYS_DATA_INDEX] = data_types & (1<<BPHYS_DATA_INDEX) ? &pf->data.index : NULL; - pf->cur[BPHYS_DATA_LOCATION] = data_types & (1<<BPHYS_DATA_LOCATION) ? &pf->data.loc : NULL; - pf->cur[BPHYS_DATA_VELOCITY] = data_types & (1<<BPHYS_DATA_VELOCITY) ? &pf->data.vel : NULL; - pf->cur[BPHYS_DATA_ROTATION] = data_types & (1<<BPHYS_DATA_ROTATION) ? &pf->data.rot : NULL; - pf->cur[BPHYS_DATA_AVELOCITY] = data_types & (1<<BPHYS_DATA_AVELOCITY) ? &pf->data.ave : NULL; - pf->cur[BPHYS_DATA_SIZE] = data_types & (1<<BPHYS_DATA_SIZE) ? &pf->data.size : NULL; - pf->cur[BPHYS_DATA_TIMES] = data_types & (1<<BPHYS_DATA_TIMES) ? &pf->data.times : NULL; - pf->cur[BPHYS_DATA_BOIDS] = data_types & (1<<BPHYS_DATA_BOIDS) ? &pf->data.boids : NULL; + pf->cur[BPHYS_DATA_INDEX] = (data_types & (1<<BPHYS_DATA_INDEX)) ? &pf->data.index : NULL; + pf->cur[BPHYS_DATA_LOCATION] = (data_types & (1<<BPHYS_DATA_LOCATION)) ? &pf->data.loc : NULL; + pf->cur[BPHYS_DATA_VELOCITY] = (data_types & (1<<BPHYS_DATA_VELOCITY)) ? &pf->data.vel : NULL; + pf->cur[BPHYS_DATA_ROTATION] = (data_types & (1<<BPHYS_DATA_ROTATION)) ? &pf->data.rot : NULL; + pf->cur[BPHYS_DATA_AVELOCITY] = (data_types & (1<<BPHYS_DATA_AVELOCITY))? &pf->data.ave : NULL; + pf->cur[BPHYS_DATA_SIZE] = (data_types & (1<<BPHYS_DATA_SIZE)) ? &pf->data.size : NULL; + pf->cur[BPHYS_DATA_TIMES] = (data_types & (1<<BPHYS_DATA_TIMES)) ? &pf->data.times : NULL; + pf->cur[BPHYS_DATA_BOIDS] = (data_types & (1<<BPHYS_DATA_BOIDS)) ? &pf->data.boids : NULL; } -static void ptcache_file_seek_pointers(int index, PTCacheFile *pf) +/* Check to see if point number "index" is in pm, uses binary search for index data. */ +int BKE_ptcache_mem_index_find(PTCacheMem *pm, unsigned int index) { - int i, size=0; - int data_types = pf->data_types; + if(pm->data[BPHYS_DATA_INDEX]) { + unsigned int *data = pm->data[BPHYS_DATA_INDEX]; + unsigned int mid, low = 0, high = pm->totpoint - 1; - if(data_types & (1<<BPHYS_DATA_INDEX)) { - int totpoint; - /* The simplest solution is to just write to the very end. This may cause - * some data duplication, but since it's on disk it's not so bad. The correct - * thing would be to search through the file for the correct index and only - * write to the end if it's not found, but this could be quite slow. - */ - fseek(pf->fp, 8 + sizeof(int), SEEK_SET); - fread(&totpoint, sizeof(int), 1, pf->fp); - - totpoint++; + if(index < *data || index > *(data+high)) + return -1; - fseek(pf->fp, 8 + sizeof(int), SEEK_SET); - fwrite(&totpoint, sizeof(int), 1, pf->fp); + /* check simple case for continuous indexes first */ + if(index-*data < high && data[index-*data] == index) + return index-*data; + + while(low <= high) { + mid= (low + high)/2; + + if(data[mid] > index) + high = mid - 1; + else if(data[mid] < index) + low = mid + 1; + else + return mid; + } - fseek(pf->fp, 0, SEEK_END); + return -1; } else { - for(i=0; i<BPHYS_TOT_DATA; i++) - size += pf->data_types & (1<<i) ? ptcache_data_size[i] : 0; - - /* size of default header + data up to index */ - fseek(pf->fp, 8 + 3*sizeof(int) + index * size, SEEK_SET); + return (index < pm->totpoint ? index : -1); } - - ptcache_file_init_pointers(pf); } -void BKE_ptcache_mem_init_pointers(PTCacheMem *pm) + +void BKE_ptcache_mem_pointers_init(PTCacheMem *pm) { int data_types = pm->data_types; int i; for(i=0; i<BPHYS_TOT_DATA; i++) - pm->cur[i] = data_types & (1<<i) ? pm->data[i] : NULL; + pm->cur[i] = ((data_types & (1<<i)) ? pm->data[i] : NULL); } -void BKE_ptcache_mem_incr_pointers(PTCacheMem *pm) +void BKE_ptcache_mem_pointers_incr(PTCacheMem *pm) { int i; @@ -1337,10 +1256,10 @@ void BKE_ptcache_mem_incr_pointers(PTCacheMem *pm) pm->cur[i] = (char*)pm->cur[i] + ptcache_data_size[i]; } } -int BKE_ptcache_mem_seek_pointers(int point_index, PTCacheMem *pm) +int BKE_ptcache_mem_pointers_seek(int point_index, PTCacheMem *pm) { int data_types = pm->data_types; - int i, index = pm->index_array ? pm->index_array[point_index] - 1 : point_index; + int i, index = BKE_ptcache_mem_index_find(pm, point_index); if(index < 0) { /* Can't give proper location without reallocation, so don't give any location. @@ -1356,7 +1275,7 @@ int BKE_ptcache_mem_seek_pointers(int point_index, PTCacheMem *pm) return 1; } -static void ptcache_alloc_data(PTCacheMem *pm) +static void ptcache_data_alloc(PTCacheMem *pm) { int data_types = pm->data_types; int totpoint = pm->totpoint; @@ -1367,7 +1286,7 @@ static void ptcache_alloc_data(PTCacheMem *pm) pm->data[i] = MEM_callocN(totpoint * ptcache_data_size[i], "PTCache Data"); } } -static void ptcache_free_data(PTCacheMem *pm) +static void ptcache_data_free(PTCacheMem *pm) { void **data = pm->data; int i; @@ -1376,13 +1295,8 @@ static void ptcache_free_data(PTCacheMem *pm) if(data[i]) MEM_freeN(data[i]); } - - if(pm->index_array) { - MEM_freeN(pm->index_array); - pm->index_array = NULL; - } } -static void ptcache_copy_data(void *from[], void *to[]) +static void ptcache_data_copy(void *from[], void *to[]) { int i; for(i=0; i<BPHYS_TOT_DATA; i++) { @@ -1393,9 +1307,20 @@ static void ptcache_copy_data(void *from[], void *to[]) } } +static void ptcache_extra_free(PTCacheMem *pm) +{ + PTCacheExtra *extra = pm->extradata.first; + if(extra) { + for(; extra; extra=extra->next) { + if(extra->data) + MEM_freeN(extra->data); + } -static int ptcache_pid_old_elemsize(PTCacheID *pid) + BLI_freelistN(&pm->extradata); + } +} +static int ptcache_old_elemsize(PTCacheID *pid) { if(pid->type==PTCACHE_TYPE_SOFTBODY) return 6 * sizeof(float); @@ -1407,268 +1332,408 @@ static int ptcache_pid_old_elemsize(PTCacheID *pid) return 0; } -/* reads cache from disk or memory */ -/* possible to get old or interpolated result */ -int BKE_ptcache_read_cache(PTCacheID *pid, float cfra, float frs_sec) +static void ptcache_find_frames_around(PTCacheID *pid, unsigned int frame, int *fra1, int *fra2) { - PTCacheFile *pf=NULL, *pf2=NULL; - PTCacheMem *pm=NULL, *pm2=NULL; - float old_data1[14], old_data2[14]; - int cfrai = (int)cfra; - int old_elemsize = ptcache_pid_old_elemsize(pid); - int i; + if(pid->cache->flag & PTCACHE_DISK_CACHE) { + int cfra1=frame-1, cfra2=frame+1; - int cfra1 = 0, cfra2 = 0; - int totpoint = 0, totpoint2 = 0; - int *index = &i, *index2 = &i; - int use_old = 0, old_frame = 0; + while(cfra1 >= pid->cache->startframe && !BKE_ptcache_id_exist(pid, cfra1)) + cfra1--; - int ret = 0, error = 0; + if(cfra1 < pid->cache->startframe) + cfra1 = 0; - /* nothing to read to */ - if(pid->totpoint(pid->calldata, (int)cfra) == 0) - return 0; + while(cfra2 <= pid->cache->endframe && !BKE_ptcache_id_exist(pid, cfra2)) + cfra2++; - if(pid->cache->flag & PTCACHE_READ_INFO) { - pid->cache->flag &= ~PTCACHE_READ_INFO; - BKE_ptcache_read_cache(pid, 0, frs_sec); + if(cfra2 > pid->cache->endframe) + cfra2 = 0; + + if(cfra1 && !cfra2) { + *fra1 = 0; + *fra2 = cfra1; + } + else { + *fra1 = cfra1; + *fra2 = cfra2; + } } + else if(pid->cache->mem_cache.first) { + PTCacheMem *pm = pid->cache->mem_cache.first; + PTCacheMem *pm2 = pid->cache->mem_cache.last; + while(pm->next && pm->next->frame < frame) + pm= pm->next; - /* first check if we have the actual frame cached */ - if(cfra == (float)cfrai) { - if(pid->cache->flag & PTCACHE_DISK_CACHE) { - pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai); - } + if(pm2 && pm2->frame < frame) + pm2 = NULL; else { - pm = pid->cache->mem_cache.first; + while(pm2->prev && pm2->prev->frame > frame) + pm2= pm2->prev; + } - for(; pm; pm=pm->next) { - if(pm->frame == cfrai) - break; - } + if(pm && !pm2) { + *fra1 = 0; + *fra2 = pm->frame; + } + else { + *fra1 = pm->frame; + *fra2 = pm2->frame; } } +} - /* no exact cache frame found so try to find cached frames around cfra */ - if(!pm && !pf) { - if(pid->cache->flag & PTCACHE_DISK_CACHE) { - pf=NULL; - while(cfrai >= pid->cache->startframe && !pf) { - cfrai--; - pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai); - cfra1 = cfrai; - } +static PTCacheMem *ptcache_disk_frame_to_mem(PTCacheID *pid, int cfra) +{ + PTCacheFile *pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra); + PTCacheMem *pm = NULL; + unsigned int i, error = 0; + + if(pf == NULL) + return 0; - old_frame = cfrai; + if(!ptcache_file_header_begin_read(pf)) + error = 1; + + if(!error && (pf->type != pid->type || !pid->read_header(pf))) + error = 1; + + if(!error) { + pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem"); - cfrai = (int)cfra; - while(cfrai < pid->cache->endframe && !pf2) { - cfrai++; - pf2= ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai); - cfra2 = cfrai; + pm->totpoint = pf->totpoint; + pm->data_types = pf->data_types; + pm->frame = pf->frame; + + ptcache_data_alloc(pm); + + if(pf->flag & PTCACHE_TYPEFLAG_COMPRESS) { + for(i=0; i<BPHYS_TOT_DATA; i++) { + unsigned int out_len = pm->totpoint*ptcache_data_size[i]; + if(pf->data_types & (1<<i)) + ptcache_file_compressed_read(pf, (unsigned char*)(pm->data[i]), out_len); } + } + else { + BKE_ptcache_mem_pointers_init(pm); + ptcache_file_pointers_init(pf); - if(pf && !pf2) { - pf2 = pf; - pf = NULL; + for(i=0; i<pm->totpoint; i++) { + if(!ptcache_file_data_read(pf)) { + error = 1; + break; + } + ptcache_data_copy(pf->cur, pm->cur); + BKE_ptcache_mem_pointers_incr(pm); } } - else if(pid->cache->mem_cache.first){ - pm = pid->cache->mem_cache.first; + } - while(pm->next && pm->next->frame < cfra) - pm= pm->next; + if(!error && pf->flag & PTCACHE_TYPEFLAG_EXTRADATA) { + unsigned int extratype = 0; - if(pm) { - old_frame = pm->frame; - cfra1 = pm->frame; - } + while(ptcache_file_read(pf, &extratype, 1, sizeof(unsigned int))) { + PTCacheExtra *extra = MEM_callocN(sizeof(PTCacheExtra), "Pointcache extradata"); - pm2 = pid->cache->mem_cache.last; + extra->type = extratype; - if(pm2 && pm2->frame < cfra) - pm2 = NULL; - else { - while(pm2->prev && pm2->prev->frame > cfra) - pm2= pm2->prev; + ptcache_file_read(pf, &extra->totdata, 1, sizeof(unsigned int)); - if(pm2) - cfra2 = pm2->frame; - } + extra->data = MEM_callocN(extra->totdata * ptcache_extra_datasize[extra->type], "Pointcache extradata->data"); - if(pm && !pm2) { - pm2 = pm; - pm = NULL; - } + if(pf->flag & PTCACHE_TYPEFLAG_COMPRESS) + ptcache_file_compressed_read(pf, (unsigned char*)(extra->data), extra->totdata*ptcache_extra_datasize[extra->type]); + else + ptcache_file_read(pf, extra->data, extra->totdata, ptcache_extra_datasize[extra->type]); + + BLI_addtail(&pm->extradata, extra); } } - if(!pm && !pm2 && !pf && !pf2) - return 0; - - if(pm) { - BKE_ptcache_mem_init_pointers(pm); - totpoint = pm->totpoint; - index = pm->data_types & (1<<BPHYS_DATA_INDEX) ? pm->cur[BPHYS_DATA_INDEX] : &i; + if(error && pm) { + ptcache_data_free(pm); + ptcache_extra_free(pm); + MEM_freeN(pm); + pm = NULL; } - if(pm2) { - BKE_ptcache_mem_init_pointers(pm2); - totpoint2 = pm2->totpoint; - index2 = pm2->data_types & (1<<BPHYS_DATA_INDEX) ? pm2->cur[BPHYS_DATA_INDEX] : &i; + + ptcache_file_close(pf); + + if (error && G.f & G_DEBUG) + printf("Error reading from disk cache\n"); + + return pm; +} +static int ptcache_mem_frame_to_disk(PTCacheID *pid, PTCacheMem *pm) +{ + PTCacheFile *pf = NULL; + unsigned int i, error = 0; + + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, pm->frame); + + pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, pm->frame); + + if(pf==NULL) { + if (G.f & G_DEBUG) + printf("Error opening disk cache file for writing\n"); + return 0; } - 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 & (1<<BPHYS_DATA_INDEX) ? &pf->data.index : &i; + + pf->data_types = pm->data_types; + pf->totpoint = pm->totpoint; + pf->type = pid->type; + pf->flag = 0; + + if(pm->extradata.first) + pf->flag |= PTCACHE_TYPEFLAG_EXTRADATA; + + if(pid->cache->compression) + pf->flag |= PTCACHE_TYPEFLAG_COMPRESS; + + if(!ptcache_file_header_begin_write(pf) || !pid->write_header(pf)) + error = 1; + + if(!error) { + if(pid->cache->compression) { + for(i=0; i<BPHYS_TOT_DATA; i++) { + if(pm->data[i]) { + unsigned int in_len = pm->totpoint*ptcache_data_size[i]; + unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len)*4, "pointcache_lzo_buffer"); + ptcache_file_compressed_write(pf, (unsigned char*)(pm->data[i]), in_len, out, pid->cache->compression); + MEM_freeN(out); + } } } else { - /* fall back to old cache file format */ - use_old = 1; - totpoint = pid->totpoint(pid->calldata, (int) cfra); + BKE_ptcache_mem_pointers_init(pm); + ptcache_file_pointers_init(pf); + + for(i=0; i<pm->totpoint; i++) { + ptcache_data_copy(pm->cur, pf->cur); + if(!ptcache_file_data_write(pf)) { + error = 1; + break; + } + BKE_ptcache_mem_pointers_incr(pm); + } } } - if(pf2) { - if(ptcache_file_read_header_begin(pf2)) { - if(pf2->type != pid->type) { - /* todo report error */ - ptcache_file_close(pf2); - pf2 = NULL; + + if(!error && pm->extradata.first) { + PTCacheExtra *extra = pm->extradata.first; + + for(; extra; extra=extra->next) { + if(extra->data == NULL || extra->totdata == 0) + continue; + + ptcache_file_write(pf, &extra->type, 1, sizeof(unsigned int)); + ptcache_file_write(pf, &extra->totdata, 1, sizeof(unsigned int)); + + if(pid->cache->compression) { + unsigned int in_len = extra->totdata * ptcache_extra_datasize[extra->type]; + unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len)*4, "pointcache_lzo_buffer"); + ptcache_file_compressed_write(pf, (unsigned char*)(extra->data), in_len, out, pid->cache->compression); + MEM_freeN(out); } - else if(pid->read_header(pf2)) { - ptcache_file_init_pointers(pf2); - totpoint2 = pf2->totpoint; - index2 = pf2->data_types & (1<<BPHYS_DATA_INDEX) ? &pf2->data.index : &i; + else { + ptcache_file_write(pf, extra->data, extra->totdata, ptcache_extra_datasize[extra->type]); } } - else { - /* fall back to old cache file format */ - use_old = 1; - totpoint2 = pid->totpoint(pid->calldata, (int) cfra); - } } - /* don't read old cache if already simulated past cached frame */ - if(!pm && !pf && cfra1 && cfra1 <= pid->cache->simframe) + ptcache_file_close(pf); + + if (error && G.f & G_DEBUG) + printf("Error writing to disk cache\n"); + + return error==0; +} + +static int ptcache_read_stream(PTCacheID *pid, int cfra) +{ + PTCacheFile *pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra); + int error = 0; + + if(pid->read_stream == NULL) + return 0; + + if(pf == NULL) { + if (G.f & G_DEBUG) + printf("Error opening disk cache file for reading\n"); + return 0; + } + + if(!ptcache_file_header_begin_read(pf)) error = 1; - if(cfra1 && cfra1==cfra2) + + if(!error && (pf->type != pid->type || !pid->read_header(pf))) error = 1; - if(!error) - { - if(pf && pid->read_stream) { - if(totpoint != pid->totpoint(pid->calldata, (int) cfra)) - error = 1; - else - { - // we have stream writing here - pid->read_stream(pf, pid->calldata); - } - } + if(!error && pf->totpoint != pid->totpoint(pid->calldata, cfra)) + error = 1; + + if(!error) { + ptcache_file_pointers_init(pf); + + // we have stream reading here + pid->read_stream(pf, pid->calldata); + } + + ptcache_file_close(pf); + + return error == 0; +} +static int ptcache_read(PTCacheID *pid, int cfra) +{ + PTCacheMem *pm = NULL; + int i; + int *index = &i; + + /* get a memory cache to read from */ + if(pid->cache->flag & PTCACHE_DISK_CACHE) { + pm = ptcache_disk_frame_to_mem(pid, cfra); + } + else { + pm = pid->cache->mem_cache.first; + + while(pm && pm->frame != cfra) + pm = pm->next; } - if((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0) - totpoint = MIN2(totpoint, pid->totpoint(pid->calldata, (int) cfra)); + /* read the cache */ + if(pm) { + int totpoint = pm->totpoint; + + if((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0) + totpoint = MIN2(totpoint, pid->totpoint(pid->calldata, cfra)); + + BKE_ptcache_mem_pointers_init(pm); - if(!error) - { for(i=0; i<totpoint; i++) { - /* read old cache file format */ - if(use_old) { - if(pid->read_elem && ptcache_file_read(pf, (void*)old_data1, 1, old_elemsize)) - pid->read_elem(i, pid->calldata, NULL, frs_sec, cfra, old_data1); - else if(pid->read_elem) - { error = 1; break; } - } - else { - if(pid->read_elem && (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 if(pid->read_elem) - { error = 1; break; } - } + if(pm->data_types & (1<<BPHYS_DATA_INDEX)) + index = pm->cur[BPHYS_DATA_INDEX]; - if(pm) { - BKE_ptcache_mem_incr_pointers(pm); - index = pm->data_types & (1<<BPHYS_DATA_INDEX) ? pm->cur[BPHYS_DATA_INDEX] : &i; - } + pid->read_point(*index, pid->calldata, pm->cur, (float)pm->frame, NULL); + + BKE_ptcache_mem_pointers_incr(pm); } - } - if(!error) - { - if(pf2 && pid->read_stream) { - if(totpoint2 != pid->totpoint(pid->calldata, (int) cfra)) - error = 1; - else - { - // we have stream writing here - pid->read_stream(pf2, pid->calldata); - } + if(pid->read_extra_data && pm->extradata.first) + pid->read_extra_data(pid->calldata, pm, (float)pm->frame); + + /* clean up temporary memory cache */ + if(pid->cache->flag & PTCACHE_DISK_CACHE) { + ptcache_data_free(pm); + ptcache_extra_free(pm); + MEM_freeN(pm); } } - if((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0) - totpoint2 = MIN2(totpoint2, pid->totpoint(pid->calldata, (int) cfra)); + return 1; +} +static int ptcache_interpolate(PTCacheID *pid, float cfra, int cfra1, int cfra2) +{ + PTCacheMem *pm = NULL; + int i; + int *index = &i; - if(!error) - { - for(i=0; i<totpoint2; i++) { - /* read old cache file format */ - if(use_old) { - if(pid->read_elem && ptcache_file_read(pf2, (void*)old_data2, 1, old_elemsize)) { - if(!pf && pf2) - pid->read_elem(i, pid->calldata, NULL, frs_sec, (float)cfra2, old_data2); - else if(pid->interpolate_elem) - pid->interpolate_elem(i, pid->calldata, NULL, frs_sec, cfra, (float)cfra1, (float)cfra2, old_data2); - else - { error = 1; break; } - } - else if(pid->read_elem) - { error = 1; break; } - } - else { - if(pid->read_elem && (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 if(pid->interpolate_elem) - pid->interpolate_elem(*index2, pid->calldata, pm2 ? pm2->cur : pf2->cur, frs_sec, cfra, (float)cfra1, (float)cfra2, NULL); - else - { error = 1; break; } - } - else if(pid->read_elem) - { error = 1; break; } - } + /* get a memory cache to read from */ + if(pid->cache->flag & PTCACHE_DISK_CACHE) { + pm = ptcache_disk_frame_to_mem(pid, cfra2); + } + else { + pm = pid->cache->mem_cache.first; + + while(pm && pm->frame != cfra2) + pm = pm->next; + } - if(pm2) { - BKE_ptcache_mem_incr_pointers(pm2); - index2 = pm2->data_types & (1<<BPHYS_DATA_INDEX) ? pm2->cur[BPHYS_DATA_INDEX] : &i; - } + /* read the cache */ + if(pm) { + int totpoint = pm->totpoint; + + if((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0) + totpoint = MIN2(totpoint, pid->totpoint(pid->calldata, (int)cfra)); + + BKE_ptcache_mem_pointers_init(pm); + + for(i=0; i<totpoint; i++) { + if(pm->data_types & (1<<BPHYS_DATA_INDEX)) + index = pm->cur[BPHYS_DATA_INDEX]; + + pid->interpolate_point(*index, pid->calldata, pm->cur, cfra, (float)cfra1, (float)cfra2, NULL); + BKE_ptcache_mem_pointers_incr(pm); + } + + if(pid->interpolate_extra_data && pm->extradata.first) + pid->interpolate_extra_data(pid->calldata, pm, cfra, (float)cfra1, (float)cfra2); + + /* clean up temporary memory cache */ + if(pid->cache->flag & PTCACHE_DISK_CACHE) { + ptcache_data_free(pm); + ptcache_extra_free(pm); + MEM_freeN(pm); } } - 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; + return 1; +} +/* reads cache from disk or memory */ +/* possible to get old or interpolated result */ +int BKE_ptcache_read(PTCacheID *pid, float cfra) +{ + int cfrai = (int)cfra, cfra1=0, cfra2=0; + int ret = 0; + + /* nothing to read to */ + if(pid->totpoint(pid->calldata, cfrai) == 0) + return 0; + + if(pid->cache->flag & PTCACHE_READ_INFO) { + pid->cache->flag &= ~PTCACHE_READ_INFO; + ptcache_read(pid, 0); } - if(pf) { - ptcache_file_close(pf); - pf = NULL; + /* first check if we have the actual frame cached */ + if(cfra == (float)cfrai && BKE_ptcache_id_exist(pid, cfrai)) + cfra1 = cfrai; + + /* no exact cache frame found so try to find cached frames around cfra */ + if(cfra1 == 0) + ptcache_find_frames_around(pid, cfrai, &cfra1, &cfra2); + + if(cfra1 == 0 && cfra2 == 0) + return 0; + + /* don't read old cache if already simulated past cached frame */ + if(cfra1 == 0 && cfra2 && cfra2 <= pid->cache->simframe) + return 0; + if(cfra1 && cfra1 == cfra2) + return 0; + + if(cfra1) { + if(pid->read_stream) + ptcache_read_stream(pid, cfra1); + else if(pid->read_point) + ptcache_read(pid, cfra1); } - if(pf2) { - ptcache_file_close(pf2); - pf = NULL; + if(cfra2) { + if(pid->read_stream) + ptcache_read_stream(pid, cfra2); + else if(pid->read_point) { + if(cfra1 && cfra2 && pid->interpolate_point) + ptcache_interpolate(pid, cfra, cfra1, cfra2); + else + ptcache_read(pid, cfra2); + } + } + + if(cfra1) + ret = (cfra2 ? PTCACHE_READ_INTERPOLATED : PTCACHE_READ_EXACT); + else if(cfra2) { + ret = PTCACHE_READ_OLD; + pid->cache->simframe = cfra2; } if((pid->cache->flag & PTCACHE_QUICK_CACHE)==0) { @@ -1681,218 +1746,208 @@ int BKE_ptcache_read_cache(PTCacheID *pid, float cfra, float frs_sec) if(cfra <= pid->cache->last_exact) pid->cache->flag &= ~PTCACHE_FRAMES_SKIPPED; - BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfrai,pid->cache->last_exact)); + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfrai, pid->cache->last_exact)); } } - return (error ? 0 : ret); + return ret; } -/* TODO for later */ -static void ptcache_make_index_array(PTCacheMem *pm, int totpoint) +static int ptcache_write_stream(PTCacheID *pid, int cfra, int totpoint) { - int i, *index; + PTCacheFile *pf = NULL; + int error = 0; + + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, cfra); + + pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, cfra); - if(pm->index_array) { - MEM_freeN(pm->index_array); - pm->index_array = NULL; + if(pf==NULL) { + if (G.f & G_DEBUG) + printf("Error opening disk cache file for writing\n"); + return 0; } - if(!pm->data[BPHYS_DATA_INDEX]) - return; + pf->data_types = pid->data_types; + pf->totpoint = totpoint; + pf->type = pid->type; + pf->flag = 0; + + if(!error && (!ptcache_file_header_begin_write(pf) || !pid->write_header(pf))) + error = 1; - pm->index_array = MEM_callocN(totpoint * sizeof(int), "PTCacheMem index_array"); - index = pm->data[BPHYS_DATA_INDEX]; + if(!error && pid->write_stream) + pid->write_stream(pf, pid->calldata); - for(i=0; i<pm->totpoint; i++, index++) - pm->index_array[*index] = i + 1; + ptcache_file_close(pf); + + if (error && G.f & G_DEBUG) + printf("Error writing to disk cache\n"); + + return error == 0; } -/* writes cache to disk or memory */ -int BKE_ptcache_write_cache(PTCacheID *pid, int cfra) +static int ptcache_write(PTCacheID *pid, int cfra, int overwrite) { PointCache *cache = pid->cache; - PTCacheFile *pf= NULL, *pf2= NULL; - int i; + PTCacheMem *pm=NULL, *pm2=NULL; int totpoint = pid->totpoint(pid->calldata, cfra); - int add = 0, overwrite = 0; + int i, error = 0; - if(totpoint == 0 || (cfra ? pid->data_types == 0 : pid->info_types == 0)) - return 0; + pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem"); - if(cache->flag & PTCACHE_DISK_CACHE) { - int ofra=0, efra = cache->endframe; + pm->totpoint = pid->totwrite(pid->calldata, cfra); + pm->data_types = cfra ? pid->data_types : pid->info_types; - if(cfra==0 && cache->startframe > 0) - add = 1; - /* allways start from scratch on the first frame */ - else if(cfra == cache->startframe) { - BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, cfra); - cache->flag &= ~PTCACHE_REDO_NEEDED; - add = 1; + ptcache_data_alloc(pm); + BKE_ptcache_mem_pointers_init(pm); + + if(overwrite) { + if(cache->flag & PTCACHE_DISK_CACHE) { + int fra = cfra-1; + + while(fra >= cache->startframe && !BKE_ptcache_id_exist(pid, fra)) + fra--; + + pm2 = ptcache_disk_frame_to_mem(pid, fra); } - else { - /* find last cached frame */ - while(efra > cache->startframe && !BKE_ptcache_id_exist(pid, efra)) - efra--; - - /* find second last cached frame */ - ofra = efra-1; - while(ofra > cache->startframe && !BKE_ptcache_id_exist(pid, ofra)) - ofra--; - - if(efra >= cache->startframe && cfra > efra) { - if(ofra >= cache->startframe && efra - ofra < cache->step) - overwrite = 1; - else - add = 1; + else + pm2 = cache->mem_cache.last; + } + + if(pid->write_point) { + for(i=0; i<totpoint; i++) { + int write = pid->write_point(i, pid->calldata, pm->cur, cfra); + if(write) { + BKE_ptcache_mem_pointers_incr(pm); + + /* newly born particles have to be copied to previous cached frame */ + if(overwrite && write == 2 && pm2 && BKE_ptcache_mem_pointers_seek(i, pm2)) + pid->write_point(i, pid->calldata, pm2->cur, cfra); } } + } - if(add || overwrite) { - if(overwrite) - BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, efra); - - pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, cfra); - if(!pf) - return 0; + if(pid->write_extra_data) + pid->write_extra_data(pid->calldata, pm, cfra); - pf->type = pid->type; - pf->totpoint = cfra ? pid->totwrite(pid->calldata, cfra) : totpoint; - pf->data_types = cfra ? pid->data_types : pid->info_types; + pm->frame = cfra; - if(!ptcache_file_write_header_begin(pf) || !pid->write_header(pf)) { - ptcache_file_close(pf); - return 0; - } + if(cache->flag & PTCACHE_DISK_CACHE) { + error += !ptcache_mem_frame_to_disk(pid, pm); - ptcache_file_init_pointers(pf); + if(pm) { + ptcache_data_free(pm); + ptcache_extra_free(pm); + MEM_freeN(pm); + } - if(pf && pid->write_stream) { - // we have stream writing here - pid->write_stream(pf, pid->calldata); - } - else - for(i=0; i<totpoint; i++) { - if(pid->write_elem) { - int write = pid->write_elem(i, pid->calldata, pf->cur, cfra); - if(write) { - if(!ptcache_file_write_data(pf)) { - ptcache_file_close(pf); - if(pf2) ptcache_file_close(pf2); - return 0; - } - /* newly born particles have to be copied to previous cached frame */ - else if(overwrite && write == 2) { - if(!pf2) { - pf2 = ptcache_file_open(pid, PTCACHE_FILE_UPDATE, ofra); - if(!pf2) { - ptcache_file_close(pf); - return 0; - } - pf2->type = pid->type; - pf2->totpoint = totpoint; - pf2->data_types = pid->data_types; - } - ptcache_file_seek_pointers(i, pf2); - pid->write_elem(i, pid->calldata, pf2->cur, cfra); - if(!ptcache_file_write_data(pf2)) { - ptcache_file_close(pf); - ptcache_file_close(pf2); - return 0; - } - } - } - } - } + if(pm2) { + error += !ptcache_mem_frame_to_disk(pid, pm2); + ptcache_data_free(pm2); + ptcache_extra_free(pm2); + MEM_freeN(pm2); } } else { - PTCacheMem *pm; - PTCacheMem *pm2; + BLI_addtail(&cache->mem_cache, pm); + } - pm2 = cache->mem_cache.first; - - /* don't write info file in memory */ - if(cfra==0) + return error; +} +static int ptcache_write_needed(PTCacheID *pid, int cfra, int *overwrite) +{ + PointCache *cache = pid->cache; + int ofra = 0, efra = cache->endframe; + + /* allways start from scratch on the first frame */ + if(cfra && cfra == cache->startframe) { + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, cfra); + cache->flag &= ~PTCACHE_REDO_NEEDED; + return 1; + } + + if(pid->cache->flag & PTCACHE_DISK_CACHE) { + if(cfra==0 && cache->startframe > 0) return 1; - /* allways start from scratch on the first frame */ - if(cfra == cache->startframe) { - BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, cfra); - cache->flag &= ~PTCACHE_REDO_NEEDED; - add = 1; - } - else if (cache->mem_cache.last) { - pm2 = cache->mem_cache.last; - if(pm2 && cfra > pm2->frame) { - if(pm2->prev && pm2->frame - pm2->prev->frame < cache->step) - overwrite = 1; - else - add = 1; - } - } - else - add = 1; + /* find last cached frame */ + while(efra > cache->startframe && !BKE_ptcache_id_exist(pid, efra)) + efra--; - if(add || overwrite) { - if(overwrite) - BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, pm2->frame); + /* find second last cached frame */ + ofra = efra-1; + while(ofra > cache->startframe && !BKE_ptcache_id_exist(pid, ofra)) + ofra--; + } + else { + PTCacheMem *pm = cache->mem_cache.last; + /* don't write info file in memory */ + if(cfra == 0) + return 0; - pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem"); + if(pm == NULL) + return 1; - pm->totpoint = pid->totwrite(pid->calldata, cfra); - pm->data_types = cfra ? pid->data_types : pid->info_types; + efra = pm->frame; + ofra = (pm->prev ? pm->prev->frame : efra - cache->step); + } - ptcache_alloc_data(pm); - BKE_ptcache_mem_init_pointers(pm); + if(efra >= cache->startframe && cfra > efra) { + if(ofra >= cache->startframe && efra - ofra < cache->step) { + /* overwrite previous frame */ + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, efra); + *overwrite = 1; + } + return 1; + } - for(i=0; i<totpoint; i++) { - if(pid->write_elem) { - int write = pid->write_elem(i, pid->calldata, pm->cur, cfra); - if(write) { - BKE_ptcache_mem_incr_pointers(pm); + return 0; +} +/* writes cache to disk or memory */ +int BKE_ptcache_write(PTCacheID *pid, unsigned int cfra) +{ + PointCache *cache = pid->cache; + int totpoint = pid->totpoint(pid->calldata, cfra); + int overwrite = 0, error = 0; - /* newly born particles have to be copied to previous cached frame */ - if(overwrite && write == 2) { - pm2 = cache->mem_cache.last; - if(BKE_ptcache_mem_seek_pointers(i, pm2)) - pid->write_elem(i, pid->calldata, pm2->cur, cfra); - } - } - } - } - ptcache_make_index_array(pm, pid->totpoint(pid->calldata, cfra)); + if(totpoint == 0 || (cfra ? pid->data_types == 0 : pid->info_types == 0)) + return 0; - pm->frame = cfra; - BLI_addtail(&cache->mem_cache, pm); - } + if(ptcache_write_needed(pid, cfra, &overwrite)==0) + return 0; + + if(pid->write_stream) { + ptcache_write_stream(pid, cfra, totpoint); + } + else if(pid->write_point) { + error += ptcache_write(pid, cfra, overwrite); } - if(add || overwrite) { - if(cfra - cache->last_exact == 1 - || cfra == cache->startframe) { - cache->last_exact = cfra; - cache->flag &= ~PTCACHE_FRAMES_SKIPPED; - } - else - cache->flag |= PTCACHE_FRAMES_SKIPPED; + /* Mark frames skipped if more than 1 frame forwards since last non-skipped frame. */ + if(cfra - cache->last_exact == 1 || cfra == cache->startframe) { + cache->last_exact = cfra; + cache->flag &= ~PTCACHE_FRAMES_SKIPPED; } - - if(pf) ptcache_file_close(pf); + /* Don't mark skipped when writing info file (frame 0) */ + else if(cfra) + cache->flag |= PTCACHE_FRAMES_SKIPPED; - if(pf2) ptcache_file_close(pf2); + /* Update timeline cache display */ + if(cfra && cache->cached_frames) + cache->cached_frames[cfra-cache->startframe] = 1; BKE_ptcache_update_info(pid); - return 1; + return !error; } /* youll need to close yourself after! * mode - PTCACHE_CLEAR_ALL, */ /* Clears & resets */ -void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) +void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra) { - int len; /* store the length of the string */ + unsigned int len; /* store the length of the string */ + unsigned int sta, end; /* mode is same as fopen's modes */ DIR *dir; @@ -1902,9 +1957,12 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) char path_full[MAX_PTCACHE_FILE]; char ext[MAX_PTCACHE_PATH]; - if(!pid->cache || pid->cache->flag & PTCACHE_BAKED) + if(!pid || !pid->cache || pid->cache->flag & PTCACHE_BAKED) return; + sta = pid->cache->startframe; + end = pid->cache->endframe; + #ifndef DURIAN_POINTCACHE_LIB_OK /* don't allow clearing for linked objects */ if(pid->ob->id.lib) @@ -1921,7 +1979,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) if(pid->cache->flag & PTCACHE_DISK_CACHE) { ptcache_path(pid, path); - len = BKE_ptcache_id_filename(pid, filename, cfra, 0, 0); /* no path */ + len = ptcache_filename(pid, filename, cfra, 0, 0); /* no path */ dir = opendir(path); if (dir==NULL) @@ -1938,7 +1996,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) BLI_delete(path_full, 0, 0); } else { /* read the number of the file */ - int frame, len2 = (int)strlen(de->d_name); + unsigned int frame, len2 = (int)strlen(de->d_name); char num[7]; if (len2 > 15) { /* could crash if trying to copy a string out of this range*/ @@ -1950,6 +2008,8 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) BLI_join_dirfile(path_full, path, de->d_name); BLI_delete(path_full, 0, 0); + if(pid->cache->cached_frames && frame >=sta && frame <= end) + pid->cache->cached_frames[frame-sta] = 0; } } } @@ -1957,25 +2017,34 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) } } closedir(dir); + + if(mode == PTCACHE_CLEAR_ALL && pid->cache->cached_frames) + memset(pid->cache->cached_frames, 0, MEM_allocN_len(pid->cache->cached_frames)); } else { PTCacheMem *pm= pid->cache->mem_cache.first; PTCacheMem *link= NULL; - pm= pid->cache->mem_cache.first; - if(mode == PTCACHE_CLEAR_ALL) { /*we want startframe if the cache starts before zero*/ pid->cache->last_exact = MIN2(pid->cache->startframe, 0); - for(; pm; pm=pm->next) - ptcache_free_data(pm); + for(; pm; pm=pm->next) { + ptcache_data_free(pm); + ptcache_extra_free(pm); + } BLI_freelistN(&pid->cache->mem_cache); + + if(pid->cache->cached_frames) + memset(pid->cache->cached_frames, 0, MEM_allocN_len(pid->cache->cached_frames)); } else { while(pm) { if((mode==PTCACHE_CLEAR_BEFORE && pm->frame < cfra) || (mode==PTCACHE_CLEAR_AFTER && pm->frame > cfra) ) { link = pm; - ptcache_free_data(pm); + if(pid->cache->cached_frames && pm->frame >=sta && pm->frame <= end) + pid->cache->cached_frames[pm->frame-sta] = 0; + ptcache_data_free(pm); + ptcache_extra_free(pm); pm = pm->next; BLI_freelinkN(&pid->cache->mem_cache, link); } @@ -1989,7 +2058,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) case PTCACHE_CLEAR_FRAME: if(pid->cache->flag & PTCACHE_DISK_CACHE) { if(BKE_ptcache_id_exist(pid, cfra)) { - BKE_ptcache_id_filename(pid, filename, cfra, 1, 1); /* no path */ + ptcache_filename(pid, filename, cfra, 1, 1); /* no path */ BLI_delete(filename, 0, 0); } } @@ -1998,27 +2067,35 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) for(; pm; pm=pm->next) { if(pm->frame == cfra) { - ptcache_free_data(pm); + ptcache_data_free(pm); + ptcache_extra_free(pm); BLI_freelinkN(&pid->cache->mem_cache, pm); break; } } } + if(pid->cache->cached_frames && cfra>=sta && cfra<=end) + pid->cache->cached_frames[cfra-sta] = 0; break; } BKE_ptcache_update_info(pid); } - -int BKE_ptcache_id_exist(PTCacheID *pid, int cfra) +int BKE_ptcache_id_exist(PTCacheID *pid, int cfra) { if(!pid->cache) return 0; + + if(cfra<pid->cache->startframe || cfra > pid->cache->endframe) + return 0; + + if(pid->cache->cached_frames && pid->cache->cached_frames[cfra-pid->cache->startframe]==0) + return 0; if(pid->cache->flag & PTCACHE_DISK_CACHE) { char filename[MAX_PTCACHE_FILE]; - BKE_ptcache_id_filename(pid, filename, cfra, 1, 1); + ptcache_filename(pid, filename, cfra, 1, 1); return BLI_exists(filename); } @@ -2032,7 +2109,6 @@ int BKE_ptcache_id_exist(PTCacheID *pid, int cfra) return 0; } } - void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startframe, int *endframe, float *timescale) { Object *ob; @@ -2073,9 +2149,71 @@ void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startfra *endframe += (int)(offset+0.5f); } } -} -int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) + /* verify cached_frames array is up to date */ + if(cache->cached_frames) { + if(MEM_allocN_len(cache->cached_frames) != sizeof(char) * (cache->endframe-cache->startframe+1)) { + MEM_freeN(cache->cached_frames); + cache->cached_frames = NULL; + } + } + + if(cache->cached_frames==NULL && cache->endframe > cache->startframe) { + unsigned int sta=cache->startframe; + unsigned int end=cache->endframe; + + cache->cached_frames = MEM_callocN(sizeof(char) * (cache->endframe-cache->startframe+1), "cached frames array"); + + if(pid->cache->flag & PTCACHE_DISK_CACHE) { + /* mode is same as fopen's modes */ + DIR *dir; + struct dirent *de; + char path[MAX_PTCACHE_PATH]; + char filename[MAX_PTCACHE_FILE]; + char ext[MAX_PTCACHE_PATH]; + unsigned int len; /* store the length of the string */ + + ptcache_path(pid, path); + + len = ptcache_filename(pid, filename, (int)cfra, 0, 0); /* no path */ + + dir = opendir(path); + if (dir==NULL) + return; + + snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, pid->stack_index); + + while ((de = readdir(dir)) != NULL) { + if (strstr(de->d_name, ext)) { /* do we have the right extension?*/ + if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */ + /* read the number of the file */ + unsigned int frame, len2 = (int)strlen(de->d_name); + char num[7]; + + if (len2 > 15) { /* could crash if trying to copy a string out of this range*/ + BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num)); + frame = atoi(num); + + if(frame >= sta && frame <= end) + cache->cached_frames[frame-sta] = 1; + } + } + } + } + closedir(dir); + } + else { + PTCacheMem *pm= pid->cache->mem_cache.first; + + while(pm) { + if(pm->frame >= sta && pm->frame <= end) + cache->cached_frames[pm->frame-sta] = 1; + pm = pm->next; + } + } + } +} +int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) { PointCache *cache; int reset, clear, after; @@ -2120,7 +2258,7 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) cache->flag &= ~PTCACHE_REDO_NEEDED; if(pid->type == PTCACHE_TYPE_CLOTH) - cloth_free_modifier(pid->ob, pid->calldata); + cloth_free_modifier(pid->calldata); else if(pid->type == PTCACHE_TYPE_SOFTBODY) sbFreeSimulation(pid->calldata); else if(pid->type == PTCACHE_TYPE_PARTICLES) @@ -2137,8 +2275,7 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) return (reset || clear || after); } - -int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode) +int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode) { PTCacheID pid; ParticleSystem *psys; @@ -2154,17 +2291,18 @@ int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode) } for(psys=ob->particlesystem.first; psys; psys=psys->next) { - /* Baked cloth hair has to be checked first, because we don't want to reset */ + /* children or just redo can be calculated without reseting anything */ + if(psys->recalc & PSYS_RECALC_REDO || psys->recalc & PSYS_RECALC_CHILD) + skip = 1; + /* Baked cloth hair has to be checked too, because we don't want to reset */ /* particles or cloth in that case -jahka */ - if(psys->clmd) { + else if(psys->clmd) { BKE_ptcache_id_from_cloth(&pid, ob, psys->clmd); if(mode == PSYS_RESET_ALL || !(psys->part->type == PART_HAIR && (pid.cache->flag & PTCACHE_BAKED))) reset |= BKE_ptcache_id_reset(scene, &pid, mode); else skip = 1; } - else if(psys->recalc & PSYS_RECALC_REDO || psys->recalc & PSYS_RECALC_CHILD) - skip = 1; if(skip == 0 && psys->part) { BKE_ptcache_id_from_particles(&pid, ob, psys); @@ -2183,9 +2321,6 @@ int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode) { BKE_ptcache_id_from_smoke(&pid, ob, (SmokeModifierData*)md); reset |= BKE_ptcache_id_reset(scene, &pid, mode); - - BKE_ptcache_id_from_smoke_turbulence(&pid, ob, (SmokeModifierData*)md); - reset |= BKE_ptcache_id_reset(scene, &pid, mode); } } } @@ -2250,12 +2385,12 @@ void BKE_ptcache_set_continue_physics(Main *bmain, Scene *scene, int enable) if(CONTINUE_PHYSICS == 0) { for(ob=bmain->object.first; ob; ob=ob->id.next) if(BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_OUTDATED)) - DAG_id_flush_update(&ob->id, OB_RECALC_DATA); + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); } } } -int BKE_ptcache_get_continue_physics() +int BKE_ptcache_get_continue_physics() { return CONTINUE_PHYSICS; } @@ -2282,8 +2417,10 @@ void BKE_ptcache_free_mem(ListBase *mem_cache) PTCacheMem *pm = mem_cache->first; if(pm) { - for(; pm; pm=pm->next) - ptcache_free_data(pm); + for(; pm; pm=pm->next) { + ptcache_data_free(pm); + ptcache_extra_free(pm); + } BLI_freelistN(mem_cache); } @@ -2293,6 +2430,8 @@ void BKE_ptcache_free(PointCache *cache) BKE_ptcache_free_mem(&cache->mem_cache); if(cache->edit && cache->free_edit) cache->free_edit(cache->edit); + if(cache->cached_frames) + MEM_freeN(cache->cached_frames); MEM_freeN(cache); } void BKE_ptcache_free_list(ListBase *ptcaches) @@ -2315,6 +2454,8 @@ static PointCache *ptcache_copy(PointCache *cache) /* hmm, should these be copied over instead? */ ncache->mem_cache.first = NULL; ncache->mem_cache.last = NULL; + ncache->cached_frames = NULL; + ncache->edit = NULL; ncache->flag= 0; ncache->simframe= 0; @@ -2353,7 +2494,7 @@ void BKE_ptcache_quick_cache_all(Main *bmain, Scene *scene) baker.scene=scene; baker.quick_step=scene->physics_settings.quick_cache_step; - BKE_ptcache_make_cache(&baker); + BKE_ptcache_bake(&baker); } /* Simulation thread, no need for interlocks as data written in both threads @@ -2366,10 +2507,10 @@ typedef struct { int *cfra_ptr; Main *main; Scene *scene; -} ptcache_make_cache_data; +} ptcache_bake_data; -static void *ptcache_make_cache_thread(void *ptr) { - ptcache_make_cache_data *data = (ptcache_make_cache_data*)ptr; +static void *ptcache_bake_thread(void *ptr) { + ptcache_bake_data *data = (ptcache_bake_data*)ptr; for(; (*data->cfra_ptr <= data->endframe) && !data->break_operation; *data->cfra_ptr+=data->step) { scene_update_for_newframe(data->main, data->scene, data->scene->lay); @@ -2383,11 +2524,11 @@ static void *ptcache_make_cache_thread(void *ptr) { } /* if bake is not given run simulations to current frame */ -void BKE_ptcache_make_cache(PTCacheBaker* baker) +void BKE_ptcache_bake(PTCacheBaker* baker) { Main *bmain = baker->main; Scene *scene = baker->scene; - Scene *sce; /* SETLOOPER macro only */ + Scene *sce_iter; /* SETLOOPER macro only */ Base *base; ListBase pidlist; PTCacheID *pid = baker->pid; @@ -2398,7 +2539,7 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) int bake = baker->bake; int render = baker->render; ListBase threads; - ptcache_make_cache_data thread_data; + ptcache_bake_data thread_data; int progress, old_progress; thread_data.endframe = baker->anim_init ? scene->r.sfra : CFRA; @@ -2458,7 +2599,7 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) cache->flag &= ~PTCACHE_BAKED; } } - else for(SETLOOPER(scene, base)) { + else for(SETLOOPER(scene, sce_iter, base)) { /* cache/bake everything in the scene */ BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR); @@ -2499,12 +2640,14 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) thread_data.break_operation = FALSE; thread_data.thread_ended = FALSE; old_progress = -1; + + WM_cursor_wait(1); if(G.background) { - ptcache_make_cache_thread((void*)&thread_data); + ptcache_bake_thread((void*)&thread_data); } else { - BLI_init_threads(&threads, ptcache_make_cache_thread, 1); + BLI_init_threads(&threads, ptcache_bake_thread, 1); BLI_insert_thread(&threads, (void*)&thread_data); while (thread_data.thread_ended == FALSE) { @@ -2542,10 +2685,10 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) cache->flag |= PTCACHE_BAKED; /* write info file */ if(cache->flag & PTCACHE_DISK_CACHE) - BKE_ptcache_write_cache(pid, 0); + BKE_ptcache_write(pid, 0); } } - else for(SETLOOPER(scene, base)) { + else for(SETLOOPER(scene, sce_iter, base)) { BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR); for(pid=pidlist.first; pid; pid=pid->next) { @@ -2565,7 +2708,7 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) if(bake) { cache->flag |= PTCACHE_BAKED; if(cache->flag & PTCACHE_DISK_CACHE) - BKE_ptcache_write_cache(pid, 0); + BKE_ptcache_write(pid, 0); } } BLI_freelistN(&pidlist); @@ -2582,126 +2725,59 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) else if (baker->progressend) baker->progressend(baker->progresscontext); + WM_cursor_wait(0); + /* TODO: call redraw all windows somehow */ } /* Helpers */ void BKE_ptcache_disk_to_mem(PTCacheID *pid) { PointCache *cache = pid->cache; - PTCacheFile *pf; - PTCacheMem *pm; - + PTCacheMem *pm = NULL; + int baked = cache->flag & PTCACHE_BAKED; int cfra, sfra = cache->startframe, efra = cache->endframe; - int i; - BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); + /* Remove possible bake flag to allow clear */ + cache->flag &= ~PTCACHE_BAKED; - 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); - BKE_ptcache_mem_init_pointers(pm); - ptcache_file_init_pointers(pf); + /* PTCACHE_DISK_CACHE flag was cleared already */ + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); - for(i=0; i<pm->totpoint; i++) { - if(!ptcache_file_read_data(pf)) { - printf("Error reading from disk cache\n"); - - cache->flag |= PTCACHE_DISK_CACHE; - - ptcache_free_data(pm); - MEM_freeN(pm); - ptcache_file_close(pf); - - return; - } - ptcache_copy_data(pf->cur, pm->cur); - BKE_ptcache_mem_incr_pointers(pm); - } + /* restore possible bake flag */ + cache->flag |= baked; - ptcache_make_index_array(pm, pid->totpoint(pid->calldata, cfra)); + for(cfra=sfra; cfra <= efra; cfra++) { + pm = ptcache_disk_frame_to_mem(pid, cfra); + if(pm) 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; + PTCacheMem *pm = cache->mem_cache.first; + int baked = cache->flag & PTCACHE_BAKED; - pm = cache->mem_cache.first; + /* Remove possible bake flag to allow clear */ + cache->flag &= ~PTCACHE_BAKED; + /* PTCACHE_DISK_CACHE flag was set already */ 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; + /* restore possible bake flag */ + cache->flag |= baked; - BKE_ptcache_mem_init_pointers(pm); - ptcache_file_init_pointers(pf); - - if(!ptcache_file_write_header_begin(pf) || !pid->write_header(pf)) { - if (G.f & G_DEBUG) - printf("Error writing to disk cache\n"); - cache->flag &= ~PTCACHE_DISK_CACHE; - - ptcache_file_close(pf); - return; - } - - for(i=0; i<pm->totpoint; i++) { - ptcache_copy_data(pm->cur, pf->cur); - if(!ptcache_file_write_data(pf)) { - if (G.f & G_DEBUG) - printf("Error writing to disk cache\n"); - cache->flag &= ~PTCACHE_DISK_CACHE; - - ptcache_file_close(pf); - return; - } - BKE_ptcache_mem_incr_pointers(pm); - } - - ptcache_file_close(pf); - - /* write info file */ - if(cache->flag & PTCACHE_BAKED) - BKE_ptcache_write_cache(pid, 0); + for(; pm; pm=pm->next) { + if(ptcache_mem_frame_to_disk(pid, pm)==0) { + cache->flag &= ~PTCACHE_DISK_CACHE; + break; } - else - if (G.f & G_DEBUG) - printf("Error creating disk cache file\n"); } + + /* write info file */ + if(cache->flag & PTCACHE_BAKED) + BKE_ptcache_write(pid, 0); } void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) { @@ -2715,6 +2791,11 @@ void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) return; } + if(cache->cached_frames) { + MEM_freeN(cache->cached_frames); + cache->cached_frames=NULL; + } + if(cache->flag & PTCACHE_DISK_CACHE) BKE_ptcache_mem_to_disk(pid); else @@ -2726,15 +2807,75 @@ void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) cache->last_exact = last_exact; + BKE_ptcache_id_time(pid, NULL, 0.0f, NULL, NULL, NULL); + BKE_ptcache_update_info(pid); } +void BKE_ptcache_disk_cache_rename(PTCacheID *pid, char *from, char *to) +{ + char old_name[80]; + int len; /* store the length of the string */ + /* mode is same as fopen's modes */ + DIR *dir; + struct dirent *de; + char path[MAX_PTCACHE_PATH]; + char old_filename[MAX_PTCACHE_FILE]; + char new_path_full[MAX_PTCACHE_FILE]; + char old_path_full[MAX_PTCACHE_FILE]; + char ext[MAX_PTCACHE_PATH]; + + /* save old name */ + strcpy(old_name, pid->cache->name); + + /* get "from" filename */ + strcpy(pid->cache->name, from); + + len = ptcache_filename(pid, old_filename, 0, 0, 0); /* no path */ + + ptcache_path(pid, path); + dir = opendir(path); + if(dir==NULL) { + strcpy(pid->cache->name, old_name); + return; + } + + snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, pid->stack_index); + + /* put new name into cache */ + strcpy(pid->cache->name, to); + + while ((de = readdir(dir)) != NULL) { + if (strstr(de->d_name, ext)) { /* do we have the right extension?*/ + if (strncmp(old_filename, de->d_name, len ) == 0) { /* do we have the right prefix */ + /* read the number of the file */ + int frame, len2 = (int)strlen(de->d_name); + char num[7]; + + if (len2 > 15) { /* could crash if trying to copy a string out of this range*/ + BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num)); + frame = atoi(num); + + BLI_join_dirfile(old_path_full, path, de->d_name); + ptcache_filename(pid, new_path_full, frame, 1, 1); + BLI_rename(old_path_full, new_path_full); + } + } + } + } + closedir(dir); + + strcpy(pid->cache->name, old_name); +} + void BKE_ptcache_load_external(PTCacheID *pid) { /*todo*/ PointCache *cache = pid->cache; int len; /* store the length of the string */ int info = 0; + int start = MAXFRAME; + int end = -1; /* mode is same as fopen's modes */ DIR *dir; @@ -2746,13 +2887,9 @@ void BKE_ptcache_load_external(PTCacheID *pid) if(!cache) return; - cache->startframe = MAXFRAME; - cache->endframe = -1; - cache->totpoint = 0; - ptcache_path(pid, path); - len = BKE_ptcache_id_filename(pid, filename, 1, 0, 0); /* no path */ + len = ptcache_filename(pid, filename, 1, 0, 0); /* no path */ dir = opendir(path); if (dir==NULL) @@ -2775,8 +2912,8 @@ void BKE_ptcache_load_external(PTCacheID *pid) frame = atoi(num); if(frame) { - cache->startframe = MIN2(cache->startframe, frame); - cache->endframe = MAX2(cache->endframe, frame); + start = MIN2(start, frame); + end = MAX2(end, frame); } else info = 1; @@ -2786,15 +2923,21 @@ void BKE_ptcache_load_external(PTCacheID *pid) } closedir(dir); - if(cache->startframe != MAXFRAME) { + if(start != MAXFRAME) { PTCacheFile *pf; + cache->startframe = start; + cache->endframe = end; + cache->totpoint = 0; + + if(pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) + ; /*necessary info in every file*/ /* read totpoint from info file (frame 0) */ - if(info) { + else if(info) { pf= ptcache_file_open(pid, PTCACHE_FILE_READ, 0); if(pf) { - if(ptcache_file_read_header_begin(pf)) { + if(ptcache_file_header_begin_read(pf)) { if(pf->type == pid->type && pid->read_header(pf)) { cache->totpoint = pf->totpoint; cache->flag |= PTCACHE_READ_INFO; @@ -2809,7 +2952,7 @@ void BKE_ptcache_load_external(PTCacheID *pid) /* or from any old format cache file */ else { float old_data[14]; - int elemsize = ptcache_pid_old_elemsize(pid); + int elemsize = ptcache_old_elemsize(pid); pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cache->startframe); if(pf) { @@ -2819,16 +2962,17 @@ void BKE_ptcache_load_external(PTCacheID *pid) ptcache_file_close(pf); } } + cache->flag |= (PTCACHE_BAKED|PTCACHE_DISK_CACHE|PTCACHE_SIMULATION_VALID); + cache->flag &= ~(PTCACHE_OUTDATED|PTCACHE_FRAMES_SKIPPED); } - cache->flag &= ~(PTCACHE_OUTDATED|PTCACHE_FRAMES_SKIPPED); - BKE_ptcache_update_info(pid); } void BKE_ptcache_update_info(PTCacheID *pid) { PointCache *cache = pid->cache; + PTCacheExtra *extra = NULL; int totframes = 0; char mem_info[64]; @@ -2840,7 +2984,10 @@ void BKE_ptcache_update_info(PTCacheID *pid) totframes++; } - if(totframes && cache->totpoint) + /* smoke doesn't use frame 0 as info frame so can't check based on totpoint */ + if(pid->type == PTCACHE_TYPE_SMOKE_DOMAIN && totframes) + sprintf(cache->info, "%i frames found!", totframes); + else if(totframes && cache->totpoint) sprintf(cache->info, "%i points found!", cache->totpoint); else sprintf(cache->info, "No valid data to read!"); @@ -2848,14 +2995,25 @@ void BKE_ptcache_update_info(PTCacheID *pid) } if(cache->flag & PTCACHE_DISK_CACHE) { - int cfra = cache->startframe; + if(pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) + { + int totpoint = pid->totpoint(pid->calldata, 0); - for(; cfra<=cache->endframe; cfra++) { - if(BKE_ptcache_id_exist(pid, cfra)) - totframes++; + if(cache->totpoint > totpoint) + sprintf(mem_info, "%i cells + High Resolution cached", totpoint); + else + sprintf(mem_info, "%i cells cached", totpoint); } + else { + int cfra = cache->startframe; - sprintf(mem_info, "%i frames on disk", totframes); + 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; @@ -2864,7 +3022,15 @@ void BKE_ptcache_update_info(PTCacheID *pid) for(; pm; pm=pm->next) { for(i=0; i<BPHYS_TOT_DATA; i++) - bytes += pm->data[i] ? MEM_allocN_len(pm->data[i]) : 0.0f; + bytes += MEM_allocN_len(pm->data[i]); + + for(extra=pm->extradata.first; extra; extra=extra->next) { + bytes += MEM_allocN_len(extra->data); + bytes += sizeof(PTCacheExtra); + } + + bytes += sizeof(PTCacheMem); + totframes++; } @@ -2888,13 +3054,17 @@ void BKE_ptcache_update_info(PTCacheID *pid) void BKE_ptcache_validate(PointCache *cache, int framenr) { - cache->flag |= PTCACHE_SIMULATION_VALID; - cache->simframe = framenr; + if(cache) { + cache->flag |= PTCACHE_SIMULATION_VALID; + cache->simframe = framenr; + } } void BKE_ptcache_invalidate(PointCache *cache) { - cache->flag &= ~PTCACHE_SIMULATION_VALID; - cache->simframe = 0; - cache->last_exact = MIN2(cache->startframe, 0); + if(cache) { + cache->flag &= ~PTCACHE_SIMULATION_VALID; + cache->simframe = 0; + cache->last_exact = MIN2(cache->startframe, 0); + } } |