545003b15761bff1c5d551a6dc6bda08f735795d
[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 #include "DNA_meshdata_types.h"
34
35 #include "BLI_math.h"
36 #include "BLI_listbase.h"
37 #include "BLI_rand.h"
38
39 #include "BKE_cdderivedmesh.h"
40 #include "BKE_lattice.h"
41 #include "BKE_modifier.h"
42 #include "BKE_particle.h"
43 #include "BKE_pointcache.h"
44 #include "BKE_utildefines.h"
45
46 #include "depsgraph_private.h"
47
48
49 static void initData(ModifierData *md)
50 {
51         ParticleInstanceModifierData *pimd= (ParticleInstanceModifierData*) md;
52
53         pimd->flag = eParticleInstanceFlag_Parents|eParticleInstanceFlag_Unborn|
54                         eParticleInstanceFlag_Alive|eParticleInstanceFlag_Dead;
55         pimd->psys = 1;
56         pimd->position = 1.0f;
57         pimd->axis = 2;
58
59 }
60 static void copyData(ModifierData *md, ModifierData *target)
61 {
62         ParticleInstanceModifierData *pimd= (ParticleInstanceModifierData*) md;
63         ParticleInstanceModifierData *tpimd= (ParticleInstanceModifierData*) target;
64
65         tpimd->ob = pimd->ob;
66         tpimd->psys = pimd->psys;
67         tpimd->flag = pimd->flag;
68         tpimd->axis = pimd->axis;
69         tpimd->position = pimd->position;
70         tpimd->random_position = pimd->random_position;
71 }
72
73 static int dependsOnTime(ModifierData *md)
74 {
75         return 0;
76 }
77 static void updateDepgraph(ModifierData *md, DagForest *forest,
78                  struct Scene *scene,Object *ob, DagNode *obNode)
79 {
80         ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData*) md;
81
82         if (pimd->ob) {
83                 DagNode *curNode = dag_get_node(forest, pimd->ob);
84
85                 dag_add_relation(forest, curNode, obNode,
86                                  DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
87                                  "Particle Instance Modifier");
88         }
89 }
90
91 static void foreachObjectLink(ModifierData *md, Object *ob,
92                 ObjectWalkFunc walk, void *userData)
93 {
94         ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData*) md;
95
96         walk(userData, ob, &pimd->ob);
97 }
98
99 static DerivedMesh * applyModifier(
100                 ModifierData *md, Object *ob, DerivedMesh *derivedData,
101   int useRenderParams, int isFinalCalc)
102 {
103         DerivedMesh *dm = derivedData, *result;
104         ParticleInstanceModifierData *pimd= (ParticleInstanceModifierData*) md;
105         ParticleSimulationData sim;
106         ParticleSystem * psys=0;
107         ParticleData *pa=0, *pars=0;
108         MFace *mface, *orig_mface;
109         MVert *mvert, *orig_mvert;
110         int i,totvert, totpart=0, totface, maxvert, maxface, first_particle=0;
111         short track=ob->trackflag%3, trackneg, axis = pimd->axis;
112         float max_co=0.0, min_co=0.0, temp_co[3], cross[3];
113         float *size=NULL;
114
115         trackneg=((ob->trackflag>2)?1:0);
116
117         if(pimd->ob==ob){
118                 pimd->ob=0;
119                 return derivedData;
120         }
121
122         if(pimd->ob){
123                 psys = BLI_findlink(&pimd->ob->particlesystem,pimd->psys-1);
124                 if(psys==0 || psys->totpart==0)
125                         return derivedData;
126         }
127         else return derivedData;
128
129         if(pimd->flag & eParticleInstanceFlag_Parents)
130                 totpart+=psys->totpart;
131         if(pimd->flag & eParticleInstanceFlag_Children){
132                 if(totpart==0)
133                         first_particle=psys->totpart;
134                 totpart+=psys->totchild;
135         }
136
137         if(totpart==0)
138                 return derivedData;
139
140         sim.scene = md->scene;
141         sim.ob = pimd->ob;
142         sim.psys = psys;
143         sim.psmd = psys_get_modifier(pimd->ob, psys);
144
145         if(pimd->flag & eParticleInstanceFlag_UseSize) {
146                 int p;
147                 float *si;
148                 si = size = MEM_callocN(totpart * sizeof(float), "particle size array");
149
150                 if(pimd->flag & eParticleInstanceFlag_Parents) {
151                         for(p=0, pa= psys->particles; p<psys->totpart; p++, pa++, si++)
152                                 *si = pa->size;
153                 }
154
155                 if(pimd->flag & eParticleInstanceFlag_Children) {
156                         ChildParticle *cpa = psys->child;
157
158                         for(p=0; p<psys->totchild; p++, cpa++, si++) {
159                                 *si = psys_get_child_size(psys, cpa, 0.0f, NULL);
160                         }
161                 }
162         }
163
164         pars=psys->particles;
165
166         totvert=dm->getNumVerts(dm);
167         totface=dm->getNumFaces(dm);
168
169         maxvert=totvert*totpart;
170         maxface=totface*totpart;
171
172         psys->lattice=psys_get_lattice(&sim);
173
174         if(psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED){
175
176                 float min_r[3], max_r[3];
177                 INIT_MINMAX(min_r, max_r);
178                 dm->getMinMax(dm, min_r, max_r);
179                 min_co=min_r[track];
180                 max_co=max_r[track];
181         }
182
183         result = CDDM_from_template(dm, maxvert,dm->getNumEdges(dm)*totpart,maxface);
184
185         mvert=result->getVertArray(result);
186         orig_mvert=dm->getVertArray(dm);
187
188         for(i=0; i<maxvert; i++){
189                 MVert *inMV;
190                 MVert *mv = mvert + i;
191                 ParticleKey state;
192
193                 inMV = orig_mvert + i%totvert;
194                 DM_copy_vert_data(dm, result, i%totvert, i, 1);
195                 *mv = *inMV;
196
197                 /*change orientation based on object trackflag*/
198                 copy_v3_v3(temp_co, mv->co);
199                 mv->co[axis]=temp_co[track];
200                 mv->co[(axis+1)%3]=temp_co[(track+1)%3];
201                 mv->co[(axis+2)%3]=temp_co[(track+2)%3];
202
203                 if((psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) && pimd->flag & eParticleInstanceFlag_Path){
204                         float ran = 0.0f;
205                         if(pimd->random_position != 0.0f) {
206                                 BLI_srandom(psys->seed + (i/totvert)%totpart);
207                                 ran = pimd->random_position * BLI_frand();
208                         }
209
210                         if(pimd->flag & eParticleInstanceFlag_KeepShape) {
211                                 state.time = pimd->position * (1.0f - ran);
212                         }
213                         else {
214                                 state.time=(mv->co[axis]-min_co)/(max_co-min_co) * pimd->position * (1.0f - ran);
215
216                                 if(trackneg)
217                                         state.time=1.0f-state.time;
218
219                                 mv->co[axis] = 0.0;
220                         }
221
222                         psys_get_particle_on_path(&sim, first_particle + i/totvert, &state,1);
223
224                         normalize_v3(state.vel);
225
226                         /* TODO: incremental rotations somehow */
227                         if(state.vel[axis] < -0.9999 || state.vel[axis] > 0.9999) {
228                                 state.rot[0] = 1;
229                                 state.rot[1] = state.rot[2] = state.rot[3] = 0.0f;
230                         }
231                         else {
232                                 float temp[3] = {0.0f,0.0f,0.0f};
233                                 temp[axis] = 1.0f;
234
235                                 cross_v3_v3v3(cross, temp, state.vel);
236
237                                 /* state.vel[axis] is the only component surviving from a dot product with the axis */
238                                 axis_angle_to_quat(state.rot,cross,saacos(state.vel[axis]));
239                         }
240
241                 }
242                 else{
243                         state.time=-1.0;
244                         psys_get_particle_state(&sim, first_particle + i/totvert, &state,1);
245                 }
246
247                 mul_qt_v3(state.rot,mv->co);
248                 if(pimd->flag & eParticleInstanceFlag_UseSize)
249                         mul_v3_fl(mv->co, size[i/totvert]);
250                 VECADD(mv->co,mv->co,state.co);
251         }
252
253         mface=result->getFaceArray(result);
254         orig_mface=dm->getFaceArray(dm);
255
256         for(i=0; i<maxface; i++){
257                 MFace *inMF;
258                 MFace *mf = mface + i;
259
260                 if(pimd->flag & eParticleInstanceFlag_Parents){
261                         if(i/totface>=psys->totpart){
262                                 if(psys->part->childtype==PART_CHILD_PARTICLES)
263                                         pa=psys->particles+(psys->child+i/totface-psys->totpart)->parent;
264                                 else
265                                         pa=0;
266                         }
267                         else
268                                 pa=pars+i/totface;
269                 }
270                 else{
271                         if(psys->part->childtype==PART_CHILD_PARTICLES)
272                                 pa=psys->particles+(psys->child+i/totface)->parent;
273                         else
274                                 pa=0;
275                 }
276
277                 if(pa){
278                         if(pa->alive==PARS_UNBORN && (pimd->flag&eParticleInstanceFlag_Unborn)==0) continue;
279                         if(pa->alive==PARS_ALIVE && (pimd->flag&eParticleInstanceFlag_Alive)==0) continue;
280                         if(pa->alive==PARS_DEAD && (pimd->flag&eParticleInstanceFlag_Dead)==0) continue;
281                 }
282
283                 inMF = orig_mface + i%totface;
284                 DM_copy_face_data(dm, result, i%totface, i, 1);
285                 *mf = *inMF;
286
287                 mf->v1+=(i/totface)*totvert;
288                 mf->v2+=(i/totface)*totvert;
289                 mf->v3+=(i/totface)*totvert;
290                 if(mf->v4)
291                         mf->v4+=(i/totface)*totvert;
292         }
293
294         CDDM_calc_edges(result);
295         CDDM_calc_normals(result);
296
297         if(psys->lattice){
298                 end_latt_deform(psys->lattice);
299                 psys->lattice= NULL;
300         }
301
302         if(size)
303                 MEM_freeN(size);
304
305         return result;
306 }
307 static DerivedMesh *applyModifierEM(
308                 ModifierData *md, Object *ob, struct EditMesh *editData,
309   DerivedMesh *derivedData)
310 {
311         return applyModifier(md, ob, derivedData, 0, 1);
312 }
313
314
315 ModifierTypeInfo modifierType_ParticleInstance = {
316         /* name */              "ParticleInstance",
317         /* structName */        "ParticleInstanceModifierData",
318         /* structSize */        sizeof(ParticleInstanceModifierData),
319         /* type */              eModifierTypeType_Constructive,
320         /* flags */             eModifierTypeFlag_AcceptsMesh |
321                                                         eModifierTypeFlag_SupportsMapping |
322                                                         eModifierTypeFlag_SupportsEditmode |
323                                                         eModifierTypeFlag_EnableInEditmode,
324
325         /* copyData */          copyData,
326         /* deformVerts */       0,
327         /* deformVertsEM */     0,
328         /* deformMatricesEM */  0,
329         /* applyModifier */     applyModifier,
330         /* applyModifierEM */   applyModifierEM,
331         /* initData */          initData,
332         /* requiredDataMask */  0,
333         /* freeData */          0,
334         /* isDisabled */        0,
335         /* updateDepgraph */    updateDepgraph,
336         /* dependsOnTime */     dependsOnTime,
337         /* foreachObjectLink */ foreachObjectLink,
338         /* foreachIDLink */     0,
339 };