[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [50558] trunk/blender/source/blender/ modifiers/intern/MOD_particleinstance.c: Fix #32338: particle instance modifier did not work well when the mesh had only

Brecht Van Lommel brechtvanlommel at pandora.be
Wed Sep 12 18:42:25 CEST 2012


Revision: 50558
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=50558
Author:   blendix
Date:     2012-09-12 16:42:24 +0000 (Wed, 12 Sep 2012)
Log Message:
-----------
Fix #32338: particle instance modifier did not work well when the mesh had only
vertices. Previously it would hide particles by creating invalid faces, but this
didn't make the vertices actually disappear.

Also found that it could generated corrupt geometry for cases with faces, which
gave wrong subsurf and could crash in edit mode.

Modified Paths:
--------------
    trunk/blender/source/blender/modifiers/intern/MOD_particleinstance.c

Modified: trunk/blender/source/blender/modifiers/intern/MOD_particleinstance.c
===================================================================
--- trunk/blender/source/blender/modifiers/intern/MOD_particleinstance.c	2012-09-12 15:48:22 UTC (rev 50557)
+++ trunk/blender/source/blender/modifiers/intern/MOD_particleinstance.c	2012-09-12 16:42:24 UTC (rev 50558)
@@ -105,6 +105,41 @@
 	walk(userData, ob, &pimd->ob);
 }
 
+static int particle_skip(ParticleInstanceModifierData *pimd, ParticleSystem *psys, int p)
+{
+	ParticleData *pa;
+
+	if (pimd->flag & eParticleInstanceFlag_Parents) {
+		if (p >= psys->totpart) {
+			if (psys->part->childtype == PART_CHILD_PARTICLES) {
+				pa = psys->particles + (psys->child + p - psys->totpart)->parent;
+			}
+			else {
+				pa = NULL;
+			}
+		}
+		else {
+			pa = psys->particles + p;
+		}
+	}
+	else {
+		if (psys->part->childtype == PART_CHILD_PARTICLES) {
+			pa = psys->particles + (psys->child + p)->parent;
+		}
+		else {
+			pa = NULL;
+		}
+	}
+
+	if (pa) {
+		if (pa->alive == PARS_UNBORN && (pimd->flag & eParticleInstanceFlag_Unborn) == 0) return 1;
+		if (pa->alive == PARS_ALIVE && (pimd->flag & eParticleInstanceFlag_Alive) == 0) return 1;
+		if (pa->alive == PARS_DEAD && (pimd->flag & eParticleInstanceFlag_Dead) == 0) return 1;
+	}
+	
+	return 0;
+}
+
 static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
                                   DerivedMesh *derivedData,
                                   ModifierApplyFlag UNUSED(flag))
@@ -113,11 +148,13 @@
 	ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
 	ParticleSimulationData sim;
 	ParticleSystem *psys = NULL;
-	ParticleData *pa = NULL, *pars = NULL;
+	ParticleData *pa = NULL;
 	MPoly *mpoly, *orig_mpoly;
 	MLoop *mloop, *orig_mloop;
 	MVert *mvert, *orig_mvert;
-	int i, totvert, totpoly, totloop, maxvert, maxpoly, maxloop, totpart = 0, first_particle = 0;
+	int totvert, totpoly, totloop, totedge;
+	int maxvert, maxpoly, maxloop, totpart = 0, first_particle = 0;
+	int k, p, p_skip;
 	short track = ob->trackflag % 3, trackneg, axis = pimd->axis;
 	float max_co = 0.0, min_co = 0.0, temp_co[3], cross[3];
 	float *size = NULL;
@@ -153,7 +190,6 @@
 	sim.psmd = psys_get_modifier(pimd->ob, psys);
 
 	if (pimd->flag & eParticleInstanceFlag_UseSize) {
-		int p;
 		float *si;
 		si = size = MEM_callocN(totpart * sizeof(float), "particle size array");
 
@@ -171,16 +207,25 @@
 		}
 	}
 
-	pars = psys->particles;
-
 	totvert = dm->getNumVerts(dm);
 	totpoly = dm->getNumPolys(dm);
 	totloop = dm->getNumLoops(dm);
+	totedge = dm->getNumEdges(dm);
 
-	maxvert = totvert * totpart;
-	maxpoly = totpoly * totpart;
-	maxloop = totloop * totpart;
+	/* count particles */
+	maxvert = 0;
+	maxpoly = 0;
+	maxloop = 0;
 
