[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