c034832bfb41edccdb45166e7cb1981ef9f62162
[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 static void updateDepgraph(ModifierData *md, DagForest *forest,
85                            struct Scene *UNUSED(scene),
86                            Object *UNUSED(ob),
87                            DagNode *obNode)
88 {
89         ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
90
91         if (pimd->ob) {
92                 DagNode *curNode = dag_get_node(forest, pimd->ob);
93
94                 dag_add_relation(forest, curNode, obNode,
95                                  DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
96                                  "Particle Instance Modifier");
97         }
98 }
99
100 static void foreachObjectLink(ModifierData *md, Object *ob,
101                               ObjectWalkFunc walk, void *userData)
102 {
103         ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
104
105         walk(userData, ob, &pimd->ob);
106 }
107
108 static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
109                                   DerivedMesh *derivedData,
110                                   ModifierApplyFlag UNUSED(flag))
111 {
112         DerivedMesh *dm = derivedData, *result;
113         ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
114         ParticleSimulationData sim;
115         ParticleSystem *psys = NULL;
116         ParticleData *pa = NULL, *pars = NULL;
117         MPoly *mpoly, *orig_mpoly;
118         MLoop *mloop, *orig_mloop;
119         MVert *mvert, *orig_mvert;
120         int i, totvert, totpoly, totloop, maxvert, maxpoly, maxloop, totpart = 0, first_particle = 0;
121         short track = ob->trackflag % 3, trackneg, axis = pimd->axis;
122         float max_co = 0.0, min_co = 0.0, temp_co[3], cross[3];
123         float *size = NULL;
124
125         trackneg = ((ob->trackflag > 2) ? 1 : 0);
126
127         if (pimd->ob == ob) {
128                 pimd->ob = NULL;
129                 return derivedData;
130         }
131
132         if (pimd->ob) {
133                 psys = BLI_findlink(&pimd->ob->particlesystem, pimd->psys - 1);
134                 if (psys == NULL || psys->totpart == 0)
135                         return derivedData;
136         }
137         else return derivedData;
138
139         if (pimd->flag & eParticleInstanceFlag_Parents)
140                 totpart += psys->totpart;
141         if (pimd->flag & eParticleInstanceFlag_Children) {
142                 if (totpart == 0)
143                         first_particle = psys->totpart;
144                 totpart += psys->totchild;
145         }
146
147         if (totpart == 0)
148                 return derivedData;
149
150         sim.scene = md->scene;
151         sim.ob = pimd->ob;
152         sim.psys = psys;
153         sim.psmd = psys_get_modifier(pimd->ob, psys);
154
155         if (pimd->flag & eParticleInstanceFlag_UseSize) {
156                 int p;
157                 float *si;
158                 si = size = MEM_callocN(totpart * sizeof(float), "particle size array");
159
160                 if (pimd->flag & eParticleInstanceFlag_Parents) {
161                         for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++, si++)
162                                 *si = pa->size;
163                 }
164
165                 if (pimd->flag & eParticleInstanceFlag_Children) {
166                         ChildParticle *cpa = psys->child;
167
168                         for (p = 0; p < psys->totchild; p++, cpa++, si++) {
169                                 *si = psys_get_child_size(psys, cpa, 0.0f, NULL);
170                         }
171                 }
172         }
173
174         pars = psys->particles;
175
176         totvert = dm->getNumVerts(dm);
177         totpoly = dm->getNumPolys(dm);
178         totloop = dm->getNumLoops(dm);
179
180         maxvert = totvert * totpart;
181         maxpoly = totpoly * totpart;
182         maxloop = totloop * totpart;
183
184         psys->lattice = psys_get_lattice(&sim);
185
186         if (psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) {
187                 float min_r[3], max_r[3];
188                 INIT_MINMAX(min_r, max_r);
189                 dm->getMinMax(dm, min_r, max_r);
190                 min_co = min_r[track];
191                 max_co = max_r[track];
192         }
193
194         result = CDDM_from_template(dm, maxvert, dm->getNumEdges(dm) * totpart, 0, maxloop, maxpoly);
195
196         mvert = result->getVertArray(result);
197         orig_mvert = dm->getVertArray(dm);
198
199         for (i = 0; i < maxvert; i++) {
200                 MVert *inMV;
201                 MVert *mv = mvert + i;
202                 ParticleKey state;
203
204                 inMV = orig_mvert + i % totvert;
205                 DM_copy_vert_data(dm, result, i % totvert, i, 1);
206                 *mv = *inMV;
207
208                 /*change orientation based on object trackflag*/
209                 copy_v3_v3(temp_co, mv->co);
210                 mv->co[axis] = temp_co[track];
211                 mv->co[(axis + 1) % 3] = temp_co[(track + 1) % 3];
212                 mv->co[(axis + 2) % 3] = temp_co[(track + 2) % 3];
213
214                 if ((psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) &&
215                     (pimd->flag & eParticleInstanceFlag_Path))
216                 {
217                         float ran = 0.0f;
218                         if (pimd->random_position != 0.0f) {
219                                 BLI_srandom(psys->seed + (i / totvert) % totpart);
220                                 ran = pimd->random_position * BLI_frand();
221                         }
222
223                         if (pimd->flag & eParticleInstanceFlag_KeepShape) {
224                                 state.time = pimd->position * (1.0f - ran);
225                         }
226                         else {
227                                 state.time = (mv->co[axis] - min_co) / (max_co - min_co) * pimd->position * (1.0f - ran);
228
229                                 if (trackneg)
230                                         state.time = 1.0f - state.time;
231
232                                 mv->co[axis] = 0.0;
233                         }
234
235                         psys_get_particle_on_path(&sim, first_particle + i / totvert, &state, 1);
236
237                         normalize_v3(state.vel);
238
239                         /* TODO: incremental rotations somehow */
240                         if (state.vel[axis] < -0.9999f || state.vel[axis] > 0.9999f) {
241                                 unit_qt(state.rot);
242                         }
243                         else {
244                                 float temp[3] = {0.0f, 0.0f, 0.0f};
245                                 temp[axis] = 1.0f;
246
247                                 cross_v3_v3v3(cross, temp, state.vel);
248
249                                 /* state.vel[axis] is the only component surviving from a dot product with the axis */
250                                 axis_angle_to_quat(state.rot, cross, saacos(state.vel[axis]));
251                         }
252                 }
253                 else {
254                         state.time = -1.0;
255                         psys_get_particle_state(&sim, first_particle + i / totvert, &state, 1);
256                 }
257
258                 mul_qt_v3(state.rot, mv->co);
259                 if (pimd->flag & eParticleInstanceFlag_UseSize)
260                         mul_v3_fl(mv->co, size[i / totvert]);
261                 add_v3_v3(mv->co, state.co);
262         }
263
264         mpoly = result->getPolyArray(result);
265         orig_mpoly = dm->getPolyArray(dm);
266         mloop = result->getLoopArray(result);
267         orig_mloop = dm->getLoopArray(dm);
268
269         for (i = 0; i < maxpoly; i++) {
270                 MPoly *inMP = orig_mpoly + i % totpoly;
271                 MPoly *mp = mpoly + i;
272
273                 if (pimd->flag & eParticleInstanceFlag_Parents) {
274                         if (i / totpoly >= psys->totpart) {
275                                 if (psys->part->childtype == PART_CHILD_PARTICLES) {
276                                         pa = psys->particles + (psys->child + i / totpoly - psys->totpart)->parent;
277                                 }
278                                 else {
279                                         pa = NULL;
280                                 }
281                         }
282                         else {
283                                 pa = pars + i / totpoly;
284                         }
285                 }
286                 else {
287                         if (psys->part->childtype == PART_CHILD_PARTICLES) {
288                                 pa = psys->particles + (psys->child + i / totpoly)->parent;
289                         }
290                         else {
291                                 pa = NULL;
292                         }
293                 }
294
295                 if (pa) {
296                         if (pa->alive == PARS_UNBORN && (pimd->flag & eParticleInstanceFlag_Unborn) == 0) continue;
297                         if (pa->alive == PARS_ALIVE && (pimd->flag & eParticleInstanceFlag_Alive) == 0) continue;
298                         if (pa->alive == PARS_DEAD && (pimd->flag & eParticleInstanceFlag_Dead) == 0) continue;
299                 }
300
301                 DM_copy_poly_data(dm, result, i % totpoly, i, 1);
302                 *mp = *inMP;
303                 mp->loopstart += (i / totpoly) * totloop;
304
305                 {
306                         MLoop *inML = orig_mloop + inMP->loopstart;
307                         MLoop *ml = mloop + mp->loopstart;
308                         int j = mp->totloop;
309
310                         DM_copy_loop_data(dm, result, inMP->loopstart, mp->loopstart, j);
311                         for (; j; j--, ml++, inML++) {
312                                 ml->v = inML->v + ((i / totpoly) * totvert);
313                         }
314                 }
315         }
316
317         CDDM_calc_edges(result);
318
319         if (psys->lattice) {
320                 end_latt_deform(psys->lattice);
321                 psys->lattice = NULL;
322         }
323
324         if (size)
325                 MEM_freeN(size);
326
327         CDDM_calc_normals(result);
328
329         return result;
330 }
331 static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
332                                     struct BMEditMesh *UNUSED(editData),
333                                     DerivedMesh *derivedData)
334 {
335         return applyModifier(md, ob, derivedData, MOD_APPLY_USECACHE);
336 }
337
338
339 ModifierTypeInfo modifierType_ParticleInstance = {
340         /* name */ "ParticleInstance",
341         /* structName */ "ParticleInstanceModifierData",
342         /* structSize */ sizeof(ParticleInstanceModifierData),
343         /* type */ eModifierTypeType_Constructive,
344         /* flags */ eModifierTypeFlag_AcceptsMesh |
345         eModifierTypeFlag_SupportsMapping |
346         eModifierTypeFlag_SupportsEditmode |
347         eModifierTypeFlag_EnableInEditmode,
348
349         /* copyData */ copyData,
350         /* deformVerts */ NULL,
351         /* deformMatrices */ NULL,
352         /* deformVertsEM */ NULL,
353         /* deformMatricesEM */ NULL,
354         /* applyModifier */ applyModifier,
355         /* applyModifierEM */ applyModifierEM,
356         /* initData */ initData,
357         /* requiredDataMask */ NULL,
358         /* freeData */ NULL,
359         /* isDisabled */ NULL,
360         /* updateDepgraph */ updateDepgraph,
361         /* dependsOnTime */ dependsOnTime,
362         /* dependsOnNormals */ NULL,
363         /* foreachObjectLink */ foreachObjectLink,
364         /* foreachIDLink */ NULL,
365         /* foreachTexLink */ NULL,
366 };