merge with/from trunk at r35190
[blender.git] / source / blender / modifiers / intern / MOD_particlesystem.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_particlesystem.c
34  *  \ingroup modifiers
35  */
36
37
38 #include "stddef.h"
39
40 #include "DNA_material_types.h"
41
42 #include "BLI_utildefines.h"
43
44
45 #include "BKE_cdderivedmesh.h"
46 #include "BKE_material.h"
47 #include "BKE_modifier.h"
48 #include "BKE_particle.h"
49
50 #include "MOD_util.h"
51
52
53 static void initData(ModifierData *md) 
54 {
55         ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md;
56         psmd->psys= 0;
57         psmd->dm=0;
58         psmd->totdmvert= psmd->totdmedge= psmd->totdmface= 0;
59 }
60 static void freeData(ModifierData *md)
61 {
62         ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md;
63
64         if(psmd->dm){
65                 psmd->dm->needsFree = 1;
66                 psmd->dm->release(psmd->dm);
67                 psmd->dm=0;
68         }
69
70         /* ED_object_modifier_remove may have freed this first before calling
71          * modifier_free (which calls this function) */
72         if(psmd->psys)
73                 psmd->psys->flag |= PSYS_DELETE;
74 }
75 static void copyData(ModifierData *md, ModifierData *target)
76 {
77         ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md;
78         ParticleSystemModifierData *tpsmd= (ParticleSystemModifierData*) target;
79
80         tpsmd->dm = 0;
81         tpsmd->totdmvert = tpsmd->totdmedge = tpsmd->totdmface = 0;
82         //tpsmd->facepa = 0;
83         tpsmd->flag = psmd->flag;
84         /* need to keep this to recognise a bit later in copy_object */
85         tpsmd->psys = psmd->psys;
86 }
87
88 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
89 {
90         ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md;
91         CustomDataMask dataMask = 0;
92         MTex *mtex;
93         int i;
94
95         if(!psmd->psys->part)
96                 return 0;
97
98         for(i=0; i<MAX_MTEX; i++) {
99                 mtex = psmd->psys->part->mtex[i];
100                 if(mtex && mtex->mapto && (mtex->texco & TEXCO_UV))
101                         dataMask |= CD_MASK_MTFACE;
102         }
103
104         if(psmd->psys->part->tanfac!=0.0)
105                 dataMask |= CD_MASK_MTFACE;
106
107         /* ask for vertexgroups if we need them */
108         for(i=0; i<PSYS_TOT_VG; i++){
109                 if(psmd->psys->vgroup[i]){
110                         dataMask |= CD_MASK_MDEFORMVERT;
111                         break;
112                 }
113         }
114         
115         /* particles only need this if they are after a non deform modifier, and
116         * the modifier stack will only create them in that case. */
117         dataMask |= CD_MASK_ORIGSPACE|CD_MASK_ORIGINDEX;
118
119         dataMask |= CD_MASK_ORCO;
120         
121         return dataMask;
122 }
123
124 /* saves the current emitter state for a particle system and calculates particles */
125 static void deformVerts(ModifierData *md, Object *ob,
126                                                 DerivedMesh *derivedData,
127                                                 float (*vertexCos)[3],
128                                                 int UNUSED(numVerts),
129                                                 int UNUSED(useRenderParams),
130                                                 int UNUSED(isFinalCalc))
131 {
132         DerivedMesh *dm = derivedData;
133         ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md;
134         ParticleSystem * psys=0;
135         int needsFree=0;
136
137         if(ob->particlesystem.first)
138                 psys=psmd->psys;
139         else
140                 return;
141         
142         if(!psys_check_enabled(ob, psys))
143                 return;
144
145         if(dm==0) {
146                 dm= get_dm(ob, NULL, NULL, vertexCos, 1);
147
148                 if(!dm)
149                         return;
150
151                 needsFree= 1;
152         }
153
154         /* clear old dm */
155         if(psmd->dm){
156                 psmd->dm->needsFree = 1;
157                 psmd->dm->release(psmd->dm);
158         }
159         else if(psmd->flag & eParticleSystemFlag_file_loaded) {
160                 /* in file read dm just wasn't saved in file so no need to reset everything */
161                 psmd->flag &= ~eParticleSystemFlag_file_loaded;
162         }
163         else {
164                 /* no dm before, so recalc particles fully */
165                 psys->recalc |= PSYS_RECALC_RESET;
166         }
167
168         /* make new dm */
169         psmd->dm=CDDM_copy(dm, 0);
170         CDDM_apply_vert_coords(psmd->dm, vertexCos);
171         CDDM_calc_normals(psmd->dm);
172
173         if(needsFree){
174                 dm->needsFree = 1;
175                 dm->release(dm);
176         }
177
178         /* protect dm */
179         psmd->dm->needsFree = 0;
180
181         /* report change in mesh structure */
182         if(psmd->dm->getNumVerts(psmd->dm)!=psmd->totdmvert ||
183                   psmd->dm->getNumEdges(psmd->dm)!=psmd->totdmedge ||
184                   psmd->dm->getNumTessFaces(psmd->dm)!=psmd->totdmface){
185
186                 psys->recalc |= PSYS_RECALC_RESET;
187
188                 psmd->totdmvert= psmd->dm->getNumVerts(psmd->dm);
189                 psmd->totdmedge= psmd->dm->getNumEdges(psmd->dm);
190                 psmd->totdmface= psmd->dm->getNumTessFaces(psmd->dm);
191         }
192
193         if(psys) {
194                 psmd->flag &= ~eParticleSystemFlag_psys_updated;
195                 particle_system_update(md->scene, ob, psys);
196                 psmd->flag |= eParticleSystemFlag_psys_updated;
197         }
198 }
199
200 /* disabled particles in editmode for now, until support for proper derivedmesh
201  * updates is coded */
202 #if 0
203 static void deformVertsEM(
204                                 ModifierData *md, Object *ob, EditMesh *editData,
205                                 DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
206 {
207         DerivedMesh *dm = derivedData;
208
209         if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
210
211         deformVerts(md, ob, dm, vertexCos, numVerts);
212
213         if(!derivedData) dm->release(dm);
214 }
215 #endif
216
217
218 ModifierTypeInfo modifierType_ParticleSystem = {
219         /* name */              "ParticleSystem",
220         /* structName */        "ParticleSystemModifierData",
221         /* structSize */        sizeof(ParticleSystemModifierData),
222         /* type */              eModifierTypeType_OnlyDeform,
223         /* flags */             eModifierTypeFlag_AcceptsMesh
224                                                         | eModifierTypeFlag_SupportsMapping
225                                                         | eModifierTypeFlag_UsesPointCache /*
226                                                         | eModifierTypeFlag_SupportsEditmode
227                                                         | eModifierTypeFlag_EnableInEditmode */,
228
229         /* copyData */          copyData,
230         /* deformVerts */       deformVerts,
231         /* deformVertsEM */     0 /* deformVertsEM */ ,
232         /* deformMatrices */    0,
233         /* deformMatricesEM */  0,
234         /* applyModifier */     0,
235         /* applyModifierEM */   0,
236         /* initData */          initData,
237         /* requiredDataMask */  requiredDataMask,
238         /* freeData */          freeData,
239         /* isDisabled */        0,
240         /* updateDepgraph */    0,
241         /* dependsOnTime */     0,
242         /* dependsOnNormals */  0,
243         /* foreachObjectLink */ 0,
244         /* foreachIDLink */     0,
245 };