2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2005 by the Blender Foundation.
19 * All rights reserved.
21 * Contributor(s): Daniel Dunbar
27 * ***** END GPL LICENSE BLOCK *****
31 /** \file blender/modifiers/intern/MOD_particleinstance.c
36 #include "DNA_meshdata_types.h"
38 #include "MEM_guardedalloc.h"
41 #include "BLI_listbase.h"
43 #include "BLI_string.h"
44 #include "BLI_utildefines.h"
46 #include "BKE_cdderivedmesh.h"
47 #include "BKE_effect.h"
48 #include "BKE_global.h"
49 #include "BKE_lattice.h"
50 #include "BKE_library_query.h"
51 #include "BKE_modifier.h"
52 #include "BKE_particle.h"
53 #include "BKE_pointcache.h"
55 #include "DEG_depsgraph_build.h"
57 static void initData(ModifierData *md)
59 ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
61 pimd->flag = eParticleInstanceFlag_Parents | eParticleInstanceFlag_Unborn |
62 eParticleInstanceFlag_Alive | eParticleInstanceFlag_Dead;
64 pimd->position = 1.0f;
66 pimd->space = eParticleInstanceSpace_World;
67 pimd->particle_amount = 1.0f;
68 pimd->particle_offset = 0.0f;
70 STRNCPY(pimd->index_layer_name, "");
71 STRNCPY(pimd->value_layer_name, "");
73 static void copyData(ModifierData *md, ModifierData *target)
76 ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
77 ParticleInstanceModifierData *tpimd = (ParticleInstanceModifierData *) target;
79 modifier_copyData_generic(md, target);
82 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
84 ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md;
85 CustomDataMask dataMask = 0;
87 if (pimd->index_layer_name[0] != '\0' ||
88 pimd->value_layer_name[0] != '\0')
90 dataMask |= CD_MASK_MLOOPCOL;
97 static bool isDisabled(ModifierData *md, int useRenderParams)
99 ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md;
100 ParticleSystem *psys;
106 psys = BLI_findlink(&pimd->ob->particlesystem, pimd->psys - 1);
110 /* If the psys modifier is disabled we cannot use its data.
111 * First look up the psys modifier from the object, then check if it is enabled.
113 for (ob_md = pimd->ob->modifiers.first; ob_md; ob_md = ob_md->next) {
114 if (ob_md->type == eModifierType_ParticleSystem) {
115 ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)ob_md;
116 if (psmd->psys == psys) {
119 if (useRenderParams) required_mode = eModifierMode_Render;
120 else required_mode = eModifierMode_Realtime;
122 if (!modifier_isEnabled(md->scene, ob_md, required_mode))
133 static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
135 ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
136 if (pimd->ob != NULL) {
137 DEG_add_object_relation(ctx->node, pimd->ob, DEG_OB_COMP_TRANSFORM, "Particle Instance Modifier");
138 DEG_add_object_relation(ctx->node, pimd->ob, DEG_OB_COMP_GEOMETRY, "Particle Instance Modifier");
142 static void foreachObjectLink(ModifierData *md, Object *ob,
143 ObjectWalkFunc walk, void *userData)
145 ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
147 walk(userData, ob, &pimd->ob, IDWALK_CB_NOP);
150 static bool particle_skip(ParticleInstanceModifierData *pimd, ParticleSystem *psys, int p)
152 const bool between = (psys->part->childtype == PART_CHILD_FACES);
154 int totpart, randp, minp, maxp;
156 if (p >= psys->totpart) {
157 ChildParticle *cpa = psys->child + (p - psys->totpart);
158 pa = psys->particles + (between? cpa->pa[0]: cpa->parent);
161 pa = psys->particles + p;
165 if (pa->alive == PARS_UNBORN && (pimd->flag & eParticleInstanceFlag_Unborn) == 0) return true;
166 if (pa->alive == PARS_ALIVE && (pimd->flag & eParticleInstanceFlag_Alive) == 0) return true;
167 if (pa->alive == PARS_DEAD && (pimd->flag & eParticleInstanceFlag_Dead) == 0) return true;
170 if (pimd->particle_amount == 1.0f) {
171 /* Early output, all particles are to be instanced. */
175 /* Randomly skip particles based on desired amount of visible particles. */
177 totpart = psys->totpart + psys->totchild;
179 /* TODO make randomization optional? */
180 randp = (int)(psys_frand(psys, 3578 + p) * totpart) % totpart;
182 minp = (int)(totpart * pimd->particle_offset) % (totpart+1);
183 maxp = (int)(totpart * (pimd->particle_offset + pimd->particle_amount)) % (totpart+1);
186 return randp < minp || randp >= maxp;
188 else if (maxp < minp) {
189 return randp < minp && randp >= maxp;
198 static void store_float_in_vcol(MLoopCol *vcol, float float_value)
200 const uchar value = FTOCHAR(float_value);
201 vcol->r = vcol->g = vcol->b = value;
205 static DerivedMesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx,
206 DerivedMesh *derivedData)
208 DerivedMesh *dm = derivedData, *result;
209 ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
210 ParticleSimulationData sim;
211 ParticleSystem *psys = NULL;
212 ParticleData *pa = NULL;
213 MPoly *mpoly, *orig_mpoly;
214 MLoop *mloop, *orig_mloop;
215 MVert *mvert, *orig_mvert;
216 int totvert, totpoly, totloop , totedge;
217 int maxvert, maxpoly, maxloop, maxedge, part_end = 0, part_start;
219 short track = ctx->object->trackflag % 3, trackneg, axis = pimd->axis;
220 float max_co = 0.0, min_co = 0.0, temp_co[3];
222 float spacemat[4][4];
223 const bool use_parents = pimd->flag & eParticleInstanceFlag_Parents;
224 const bool use_children = pimd->flag & eParticleInstanceFlag_Children;
227 trackneg = ((ctx->object->trackflag > 2) ? 1 : 0);
229 if (pimd->ob == ctx->object) {
235 psys = BLI_findlink(&pimd->ob->particlesystem, pimd->psys - 1);
236 if (psys == NULL || psys->totpart == 0)
243 part_start = use_parents ? 0 : psys->totpart;
247 part_end += psys->totpart;
249 part_end += psys->totchild;
254 sim.depsgraph = ctx->depsgraph;
255 sim.scene = md->scene;
258 sim.psmd = psys_get_modifier(pimd->ob, psys);
259 between = (psys->part->childtype == PART_CHILD_FACES);
261 if (pimd->flag & eParticleInstanceFlag_UseSize) {
263 si = size = MEM_calloc_arrayN(part_end, sizeof(float), "particle size array");
265 if (pimd->flag & eParticleInstanceFlag_Parents) {
266 for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++, si++)
270 if (pimd->flag & eParticleInstanceFlag_Children) {
271 ChildParticle *cpa = psys->child;
273 for (p = 0; p < psys->totchild; p++, cpa++, si++) {
274 *si = psys_get_child_size(psys, cpa, 0.0f, NULL);
279 switch (pimd->space) {
280 case eParticleInstanceSpace_World:
281 /* particle states are in world space already */
284 case eParticleInstanceSpace_Local:
285 /* get particle states in the particle object's local space */
286 invert_m4_m4(spacemat, pimd->ob->obmat);
289 /* should not happen */
294 totvert = dm->getNumVerts(dm);
295 totpoly = dm->getNumPolys(dm);
296 totloop = dm->getNumLoops(dm);
297 totedge = dm->getNumEdges(dm);
299 /* count particles */
305 for (p = part_start; p < part_end; p++) {
306 if (particle_skip(pimd, psys, p))
315 psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
317 if (psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) {
318 float min[3], max[3];
319 INIT_MINMAX(min, max);
320 dm->getMinMax(dm, min, max);
325 result = CDDM_from_template(dm, maxvert, maxedge, 0, maxloop, maxpoly);
327 mvert = result->getVertArray(result);
328 orig_mvert = dm->getVertArray(dm);
329 mpoly = result->getPolyArray(result);
330 orig_mpoly = dm->getPolyArray(dm);
331 mloop = result->getLoopArray(result);
332 orig_mloop = dm->getLoopArray(dm);
334 MLoopCol *mloopcols_index = CustomData_get_layer_named(&result->loopData, CD_MLOOPCOL, pimd->index_layer_name);
335 MLoopCol *mloopcols_value = CustomData_get_layer_named(&result->loopData, CD_MLOOPCOL, pimd->value_layer_name);
336 int *vert_part_index = NULL;
337 float *vert_part_value = NULL;
338 if (mloopcols_index != NULL) {
339 vert_part_index = MEM_calloc_arrayN(maxvert, sizeof(int), "vertex part index array");
341 if (mloopcols_value) {
342 vert_part_value = MEM_calloc_arrayN(maxvert, sizeof(float), "vertex part value array");
345 for (p = part_start, p_skip = 0; p < part_end; p++) {
347 float frame[4]; /* frame orientation quaternion */
348 float p_random = psys_frand(psys, 77091 + 283*p);
351 if (particle_skip(pimd, psys, p))
354 /* set vertices coordinates */
355 for (k = 0; k < totvert; k++) {
358 int vindex = p_skip * totvert + k;
359 MVert *mv = mvert + vindex;
361 inMV = orig_mvert + k;
362 DM_copy_vert_data(dm, result, k, p_skip * totvert + k, 1);
365 if (vert_part_index != NULL) {
366 vert_part_index[vindex] = p;
368 if (vert_part_value != NULL) {
369 vert_part_value[vindex] = p_random;
372 /*change orientation based on object trackflag*/
373 copy_v3_v3(temp_co, mv->co);
374 mv->co[axis] = temp_co[track];
375 mv->co[(axis + 1) % 3] = temp_co[(track + 1) % 3];
376 mv->co[(axis + 2) % 3] = temp_co[(track + 2) % 3];
378 /* get particle state */
379 if ((psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) &&
380 (pimd->flag & eParticleInstanceFlag_Path))
383 if (pimd->random_position != 0.0f) {
384 ran = pimd->random_position * BLI_hash_frand(psys->seed + p);
387 if (pimd->flag & eParticleInstanceFlag_KeepShape) {
388 state.time = pimd->position * (1.0f - ran);
391 state.time = (mv->co[axis] - min_co) / (max_co - min_co) * pimd->position * (1.0f - ran);
394 state.time = 1.0f - state.time;
399 psys_get_particle_on_path(&sim, p, &state, 1);
401 normalize_v3(state.vel);
403 /* Incrementally Rotating Frame (Bishop Frame) */
408 if (p < psys->totpart)
409 pa = psys->particles + p;
411 ChildParticle *cpa = psys->child + (p - psys->totpart);
412 pa = psys->particles + (between? cpa->pa[0]: cpa->parent);
414 psys_mat_hair_to_global(sim.ob, sim.psmd->dm_final, sim.psys->part->from, pa, hairmat);
415 copy_m3_m4(mat, hairmat);
417 mat3_to_quat(frame, mat);
419 if (pimd->rotation > 0.0f || pimd->random_rotation > 0.0f) {
420 float angle = 2.0f*M_PI * (pimd->rotation + pimd->random_rotation * (psys_frand(psys, 19957323 + p) - 0.5f));
421 float eul[3] = { 0.0f, 0.0f, angle };
424 eul_to_quat(rot, eul);
425 mul_qt_qtqt(frame, frame, rot);
428 /* note: direction is same as normal vector currently,
429 * but best to keep this separate so the frame can be
430 * rotated later if necessary
432 copy_v3_v3(prev_dir, state.vel);
437 /* incrementally rotate along bend direction */
438 rotation_between_vecs_to_quat(rot, prev_dir, state.vel);
439 mul_qt_qtqt(frame, rot, frame);
441 copy_v3_v3(prev_dir, state.vel);
444 copy_qt_qt(state.rot, frame);
446 /* Absolute Frame (Frenet Frame) */
447 if (state.vel[axis] < -0.9999f || state.vel[axis] > 0.9999f) {
452 float temp[3] = {0.0f, 0.0f, 0.0f};
455 cross_v3_v3v3(cross, temp, state.vel);
457 /* state.vel[axis] is the only component surviving from a dot product with the axis */
458 axis_angle_to_quat(state.rot, cross, saacos(state.vel[axis]));
464 psys_get_particle_state(&sim, p, &state, 1);
467 mul_qt_v3(state.rot, mv->co);
468 if (pimd->flag & eParticleInstanceFlag_UseSize)
469 mul_v3_fl(mv->co, size[p]);
470 add_v3_v3(mv->co, state.co);
472 mul_m4_v3(spacemat, mv->co);
475 /* create edges and adjust edge vertex indices*/
476 DM_copy_edge_data(dm, result, 0, p_skip * totedge, totedge);
477 MEdge *me = CDDM_get_edges(result) + p_skip * totedge;
478 for (k = 0; k < totedge; k++, me++) {
479 me->v1 += p_skip * totvert;
480 me->v2 += p_skip * totvert;
483 /* create polys and loops */
484 for (k = 0; k < totpoly; k++) {
486 MPoly *inMP = orig_mpoly + k;
487 MPoly *mp = mpoly + p_skip * totpoly + k;
489 DM_copy_poly_data(dm, result, k, p_skip * totpoly + k, 1);
491 mp->loopstart += p_skip * totloop;
494 MLoop *inML = orig_mloop + inMP->loopstart;
495 MLoop *ml = mloop + mp->loopstart;
498 DM_copy_loop_data(dm, result, inMP->loopstart, mp->loopstart, j);
499 for (; j; j--, ml++, inML++) {
500 ml->v = inML->v + (p_skip * totvert);
501 ml->e = inML->e + (p_skip * totedge);
502 const int ml_index = (ml - mloop);
503 if (mloopcols_index != NULL) {
504 const int part_index = vert_part_index[ml->v];
505 store_float_in_vcol(&mloopcols_index[ml_index], (float)part_index / psys->totpart);
507 if (mloopcols_value != NULL) {
508 const float part_value = vert_part_value[ml->v];
509 store_float_in_vcol(&mloopcols_value[ml_index], part_value);
517 if (psys->lattice_deform_data) {
518 end_latt_deform(psys->lattice_deform_data);
519 psys->lattice_deform_data = NULL;
525 MEM_SAFE_FREE(vert_part_index);
526 MEM_SAFE_FREE(vert_part_value);
528 result->dirty |= DM_DIRTY_NORMALS;
532 ModifierTypeInfo modifierType_ParticleInstance = {
533 /* name */ "ParticleInstance",
534 /* structName */ "ParticleInstanceModifierData",
535 /* structSize */ sizeof(ParticleInstanceModifierData),
536 /* type */ eModifierTypeType_Constructive,
537 /* flags */ eModifierTypeFlag_AcceptsMesh |
538 eModifierTypeFlag_SupportsMapping |
539 eModifierTypeFlag_SupportsEditmode |
540 eModifierTypeFlag_EnableInEditmode,
542 /* copyData */ copyData,
544 /* deformVerts_DM */ NULL,
545 /* deformMatrices_DM */ NULL,
546 /* deformVertsEM_DM */ NULL,
547 /* deformMatricesEM_DM*/NULL,
548 /* applyModifier_DM */ applyModifier,
549 /* applyModifierEM_DM */NULL,
551 /* deformVerts */ NULL,
552 /* deformMatrices */ NULL,
553 /* deformVertsEM */ NULL,
554 /* deformMatricesEM */ NULL,
555 /* applyModifier */ NULL,
556 /* applyModifierEM */ NULL,
558 /* initData */ initData,
559 /* requiredDataMask */ requiredDataMask,
561 /* isDisabled */ isDisabled,
562 /* updateDepsgraph */ updateDepsgraph,
563 /* dependsOnTime */ NULL,
564 /* dependsOnNormals */ NULL,
565 /* foreachObjectLink */ foreachObjectLink,
566 /* foreachIDLink */ NULL,
567 /* foreachTexLink */ NULL,