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