4984682455a824ebbfa05f330b6c06cd3142baf8
[blender.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_lattice.h"
47 #include "BKE_modifier.h"
48 #include "BKE_particle.h"
49 #include "BKE_pointcache.h"
50
51 #include "MOD_util.h"
52
53 #include "depsgraph_private.h"
54
55
56 static void initData(ModifierData *md)
57 {
58         ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
59
60         pimd->flag = eParticleInstanceFlag_Parents | eParticleInstanceFlag_Unborn |
61                      eParticleInstanceFlag_Alive | eParticleInstanceFlag_Dead;
62         pimd->psys = 1;
63         pimd->position = 1.0f;
64         pimd->axis = 2;
65
66 }
67 static void copyData(ModifierData *md, ModifierData *target)
68 {
69         ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
70         ParticleInstanceModifierData *tpimd = (ParticleInstanceModifierData *) target;
71
72         tpimd->ob = pimd->ob;
73         tpimd->psys = pimd->psys;
74         tpimd->flag = pimd->flag;
75         tpimd->axis = pimd->axis;
76         tpimd->position = pimd->position;
77         tpimd->random_position = pimd->random_position;
78 }
79
80 static int dependsOnTime(ModifierData *UNUSED(md))
81 {
82         return 0;
83 }
84
85 static int isDisabled(ModifierData *md, int useRenderParams)
86 {
87         ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md;
88         ParticleSystem *psys;
89         ModifierData *ob_md;
90         
91         if (!pimd->ob)
92                 return TRUE;
93         
94         psys = BLI_findlink(&pimd->ob->particlesystem, pimd->psys - 1);
95         if (psys == NULL)
96                 return TRUE;
97         
98         /* If the psys modifier is disabled we cannot use its data.
99          * First look up the psys modifier from the object, then check if it is enabled.
100          */
101         for (ob_md = pimd->ob->modifiers.first; ob_md; ob_md = ob_md->next) {
102                 if (ob_md->type == eModifierType_ParticleSystem) {
103                         ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)ob_md;
104                         if (psmd->psys == psys) {
105                                 int required_mode;
106                                 
107                                 if (useRenderParams) required_mode = eModifierMode_Render;
108                                 else required_mode = eModifierMode_Realtime;
109                                 
110                                 if (!modifier_isEnabled(md->scene, ob_md, required_mode))
111                                         return TRUE;
112                                 
113                                 break;
114                         }
115                 }
116         }
117         
118         return FALSE;
119 }
120
121
122 static void updateDepgraph(ModifierData *md, DagForest *forest,
123                            struct Scene *UNUSED(scene),
124                            Object *UNUSED(ob),
125                            DagNode *obNode)
126 {
127         ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
128
129         if (pimd->ob) {
130                 DagNode *curNode = dag_get_node(forest, pimd->ob);
131
132                 dag_add_relation(forest, curNode, obNode,
133                                  DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
134                                  "Particle Instance Modifier");
135         }
136 }
137
138 static void foreachObjectLink(ModifierData *md, Object *ob,
139                               ObjectWalkFunc walk, void *userData)
140 {
141         ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
142
143         walk(userData, ob, &pimd->ob);
144 }
145
146 static int particle_skip(ParticleInstanceModifierData *pimd, ParticleSystem *psys, int p)
147 {
148         ParticleData *pa;
149
150         if (pimd->flag & eParticleInstanceFlag_Parents) {
151                 if (p >= psys->totpart) {
152                         if (psys->part->childtype == PART_CHILD_PARTICLES) {
153                                 pa = psys->particles + (psys->child + p - psys->totpart)->parent;
154                         }
155                         else {
156                                 pa = NULL;
157                         }
158                 }
159                 else {
160                         pa = psys->particles + p;
161                 }
162         }
163         else {
164                 if (psys->part->childtype == PART_CHILD_PARTICLES) {
165                         pa = psys->particles + (psys->child + p)->parent;
166                 }
167                 else {
168                         pa = NULL;
169                 }
170         }
171
172         if (pa) {
173                 if (pa->alive == PARS_UNBORN && (pimd->flag & eParticleInstanceFlag_Unborn) == 0) return 1;
174                 if (pa->alive == PARS_ALIVE && (pimd->flag & eParticleInstanceFlag_Alive) == 0) return 1;
175                 if (pa->alive == PARS_DEAD && (pimd->flag & eParticleInstanceFlag_Dead) == 0) return 1;
176         }
177         
178         return 0;
179 }
180
181 static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
182                                   DerivedMesh *derivedData,
183                                   ModifierApplyFlag UNUSED(flag))
184 {
185         DerivedMesh *dm = derivedData, *result;
186         ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
187         ParticleSimulationData sim;
188         ParticleSystem *psys = NULL;
189         ParticleData *pa = NULL;
190         MPoly *mpoly, *orig_mpoly;
191         MLoop *mloop, *orig_mloop;
192         MVert *mvert, *orig_mvert;
193         int totvert, totpoly, totloop /* , totedge */;
194         int maxvert, maxpoly, maxloop, totpart = 0, first_particle = 0;
195         int k, p, p_skip;
196         short track = ob->trackflag % 3, trackneg, axis = pimd->axis;
197         float max_co = 0.0, min_co = 0.0, temp_co[3], cross[3];
198         float *size = NULL;
199
200         trackneg = ((ob->trackflag > 2) ? 1 : 0);
201
202         if (pimd->ob == ob) {
203                 pimd->ob = NULL;
204                 return derivedData;
205         }
206
207         if (pimd->ob) {
208                 psys = BLI_findlink(&pimd->ob->particlesystem, pimd->psys - 1);
209                 if (psys == NULL || psys->totpart == 0)
210                         return derivedData;
211         }
212         else return derivedData;
213
214         if (pimd->flag & eParticleInstanceFlag_Parents)
215                 totpart += psys->totpart;
216         if (pimd->flag & eParticleInstanceFlag_Children) {
217                 if (totpart == 0)
218                         first_particle = psys->totpart;
219                 totpart += psys->totchild;
220         }
221
222         if (totpart == 0)
223                 return derivedData;
224
225         sim.scene = md->scene;
226         sim.ob = pimd->ob;
227         sim.psys = psys;
228         sim.psmd = psys_get_modifier(pimd->ob, psys);
229
230         if (pimd->flag & eParticleInstanceFlag_UseSize) {
231                 float *si;
232                 si = size = MEM_callocN(totpart * sizeof(float), "particle size array");
233
234                 if (pimd->flag & eParticleInstanceFlag_Parents) {
235                         for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++, si++)
236                                 *si = pa->size;
237                 }
238
239                 if (pimd->flag & eParticleInstanceFlag_Children) {
240                         ChildParticle *cpa = psys->child;
241
242                         for (p = 0; p < psys->totchild; p++, cpa++, si++) {
243                                 *si = psys_get_child_size(psys, cpa, 0.0f, NULL);
244                         }
245                 }
246         }
247
248         totvert = dm->getNumVerts(dm);
249         totpoly = dm->getNumPolys(dm);
250         totloop = dm->getNumLoops(dm);
251         /* totedge = dm->getNumEdges(dm); */ /* UNUSED */
252
253         /* count particles */
254         maxvert = 0;
255         maxpoly = 0;
256         maxloop = 0;
257
258         for (p = 0; p < totpart; p++) {
259                 if (particle_skip(pimd, psys, p))
260                         continue;
261
262                 maxvert += totvert;
263                 maxpoly += totpoly;
264                 maxloop += totloop;
265         }
266
267         psys->lattice = psys_get_lattice(&sim);
268
269         if (psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) {
270                 float min_r[3], max_r[3];
271                 INIT_MINMAX(min_r, max_r);
272                 dm->getMinMax(dm, min_r, max_r);
273                 min_co = min_r[track];
274                 max_co = max_r[track];
275         }
276
277         result = CDDM_from_template(dm, maxvert, 0, 0, maxloop, maxpoly);
278
279         mvert = result->getVertArray(result);
280         orig_mvert = dm->getVertArray(dm);
281
282         mpoly = result->getPolyArray(result);
283         orig_mpoly = dm->getPolyArray(dm);
284         mloop = result->getLoopArray(result);
285         orig_mloop = dm->getLoopArray(dm);
286
287         for (p = 0, p_skip = 0; p < totpart; p++) {
288                 /* skip particle? */
289                 if (particle_skip(pimd, psys, p))
290                         continue;
291
292                 /* set vertices coordinates */
293                 for (k = 0; k < totvert; k++) {
294                         ParticleKey state;
295                         MVert *inMV;
296                         MVert *mv = mvert + p_skip * totvert + k;
297
298                         inMV = orig_mvert + k;
299                         DM_copy_vert_data(dm, result, k, p_skip * totvert + k, 1);
300                         *mv = *inMV;
301
302                         /*change orientation based on object trackflag*/
303                         copy_v3_v3(temp_co, mv->co);
304                         mv->co[axis] = temp_co[track];
305                         mv->co[(axis + 1) % 3] = temp_co[(track + 1) % 3];
306                         mv->co[(axis + 2) % 3] = temp_co[(track + 2) % 3];
307
308                         /* get particle state */
309                         if ((psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) &&
310                                 (pimd->flag & eParticleInstanceFlag_Path))
311                         {
312                                 float ran = 0.0f;
313                                 if (pimd->random_position != 0.0f) {
314                                         BLI_srandom(psys->seed + p);
315                                         ran = pimd->random_position * BLI_frand();
316                                 }
317
318                                 if (pimd->flag & eParticleInstanceFlag_KeepShape) {
319                                         state.time = pimd->position * (1.0f - ran);
320                                 }
321                                 else {
322                                         state.time = (mv->co[axis] - min_co) / (max_co - min_co) * pimd->position * (1.0f - ran);
323
324                                         if (trackneg)
325                                                 state.time = 1.0f - state.time;
326
327                                         mv->co[axis] = 0.0;
328                                 }
329
330                                 psys_get_particle_on_path(&sim, first_particle + p, &state, 1);
331
332                                 normalize_v3(state.vel);
333
334                                 /* TODO: incremental rotations somehow */
335                                 if (state.vel[axis] < -0.9999f || state.vel[axis] > 0.9999f) {
336                                         unit_qt(state.rot);
337                                 }
338                                 else {
339                                         float temp[3] = {0.0f, 0.0f, 0.0f};
340                                         temp[axis] = 1.0f;
341
342                                         cross_v3_v3v3(cross, temp, state.vel);
343
344                                         /* state.vel[axis] is the only component surviving from a dot product with the axis */
345                                         axis_angle_to_quat(state.rot, cross, saacos(state.vel[axis]));
346                                 }
347                         }
348                         else {
349                                 state.time = -1.0;
350                                 psys_get_particle_state(&sim, first_particle + p, &state, 1);
351                         }
352
353                         mul_qt_v3(state.rot, mv->co);
354                         if (pimd->flag & eParticleInstanceFlag_UseSize)
355                                 mul_v3_fl(mv->co, size[p]);
356                         add_v3_v3(mv->co, state.co);
357                 }
358
359                 /* create polys and loops */
360                 for (k = 0; k < totpoly; k++) {
361                         MPoly *inMP = orig_mpoly + k;
362                         MPoly *mp = mpoly + p_skip * totpoly + k;
363
364                         DM_copy_poly_data(dm, result, k, p_skip * totpoly + k, 1);
365                         *mp = *inMP;
366                         mp->loopstart += p_skip * totloop;
367
368                         {
369                                 MLoop *inML = orig_mloop + inMP->loopstart;
370                                 MLoop *ml = mloop + mp->loopstart;
371                                 int j = mp->totloop;
372
373                                 DM_copy_loop_data(dm, result, inMP->loopstart, mp->loopstart, j);
374                                 for (; j; j--, ml++, inML++) {
375                                         ml->v = inML->v + (p_skip * totvert);
376                                 }
377                         }
378                 }
379
380                 p_skip++;
381         }
382
383         CDDM_calc_edges(result);
384
385         if (psys->lattice) {
386                 end_latt_deform(psys->lattice);
387                 psys->lattice = NULL;
388         }
389
390         if (size)
391                 MEM_freeN(size);
392
393         CDDM_calc_normals(result);
394
395         return result;
396 }
397 static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
398                                     struct BMEditMesh *UNUSED(editData),
399                                     DerivedMesh *derivedData)
400 {
401         return applyModifier(md, ob, derivedData, MOD_APPLY_USECACHE);
402 }
403
404 ModifierTypeInfo modifierType_ParticleInstance = {
405         /* name */              "ParticleInstance",
406         /* structName */        "ParticleInstanceModifierData",
407         /* structSize */        sizeof(ParticleInstanceModifierData),
408         /* type */              eModifierTypeType_Constructive,
409         /* flags */             eModifierTypeFlag_AcceptsMesh |
410                                 eModifierTypeFlag_SupportsMapping |
411                                 eModifierTypeFlag_SupportsEditmode |
412                                 eModifierTypeFlag_EnableInEditmode,
413
414         /* copyData */          copyData,
415         /* deformVerts */       NULL,
416         /* deformMatrices */    NULL,
417         /* deformVertsEM */     NULL,
418         /* deformMatricesEM */  NULL,
419         /* applyModifier */     applyModifier,
420         /* applyModifierEM */   applyModifierEM,
421         /* initData */          initData,
422         /* requiredDataMask */  NULL,
423         /* freeData */          NULL,
424         /* isDisabled */        isDisabled,
425         /* updateDepgraph */    updateDepgraph,
426         /* dependsOnTime */     dependsOnTime,
427         /* dependsOnNormals */  NULL,
428         /* foreachObjectLink */ foreachObjectLink,
429         /* foreachIDLink */     NULL,
430         /* foreachTexLink */    NULL,
431 };