svn merge -r39286:39385 https://svn.blender.org/svnroot/bf-blender/trunk/blender
[blender.git] / source / blender / modifiers / intern / MOD_particleinstance.c
1 /*
2 * $Id$
3 *
4 * ***** BEGIN GPL LICENSE BLOCK *****
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software  Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 *
20 * The Original Code is Copyright (C) 2005 by the Blender Foundation.
21 * All rights reserved.
22 *
23 * Contributor(s): Daniel Dunbar
24 *                 Ton Roosendaal,
25 *                 Ben Batt,
26 *                 Brecht Van Lommel,
27 *                 Campbell Barton
28 *
29 * ***** END GPL LICENSE BLOCK *****
30 *
31 */
32
33 /** \file blender/modifiers/intern/MOD_particleinstance.c
34  *  \ingroup modifiers
35  */
36
37
38 #include "DNA_meshdata_types.h"
39
40 #include "MEM_guardedalloc.h"
41
42 #include "BLI_math.h"
43 #include "BLI_listbase.h"
44 #include "BLI_rand.h"
45 #include "BLI_utildefines.h"
46
47 #include "BKE_cdderivedmesh.h"
48 #include "BKE_lattice.h"
49 #include "BKE_modifier.h"
50 #include "BKE_particle.h"
51 #include "BKE_pointcache.h"
52
53 #include "MOD_util.h"
54
55 #include "depsgraph_private.h"
56
57
58 static void initData(ModifierData *md)
59 {
60         ParticleInstanceModifierData *pimd= (ParticleInstanceModifierData*) md;
61
62         pimd->flag = eParticleInstanceFlag_Parents|eParticleInstanceFlag_Unborn|
63                         eParticleInstanceFlag_Alive|eParticleInstanceFlag_Dead;
64         pimd->psys = 1;
65         pimd->position = 1.0f;
66         pimd->axis = 2;
67
68 }
69 static void copyData(ModifierData *md, ModifierData *target)
70 {
71         ParticleInstanceModifierData *pimd= (ParticleInstanceModifierData*) md;
72         ParticleInstanceModifierData *tpimd= (ParticleInstanceModifierData*) target;
73
74         tpimd->ob = pimd->ob;
75         tpimd->psys = pimd->psys;
76         tpimd->flag = pimd->flag;
77         tpimd->axis = pimd->axis;
78         tpimd->position = pimd->position;
79         tpimd->random_position = pimd->random_position;
80 }
81
82 static int dependsOnTime(ModifierData *UNUSED(md))
83 {
84         return 0;
85 }
86 static void updateDepgraph(ModifierData *md, DagForest *forest,
87                                                 struct Scene *UNUSED(scene),
88                                                 Object *UNUSED(ob),
89                                                 DagNode *obNode)
90 {
91         ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData*) md;
92
93         if (pimd->ob) {
94                 DagNode *curNode = dag_get_node(forest, pimd->ob);
95
96                 dag_add_relation(forest, curNode, obNode,
97                                  DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
98                                  "Particle Instance Modifier");
99         }
100 }
101
102 static void foreachObjectLink(ModifierData *md, Object *ob,
103                 ObjectWalkFunc walk, void *userData)
104 {
105         ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData*) md;
106
107         walk(userData, ob, &pimd->ob);
108 }
109
110 static DerivedMesh * applyModifier(ModifierData *md, Object *ob,
111                                                 DerivedMesh *derivedData,
112                                                 int UNUSED(useRenderParams),
113                                                 int UNUSED(isFinalCalc))
114 {
115         DerivedMesh *dm = derivedData, *result;
116         ParticleInstanceModifierData *pimd= (ParticleInstanceModifierData*) md;
117         ParticleSimulationData sim;
118         ParticleSystem *psys= NULL;
119         ParticleData *pa= NULL, *pars= NULL;
120         MFace *mface, *orig_mface;
121         MVert *mvert, *orig_mvert;
122         int i,totvert, totpart=0, totface, maxvert, maxface, first_particle=0;
123         short track=ob->trackflag%3, trackneg, axis = pimd->axis;
124         float max_co=0.0, min_co=0.0, temp_co[3], cross[3];
125         float *size=NULL;
126
127         trackneg=((ob->trackflag>2)?1:0);
128
129         if(pimd->ob==ob){
130                 pimd->ob= NULL;
131                 return derivedData;
132         }
133
134         if(pimd->ob){
135                 psys = BLI_findlink(&pimd->ob->particlesystem,pimd->psys-1);
136                 if(psys==NULL || psys->totpart==0)
137                         return derivedData;
138         }
139         else return derivedData;
140
141         if(pimd->flag & eParticleInstanceFlag_Parents)
142                 totpart+=psys->totpart;
143         if(pimd->flag & eParticleInstanceFlag_Children){
144                 if(totpart==0)
145                         first_particle=psys->totpart;
146                 totpart+=psys->totchild;
147         }
148
149         if(totpart==0)
150                 return derivedData;
151
152         sim.scene = md->scene;
153         sim.ob = pimd->ob;
154         sim.psys = psys;
155         sim.psmd = psys_get_modifier(pimd->ob, psys);
156
157         if(pimd->flag & eParticleInstanceFlag_UseSize) {
158                 int p;
159                 float *si;
160                 si = size = MEM_callocN(totpart * sizeof(float), "particle size array");
161
162                 if(pimd->flag & eParticleInstanceFlag_Parents) {
163                         for(p=0, pa= psys->particles; p<psys->totpart; p++, pa++, si++)
164                                 *si = pa->size;
165                 }
166
167                 if(pimd->flag & eParticleInstanceFlag_Children) {
168                         ChildParticle *cpa = psys->child;
169
170                         for(p=0; p<psys->totchild; p++, cpa++, si++) {
171                                 *si = psys_get_child_size(psys, cpa, 0.0f, NULL);
172                         }
173                 }
174         }
175
176         pars=psys->particles;
177
178         totvert=dm->getNumVerts(dm);
179         totface=dm->getNumTessFaces(dm);
180
181         maxvert=totvert*totpart;
182         maxface=totface*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
188                 float min_r[3], max_r[3];
189                 INIT_MINMAX(min_r, max_r);
190                 dm->getMinMax(dm, min_r, max_r);
191                 min_co=min_r[track];
192                 max_co=max_r[track];
193         }
194
195         result = CDDM_from_template(dm, maxvert,dm->getNumEdges(dm)*totpart,maxface, 0, 0);
196
197         mvert=result->getVertArray(result);
198         orig_mvert=dm->getVertArray(dm);
199
200         for(i=0; i<maxvert; i++){
201                 MVert *inMV;
202                 MVert *mv = mvert + i;
203                 ParticleKey state;
204
205                 inMV = orig_mvert + i%totvert;
206                 DM_copy_vert_data(dm, result, i%totvert, i, 1);
207                 *mv = *inMV;
208
209                 /*change orientation based on object trackflag*/
210                 copy_v3_v3(temp_co, mv->co);
211                 mv->co[axis]=temp_co[track];
212                 mv->co[(axis+1)%3]=temp_co[(track+1)%3];
213                 mv->co[(axis+2)%3]=temp_co[(track+2)%3];
214
215                 if((psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) && pimd->flag & eParticleInstanceFlag_Path){
216                         float ran = 0.0f;
217                         if(pimd->random_position != 0.0f) {
218                                 BLI_srandom(psys->seed + (i/totvert)%totpart);
219                                 ran = pimd->random_position * BLI_frand();
220                         }
221
222                         if(pimd->flag & eParticleInstanceFlag_KeepShape) {
223                                 state.time = pimd->position * (1.0f - ran);
224                         }
225                         else {
226                                 state.time=(mv->co[axis]-min_co)/(max_co-min_co) * pimd->position * (1.0f - ran);
227
228                                 if(trackneg)
229                                         state.time=1.0f-state.time;
230
231                                 mv->co[axis] = 0.0;
232                         }
233
234                         psys_get_particle_on_path(&sim, first_particle + i/totvert, &state,1);
235
236                         normalize_v3(state.vel);
237
238                         /* TODO: incremental rotations somehow */
239                         if(state.vel[axis] < -0.9999f || state.vel[axis] > 0.9999f) {
240                                 state.rot[0] = 1;
241                                 state.rot[1] = state.rot[2] = state.rot[3] = 0.0f;
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                 }
254                 else{
255                         state.time=-1.0;
256                         psys_get_particle_state(&sim, first_particle + i/totvert, &state,1);
257                 }
258
259                 mul_qt_v3(state.rot,mv->co);
260                 if(pimd->flag & eParticleInstanceFlag_UseSize)
261                         mul_v3_fl(mv->co, size[i/totvert]);
262                 VECADD(mv->co,mv->co,state.co);
263         }
264
265         mface=result->getTessFaceArray(result);
266         orig_mface=dm->getTessFaceArray(dm);
267
268         for(i=0; i<maxface; i++){
269                 MFace *inMF;
270                 MFace *mf = mface + i;
271
272                 if(pimd->flag & eParticleInstanceFlag_Parents){
273                         if(i/totface>=psys->totpart){
274                                 if(psys->part->childtype==PART_CHILD_PARTICLES)
275                                         pa=psys->particles+(psys->child+i/totface-psys->totpart)->parent;
276                                 else
277                                         pa= NULL;
278                         }
279                         else
280                                 pa=pars+i/totface;
281                 }
282                 else{
283                         if(psys->part->childtype==PART_CHILD_PARTICLES)
284                                 pa=psys->particles+(psys->child+i/totface)->parent;
285                         else
286                                 pa= NULL;
287                 }
288
289                 if(pa){
290                         if(pa->alive==PARS_UNBORN && (pimd->flag&eParticleInstanceFlag_Unborn)==0) continue;
291                         if(pa->alive==PARS_ALIVE && (pimd->flag&eParticleInstanceFlag_Alive)==0) continue;
292                         if(pa->alive==PARS_DEAD && (pimd->flag&eParticleInstanceFlag_Dead)==0) continue;
293                 }
294
295                 inMF = orig_mface + i%totface;
296                 DM_copy_face_data(dm, result, i%totface, i, 1);
297                 *mf = *inMF;
298
299                 mf->v1+=(i/totface)*totvert;
300                 mf->v2+=(i/totface)*totvert;
301                 mf->v3+=(i/totface)*totvert;
302                 if(mf->v4)
303                         mf->v4+=(i/totface)*totvert;
304         }
305
306         CDDM_calc_edges(result);
307         CDDM_calc_normals(result);
308
309         if(psys->lattice){
310                 end_latt_deform(psys->lattice);
311                 psys->lattice= NULL;
312         }
313
314         if(size)
315                 MEM_freeN(size);
316
317         dm = CDDM_copy(result, 1); /*builds ngon faces from tess (mface) faces*/
318         result->needsFree = 1;
319         result->release(result);
320
321         return dm;
322 }
323 static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
324                                                 struct BMEditMesh *UNUSED(editData),
325                                                 DerivedMesh *derivedData)
326 {
327         return applyModifier(md, ob, derivedData, 0, 1);
328 }
329
330
331 ModifierTypeInfo modifierType_ParticleInstance = {
332         /* name */              "ParticleInstance",
333         /* structName */        "ParticleInstanceModifierData",
334         /* structSize */        sizeof(ParticleInstanceModifierData),
335         /* type */              eModifierTypeType_Constructive,
336         /* flags */             eModifierTypeFlag_AcceptsMesh
337                                                         | eModifierTypeFlag_SupportsMapping
338                                                         | eModifierTypeFlag_SupportsEditmode
339                                                         | eModifierTypeFlag_EnableInEditmode,
340
341         /* copyData */          copyData,
342         /* deformVerts */       NULL,
343         /* deformMatrices */    NULL,
344         /* deformVertsEM */     NULL,
345         /* deformMatricesEM */  NULL,
346         /* applyModifier */     applyModifier,
347         /* applyModifierEM */   applyModifierEM,
348         /* initData */          initData,
349         /* requiredDataMask */  NULL,
350         /* freeData */          NULL,
351         /* isDisabled */        NULL,
352         /* updateDepgraph */    updateDepgraph,
353         /* dependsOnTime */     dependsOnTime,
354         /* dependsOnNormals */  NULL,
355         /* foreachObjectLink */ foreachObjectLink,
356         /* foreachIDLink */     NULL,
357         /* foreachTexLink */    NULL,
358 };