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:
authorCampbell Barton <ideasman42@gmail.com>2018-04-19 13:53:21 +0300
committerCampbell Barton <ideasman42@gmail.com>2018-04-19 13:53:21 +0300
commit9d6a175756c8db989fc95bae47bbd1e77ff07980 (patch)
treec60ad0c6318ac38cba576da2bfd3b792be787a1c /source/blender/modifiers/intern/MOD_particleinstance.c
parent0a679c6b685a4a046a9c4074cff8c508d6f91618 (diff)
parentda82269c58bd7ec1c0ebcb5e1433c731120ec389 (diff)
Merge branch 'master' into blender2.8
Diffstat (limited to 'source/blender/modifiers/intern/MOD_particleinstance.c')
-rw-r--r--source/blender/modifiers/intern/MOD_particleinstance.c191
1 files changed, 147 insertions, 44 deletions
diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c
index 99433ae3725..d7cb7fd8d94 100644
--- a/source/blender/modifiers/intern/MOD_particleinstance.c
+++ b/source/blender/modifiers/intern/MOD_particleinstance.c
@@ -40,10 +40,12 @@
#include "BLI_math.h"
#include "BLI_listbase.h"
#include "BLI_rand.h"
+#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_effect.h"
+#include "BKE_global.h"
#include "BKE_lattice.h"
#include "BKE_library_query.h"
#include "BKE_modifier.h"
@@ -52,8 +54,6 @@
#include "DEG_depsgraph_build.h"
-#include "MOD_modifiertypes.h"
-
static void initData(ModifierData *md)
{
ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
@@ -63,7 +63,12 @@ static void initData(ModifierData *md)
pimd->psys = 1;
pimd->position = 1.0f;
pimd->axis = 2;
+ pimd->space = eParticleInstanceSpace_World;
+ pimd->particle_amount = 1.0f;
+ pimd->particle_offset = 0.0f;
+ STRNCPY(pimd->index_layer_name, "");
+ STRNCPY(pimd->value_layer_name, "");
}
static void copyData(ModifierData *md, ModifierData *target)
{
@@ -74,6 +79,21 @@ static void copyData(ModifierData *md, ModifierData *target)
modifier_copyData_generic(md, target);
}
+static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
+{
+ ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md;
+ CustomDataMask dataMask = 0;
+
+ if (pimd->index_layer_name[0] != '\0' ||
+ pimd->value_layer_name[0] != '\0')
+ {
+ dataMask |= CD_MASK_MLOOPCOL;
+ }
+
+ return dataMask;
+
+}
+
static bool isDisabled(ModifierData *md, int useRenderParams)
{
ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md;
@@ -127,39 +147,59 @@ static void foreachObjectLink(ModifierData *md, Object *ob,
walk(userData, ob, &pimd->ob, IDWALK_CB_NOP);
}
-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;
+ if (pimd->particle_amount == 1.0f) {
+ /* Early output, all particles are to be instanced. */
+ return false;
+ }
+
+ /* Randomly skip particles based on desired amount of visible particles. */
+
+ 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 void store_float_in_vcol(MLoopCol *vcol, float float_value)
+{
+ const uchar value = FTOCHAR(float_value);
+ vcol->r = vcol->g = vcol->b = value;
+ vcol->a = 1.0f;
}
static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
@@ -175,11 +215,15 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
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];
+ const bool use_parents = pimd->flag & eParticleInstanceFlag_Parents;
+ const bool use_children = pimd->flag & eParticleInstanceFlag_Children;
+ bool between;
trackneg = ((ob->trackflag > 2) ? 1 : 0);
@@ -197,15 +241,15 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
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.depsgraph = depsgraph;
@@ -213,10 +257,11 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
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_calloc_arrayN(totpart, sizeof(float), "particle size array");
+ si = size = MEM_calloc_arrayN(part_end, sizeof(float), "particle size array");
if (pimd->flag & eParticleInstanceFlag_Parents) {
for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++, si++)
@@ -232,6 +277,21 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
}
}
+ 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);
@@ -242,7 +302,7 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
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;
@@ -271,9 +331,21 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
mloop = result->getLoopArray(result);
orig_mloop = dm->getLoopArray(dm);
- for (p = 0, p_skip = 0; p < totpart; p++) {
+ MLoopCol *mloopcols_index = CustomData_get_layer_named(&result->loopData, CD_MLOOPCOL, pimd->index_layer_name);
+ MLoopCol *mloopcols_value = CustomData_get_layer_named(&result->loopData, CD_MLOOPCOL, pimd->value_layer_name);
+ int *vert_part_index = NULL;
+ float *vert_part_value = NULL;
+ if (mloopcols_index != NULL) {
+ vert_part_index = MEM_calloc_arrayN(maxvert, sizeof(int), "vertex part index array");
+ }
+ if (mloopcols_value) {
+ vert_part_value = MEM_calloc_arrayN(maxvert, sizeof(float), "vertex part value array");
+ }
+
+ 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))
@@ -283,12 +355,20 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
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 (vert_part_index != NULL) {
+ vert_part_index[vindex] = p;
+ }
+ if (vert_part_value != NULL) {
+ vert_part_value[vindex] = p_random;
+ }
+
/*change orientation based on object trackflag*/
copy_v3_v3(temp_co, mv->co);
mv->co[axis] = temp_co[track];
@@ -316,7 +396,7 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
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);
@@ -325,17 +405,26 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
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_final, 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
@@ -372,13 +461,15 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
}
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 */
@@ -398,6 +489,15 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
DM_copy_loop_data(dm, result, inMP->loopstart, mp->loopstart, j);
for (; j; j--, ml++, inML++) {
ml->v = inML->v + (p_skip * totvert);
+ const int ml_index = (ml - mloop);
+ if (mloopcols_index != NULL) {
+ const int part_index = vert_part_index[ml->v];
+ store_float_in_vcol(&mloopcols_index[ml_index], (float)part_index / psys->totpart);
+ }
+ if (mloopcols_value != NULL) {
+ const float part_value = vert_part_value[ml->v];
+ store_float_in_vcol(&mloopcols_value[ml_index], part_value);
+ }
}
}
}
@@ -415,6 +515,9 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
if (size)
MEM_freeN(size);
+ MEM_SAFE_FREE(vert_part_index);
+ MEM_SAFE_FREE(vert_part_value);
+
result->dirty |= DM_DIRTY_NORMALS;
return result;
@@ -437,7 +540,7 @@ ModifierTypeInfo modifierType_ParticleInstance = {
/* applyModifier */ applyModifier,
/* applyModifierEM */ NULL,
/* initData */ initData,
- /* requiredDataMask */ NULL,
+ /* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ isDisabled,
/* updateDepsgraph */ updateDepsgraph,