[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [34186] trunk/blender/source/blender: Fix for [#25544] Blender crashes when changing the particles emission amount

Janne Karhu jhkarh at gmail.com
Sun Jan 9 08:41:51 CET 2011


Revision: 34186
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=34186
Author:   jhk
Date:     2011-01-09 07:41:51 +0000 (Sun, 09 Jan 2011)
Log Message:
-----------
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.

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/BKE_pointcache.h
    trunk/blender/source/blender/blenkernel/intern/particle.c
    trunk/blender/source/blender/blenkernel/intern/pointcache.c
    trunk/blender/source/blender/blenloader/intern/readfile.c
    trunk/blender/source/blender/blenloader/intern/writefile.c
    trunk/blender/source/blender/editors/physics/particle_edit.c
    trunk/blender/source/blender/makesdna/DNA_object_force.h

Modified: trunk/blender/source/blender/blenkernel/BKE_pointcache.h
===================================================================
--- trunk/blender/source/blender/blenkernel/BKE_pointcache.h	2011-01-09 07:07:15 UTC (rev 34185)
+++ trunk/blender/source/blender/blenkernel/BKE_pointcache.h	2011-01-09 07:41:51 UTC (rev 34186)
@@ -89,7 +89,7 @@
 
 /* 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 @@
 /* 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);

Modified: trunk/blender/source/blender/blenkernel/intern/particle.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/particle.c	2011-01-09 07:07:15 UTC (rev 34185)
+++ trunk/blender/source/blender/blenkernel/intern/particle.c	2011-01-09 07:41:51 UTC (rev 34186)
@@ -1056,6 +1056,7 @@
 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 @@
 
 			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 @@
 	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 @@
 	}
 
 	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 @@
 	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;

Modified: trunk/blender/source/blender/blenkernel/intern/pointcache.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/pointcache.c	2011-01-09 07:07:15 UTC (rev 34185)
+++ trunk/blender/source/blender/blenkernel/intern/pointcache.c	2011-01-09 07:41:51 UTC (rev 34186)
@@ -1161,6 +1161,39 @@
 	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 @@
 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 @@
 		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,25 +1334,7 @@
 		}
 	}
 }
-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)
 {
 	PTCacheFile *pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra);
@@ -1398,9 +1408,6 @@
 		}
 	}
 
-	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 @@
 		}
 	}
 	else {
-		ptcache_make_index_array(pm, pid->totpoint(pid->calldata, cfra));
 		BLI_addtail(&cache->mem_cache, pm);
 	}
 
@@ -2989,7 +2995,6 @@
 				bytes += sizeof(PTCacheExtra);
 			}
 
-			bytes += MEM_allocN_len(pm->index_array);
 			bytes += sizeof(PTCacheMem);
 			
 			totframes++;

Modified: trunk/blender/source/blender/blenloader/intern/readfile.c
===================================================================
--- trunk/blender/source/blender/blenloader/intern/readfile.c	2011-01-09 07:07:15 UTC (rev 34185)
+++ trunk/blender/source/blender/blenloader/intern/readfile.c	2011-01-09 07:41:51 UTC (rev 34186)
@@ -2936,15 +2936,6 @@
 		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]);
 				

Modified: trunk/blender/source/blender/blenloader/intern/writefile.c
===================================================================
--- trunk/blender/source/blender/blenloader/intern/writefile.c	2011-01-09 07:07:15 UTC (rev 34185)
+++ trunk/blender/source/blender/blenloader/intern/writefile.c	2011-01-09 07:41:51 UTC (rev 34186)
@@ -784,8 +784,6 @@
 
 			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))

Modified: trunk/blender/source/blender/editors/physics/particle_edit.c
===================================================================
--- trunk/blender/source/blender/editors/physics/particle_edit.c	2011-01-09 07:07:15 UTC (rev 34185)
+++ trunk/blender/source/blender/editors/physics/particle_edit.c	2011-01-09 07:41:51 UTC (rev 34186)
@@ -3719,8 +3719,6 @@
 		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 @@
 			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 @@
 				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");

Modified: trunk/blender/source/blender/makesdna/DNA_object_force.h
===================================================================
--- trunk/blender/source/blender/makesdna/DNA_object_force.h	2011-01-09 07:07:15 UTC (rev 34185)
+++ trunk/blender/source/blender/makesdna/DNA_object_force.h	2011-01-09 07:41:51 UTC (rev 34186)
@@ -152,7 +152,6 @@
 	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 */




More information about the Bf-blender-cvs mailing list