[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [29710] branches/particles-2010/source/ blender/blenkernel/intern/particle_system.c: Fixed memory leak caused by not freeing the emitter cache when freeing a particle system .

Lukas Tönne lukas.toenne at hotmail.com
Sat Jun 26 16:35:28 CEST 2010


Revision: 29710
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=29710
Author:   lukastoenne
Date:     2010-06-26 16:35:28 +0200 (Sat, 26 Jun 2010)

Log Message:
-----------
Fixed memory leak caused by not freeing the emitter cache when freeing a particle system.

Modified Paths:
--------------
    branches/particles-2010/source/blender/blenkernel/intern/particle_system.c

Modified: branches/particles-2010/source/blender/blenkernel/intern/particle_system.c
===================================================================
--- branches/particles-2010/source/blender/blenkernel/intern/particle_system.c	2010-06-26 14:12:28 UTC (rev 29709)
+++ branches/particles-2010/source/blender/blenkernel/intern/particle_system.c	2010-06-26 14:35:28 UTC (rev 29710)
@@ -549,7 +549,180 @@
 {
 	return sim->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY && sim->psys->part && sim->psys->part->effector_weights->global_gravity != 0.0f;
 }
+
 /************************************************/
+/*			Emitter cache						*/
+/************************************************/
+static void clear_emitter_cache(ParticleSystem *psys)
+{
+	ParticleEmitterCache *ca;
+	int i;
+
+	if (!psys->emitter_cache)
+		return;
+
+	for (i=0, ca=psys->emitter_cache; i < psys->num_emitters; ++i, ++ca) {
+		if (ca->faceweight)
+			MEM_freeN(ca->faceweight);
+		if (ca->jit)
+			MEM_freeN(ca->jit);
+		if (ca->jitoff)
+			MEM_freeN(ca->jitoff);
+	}
+	MEM_freeN(psys->emitter_cache);
+	psys->emitter_cache = NULL;
+}
+
+static void create_emitter_cache(ParticleSystem *psys)
+{
+	ParticleSettings *pset= psys->part;
+	int emi;
+	bNode *node;
+	ParticleNodeEmitter *pne;
+	
+	clear_emitter_cache(psys);
+	
+	/* Count regular emitters + emitter nodes */
+	psys->num_emitters = BLI_countlist(&pset->emitters);
+	/* starting index for node emitters */
+	emi = psys->num_emitters;
+	for (node=pset->nodetree->nodes.first; node; node = node->next)
+		if (node->type == PAR_NODE_EMITTER)
+			++psys->num_emitters;
+	
+	if (psys->num_emitters > 0) {
+		psys->emitter_cache= MEM_callocN(psys->num_emitters * sizeof(struct ParticleEmitterCache), "ParticleEmitterCache");
+		
+		/* set cache emitter node indices */
+		for (node=pset->nodetree->nodes.first; node; node = node->next) {
+			if (node->type != PAR_NODE_EMITTER)
+				continue;
+			pne = (ParticleNodeEmitter*)node->storage;
+			
+			pne->emitter_index = emi++;
+		}
+	}
+}
+
+void psys_update_emitter_cache(ParticleSystem *psys, int emi, Object *emob)
+{
+	ParticleSettings *pset= psys->part;
+	ParticleEmitterCache *ca;
+	DerivedMesh *dm;
+	
+	ca = psys->emitter_cache + emi;
+	ca->ob = emob;
+	ca->pemd = (ca->ob ? (ParticleEmitterModifierData*)modifiers_findByType(ca->ob, eModifierType_ParticleEmitter) : NULL);
+
+//	ca->vgroup = olas->vgroup;
+//	ca->vg_neg = olas->vg_neg;
+	
+	ca->faceweight = NULL;
+	ca->max_faceweight = 0.0f;
+	ca->jit = NULL;
+	ca->jitoff = NULL;
+	ca->jitlevel = 0;
+	dm = (ca->pemd ? ca->pemd->dm : NULL);
+	
+	if (!ca->ob || !ca->pemd || !ca->pemd->dm)
+		return;
+	
+	if (!ca->faceweight || (ca->pemd->flag & eParticleEmitterFlag_DM_changed)) {
+		MVert *v1, *v2, *v3, *v4;
+		float co1[3], co2[3], co3[3], co4[3];
+		float (*orcodata)[3];
+		float area, totarea;
+		int i;
+		
+		/* update face weight array */
+		if (ca->faceweight)
+			MEM_freeN(ca->faceweight);
+		ca->faceweight = MEM_callocN(ca->pemd->totdmface * sizeof(float), "face weight data");
+		
+		/* calculate face weights from relative area */
+		orcodata= dm->getVertDataArray(dm, CD_ORCO);
+		totarea = 0.0f;
+		for(i=0; i < ca->pemd->totdmface; i++){
+			MFace *mf = dm->getFaceData(dm,i,CD_MFACE);
+			
+			/* use orco face data if available, otherwise retrieve from DM directly */
+			if(orcodata) {
+				copy_v3_v3(co1, orcodata[mf->v1]);
+				copy_v3_v3(co2, orcodata[mf->v2]);
+				copy_v3_v3(co3, orcodata[mf->v3]);
+				transform_mesh_orco_verts((Mesh*)ca->ob->data, &co1, 1, 1);
+				transform_mesh_orco_verts((Mesh*)ca->ob->data, &co2, 1, 1);
+				transform_mesh_orco_verts((Mesh*)ca->ob->data, &co3, 1, 1);
+			}
+			else {
+				v1= (MVert*)dm->getVertData(dm, mf->v1, CD_MVERT);
+				v2= (MVert*)dm->getVertData(dm, mf->v2, CD_MVERT);
+				v3= (MVert*)dm->getVertData(dm, mf->v3, CD_MVERT);
+				copy_v3_v3(co1, v1->co);
+				copy_v3_v3(co2, v2->co);
+				copy_v3_v3(co3, v3->co);
+			}
+			
+			if (mf->v4){
+				if(orcodata) {
+					copy_v3_v3(co4, orcodata[mf->v4]);
+					transform_mesh_orco_verts((Mesh*)ca->ob->data, &co4, 1, 1);
+				}
+				else {
+					v4= (MVert*)dm->getVertData(dm, mf->v4, CD_MVERT);
+					copy_v3_v3(co4, v4->co);
+				}
+				area = area_quad_v3(co1, co2, co3, co4);
+			}
+			else
+				area = area_tri_v3(co1, co2, co3);
+			
+			if(area > ca->max_faceweight)
+				ca->max_faceweight = area;
+			
+			/* store the accumulated face area */
+			totarea += area;
+			ca->faceweight[i]= totarea;
+		}
+		
+		/* TODO use vertex groups */
+		
+		/* normalize to (accumulated) weight */
+		for(i=0; i < ca->pemd->totdmface; i++)
+			ca->faceweight[i] /= totarea;
+		ca->max_faceweight /= totarea;
+	}
+	
+	if (!ca->jitoff || (ca->pemd->flag & eParticleEmitterFlag_DM_changed)) {
+		/* update jitter arrays */
+		if (ca->jitoff)
+			MEM_freeN(ca->jitoff);
+		ca->jitoff = MEM_callocN(ca->pemd->totdmface * sizeof(float), "face weight data");
+		
+		ca->jitlevel= pset->userjit;
+		
+		/* XXX is there a way to make this an iterative process, so the total amount is not needed? - phonybone*/
+#if 0
+		if(ca->jitlevel == 0) {
+			ca->jitlevel= totpart/tot;
+			if(part->flag & PART_EDISTR) jitlevel*= 2;	/* looks better in general, not very scietific */
+			if(jitlevel<3) jitlevel= 3;
+		}
+		
+		jit= MEM_callocN((2+ jitlevel*2)*sizeof(float), "jit");
+		
+		/* for small amounts of particles we use regular jitter since it looks
+		 * a bit better, for larger amounts we switch to hammersley sequence 
+		 * because it is much faster */
+		if(jitlevel < 25)
+			init_mv_jit(jit, jitlevel, psys->seed, part->jitfac);
+		else
+			hammersley_create(jit, jitlevel+1, psys->seed, part->jitfac);
+		BLI_array_randomize(jit, 2*sizeof(float), jitlevel, psys->seed); /* for custom jit or even distribution */
+#endif
+	}
+}
+/************************************************/
 /*			Freeing stuff						*/
 /************************************************/
 void free_hair(Object *ob, ParticleSystem *psys, int dynamics)
@@ -691,6 +864,8 @@
 
 		psys_clear_all_links(ob, psys);
 
+		clear_emitter_cache(psys);
+
 		if(psys->frand)
 			MEM_freeN(psys->frand);
 
@@ -4821,176 +4996,6 @@
 	return psys->totalive * get_psys_child_number(scene, psys);
 }
 
