code cleanup: make bmesh operator names more consistant since python has access to...
[blender.git] / source / blender / modifiers / intern / MOD_particlesystem.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_particlesystem.c
32  *  \ingroup modifiers
33  */
34
35
36 #include <stddef.h>
37
38 #include "DNA_material_types.h"
39
40 #include "BLI_utildefines.h"
41
42
43 #include "BKE_cdderivedmesh.h"
44 #include "BKE_material.h"
45 #include "BKE_modifier.h"
46 #include "BKE_particle.h"
47 #include "BKE_scene.h"
48
49 #include "MOD_util.h"
50
51
52 static void initData(ModifierData *md) 
53 {
54         ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
55         psmd->psys = NULL;
56         psmd->dm = NULL;
57         psmd->totdmvert = psmd->totdmedge = psmd->totdmface = 0;
58 }
59 static void freeData(ModifierData *md)
60 {
61         ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
62
63         if (psmd->dm) {
64                 psmd->dm->needsFree = 1;
65                 psmd->dm->release(psmd->dm);
66                 psmd->dm = NULL;
67         }
68
69         /* ED_object_modifier_remove may have freed this first before calling
70          * modifier_free (which calls this function) */
71         if (psmd->psys)
72                 psmd->psys->flag |= PSYS_DELETE;
73 }
74 static void copyData(ModifierData *md, ModifierData *target)
75 {
76         ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
77         ParticleSystemModifierData *tpsmd = (ParticleSystemModifierData *) target;
78
79         tpsmd->dm = NULL;
80         tpsmd->totdmvert = tpsmd->totdmedge = tpsmd->totdmface = 0;
81         //tpsmd->facepa = 0;
82         tpsmd->flag = psmd->flag;
83         /* need to keep this to recognise a bit later in BKE_object_copy */
84         tpsmd->psys = psmd->psys;
85 }
86
87 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
88 {
89         ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
90         CustomDataMask dataMask = 0;
91         MTex *mtex;
92         int i;
93
94         if (!psmd->psys->part)
95                 return 0;
96
97         for (i = 0; i < MAX_MTEX; i++) {
98                 mtex = psmd->psys->part->mtex[i];
99                 if (mtex && mtex->mapto && (mtex->texco & TEXCO_UV))
100                         dataMask |= CD_MASK_MTFACE;
101         }
102
103         if (psmd->psys->part->tanfac != 0.0f)
104                 dataMask |= CD_MASK_MTFACE;
105
106         /* ask for vertexgroups if we need them */
107         for (i = 0; i < PSYS_TOT_VG; i++) {
108                 if (psmd->psys->vgroup[i]) {
109                         dataMask |= CD_MASK_MDEFORMVERT;
110                         break;
111                 }
112         }
113         
114         /* particles only need this if they are after a non deform modifier, and
115          * the modifier stack will only create them in that case. */
116         dataMask |= CD_MASK_ORIGSPACE_MLOOP | CD_MASK_ORIGINDEX;
117
118         dataMask |= CD_MASK_ORCO;
119         
120         return dataMask;
121 }
122
123 /* saves the current emitter state for a particle system and calculates particles */
124 static void deformVerts(ModifierData *md, Object *ob,
125                         DerivedMesh *derivedData,
126                         float (*vertexCos)[3],
127                         int UNUSED(numVerts),
128                         ModifierApplyFlag UNUSED(flag))
129 {
130         DerivedMesh *dm = derivedData;
131         ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
132         ParticleSystem *psys = NULL;
133         int needsFree = 0;
134         /* float cfra = BKE_scene_frame_get(md->scene); */  /* UNUSED */
135
136         if (ob->particlesystem.first)
137                 psys = psmd->psys;
138         else
139                 return;
140         
141         if (!psys_check_enabled(ob, psys))
142                 return;
143
144         if (dm == NULL) {
145                 dm = get_dm(ob, NULL, NULL, vertexCos, 1);
146
147                 if (!dm)
148                         return;
149
150                 needsFree = 1;
151         }
152
153         /* clear old dm */
154         if (psmd->dm) {
155                 psmd->dm->needsFree = 1;
156                 psmd->dm->release(psmd->dm);
157         }
158         else if (psmd->flag & eParticleSystemFlag_file_loaded) {
159                 /* in file read dm just wasn't saved in file so no need to reset everything */
160                 psmd->flag &= ~eParticleSystemFlag_file_loaded;
161         }
162         else {
163                 /* no dm before, so recalc particles fully */
164                 psys->recalc |= PSYS_RECALC_RESET;
165         }
166
167         /* make new dm */
168         psmd->dm = CDDM_copy(dm);
169         CDDM_apply_vert_coords(psmd->dm, vertexCos);
170         CDDM_calc_normals(psmd->dm);
171
172         if (needsFree) {
173                 dm->needsFree = 1;
174                 dm->release(dm);
175         }
176
177         /* protect dm */
178         psmd->dm->needsFree = 0;
179
180         /* report change in mesh structure */
181         DM_ensure_tessface(psmd->dm);
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 (!(ob->transflag & OB_NO_PSYS_UPDATE)) {
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 */     NULL,
232         /* deformMatrices */    NULL,
233         /* deformMatricesEM */  NULL,
234         /* applyModifier */     NULL,
235         /* applyModifierEM */   NULL,
236         /* initData */          initData,
237         /* requiredDataMask */  requiredDataMask,
238         /* freeData */          freeData,
239         /* isDisabled */        NULL,
240         /* updateDepgraph */    NULL,
241         /* dependsOnTime */     NULL,
242         /* dependsOnNormals */  NULL,
243         /* foreachObjectLink */ NULL,
244         /* foreachIDLink */     NULL,
245         /* foreachTexLink */    NULL,
246 };