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
diff options
context:
space:
mode:
-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);