diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/modifiers/intern/MOD_particleinstance.c | 238 |
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); |