de1b11eddd92fecd346cc7a5d26b03dd01166948
[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_modifier.h"
45 #include "BKE_particle.h"
46
47 #include "MOD_util.h"
48
49
50 static void initData(ModifierData *md) 
51 {
52         ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
53         psmd->psys = NULL;
54         psmd->dm = NULL;
55         psmd->totdmvert = psmd->totdmedge = psmd->totdmface = 0;
56 }
57 static void freeData(ModifierData *md)
58 {
59         ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
60
61         if (psmd->dm) {
62                 psmd->dm->needsFree = 1;
63                 psmd->dm->release(psmd->dm);
64                 psmd->dm = NULL;
65         }
66
67         /* ED_object_modifier_remove may have freed this first before calling
68          * modifier_free (which calls this function) */
69         if (psmd->psys)
70                 psmd->psys->flag |= PSYS_DELETE;
71 }
72 static void copyData(ModifierData *md, ModifierData *target)
73 {
74 #if 0
75         ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
76 #endif
77         ParticleSystemModifierData *tpsmd = (ParticleSystemModifierData *) target;
78
79         modifier_copyData_generic(md, target);
80
81         tpsmd->dm = NULL;
82         tpsmd->totdmvert = tpsmd->totdmedge = tpsmd->totdmface = 0;
83 }
84
85 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
86 {
87         ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
88         return psys_emitter_customdata_mask(psmd->psys);
89 }
90
91 /* saves the current emitter state for a particle system and calculates particles */
92 static void deformVerts(ModifierData *md, Object *ob,
93                         DerivedMesh *derivedData,
94                         float (*vertexCos)[3],
95                         int UNUSED(numVerts),
96                         ModifierApplyFlag UNUSED(flag))
97 {
98         DerivedMesh *dm = derivedData;
99         ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
100         ParticleSystem *psys = NULL;
101         int needsFree = 0;
102         /* float cfra = BKE_scene_frame_get(md->scene); */  /* UNUSED */
103
104         if (ob->particlesystem.first)
105                 psys = psmd->psys;
106         else
107                 return;
108         
109         if (!psys_check_enabled(ob, psys))
110                 return;
111
112         if (dm == NULL) {
113                 dm = get_dm(ob, NULL, NULL, vertexCos, false, true);
114
115                 if (!dm)
116                         return;
117
118                 needsFree = 1;
119         }
120
121         /* clear old dm */
122         if (psmd->dm) {
123                 psmd->dm->needsFree = 1;
124                 psmd->dm->release(psmd->dm);
125         }
126         else if (psmd->flag & eParticleSystemFlag_file_loaded) {
127                 /* in file read dm just wasn't saved in file so no need to reset everything */
128                 psmd->flag &= ~eParticleSystemFlag_file_loaded;
129         }
130         else {
131                 /* no dm before, so recalc particles fully */
132                 psys->recalc |= PSYS_RECALC_RESET;
133         }
134
135         /* make new dm */
136         psmd->dm = CDDM_copy(dm);
137         CDDM_apply_vert_coords(psmd->dm, vertexCos);
138         CDDM_calc_normals(psmd->dm);
139
140         if (needsFree) {
141                 dm->needsFree = 1;
142                 dm->release(dm);
143         }
144
145         /* protect dm */
146         psmd->dm->needsFree = 0;
147
148         /* report change in mesh structure */
149         DM_ensure_tessface(psmd->dm);
150         if (psmd->dm->getNumVerts(psmd->dm) != psmd->totdmvert ||
151             psmd->dm->getNumEdges(psmd->dm) != psmd->totdmedge ||
152             psmd->dm->getNumTessFaces(psmd->dm) != psmd->totdmface)
153         {
154                 psys->recalc |= PSYS_RECALC_RESET;
155
156                 psmd->totdmvert = psmd->dm->getNumVerts(psmd->dm);
157                 psmd->totdmedge = psmd->dm->getNumEdges(psmd->dm);
158                 psmd->totdmface = psmd->dm->getNumTessFaces(psmd->dm);
159         }
160
161         if (!(ob->transflag & OB_NO_PSYS_UPDATE)) {
162                 psmd->flag &= ~eParticleSystemFlag_psys_updated;
163                 particle_system_update(md->scene, ob, psys);
164                 psmd->flag |= eParticleSystemFlag_psys_updated;
165         }
166 }
167
168 /* disabled particles in editmode for now, until support for proper derivedmesh
169  * updates is coded */
170 #if 0
171 static void deformVertsEM(
172         ModifierData *md, Object *ob, EditMesh *editData,
173         DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
174 {
175         DerivedMesh *dm = derivedData;
176
177         if (!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
178
179         deformVerts(md, ob, dm, vertexCos, numVerts);
180
181         if (!derivedData) dm->release(dm);
182 }
183 #endif
184
185
186 ModifierTypeInfo modifierType_ParticleSystem = {
187         /* name */              "ParticleSystem",
188         /* structName */        "ParticleSystemModifierData",
189         /* structSize */        sizeof(ParticleSystemModifierData),
190         /* type */              eModifierTypeType_OnlyDeform,
191         /* flags */             eModifierTypeFlag_AcceptsMesh |
192                                 eModifierTypeFlag_SupportsMapping |
193                                 eModifierTypeFlag_UsesPointCache /* |
194                                 eModifierTypeFlag_SupportsEditmode |
195                                 eModifierTypeFlag_EnableInEditmode */,
196
197         /* copyData */          copyData,
198         /* deformVerts */       deformVerts,
199         /* deformVertsEM */     NULL,
200         /* deformMatrices */    NULL,
201         /* deformMatricesEM */  NULL,
202         /* applyModifier */     NULL,
203         /* applyModifierEM */   NULL,
204         /* initData */          initData,
205         /* requiredDataMask */  requiredDataMask,
206         /* freeData */          freeData,
207         /* isDisabled */        NULL,
208         /* updateDepgraph */    NULL,
209         /* updateDepsgraph */   NULL,
210         /* dependsOnTime */     NULL,
211         /* dependsOnNormals */  NULL,
212         /* foreachObjectLink */ NULL,
213         /* foreachIDLink */     NULL,
214         /* foreachTexLink */    NULL,
215 };