Cleanup: Rename callback flags from library_query to `IDWALK_CB_...`
[blender-staging.git] / source / blender / modifiers / intern / MOD_particleinstance.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
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.
8  *
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.
13  *
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.
17  *
18  * The Original Code is Copyright (C) 2005 by the Blender Foundation.
19  * All rights reserved.
20  *
21  * Contributor(s): Daniel Dunbar
22  *                 Ton Roosendaal,
23  *                 Ben Batt,
24  *                 Brecht Van Lommel,
25  *                 Campbell Barton
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  *
29  */
30
31 /** \file blender/modifiers/intern/MOD_particleinstance.c
32  *  \ingroup modifiers
33  */
34
35
36 #include "DNA_meshdata_types.h"
37
38 #include "MEM_guardedalloc.h"
39
40 #include "BLI_math.h"
41 #include "BLI_listbase.h"
42 #include "BLI_rand.h"
43 #include "BLI_utildefines.h"
44
45 #include "BKE_cdderivedmesh.h"
46 #include "BKE_effect.h"
47 #include "BKE_global.h"
48 #include "BKE_lattice.h"
49 #include "BKE_library_query.h"
50 #include "BKE_modifier.h"
51 #include "BKE_particle.h"
52 #include "BKE_pointcache.h"
53
54 #include "depsgraph_private.h"
55 #include "DEG_depsgraph_build.h"
56
57 static void initData(ModifierData *md)
58 {
59         ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
60
61         pimd->flag = eParticleInstanceFlag_Parents | eParticleInstanceFlag_Unborn |
62                      eParticleInstanceFlag_Alive | eParticleInstanceFlag_Dead;
63         pimd->psys = 1;
64         pimd->position = 1.0f;
65         pimd->axis = 2;
66
67 }
68 static void copyData(ModifierData *md, ModifierData *target)
69 {
70 #if 0
71         ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
72         ParticleInstanceModifierData *tpimd = (ParticleInstanceModifierData *) target;
73 #endif
74         modifier_copyData_generic(md, target);
75 }
76
77 static bool isDisabled(ModifierData *md, int useRenderParams)
78 {
79         ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md;
80         ParticleSystem *psys;
81         ModifierData *ob_md;
82         
83         if (!pimd->ob)
84                 return true;
85         
86         psys = BLI_findlink(&pimd->ob->particlesystem, pimd->psys - 1);
87         if (psys == NULL)
88                 return true;
89         
90         /* If the psys modifier is disabled we cannot use its data.
91          * First look up the psys modifier from the object, then check if it is enabled.
92          */
93         for (ob_md = pimd->ob->modifiers.first; ob_md; ob_md = ob_md->next) {
94                 if (ob_md->type == eModifierType_ParticleSystem) {
95                         ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)ob_md;
96                         if (psmd->psys == psys) {
97                                 int required_mode;
98                                 
99                                 if (useRenderParams) required_mode = eModifierMode_Render;
100                                 else required_mode = eModifierMode_Realtime;
101                                 
102                                 if (!modifier_isEnabled(md->scene, ob_md, required_mode))
103                                         return true;
104                                 
105                                 break;
106                         }
107                 }
108         }
109         
110         return false;
111 }
112
113
114 static void updateDepgraph(ModifierData *md, DagForest *forest,
115                            struct Main *UNUSED(bmain),
116                            struct Scene *UNUSED(scene),
117                            Object *UNUSED(ob),
118                            DagNode *obNode)
119 {
120         ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
121
122         if (pimd->ob) {
123                 DagNode *curNode = dag_get_node(forest, pimd->ob);
124
125                 dag_add_relation(forest, curNode, obNode,
126                                  DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
127                                  "Particle Instance Modifier");
128         }
129 }
130
131 static void updateDepsgraph(ModifierData *md,
132                             struct Main *UNUSED(bmain),
133                             struct Scene *UNUSED(scene),
134                             Object *UNUSED(ob),
135                             struct DepsNodeHandle *node)
136 {
137         ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
138         if (pimd->ob != NULL) {
139                 DEG_add_object_relation(node, pimd->ob, DEG_OB_COMP_TRANSFORM, "Particle Instance Modifier");
140         }
141 }
142
143 static void foreachObjectLink(ModifierData *md, Object *ob,
144                               ObjectWalkFunc walk, void *userData)
145 {
146         ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
147
148         walk(userData, ob, &pimd->ob, IDWALK_CB_NOP);
149 }
150
151 static int particle_skip(ParticleInstanceModifierData *pimd, ParticleSystem *psys, int p)
152 {
153         ParticleData *pa;
154
155         if (pimd->flag & eParticleInstanceFlag_Parents) {
156                 if (p >= psys->totpart) {
157                         if (psys->part->childtype == PART_CHILD_PARTICLES) {
158                                 pa = psys->particles + (psys->child + p - psys->totpart)->parent;
159                         }
160                         else {
161                                 pa = NULL;
162                         }
163                 }
164                 else {
165                         pa = psys->particles + p;
166                 }
167         }
168         else {
169                 if (psys->part->childtype == PART_CHILD_PARTICLES) {
170                         pa = psys->particles + (psys->child + p)->parent;
171                 }
172                 else {
173                         pa = NULL;
174                 }
175         }
176
177         if (pa) {
178                 if (pa->alive == PARS_UNBORN && (pimd->flag & eParticleInstanceFlag_Unborn) == 0) return 1;
179                 if (pa->alive == PARS_ALIVE && (pimd->flag & eParticleInstanceFlag_Alive) == 0) return 1;
180                 if (pa->alive == PARS_DEAD && (pimd->flag & eParticleInstanceFlag_Dead) == 0) return 1;
181         }
182         
183         return 0;
184 }
185
186 static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
187                                   DerivedMesh *derivedData,
188                                   ModifierApplyFlag UNUSED(flag))
189 {
190         DerivedMesh *dm = derivedData, *result;
191         ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
192         ParticleSimulationData sim;
193         ParticleSystem *psys = NULL;
194         ParticleData *pa = NULL;
195         MPoly *mpoly, *orig_mpoly;
196         MLoop *mloop, *orig_mloop;
197         MVert *mvert, *orig_mvert;
198         int totvert, totpoly, totloop /* , totedge */;
199         int maxvert, maxpoly, maxloop, totpart = 0, first_particle = 0;
200         int k, p, p_skip;
201         short track = ob->trackflag % 3, trackneg, axis = pimd->axis;
202         float max_co = 0.0, min_co = 0.0, temp_co[3];
203         float *size = NULL;
204
205         trackneg = ((ob->trackflag > 2) ? 1 : 0);
206
207         if (pimd->ob == ob) {
208                 pimd->ob = NULL;
209                 return derivedData;
210         }
211
212         if (pimd->ob) {
213                 psys = BLI_findlink(&pimd->ob->particlesystem, pimd->psys - 1);
214                 if (psys == NULL || psys->totpart == 0)
215                         return derivedData;
216         }
217         else {
218                 return derivedData;
219         }
220
221         if (pimd->flag & eParticleInstanceFlag_Parents)
222                 totpart += psys->totpart;
223         if (pimd->flag & eParticleInstanceFlag_Children) {
224                 if (totpart == 0)
225                         first_particle = psys->totpart;
226                 totpart += psys->totchild;
227         }
228
229         if (totpart == 0)
230                 return derivedData;
231
232         sim.scene = md->scene;
233         sim.ob = pimd->ob;
234         sim.psys = psys;
235         sim.psmd = psys_get_modifier(pimd->ob, psys);
236
237         if (pimd->flag & eParticleInstanceFlag_UseSize) {
238                 float *si;
239                 si = size = MEM_callocN(totpart * sizeof(float), "particle size array");
240
241                 if (pimd->flag & eParticleInstanceFlag_Parents) {
242                         for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++, si++)
243                                 *si = pa->size;
244                 }
245
246                 if (pimd->flag & eParticleInstanceFlag_Children) {
247                         ChildParticle *cpa = psys->child;
248
249                         for (p = 0; p < psys->totchild; p++, cpa++, si++) {
250                                 *si = psys_get_child_size(psys, cpa, 0.0f, NULL);
251                         }
252                 }
253         }
254
255         totvert = dm->getNumVerts(dm);
256         totpoly = dm->getNumPolys(dm);
257         totloop = dm->getNumLoops(dm);
258         /* totedge = dm->getNumEdges(dm); */ /* UNUSED */
259
260         /* count particles */
261         maxvert = 0;
262         maxpoly = 0;
263         maxloop = 0;
264
265         for (p = 0; p < totpart; p++) {
266                 if (particle_skip(pimd, psys, p))
267                         continue;
268
269                 maxvert += totvert;
270                 maxpoly += totpoly;
271                 maxloop += totloop;
272         }
273
274         psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
275
276         if (psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) {
277                 float min[3], max[3];
278                 INIT_MINMAX(min, max);
279                 dm->getMinMax(dm, min, max);
280                 min_co = min[track];
281                 max_co = max[track];
282         }
283
284         result = CDDM_from_template(dm, maxvert, 0, 0, maxloop, maxpoly);
285
286         mvert = result->getVertArray(result);
287         orig_mvert = dm->getVertArray(dm);
288
289         mpoly = result->getPolyArray(result);
290         orig_mpoly = dm->getPolyArray(dm);
291         mloop = result->getLoopArray(result);
292         orig_mloop = dm->getLoopArray(dm);
293
294         for (p = 0, p_skip = 0; p < totpart; p++) {
295                 float prev_dir[3];
296                 float frame[4]; /* frame orientation quaternion */
297                 
298                 /* skip particle? */
299                 if (particle_skip(pimd, psys, p))
300                         continue;
301
302                 /* set vertices coordinates */
303                 for (k = 0; k < totvert; k++) {
304                         ParticleKey state;
305                         MVert *inMV;
306                         MVert *mv = mvert + p_skip * totvert + k;
307
308                         inMV = orig_mvert + k;
309                         DM_copy_vert_data(dm, result, k, p_skip * totvert + k, 1);
310                         *mv = *inMV;
311
312                         /*change orientation based on object trackflag*/
313                         copy_v3_v3(temp_co, mv->co);
314                         mv->co[axis] = temp_co[track];
315                         mv->co[(axis + 1) % 3] = temp_co[(track + 1) % 3];
316                         mv->co[(axis + 2) % 3] = temp_co[(track + 2) % 3];
317
318                         /* get particle state */
319                         if ((psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) &&
320                             (pimd->flag & eParticleInstanceFlag_Path))
321                         {
322                                 float ran = 0.0f;
323                                 if (pimd->random_position != 0.0f) {
324                                         ran = pimd->random_position * BLI_hash_frand(psys->seed + p);
325                                 }
326
327                                 if (pimd->flag & eParticleInstanceFlag_KeepShape) {
328                                         state.time = pimd->position * (1.0f - ran);
329                                 }
330                                 else {
331                                         state.time = (mv->co[axis] - min_co) / (max_co - min_co) * pimd->position * (1.0f - ran);
332
333                                         if (trackneg)
334                                                 state.time = 1.0f - state.time;
335
336                                         mv->co[axis] = 0.0;
337                                 }
338
339                                 psys_get_particle_on_path(&sim, first_particle + p, &state, 1);
340
341                                 normalize_v3(state.vel);
342
343                                 /* Incrementally Rotating Frame (Bishop Frame) */
344                                 if (k == 0) {
345                                         float hairmat[4][4];
346                                         float mat[3][3];
347                                         
348                                         if (first_particle + p < psys->totpart)
349                                                 pa = psys->particles + first_particle + p;
350                                         else {
351                                                 ChildParticle *cpa = psys->child + (p - psys->totpart);
352                                                 pa = psys->particles + cpa->parent;
353                                         }
354                                         psys_mat_hair_to_global(sim.ob, sim.psmd->dm_final, sim.psys->part->from, pa, hairmat);
355                                         copy_m3_m4(mat, hairmat);
356                                         /* to quaternion */
357                                         mat3_to_quat(frame, mat);
358                                         
359                                         /* note: direction is same as normal vector currently,
360                                          * but best to keep this separate so the frame can be
361                                          * rotated later if necessary
362                                          */
363                                         copy_v3_v3(prev_dir, state.vel);
364                                 }
365                                 else {
366                                         float rot[4];
367                                         
368                                         /* incrementally rotate along bend direction */
369                                         rotation_between_vecs_to_quat(rot, prev_dir, state.vel);
370                                         mul_qt_qtqt(frame, rot, frame);
371                                         
372                                         copy_v3_v3(prev_dir, state.vel);
373                                 }
374                                 
375                                 copy_qt_qt(state.rot, frame);
376 #if 0
377                                 /* Absolute Frame (Frenet Frame) */
378                                 if (state.vel[axis] < -0.9999f || state.vel[axis] > 0.9999f) {
379                                         unit_qt(state.rot);
380                                 }
381                                 else {
382                                         float cross[3];
383                                         float temp[3] = {0.0f, 0.0f, 0.0f};
384                                         temp[axis] = 1.0f;
385                                         
386                                         cross_v3_v3v3(cross, temp, state.vel);
387                                         
388                                         /* state.vel[axis] is the only component surviving from a dot product with the axis */
389                                         axis_angle_to_quat(state.rot, cross, saacos(state.vel[axis]));
390                                 }
391 #endif
392                         }
393                         else {
394                                 state.time = -1.0;
395                                 psys_get_particle_state(&sim, first_particle + p, &state, 1);
396                         }
397
398                         mul_qt_v3(state.rot, mv->co);
399                         if (pimd->flag & eParticleInstanceFlag_UseSize)
400                                 mul_v3_fl(mv->co, size[p]);
401                         add_v3_v3(mv->co, state.co);
402                 }
403
404                 /* create polys and loops */
405                 for (k = 0; k < totpoly; k++) {
406                         MPoly *inMP = orig_mpoly + k;
407                         MPoly *mp = mpoly + p_skip * totpoly + k;
408
409                         DM_copy_poly_data(dm, result, k, p_skip * totpoly + k, 1);
410                         *mp = *inMP;
411                         mp->loopstart += p_skip * totloop;
412
413                         {
414                                 MLoop *inML = orig_mloop + inMP->loopstart;
415                                 MLoop *ml = mloop + mp->loopstart;
416                                 int j = mp->totloop;
417
418                                 DM_copy_loop_data(dm, result, inMP->loopstart, mp->loopstart, j);
419                                 for (; j; j--, ml++, inML++) {
420                                         ml->v = inML->v + (p_skip * totvert);
421                                 }
422                         }
423                 }
424
425                 p_skip++;
426         }
427
428         CDDM_calc_edges(result);
429
430         if (psys->lattice_deform_data) {
431                 end_latt_deform(psys->lattice_deform_data);
432                 psys->lattice_deform_data = NULL;
433         }
434
435         if (size)
436                 MEM_freeN(size);
437
438         result->dirty |= DM_DIRTY_NORMALS;
439
440         return result;
441 }
442 ModifierTypeInfo modifierType_ParticleInstance = {
443         /* name */              "ParticleInstance",
444         /* structName */        "ParticleInstanceModifierData",
445         /* structSize */        sizeof(ParticleInstanceModifierData),
446         /* type */              eModifierTypeType_Constructive,
447         /* flags */             eModifierTypeFlag_AcceptsMesh |
448                                 eModifierTypeFlag_SupportsMapping |
449                                 eModifierTypeFlag_SupportsEditmode |
450                                 eModifierTypeFlag_EnableInEditmode,
451
452         /* copyData */          copyData,
453         /* deformVerts */       NULL,
454         /* deformMatrices */    NULL,
455         /* deformVertsEM */     NULL,
456         /* deformMatricesEM */  NULL,
457         /* applyModifier */     applyModifier,
458         /* applyModifierEM */   NULL,
459         /* initData */          initData,
460         /* requiredDataMask */  NULL,
461         /* freeData */          NULL,
462         /* isDisabled */        isDisabled,
463         /* updateDepgraph */    updateDepgraph,
464         /* updateDepsgraph */   updateDepsgraph,
465         /* dependsOnTime */     NULL,
466         /* dependsOnNormals */  NULL,
467         /* foreachObjectLink */ foreachObjectLink,
468         /* foreachIDLink */     NULL,
469         /* foreachTexLink */    NULL,
470 };