-void psys_update_emitter_cache(ParticleSystem *psys, int emi, Object *emob)
-{
-	ParticleSettings *pset= psys->part;
-	ParticleEmitterCache *ca;
-	DerivedMesh *dm;
-	
-	ca = psys->emitter_cache + emi;
-	ca->ob = emob;
-	ca->pemd = (ca->ob ? (ParticleEmitterModifierData*)modifiers_findByType(ca->ob, eModifierType_ParticleEmitter) : NULL);
-
-//	ca->vgroup = olas->vgroup;
-//	ca->vg_neg = olas->vg_neg;
-	
-	ca->faceweight = NULL;
-	ca->max_faceweight = 0.0f;
-	ca->jit = NULL;
-	ca->jitoff = NULL;
-	ca->jitlevel = 0;
-	dm = (ca->pemd ? ca->pemd->dm : NULL);
-	
-	if (!ca->ob || !ca->pemd || !ca->pemd->dm)
-		return;
-	
-	if (!ca->faceweight || (ca->pemd->flag & eParticleEmitterFlag_DM_changed)) {
-		MVert *v1, *v2, *v3, *v4;
-		float co1[3], co2[3], co3[3], co4[3];
-		float (*orcodata)[3];
-		float area, totarea;
-		int i;
-		
-		/* update face weight array */
-		if (ca->faceweight)
-			MEM_freeN(ca->faceweight);
-		ca->faceweight = MEM_callocN(ca->pemd->totdmface * sizeof(float), "face weight data");
-		
-		/* calculate face weights from relative area */
-		orcodata= dm->getVertDataArray(dm, CD_ORCO);
-		totarea = 0.0f;
-		for(i=0; i < ca->pemd->totdmface; i++){
-			MFace *mf = dm->getFaceData(dm,i,CD_MFACE);
-			
-			/* use orco face data if available, otherwise retrieve from DM directly */
-			if(orcodata) {
-				copy_v3_v3(co1, orcodata[mf->v1]);
-				copy_v3_v3(co2, orcodata[mf->v2]);
-				copy_v3_v3(co3, orcodata[mf->v3]);
-				transform_mesh_orco_verts((Mesh*)ca->ob->data, &co1, 1, 1);
-				transform_mesh_orco_verts((Mesh*)ca->ob->data, &co2, 1, 1);
-				transform_mesh_orco_verts((Mesh*)ca->ob->data, &co3, 1, 1);
-			}
-			else {
-				v1= (MVert*)dm->getVertData(dm, mf->v1, CD_MVERT);
-				v2= (MVert*)dm->getVertData(dm, mf->v2, CD_MVERT);
-				v3= (MVert*)dm->getVertData(dm, mf->v3, CD_MVERT);
-				copy_v3_v3(co1, v1->co);
-				copy_v3_v3(co2, v2->co);
-				copy_v3_v3(co3, v3->co);
-			}
-			
-			if (mf->v4){
-				if(orcodata) {
-					copy_v3_v3(co4, orcodata[mf->v4]);
-					transform_mesh_orco_verts((Mesh*)ca->ob->data, &co4, 1, 1);
-				}
-				else {
-					v4= (MVert*)dm->getVertData(dm, mf->v4, CD_MVERT);
-					copy_v3_v3(co4, v4->co);
-				}
-				area = area_quad_v3(co1, co2, co3, co4);
-			}
-			else
-				area = area_tri_v3(co1, co2, co3);
-			
-			if(area > ca->max_faceweight)
-				ca->max_faceweight = area;
-			
-			/* store the accumulated face area */
-			totarea += area;
-			ca->faceweight[i]= totarea;
-		}
-		
-		/* TODO use vertex groups */
-		
-		/* normalize to (accumulated) weight */
-		for(i=0; i < ca->pemd->totdmface; i++)
-			ca->faceweight[i] /= totarea;
-		ca->max_faceweight /= totarea;
-	}
-	
-	if (!ca->jitoff || (ca->pemd->flag & eParticleEmitterFlag_DM_changed)) {
-		/* update jitter arrays */
-		if (ca->jitoff)
-			MEM_freeN(ca->jitoff);
-		ca->jitoff = MEM_callocN(ca->pemd->totdmface * sizeof(float), "face weight data");
-		
-		ca->jitlevel= pset->userjit;
-		
-		/* XXX is there a way to make this an iterative process, so the total amount is not needed? - phonybone*/
-#if 0
-		if(ca->jitlevel == 0) {
-			ca->jitlevel= totpart/tot;
-			if(part->flag & PART_EDISTR) jitlevel*= 2;	/* looks better in general, not very scietific */
-			if(jitlevel<3) jitlevel= 3;
-		}
-		
-		jit= MEM_callocN((2+ jitlevel*2)*sizeof(float), "jit");
-		
-		/* for small amounts of particles we use regular jitter since it looks
-		 * a bit better, for larger amounts we switch to hammersley sequence 
-		 * because it is much faster */
-		if(jitlevel < 25)
-			init_mv_jit(jit, jitlevel, psys->seed, part->jitfac);
-		else
-			hammersley_create(jit, jitlevel+1, psys->seed, part->jitfac);
-		BLI_array_randomize(jit, 2*sizeof(float), jitlevel, psys->seed); /* for custom jit or even distribution */
-#endif
-	}
-}
-
-static void clear_emitter_cache(ParticleSystem *psys)
-{
-	ParticleEmitterCache *ca;
-	int i;
-
-	if (!psys->emitter_cache)
-		return;
-
-	for (i=0, ca=psys->emitter_cache; i < psys->num_emitters; ++i, ++ca) {
-		if (ca->faceweight)
-			MEM_freeN(ca->faceweight);
-		if (ca->jit)
-			MEM_freeN(ca->jit);
-		if (ca->jitoff)
-			MEM_freeN(ca->jitoff);
-	}
-	MEM_freeN(psys->emitter_cache);
-	psys->emitter_cache = NULL;
-}
-
-static void create_emitter_cache(ParticleSystem *psys)
-{
-	ParticleSettings *pset= psys->part;
-	int emi;
-	bNode *node;

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list