diff options
Diffstat (limited to 'source/blender/modifiers/intern')
-rw-r--r-- | source/blender/modifiers/intern/MOD_particleinstance.c | 143 | ||||
-rw-r--r-- | source/blender/modifiers/intern/MOD_surface.c | 1 |
2 files changed, 102 insertions, 42 deletions
diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c index cb6234d50b7..d0e93dff01f 100644 --- a/source/blender/modifiers/intern/MOD_particleinstance.c +++ b/source/blender/modifiers/intern/MOD_particleinstance.c @@ -40,6 +40,7 @@ #include "BLI_math.h" #include "BLI_listbase.h" #include "BLI_rand.h" +#include "BLI_string.h" #include "BLI_utildefines.h" #include "BKE_cdderivedmesh.h" @@ -62,7 +63,12 @@ static void initData(ModifierData *md) pimd->psys = 1; pimd->position = 1.0f; pimd->axis = 2; - + pimd->space = eParticleInstanceSpace_Local; + pimd->particle_amount = 1.0f; + pimd->particle_offset = 0.0f; + + BLI_strncpy(pimd->index_layer_name, "particle_index", sizeof(pimd->index_layer_name)); + BLI_strncpy(pimd->value_layer_name, "particle_value", sizeof(pimd->value_layer_name)); } static void copyData(ModifierData *md, ModifierData *target) { @@ -147,39 +153,44 @@ static void foreachObjectLink(ModifierData *md, Object *ob, walk(userData, ob, &pimd->ob); } -static int particle_skip(ParticleInstanceModifierData *pimd, ParticleSystem *psys, int p) +static bool particle_skip(ParticleInstanceModifierData *pimd, ParticleSystem *psys, int p) { + const bool between = (psys->part->childtype == PART_CHILD_FACES); ParticleData *pa; + int totpart, randp, minp, maxp; - 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; - } + if (p >= psys->totpart) { + ChildParticle *cpa = psys->child + (p - psys->totpart); + pa = psys->particles + (between? cpa->pa[0]: cpa->parent); } else { - if (psys->part->childtype == PART_CHILD_PARTICLES) { - pa = psys->particles + (psys->child + p)->parent; - } - else { - pa = NULL; - } + pa = psys->particles + p; } 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; + if (pa->alive == PARS_UNBORN && (pimd->flag & eParticleInstanceFlag_Unborn) == 0) return true; + if (pa->alive == PARS_ALIVE && (pimd->flag & eParticleInstanceFlag_Alive) == 0) return true; + if (pa->alive == PARS_DEAD && (pimd->flag & eParticleInstanceFlag_Dead) == 0) return true; } - return 0; + totpart = psys->totpart + psys->totchild; + + /* TODO make randomization optional? */ + randp = (int)(psys_frand(psys, 3578 + p) * totpart) % totpart; + + minp = (int)(totpart * pimd->particle_offset) % (totpart+1); + maxp = (int)(totpart * (pimd->particle_offset + pimd->particle_amount)) % (totpart+1); + + if (maxp > minp) { + return randp < minp || randp >= maxp; + } + else if (maxp < minp) { + return randp < minp && randp >= maxp; + } + else + return true; + + return false; } static DerivedMesh *applyModifier(ModifierData *md, Object *ob, @@ -195,11 +206,17 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, MLoop *mloop, *orig_mloop; MVert *mvert, *orig_mvert; int totvert, totpoly, totloop /* , totedge */; - int maxvert, maxpoly, maxloop, totpart = 0, first_particle = 0; + int maxvert, maxpoly, maxloop, part_end = 0, part_start; 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]; float *size = NULL; + float spacemat[4][4]; + int *cd_index = NULL; + float *cd_value = NULL; + const bool use_parents = pimd->flag & eParticleInstanceFlag_Parents; + const bool use_children = pimd->flag & eParticleInstanceFlag_Children; + bool between; trackneg = ((ob->trackflag > 2) ? 1 : 0); @@ -217,25 +234,26 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, return derivedData; } - if (pimd->flag & eParticleInstanceFlag_Parents) - totpart += psys->totpart; - if (pimd->flag & eParticleInstanceFlag_Children) { - if (totpart == 0) - first_particle = psys->totpart; - totpart += psys->totchild; - } + part_start = use_parents ? 0 : psys->totpart; + + part_end = 0; + if (use_parents) + part_end += psys->totpart; + if (use_children) + part_end += psys->totchild; - if (totpart == 0) + if (part_end == 0) return derivedData; sim.scene = md->scene; sim.ob = pimd->ob; sim.psys = psys; sim.psmd = psys_get_modifier(pimd->ob, psys); + between = (psys->part->childtype == PART_CHILD_FACES); if (pimd->flag & eParticleInstanceFlag_UseSize) { float *si; - si = size = MEM_callocN(totpart * sizeof(float), "particle size array"); + si = size = MEM_callocN(part_end * sizeof(float), "particle size array"); if (pimd->flag & eParticleInstanceFlag_Parents) { for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++, si++) @@ -251,6 +269,21 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, } } + switch (pimd->space) { + case eParticleInstanceSpace_World: + /* particle states are in world space already */ + unit_m4(spacemat); + break; + case eParticleInstanceSpace_Local: + /* get particle states in the particle object's local space */ + invert_m4_m4(spacemat, pimd->ob->obmat); + break; + default: + /* should not happen */ + BLI_assert(false); + break; + } + totvert = dm->getNumVerts(dm); totpoly = dm->getNumPolys(dm); totloop = dm->getNumLoops(dm); @@ -261,7 +294,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, maxpoly = 0; maxloop = 0; - for (p = 0; p < totpart; p++) { + for (p = part_start; p < part_end; p++) { if (particle_skip(pimd, psys, p)) continue; @@ -290,9 +323,18 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, mloop = result->getLoopArray(result); orig_mloop = dm->getLoopArray(dm); - for (p = 0, p_skip = 0; p < totpart; p++) { + /* create customdata layer for particle index storage */ + if (pimd->index_layer_name[0] != '\0') + cd_index = CustomData_add_layer_named(&result->vertData, CD_PROP_INT, CD_CALLOC, + NULL, maxvert, pimd->index_layer_name); + if (pimd->value_layer_name[0] != '\0') + cd_value = CustomData_add_layer_named(&result->vertData, CD_PROP_FLT, CD_CALLOC, + NULL, maxvert, pimd->value_layer_name); + + for (p = part_start, p_skip = 0; p < part_end; p++) { float prev_dir[3]; float frame[4]; /* frame orientation quaternion */ + float p_random = psys_frand(psys, 77091 + 283*p); /* skip particle? */ if (particle_skip(pimd, psys, p)) @@ -302,12 +344,18 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, for (k = 0; k < totvert; k++) { ParticleKey state; MVert *inMV; - MVert *mv = mvert + p_skip * totvert + k; + int vindex = p_skip * totvert + k; + MVert *mv = mvert + vindex; inMV = orig_mvert + k; DM_copy_vert_data(dm, result, k, p_skip * totvert + k, 1); *mv = *inMV; + if (cd_index) + cd_index[vindex] = p; + if (cd_value) + cd_value[vindex] = p_random; + /*change orientation based on object trackflag*/ copy_v3_v3(temp_co, mv->co); mv->co[axis] = temp_co[track]; @@ -335,7 +383,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, mv->co[axis] = 0.0; } - psys_get_particle_on_path(&sim, first_particle + p, &state, 1); + psys_get_particle_on_path(&sim, p, &state, 1); normalize_v3(state.vel); @@ -344,17 +392,26 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, float hairmat[4][4]; float mat[3][3]; - if (first_particle + p < psys->totpart) - pa = psys->particles + first_particle + p; + if (p < psys->totpart) + pa = psys->particles + p; else { ChildParticle *cpa = psys->child + (p - psys->totpart); - pa = psys->particles + cpa->parent; + pa = psys->particles + (between? cpa->pa[0]: cpa->parent); } psys_mat_hair_to_global(sim.ob, sim.psmd->dm, sim.psys->part->from, pa, hairmat); copy_m3_m4(mat, hairmat); /* to quaternion */ mat3_to_quat(frame, mat); + if (pimd->rotation > 0.0f || pimd->random_rotation > 0.0f) { + float angle = 2.0f*M_PI * (pimd->rotation + pimd->random_rotation * (psys_frand(psys, 19957323 + p) - 0.5f)); + float eul[3] = { 0.0f, 0.0f, angle }; + float rot[4]; + + eul_to_quat(rot, eul); + mul_qt_qtqt(frame, frame, rot); + } + /* note: direction is same as normal vector currently, * but best to keep this separate so the frame can be * rotated later if necessary @@ -391,13 +448,15 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, } else { state.time = -1.0; - psys_get_particle_state(&sim, first_particle + p, &state, 1); + psys_get_particle_state(&sim, p, &state, 1); } 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); + + mul_m4_v3(spacemat, mv->co); } /* create polys and loops */ diff --git a/source/blender/modifiers/intern/MOD_surface.c b/source/blender/modifiers/intern/MOD_surface.c index 3d998f2d95a..31ff8dee562 100644 --- a/source/blender/modifiers/intern/MOD_surface.c +++ b/source/blender/modifiers/intern/MOD_surface.c @@ -111,6 +111,7 @@ static void deformVerts(ModifierData *md, Object *ob, float *vec; MVert *x, *v; + DM_ensure_tessface(surmd->dm); CDDM_apply_vert_coords(surmd->dm, vertexCos); CDDM_calc_normals(surmd->dm); |