code cleanup: favor braces when blocks have mixed brace use.
[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 {
213                 return derivedData;
214         }
215
216         if (pimd->flag & eParticleInstanceFlag_Parents)
217                 totpart += psys->totpart;
218         if (pimd->flag & eParticleInstanceFlag_Children) {
219                 if (totpart == 0)
220                         first_particle = psys->totpart;
221                 totpart += psys->totchild;
222         }
223
224         if (totpart == 0)
225                 return derivedData;
226
227         sim.scene = md->scene;
228         sim.ob = pimd->ob;
229         sim.psys = psys;
230         sim.psmd = psys_get_modifier(pimd->ob, psys);
231
232         if (pimd->flag & eParticleInstanceFlag_UseSize) {
233                 float *si;
234                 si = size = MEM_callocN(totpart * sizeof(float), "particle size array");
235
236                 if (pimd->flag & eParticleInstanceFlag_Parents) {
237                         for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++, si++)
238                                 *si = pa->size;
239                 }
240
241                 if (pimd->flag & eParticleInstanceFlag_Children) {
242                         ChildParticle *cpa = psys->child;
243
244                         for (p = 0; p < psys->totchild; p++, cpa++, si++) {
245                                 *si = psys_get_child_size(psys, cpa, 0.0f, NULL);
246                         }
247                 }
248         }
249
250         totvert = dm->getNumVerts(dm);
251         totpoly = dm->getNumPolys(dm);
252         totloop = dm->getNumLoops(dm);
253         /* totedge = dm->getNumEdges(dm); */ /* UNUSED */
254
255         /* count particles */
256         maxvert = 0;
257         maxpoly = 0;
258         maxloop = 0;
259
260         for (p = 0; p < totpart; p++) {
261                 if (particle_skip(pimd, psys, p))
262                         continue;
263
264                 maxvert += totvert;
265                 maxpoly += totpoly;
266                 maxloop += totloop;
267         }
268
269         psys->lattice = psys_get_lattice(&sim);
270
271         if (psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) {
272                 float min_r[3], max_r[3];
273                 INIT_MINMAX(min_r, max_r);
274                 dm->getMinMax(dm, min_r, max_r);
275                 min_co = min_r[track];
276                 max_co = max_r[track];
277         }
278
279         result = CDDM_from_template(dm, maxvert, 0, 0, maxloop, maxpoly);
280
281         mvert = result->getVertArray(result);
282         orig_mvert = dm->getVertArray(dm);
283
284         mpoly = result->getPolyArray(result);
285         orig_mpoly = dm->getPolyArray(dm);
286         mloop = result->getLoopArray(result);
287         orig_mloop = dm->getLoopArray(dm);
288
289         for (p = 0, p_skip = 0; p < totpart; p++) {
290                 /* skip particle? */
291                 if (particle_skip(pimd, psys, p))
292                         continue;
293
294                 /* set vertices coordinates */
295                 for (k = 0; k < totvert; k++) {
296                         ParticleKey state;
297                         MVert *inMV;
298                         MVert *mv = mvert + p_skip * totvert + k;
299
300                         inMV = orig_mvert + k;
301                         DM_copy_vert_data(dm, result, k, p_skip * totvert + k, 1);
302                         *mv = *inMV;
303
304                         /*change orientation based on object trackflag*/
305                         copy_v3_v3(temp_co, mv->co);
306                         mv->co[axis] = temp_co[track];
307                         mv->co[(axis + 1) % 3] = temp_co[(track + 1) % 3];
308                         mv->co[(axis + 2) % 3] = temp_co[(track + 2) % 3];
309
310                         /* get particle state */
311                         if ((psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) &&
312                                 (pimd->flag & eParticleInstanceFlag_Path))
313                         {
314                                 float ran = 0.0f;
315                                 if (pimd->random_position != 0.0f) {
316                                         BLI_srandom(psys->seed + p);
317                                         ran = pimd->random_position * BLI_frand();
318                                 }
319
320                                 if (pimd->flag & eParticleInstanceFlag_KeepShape) {
321                                         state.time = pimd->position * (1.0f - ran);
322                                 }
323                                 else {
324                                         state.time = (mv->co[axis] - min_co) / (max_co - min_co) * pimd->position * (1.0f - ran);
325
326                                         if (trackneg)
327                                                 state.time = 1.0f - state.time;
328
329                                         mv->co[axis] = 0.0;
330                                 }
331
332                                 psys_get_particle_on_path(&sim, first_particle + p, &state, 1);
333
334                                 normalize_v3(state.vel);
335
336                                 /* TODO: incremental rotations somehow */
337                                 if (state.vel[axis] < -0.9999f || state.vel[axis] > 0.9999f) {
338                                         unit_qt(state.rot);
339                                 }
340                                 else {
341                                         float temp[3] = {0.0f, 0.0f, 0.0f};
342                                         temp[axis] = 1.0f;
343
344                                         cross_v3_v3v3(cross, temp, state.vel);
345
346                                         /* state.vel[axis] is the only component surviving from a dot product with the axis */
347                                         axis_angle_to_quat(state.rot, cross, saacos(state.vel[axis]));
348                                 }
349                         }
350                         else {
351                                 state.time = -1.0;
352                                 psys_get_particle_state(&sim, first_particle + p, &state, 1);
353                         }
354
355                         mul_qt_v3(state.rot, mv->co);
356                         if (pimd->flag & eParticleInstanceFlag_UseSize)
357                                 mul_v3_fl(mv->co, size[p]);
358                         add_v3_v3(mv->co, state.co);
359                 }
360
361                 /* create polys and loops */
362                 for (k = 0; k < totpoly; k++) {
363                         MPoly *inMP = orig_mpoly + k;
364                         MPoly *mp = mpoly + p_skip * totpoly + k;
365
366                         DM_copy_poly_data(dm, result, k, p_skip * totpoly + k, 1);
367                         *mp = *inMP;
368                         mp->loopstart += p_skip * totloop;
369
370                         {
371                                 MLoop *inML = orig_mloop + inMP->loopstart;
372                                 MLoop *ml = mloop + mp->loopstart;
373                                 int j = mp->totloop;
374
375                                 DM_copy_loop_data(dm, result, inMP->loopstart, mp->loopstart, j);
376                                 for (; j; j--, ml++, inML++) {
377                                         ml->v = inML->v + (p_skip * totvert);
378                                 }
379                         }
380                 }
381
382                 p_skip++;
383         }
384
385         CDDM_calc_edges(result);
386
387         if (psys->lattice) {
388                 end_latt_deform(psys->lattice);
389                 psys->lattice = NULL;
390         }
391
392         if (size)
393                 MEM_freeN(size);
394
395         CDDM_calc_normals(result);
396
397         return result;
398 }
399 static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
400                                     struct BMEditMesh *UNUSED(editData),
401                                     DerivedMesh *derivedData)
402 {
403         return applyModifier(md, ob, derivedData, MOD_APPLY_USECACHE);
404 }
405
406 ModifierTypeInfo modifierType_ParticleInstance = {
407         /* name */              "ParticleInstance",
408         /* structName */        "ParticleInstanceModifierData",
409         /* structSize */        sizeof(ParticleInstanceModifierData),
410         /* type */              eModifierTypeType_Constructive,
411         /* flags */             eModifierTypeFlag_AcceptsMesh |
412                                 eModifierTypeFlag_SupportsMapping |
413                                 eModifierTypeFlag_SupportsEditmode |
414                                 eModifierTypeFlag_EnableInEditmode,
415
416         /* copyData */          copyData,
417         /* deformVerts */       NULL,
418         /* deformMatrices */    NULL,
419         /* deformVertsEM */     NULL,
420         /* deformMatricesEM */  NULL,
421         /* applyModifier */     applyModifier,
422         /* applyModifierEM */   applyModifierEM,
423         /* initData */          initData,
424         /* requiredDataMask */  NULL,
425         /* freeData */          NULL,
426         /* isDisabled */        isDisabled,
427         /* updateDepgraph */    updateDepgraph,
428         /* dependsOnTime */     dependsOnTime,
429         /* dependsOnNormals */  NULL,
430         /* foreachObjectLink */ foreachObjectLink,
431         /* foreachIDLink */     NULL,
432         /* foreachTexLink */    NULL,
433 };