+	for (p = 0; p < totpart; p++) {
+		if (particle_skip(pimd, psys, p))
+			continue;
+
+		maxvert += totvert;
+		maxpoly += totpoly;
+		maxloop += totloop;
+	}
+
 	psys->lattice = psys_get_lattice(&sim);
 
 	if (psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) {
@@ -191,127 +236,110 @@
 		max_co = max_r[track];
 	}
 
-	result = CDDM_from_template(dm, maxvert, dm->getNumEdges(dm) * totpart, 0, maxloop, maxpoly);
+	result = CDDM_from_template(dm, maxvert, 0, 0, maxloop, maxpoly);
 
 	mvert = result->getVertArray(result);
 	orig_mvert = dm->getVertArray(dm);
 
-	for (i = 0; i < maxvert; i++) {
-		MVert *inMV;
-		MVert *mv = mvert + i;
-		ParticleKey state;
+	mpoly = result->getPolyArray(result);
+	orig_mpoly = dm->getPolyArray(dm);
+	mloop = result->getLoopArray(result);
+	orig_mloop = dm->getLoopArray(dm);
 
-		inMV = orig_mvert + i % totvert;
-		DM_copy_vert_data(dm, result, i % totvert, i, 1);
-		*mv = *inMV;
+	for (p = 0, p_skip = 0; p < totpart; p++) {
+		/* skip particle? */
+		if (particle_skip(pimd, psys, p))
+			continue;
 
-		/*change orientation based on object trackflag*/
-		copy_v3_v3(temp_co, mv->co);
-		mv->co[axis] = temp_co[track];
-		mv->co[(axis + 1) % 3] = temp_co[(track + 1) % 3];
-		mv->co[(axis + 2) % 3] = temp_co[(track + 2) % 3];
+		/* set vertices coordinates */
+		for (k = 0; k < totvert; k++) {
+			ParticleKey state;
+			MVert *inMV;
+			MVert *mv = mvert + p_skip * totvert + k;
 
-		if ((psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) &&
-		    (pimd->flag & eParticleInstanceFlag_Path))
-		{
-			float ran = 0.0f;
-			if (pimd->random_position != 0.0f) {
-				BLI_srandom(psys->seed + (i / totvert) % totpart);
-				ran = pimd->random_position * BLI_frand();
-			}
+			inMV = orig_mvert + k;
+			DM_copy_vert_data(dm, result, k, p_skip * totvert + k, 1);
+			*mv = *inMV;
 
-			if (pimd->flag & eParticleInstanceFlag_KeepShape) {
-				state.time = pimd->position * (1.0f - ran);
-			}
-			else {
-				state.time = (mv->co[axis] - min_co) / (max_co - min_co) * pimd->position * (1.0f - ran);
+			/*change orientation based on object trackflag*/
+			copy_v3_v3(temp_co, mv->co);
+			mv->co[axis] = temp_co[track];
+			mv->co[(axis + 1) % 3] = temp_co[(track + 1) % 3];
+			mv->co[(axis + 2) % 3] = temp_co[(track + 2) % 3];
 
-				if (trackneg)
-					state.time = 1.0f - state.time;
+			/* get particle state */
+			if ((psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) &&
+				(pimd->flag & eParticleInstanceFlag_Path))
+			{
+				float ran = 0.0f;
+				if (pimd->random_position != 0.0f) {
+					BLI_srandom(psys->seed + p);
+					ran = pimd->random_position * BLI_frand();
+				}
 
-				mv->co[axis] = 0.0;
-			}
+				if (pimd->flag & eParticleInstanceFlag_KeepShape) {
+					state.time = pimd->position * (1.0f - ran);
+				}
+				else {
+					state.time = (mv->co[axis] - min_co) / (max_co - min_co) * pimd->position * (1.0f - ran);
 
-			psys_get_particle_on_path(&sim, first_particle + i / totvert, &state, 1);
+					if (trackneg)
+						state.time = 1.0f - state.time;
 
-			normalize_v3(state.vel);
+					mv->co[axis] = 0.0;
+				}
 
-			/* TODO: incremental rotations somehow */
-			if (state.vel[axis] < -0.9999f || state.vel[axis] > 0.9999f) {
-				unit_qt(state.rot);
-			}
-			else {
-				float temp[3] = {0.0f, 0.0f, 0.0f};
-				temp[axis] = 1.0f;
+				psys_get_particle_on_path(&sim, first_particle + p, &state, 1);
 
-				cross_v3_v3v3(cross, temp, state.vel);
+				normalize_v3(state.vel);
 
-				/* state.vel[axis] is the only component surviving from a dot product with the axis */
-				axis_angle_to_quat(state.rot, cross, saacos(state.vel[axis]));
-			}
-		}
-		else {
-			state.time = -1.0;
-			psys_get_particle_state(&sim, first_particle + i / totvert, &state, 1);
-		}
+				/* TODO: incremental rotations somehow */
+				if (state.vel[axis] < -0.9999f || state.vel[axis] > 0.9999f) {
+					unit_qt(state.rot);
+				}
+				else {
+					float temp[3] = {0.0f, 0.0f, 0.0f};
+					temp[axis] = 1.0f;
 
-		mul_qt_v3(state.rot, mv->co);
-		if (pimd->flag & eParticleInstanceFlag_UseSize)
-			mul_v3_fl(mv->co, size[i / totvert]);
-		add_v3_v3(mv->co, state.co);
-	}
+					cross_v3_v3v3(cross, temp, state.vel);
 
-	mpoly = result->getPolyArray(result);
-	orig_mpoly = dm->getPolyArray(dm);
-	mloop = result->getLoopArray(result);
-	orig_mloop = dm->getLoopArray(dm);
-
-	for (i = 0; i < maxpoly; i++) {
-		MPoly *inMP = orig_mpoly + i % totpoly;
-		MPoly *mp = mpoly + i;
-
-		if (pimd->flag & eParticleInstanceFlag_Parents) {
-			if (i / totpoly >= psys->totpart) {
-				if (psys->part->childtype == PART_CHILD_PARTICLES) {
-					pa = psys->particles + (psys->child + i / totpoly - psys->totpart)->parent;
+					/* state.vel[axis] is the only component surviving from a dot product with the axis */
+					axis_angle_to_quat(state.rot, cross, saacos(state.vel[axis]));
 				}
-				else {
-					pa = NULL;
-				}
 			}
 			else {
-				pa = pars + i / totpoly;
+				state.time = -1.0;
+				psys_get_particle_state(&sim, first_particle + p, &state, 1);
 			}
-		}
-		else {
-			if (psys->part->childtype == PART_CHILD_PARTICLES) {
-				pa = psys->particles + (psys->child + i / totpoly)->parent;
-			}
-			else {
-				pa = NULL;
-			}
-		}
 
-		if (pa) {
-			if (pa->alive == PARS_UNBORN && (pimd->flag & eParticleInstanceFlag_Unborn) == 0) continue;
-			if (pa->alive == PARS_ALIVE && (pimd->flag & eParticleInstanceFlag_Alive) == 0) continue;
-			if (pa->alive == PARS_DEAD && (pimd->flag & eParticleInstanceFlag_Dead) == 0) continue;
+			mul_qt_v3(state.rot, mv->co);
+			if (pimd->flag & eParticleInstanceFlag_UseSize)
+				mul_v3_fl(mv->co, size[p]);
+			add_v3_v3(mv->co, state.co);
 		}
 
-		DM_copy_poly_data(dm, result, i % totpoly, i, 1);
-		*mp = *inMP;
-		mp->loopstart += (i / totpoly) * totloop;
+		/* create polys and loops */
+		for (k = 0; k < totpoly; k++) {
+			MPoly *inMP = orig_mpoly + k;
+			MPoly *mp = mpoly + p_skip * totpoly + k;
 
-		{
-			MLoop *inML = orig_mloop + inMP->loopstart;
-			MLoop *ml = mloop + mp->loopstart;
-			int j = mp->totloop;
+			DM_copy_poly_data(dm, result, k, p_skip * totpoly + k, 1);
+			*mp = *inMP;
+			mp->loopstart += p_skip * totloop;
 
-			DM_copy_loop_data(dm, result, inMP->loopstart, mp->loopstart, j);
-			for (; j; j--, ml++, inML++) {
-				ml->v = inML->v + ((i / totpoly) * totvert);
+			{
+				MLoop *inML = orig_mloop + inMP->loopstart;
+				MLoop *ml = mloop + mp->loopstart;
+				int j = mp->totloop;
+
+				DM_copy_loop_data(dm, result, inMP->loopstart, mp->loopstart, j);
+				for (; j; j--, ml++, inML++) {
+					ml->v = inML->v + (p_skip * totvert);
+				}
 			}
 		}
+
+		p_skip++;
 	}
 
 	CDDM_calc_edges(result);




More information about the Bf-blender-cvs mailing list