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