Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2012-09-12 20:42:24 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2012-09-12 20:42:24 +0400
commit272700728f411fa8099883e4866dc65d837d23ce (patch)
treeb5c48c803f985e379ec51e38d23096d879e1441c /source
parentab77d11bdbc45955988b5e77c1ce6899c86a2882 (diff)
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.
Diffstat (limited to 'source')
-rw-r--r--source/blender/modifiers/intern/MOD_particleinstance.c238
1 files changed, 133 insertions, 105 deletions
diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c
index c034832bfb4..d46ef3c3fc4 100644
--- a/source/blender/modifiers/intern/MOD_particleinstance.c
+++ b/source/blender/modifiers/intern/MOD_particleinstance.c
@@ -105,6 +105,41 @@ static void foreachObjectLink(ModifierData *md, Object *ob,
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 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
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 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
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,15 +207,24 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
}
}
- 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);
@@ -191,127 +236,110 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
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;
-
- inMV = orig_mvert + i % totvert;
- DM_copy_vert_data(dm, result, i % totvert, i, 1);
- *mv = *inMV;
-
- /*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 ((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();
- }
-
- 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);
-
- if (trackneg)
- state.time = 1.0f - state.time;
-
- mv->co[axis] = 0.0;
- }
-
- psys_get_particle_on_path(&sim, first_particle + i / totvert, &state, 1);
-
- normalize_v3(state.vel);
+ mpoly = result->getPolyArray(result);
+ orig_mpoly = dm->getPolyArray(dm);
+ mloop = result->getLoopArray(result);
+ orig_mloop = dm->getLoopArray(dm);
- /* 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;
+ for (p = 0, p_skip = 0; p < totpart; p++) {
+ /* skip particle? */
+ if (particle_skip(pimd, psys, p))
+ continue;
+
+ /* set vertices coordinates */
+ for (k = 0; k < totvert; k++) {
+ ParticleKey state;
+ MVert *inMV;
+ MVert *mv = mvert + p_skip * totvert + k;
+
+ inMV = orig_mvert + k;
+ DM_copy_vert_data(dm, result, k, p_skip * totvert + k, 1);
+ *mv = *inMV;
+
+ /*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];
+
+ /* 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();
+ }
- cross_v3_v3v3(cross, temp, state.vel);
+ 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);
- /* 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);
- }
+ if (trackneg)
+ state.time = 1.0f - state.time;
- 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);
- }
+ mv->co[axis] = 0.0;
+ }
- mpoly = result->getPolyArray(result);
- orig_mpoly = dm->getPolyArray(dm);
- mloop = result->getLoopArray(result);
- orig_mloop = dm->getLoopArray(dm);
+ psys_get_particle_on_path(&sim, first_particle + p, &state, 1);
- for (i = 0; i < maxpoly; i++) {
- MPoly *inMP = orig_mpoly + i % totpoly;
- MPoly *mp = mpoly + i;
+ normalize_v3(state.vel);
- 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;
+ /* TODO: incremental rotations somehow */
+ if (state.vel[axis] < -0.9999f || state.vel[axis] > 0.9999f) {
+ unit_qt(state.rot);
}
else {
- pa = NULL;
+ float temp[3] = {0.0f, 0.0f, 0.0f};
+ temp[axis] = 1.0f;
+
+ cross_v3_v3v3(cross, temp, 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 {
- pa = pars + i / totpoly;
- }
- }
- else {
- if (psys->part->childtype == PART_CHILD_PARTICLES) {
- pa = psys->particles + (psys->child + i / totpoly)->parent;
- }
- else {
- pa = NULL;
+ state.time = -1.0;
+ psys_get_particle_state(&sim, first_particle + p, &state, 1);
}
- }
- 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;
+
+ DM_copy_poly_data(dm, result, k, p_skip * totpoly + k, 1);
+ *mp = *inMP;
+ mp->loopstart += p_skip * totloop;
- {
- MLoop *inML = orig_mloop + inMP->loopstart;
- MLoop *ml = mloop + mp->loopstart;
- int j = mp->totloop;
+ {
+ 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 + ((i / totpoly) * totvert);
+ 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);