svn merge ^/trunk/blender -r41226:41227 .
[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                                                 int UNUSED(useRenderParams),
111                                                 int UNUSED(isFinalCalc))
112 {
113         DerivedMesh *dm = derivedData, *result;
114         ParticleInstanceModifierData *pimd= (ParticleInstanceModifierData*) md;
115         ParticleSimulationData sim;
116         ParticleSystem *psys= NULL;
117         ParticleData *pa= NULL, *pars= NULL;
118         MFace *mface, *orig_mface;
119         MVert *mvert, *orig_mvert;
120         int i,totvert, totpart=0, totface, maxvert, maxface, 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         totface=dm->getNumTessFaces(dm);
178
179         maxvert=totvert*totpart;
180         maxface=totface*totpart;
181
182         psys->lattice=psys_get_lattice(&sim);
183
184         if(psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED){
185
186                 float min_r[3], max_r[3];
187                 INIT_MINMAX(min_r, max_r);
188                 dm->getMinMax(dm, min_r, max_r);
189                 min_co=min_r[track];
190                 max_co=max_r[track];
191         }
192
193         result = CDDM_from_template(dm, maxvert,dm->getNumEdges(dm)*totpart,maxface, 0, 0);
194
195         mvert=result->getVertArray(result);
196         orig_mvert=dm->getVertArray(dm);
197
198         for(i=0; i<maxvert; i++){
199                 MVert *inMV;
200                 MVert *mv = mvert + i;
201                 ParticleKey state;
202
203                 inMV = orig_mvert + i%totvert;
204                 DM_copy_vert_data(dm, result, i%totvert, i, 1);
205                 *mv = *inMV;
206
207                 /*change orientation based on object trackflag*/
208                 copy_v3_v3(temp_co, mv->co);
209                 mv->co[axis]=temp_co[track];
210                 mv->co[(axis+1)%3]=temp_co[(track+1)%3];
211                 mv->co[(axis+2)%3]=temp_co[(track+2)%3];
212
213                 if((psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) && pimd->flag & eParticleInstanceFlag_Path){
214                         float ran = 0.0f;
215                         if(pimd->random_position != 0.0f) {
216                                 BLI_srandom(psys->seed + (i/totvert)%totpart);
217                                 ran = pimd->random_position * BLI_frand();
218                         }
219
220                         if(pimd->flag & eParticleInstanceFlag_KeepShape) {
221                                 state.time = pimd->position * (1.0f - ran);
222                         }
223                         else {
224                                 state.time=(mv->co[axis]-min_co)/(max_co-min_co) * pimd->position * (1.0f - ran);
225
226                                 if(trackneg)
227                                         state.time=1.0f-state.time;
228
229                                 mv->co[axis] = 0.0;
230                         }
231
232                         psys_get_particle_on_path(&sim, first_particle + i/totvert, &state,1);
233
234                         normalize_v3(state.vel);
235
236                         /* TODO: incremental rotations somehow */
237                         if(state.vel[axis] < -0.9999f || state.vel[axis] > 0.9999f) {
238                                 state.rot[0] = 1;
239                                 state.rot[1] = state.rot[2] = state.rot[3] = 0.0f;
240                         }
241                         else {
242                                 float temp[3] = {0.0f,0.0f,0.0f};
243                                 temp[axis] = 1.0f;
244
245                                 cross_v3_v3v3(cross, temp, state.vel);
246
247                                 /* state.vel[axis] is the only component surviving from a dot product with the axis */
248                                 axis_angle_to_quat(state.rot,cross,saacos(state.vel[axis]));
249                         }
250
251                 }
252                 else{
253                         state.time=-1.0;
254                         psys_get_particle_state(&sim, first_particle + i/totvert, &state,1);
255                 }
256
257                 mul_qt_v3(state.rot,mv->co);
258                 if(pimd->flag & eParticleInstanceFlag_UseSize)
259                         mul_v3_fl(mv->co, size[i/totvert]);
260                 VECADD(mv->co,mv->co,state.co);
261         }
262
263         mface=result->getTessFaceArray(result);
264         orig_mface=dm->getTessFaceArray(dm);
265
266         for(i=0; i<maxface; i++){
267                 MFace *inMF;
268                 MFace *mf = mface + i;
269
270                 if(pimd->flag & eParticleInstanceFlag_Parents){
271                         if(i/totface>=psys->totpart){
272                                 if(psys->part->childtype==PART_CHILD_PARTICLES)
273                                         pa=psys->particles+(psys->child+i/totface-psys->totpart)->parent;
274                                 else
275                                         pa= NULL;
276                         }
277                         else
278                                 pa=pars+i/totface;
279                 }
280                 else{
281                         if(psys->part->childtype==PART_CHILD_PARTICLES)
282                                 pa=psys->particles+(psys->child+i/totface)->parent;
283                         else
284                                 pa= NULL;
285                 }
286
287                 if(pa){
288                         if(pa->alive==PARS_UNBORN && (pimd->flag&eParticleInstanceFlag_Unborn)==0) continue;
289                         if(pa->alive==PARS_ALIVE && (pimd->flag&eParticleInstanceFlag_Alive)==0) continue;
290                         if(pa->alive==PARS_DEAD && (pimd->flag&eParticleInstanceFlag_Dead)==0) continue;
291                 }
292
293                 inMF = orig_mface + i%totface;
294                 DM_copy_face_data(dm, result, i%totface, i, 1);
295                 *mf = *inMF;
296
297                 mf->v1+=(i/totface)*totvert;
298                 mf->v2+=(i/totface)*totvert;
299                 mf->v3+=(i/totface)*totvert;
300                 if(mf->v4)
301                         mf->v4+=(i/totface)*totvert;
302         }
303
304         CDDM_calc_edges(result);
305         CDDM_calc_normals(result);
306
307         if(psys->lattice){
308                 end_latt_deform(psys->lattice);
309                 psys->lattice= NULL;
310         }
311
312         if(size)
313                 MEM_freeN(size);
314
315         dm = CDDM_copy(result, 1); /*builds ngon faces from tess (mface) faces*/
316         result->needsFree = 1;
317         result->release(result);
318
319         return dm;
320 }
321 static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
322                                                 struct BMEditMesh *UNUSED(editData),
323                                                 DerivedMesh *derivedData)
324 {
325         return applyModifier(md, ob, derivedData, 0, 1);
326 }
327
328
329 ModifierTypeInfo modifierType_ParticleInstance = {
330         /* name */              "ParticleInstance",
331         /* structName */        "ParticleInstanceModifierData",
332         /* structSize */        sizeof(ParticleInstanceModifierData),
333         /* type */              eModifierTypeType_Constructive,
334         /* flags */             eModifierTypeFlag_AcceptsMesh
335                                                         | eModifierTypeFlag_SupportsMapping
336                                                         | eModifierTypeFlag_SupportsEditmode
337                                                         | eModifierTypeFlag_EnableInEditmode,
338
339         /* copyData */          copyData,
340         /* deformVerts */       NULL,
341         /* deformMatrices */    NULL,
342         /* deformVertsEM */     NULL,
343         /* deformMatricesEM */  NULL,
344         /* applyModifier */     applyModifier,
345         /* applyModifierEM */   applyModifierEM,
346         /* initData */          initData,
347         /* requiredDataMask */  NULL,
348         /* freeData */          NULL,
349         /* isDisabled */        NULL,
350         /* updateDepgraph */    updateDepgraph,
351         /* dependsOnTime */     dependsOnTime,
352         /* dependsOnNormals */  NULL,
353         /* foreachObjectLink */ foreachObjectLink,
354         /* foreachIDLink */     NULL,
355         /* foreachTexLink */    NULL,
356 };