diff options
author | Janne Karhu <jhkarh@gmail.com> | 2010-02-25 03:03:16 +0300 |
---|---|---|
committer | Janne Karhu <jhkarh@gmail.com> | 2010-02-25 03:03:16 +0300 |
commit | d1f19d7e844010f4ba1d58f97ed1caf8c33f7ae5 (patch) | |
tree | 662b0f7a299f826df203cbc14ba574e8b9cb7b19 /source | |
parent | 47d79b04d1deda821925da98319984211920210e (diff) |
Fix for [#19955] 2.5 Particles are calculated wrong when object has any transform animation
* The exact location of particle birth wasn't cached if cache step was greater than 1, so the interpolation from an unborn particle to a living one wasn't accurate at all.
* Although not ideal, the current solution is to copy the birth location to the previous cached frame so it's always exact. This should work properly for memory & disk cache.
* This fix shouldn't cause any problems, but exhaustive tests of caching are difficult so be sure to let me know if there's strange behavior.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_pointcache.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/pointcache.c | 92 |
2 files changed, 79 insertions, 14 deletions
diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index b291d9126ee..10550ccdc05 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -55,6 +55,7 @@ /* File open options, for BKE_ptcache_file_open */ #define PTCACHE_FILE_READ 0 #define PTCACHE_FILE_WRITE 1 +#define PTCACHE_FILE_UPDATE 2 /* PTCacheID types */ #define PTCACHE_TYPE_SOFTBODY 0 diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 6859aba57c9..b1319a81f5d 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -203,9 +203,9 @@ static int ptcache_write_particle(int index, void *psys_v, void **data) 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}; + int step = psys->pointcache->step; if(data[BPHYS_DATA_INDEX]) { - int step = psys->pointcache->step; /* No need to store unborn or died particles */ if(pa->time - step > pa->state.time || pa->dietime + step < pa->state.time) return 0; @@ -222,7 +222,8 @@ static int ptcache_write_particle(int index, void *psys_v, void **data) if(boid) PTCACHE_DATA_FROM(data, BPHYS_DATA_BOIDS, &boid->data); - return 1; + /* 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) { @@ -249,6 +250,10 @@ static void ptcache_read_particle(int index, void *psys_v, void **data, float fr BKE_ptcache_make_particle_key(&pa->state, 0, data, cfra); + /* set frames cached before birth to birth time */ + if(cfra < pa->time) + pa->state.time = pa->time; + if(data[BPHYS_DATA_SIZE]) PTCACHE_DATA_TO(data, BPHYS_DATA_SIZE, 0, &pa->size); @@ -1148,6 +1153,9 @@ static PTCacheFile *ptcache_file_open(PTCacheID *pid, int mode, int cfra) } else if (mode==PTCACHE_FILE_WRITE) { BLI_make_existing_file(filename); /* will create the dir if needs be, same as //textures is created */ fp = fopen(filename, "wb"); + } else if (mode==PTCACHE_FILE_UPDATE) { + BLI_make_existing_file(filename); + fp = fopen(filename, "rb+"); } if (!fp) @@ -1253,6 +1261,18 @@ static void ptcache_file_init_pointers(PTCacheFile *pf) 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) +{ + int i, size=0; + int data_types = pf->data_types; + + for(i=0; i<BPHYS_TOT_DATA; i++) + size += pf->data_types & (1<<i) ? ptcache_data_size[i] : 0; + + ptcache_file_init_pointers(pf); + /* size of default header + data up to index */ + fseek(pf->fp, 8 + 3*sizeof(int) + index * size, SEEK_SET); +} void BKE_ptcache_mem_init_pointers(PTCacheMem *pm) { int data_types = pm->data_types; @@ -1271,6 +1291,14 @@ void BKE_ptcache_mem_incr_pointers(PTCacheMem *pm) pm->cur[i] = (char*)pm->cur[i] + ptcache_data_size[i]; } } +void BKE_ptcache_mem_seek_pointers(int index, 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) ? (char*)pm->data[i] + index * ptcache_data_size[i] : NULL; +} static void ptcache_alloc_data(PTCacheMem *pm) { int data_types = pm->data_types; @@ -1453,7 +1481,7 @@ int BKE_ptcache_read_cache(PTCacheID *pid, float cfra, float frs_sec) else if(pid->read_header(pf2)) { ptcache_file_init_pointers(pf2); totpoint2 = pf2->totpoint; - index2 = pf->data_types & BPHYS_DATA_INDEX ? &pf2->data.index : &i; + index2 = pf2->data_types & BPHYS_DATA_INDEX ? &pf2->data.index : &i; } } else { @@ -1615,7 +1643,7 @@ int BKE_ptcache_read_cache(PTCacheID *pid, float cfra, float frs_sec) int BKE_ptcache_write_cache(PTCacheID *pid, int cfra) { PointCache *cache = pid->cache; - PTCacheFile *pf= NULL; + PTCacheFile *pf= NULL, *pf2= NULL; int i; int totpoint = pid->totpoint(pid->calldata); int add = 0, overwrite = 0; @@ -1625,7 +1653,7 @@ int BKE_ptcache_write_cache(PTCacheID *pid, int cfra) return 0; if(cache->flag & PTCACHE_DISK_CACHE) { - int efra = cache->endframe; + int ofra, efra = cache->endframe; if(cfra==0) add = 1; @@ -1636,7 +1664,6 @@ int BKE_ptcache_write_cache(PTCacheID *pid, int cfra) add = 1; } else { - int ofra; /* find last cached frame */ while(efra > cache->startframe && !BKE_ptcache_id_exist(pid, efra)) efra--; @@ -1679,11 +1706,36 @@ int BKE_ptcache_write_cache(PTCacheID *pid, int cfra) } else for(i=0; i<totpoint; i++) { - if(pid->write_elem && pid->write_elem(i, pid->calldata, pf->cur)) - if(!ptcache_file_write_data(pf)) { - ptcache_file_close(pf); - return 0; + if(pid->write_elem) { + int write = pid->write_elem(i, pid->calldata, pf->cur); + 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); + if(!ptcache_file_write_data(pf2)) { + ptcache_file_close(pf); + ptcache_file_close(pf2); + return 0; + } + } } + } } } } @@ -1728,8 +1780,19 @@ int BKE_ptcache_write_cache(PTCacheID *pid, int cfra) BKE_ptcache_mem_init_pointers(pm); for(i=0; i<totpoint; i++) { - if(pid->write_elem && pid->write_elem(i, pid->calldata, pm->cur)) - BKE_ptcache_mem_incr_pointers(pm); + if(pid->write_elem) { + int write = pid->write_elem(i, pid->calldata, pm->cur); + if(write) { + BKE_ptcache_mem_incr_pointers(pm); + + /* newly born particles have to be copied to previous cached frame */ + if(overwrite && write == 2) { + pm2 = cache->mem_cache.last; + BKE_ptcache_mem_seek_pointers(i, pm2); + pid->write_elem(i, pid->calldata, pm2->cur); + } + } + } } //ptcache_make_index_array(pm, pid->totpoint(pid->calldata)); @@ -1748,8 +1811,9 @@ int BKE_ptcache_write_cache(PTCacheID *pid, int cfra) cache->flag |= PTCACHE_FRAMES_SKIPPED; } - if(pf) - ptcache_file_close(pf); + if(pf) ptcache_file_close(pf); + + if(pf2) ptcache_file_close(pf2); BKE_ptcache_update_info(pid); |