diff options
author | Janne Karhu <jhkarh@gmail.com> | 2011-01-09 10:41:51 +0300 |
---|---|---|
committer | Janne Karhu <jhkarh@gmail.com> | 2011-01-09 10:41:51 +0300 |
commit | e32bbef017df64a99acedd4f3f4ba32713c50a3b (patch) | |
tree | 881bf3c46da067ae6715a77a1763f2eb04d7600c /source | |
parent | 76a762aa51a4cb774dfd7940fb77916037efad8c (diff) |
Fix for [#25544] Blender crashes when changing the particles emission amount
* I've getting bad feelings about the point cache index_array for a while (cause for this bug too), so from now on memory cache uses a simple binary search directly on the index data to handle queries to specific data points.
* This is a bit slower than just checking from a dedicated array, but it's much less error prone, uses less memory and makes the code more readable too, so it's not a tough choice.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_pointcache.h | 5 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/particle.c | 38 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/pointcache.c | 65 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 9 | ||||
-rw-r--r-- | source/blender/blenloader/intern/writefile.c | 2 | ||||
-rw-r--r-- | source/blender/editors/physics/particle_edit.c | 24 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_object_force.h | 1 |
7 files changed, 53 insertions, 91 deletions
diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index f3548888168..c7f76c033c8 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -89,7 +89,7 @@ struct SoftBody; /* temp structure for read/write */ typedef struct PTCacheData { - int index; + uint32_t index; float loc[3]; float vel[3]; float rot[4]; @@ -270,6 +270,9 @@ void BKE_ptcache_update_info(PTCacheID *pid); /* Size of cache data type. */ int BKE_ptcache_data_size(int data_type); +/* Is point with indes in memory cache */ +int BKE_ptcache_mem_index_find(struct PTCacheMem *pm, int index); + /* Memory cache read/write helpers. */ void BKE_ptcache_mem_pointers_init(struct PTCacheMem *pm); void BKE_ptcache_mem_pointers_incr(struct PTCacheMem *pm); diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 018b882f7a2..26f96d0c304 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -1056,6 +1056,7 @@ typedef struct ParticleInterpolationData { static void get_pointcache_keys_for_time(Object *UNUSED(ob), PointCache *cache, PTCacheMem **cur, int index, float t, ParticleKey *key1, ParticleKey *key2) { static PTCacheMem *pm = NULL; + int index1, index2; if(index < 0) { /* initialize */ *cur = cache->mem_cache.first; @@ -1070,15 +1071,19 @@ static void get_pointcache_keys_for_time(Object *UNUSED(ob), PointCache *cache, pm = *cur; - BKE_ptcache_make_particle_key(key2, pm->index_array ? pm->index_array[index] - 1 : index, pm->data, (float)pm->frame); - if(pm->prev->index_array && pm->prev->index_array[index] == 0) + index2 = BKE_ptcache_mem_index_find(pm, index); + index1 = BKE_ptcache_mem_index_find(pm->prev, index); + + BKE_ptcache_make_particle_key(key2, index2, pm->data, (float)pm->frame); + if(index1 < 0) copy_particle_key(key1, key2, 1); else - BKE_ptcache_make_particle_key(key1, pm->prev->index_array ? pm->prev->index_array[index] - 1 : index, pm->prev->data, (float)pm->prev->frame); + BKE_ptcache_make_particle_key(key1, index1, pm->prev->data, (float)pm->prev->frame); } else if(cache->mem_cache.first) { pm = cache->mem_cache.first; - BKE_ptcache_make_particle_key(key2, pm->index_array ? pm->index_array[index] - 1 : index, pm->data, (float)pm->frame); + index2 = BKE_ptcache_mem_index_find(pm, index); + BKE_ptcache_make_particle_key(key2, index2, pm->data, (float)pm->frame); copy_particle_key(key1, key2, 1); } } @@ -1089,14 +1094,7 @@ static int get_pointcache_times_for_particle(PointCache *cache, int index, float int ret = 0; for(pm=cache->mem_cache.first; pm; pm=pm->next) { - if(pm->index_array) { - if(pm->index_array[index]) { - *start = pm->frame; - ret++; - break; - } - } - else { + if(BKE_ptcache_mem_index_find(pm, index) >= 0) { *start = pm->frame; ret++; break; @@ -1104,14 +1102,7 @@ static int get_pointcache_times_for_particle(PointCache *cache, int index, float } for(pm=cache->mem_cache.last; pm; pm=pm->prev) { - if(pm->index_array) { - if(pm->index_array[index]) { - *end = pm->frame; - ret++; - break; - } - } - else { + if(BKE_ptcache_mem_index_find(pm, index) >= 0) { *end = pm->frame; ret++; break; @@ -1126,13 +1117,8 @@ float psys_get_dietime_from_cache(PointCache *cache, int index) { int dietime = 10000000; /* some max value so that we can default to pa->time+lifetime */ for(pm=cache->mem_cache.last; pm; pm=pm->prev) { - if(pm->index_array) { - if(pm->index_array[index]) - return (float)pm->frame; - } - else { + if(BKE_ptcache_mem_index_find(pm, index) >= 0) return (float)pm->frame; - } } return (float)dietime; diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 317723aef7f..1d58f276117 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -1161,6 +1161,39 @@ static void ptcache_file_pointers_init(PTCacheFile *pf) pf->cur[BPHYS_DATA_BOIDS] = (data_types & (1<<BPHYS_DATA_BOIDS)) ? &pf->data.boids : NULL; } +/* Check to see if point number "index" is in pm, uses binary search for index data. */ +int BKE_ptcache_mem_index_find(PTCacheMem *pm, int index) +{ + if(pm->data[BPHYS_DATA_INDEX]) { + uint32_t key = index; + uint32_t *data = pm->data[BPHYS_DATA_INDEX]; + uint32_t mid, low = 0, high = pm->totpoint - 1; + + if(key < *data || key > *(data+high)) + return -1; + + /* check simple case for continuous indexes first */ + if(data[key-*data]==key) + return key-*data; + + while(low <= high) { + mid= (low + high)/2; + + if(data[mid] > key) + high = mid - 1; + else if(data[mid] < key) + low = mid + 1; + else + return mid; + } + + return -1; + } + else { + return (index < pm->totpoint ? index : -1); + } +} + void BKE_ptcache_mem_pointers_init(PTCacheMem *pm) { int data_types = pm->data_types; @@ -1182,9 +1215,9 @@ void BKE_ptcache_mem_pointers_incr(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 || point_index >= MEM_allocN_len(pm->index_array)/sizeof(int)) { + if(index < 0) { /* Can't give proper location without reallocation, so don't give any location. * Some points will be cached improperly, but this only happens with simulation * steps bigger than cache->step, so the cache has to be recalculated anyways @@ -1218,11 +1251,6 @@ static void ptcache_data_free(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_data_copy(void *from[], void *to[]) { @@ -1306,24 +1334,6 @@ static void ptcache_find_frames_around(PTCacheID *pid, int frame, int *fra1, int } } } -static void ptcache_make_index_array(PTCacheMem *pm, int totpoint) -{ - int i, *index; - - if(pm->index_array) { - MEM_freeN(pm->index_array); - pm->index_array = NULL; - } - - if(!pm->data[BPHYS_DATA_INDEX]) - return; - - pm->index_array = MEM_callocN(totpoint * sizeof(int), "PTCacheMem index_array"); - index = pm->data[BPHYS_DATA_INDEX]; - - for(i=0; i<pm->totpoint; i++, index++) - pm->index_array[*index] = i + 1; -} static PTCacheMem *ptcache_disk_frame_to_mem(PTCacheID *pid, int cfra) { @@ -1398,9 +1408,6 @@ static PTCacheMem *ptcache_disk_frame_to_mem(PTCacheID *pid, int cfra) } } - if(!error) - ptcache_make_index_array(pm, pid->totpoint(pid->calldata, pm->frame)); - if(error && pm) { ptcache_data_free(pm); ptcache_extra_free(pm); @@ -1806,7 +1813,6 @@ static int ptcache_write(PTCacheID *pid, int cfra, int overwrite) } } else { - ptcache_make_index_array(pm, pid->totpoint(pid->calldata, cfra)); BLI_addtail(&cache->mem_cache, pm); } @@ -2989,7 +2995,6 @@ void BKE_ptcache_update_info(PTCacheID *pid) bytes += sizeof(PTCacheExtra); } - bytes += MEM_allocN_len(pm->index_array); bytes += sizeof(PTCacheMem); totframes++; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index f3bd91d12ed..9772074207d 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2936,15 +2936,6 @@ static void direct_link_pointcache(FileData *fd, PointCache *cache) pm = cache->mem_cache.first; for(; pm; pm=pm->next) { - if(pm->index_array) - pm->index_array = newdataadr(fd, pm->index_array); - - /* writedata saved array of ints */ - if(pm->index_array && (fd->flags & FD_FLAGS_SWITCH_ENDIAN)) { - for(i=0; i<pm->totpoint; i++) - SWITCH_INT(pm->index_array[i]); - } - for(i=0; i<BPHYS_TOT_DATA; i++) { pm->data[i] = newdataadr(fd, pm->data[i]); diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index dd6d56572e8..050fd5bcaf1 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -784,8 +784,6 @@ static void write_pointcaches(WriteData *wd, ListBase *ptcaches) for(; pm; pm=pm->next) { writestruct(wd, DATA, "PTCacheMem", 1, pm); - if(pm->index_array) - writedata(wd, DATA, MEM_allocN_len(pm->index_array), pm->index_array); for(i=0; i<BPHYS_TOT_DATA; i++) { if(pm->data[i] && pm->data_types & (1<<i)) diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index cca5df50118..4ac4bf9fa9b 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -3719,8 +3719,6 @@ static void make_PTCacheUndo(PTCacheEdit *edit, PTCacheUndo *undo) for(; pm; pm=pm->next) { for(i=0; i<BPHYS_TOT_DATA; i++) pm->data[i] = MEM_dupallocN(pm->data[i]); - - pm->index_array = MEM_dupallocN(pm->index_array); } } @@ -3795,8 +3793,6 @@ static void get_PTCacheUndo(PTCacheEdit *edit, PTCacheUndo *undo) for(i=0; i<BPHYS_TOT_DATA; i++) pm->data[i] = MEM_dupallocN(pm->data[i]); - pm->index_array = MEM_dupallocN(pm->index_array); - BKE_ptcache_mem_pointers_init(pm); LOOP_POINTS { @@ -4061,25 +4057,9 @@ static void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, totframe++; for(pm=cache->mem_cache.first; pm; pm=pm->next) { - BKE_ptcache_mem_pointers_init(pm); - LOOP_POINTS { - if(psys) { - if(pm->index_array) { - if(pm->index_array[p]) - BKE_ptcache_mem_pointers_seek(p, pm); - else - continue; - } - else { - pa = psys->particles + p; - if((pm->next && pm->next->frame < pa->time) - || (pm->prev && pm->prev->frame >= pa->dietime)) { - BKE_ptcache_mem_pointers_incr(pm); - continue; - } - } - } + if(BKE_ptcache_mem_pointers_seek(p, pm) == 0) + continue; if(!point->totkey) { key = point->keys = MEM_callocN(totframe*sizeof(PTCacheEditKey),"ParticleEditKeys"); diff --git a/source/blender/makesdna/DNA_object_force.h b/source/blender/makesdna/DNA_object_force.h index 96f2c1ccc79..1d1ad6ad021 100644 --- a/source/blender/makesdna/DNA_object_force.h +++ b/source/blender/makesdna/DNA_object_force.h @@ -152,7 +152,6 @@ typedef struct PTCacheMem { struct PTCacheMem *next, *prev; int frame, totpoint; unsigned int data_types, flag; - int *index_array; /* quick access to stored points with index */ void *data[8]; /* BPHYS_TOT_DATA */ void *cur[8]; /* BPHYS_TOT_DATA */ |