Extract common modifier parameters into ModifierEvalContext struct
[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 #include "DNA_mesh_types.h"
40
41 #include "BLI_utildefines.h"
42
43
44 #include "BKE_cdderivedmesh.h"
45 #include "BKE_modifier.h"
46 #include "BKE_particle.h"
47
48 #include "MOD_util.h"
49
50
51 static void initData(ModifierData *md) 
52 {
53         ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
54         psmd->psys = NULL;
55         psmd->dm_final = NULL;
56         psmd->dm_deformed = 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_final) {
64                 psmd->dm_final->needsFree = true;
65                 psmd->dm_final->release(psmd->dm_final);
66                 psmd->dm_final = NULL;
67                 if (psmd->dm_deformed) {
68                         psmd->dm_deformed->needsFree = true;
69                         psmd->dm_deformed->release(psmd->dm_deformed);
70                         psmd->dm_deformed = NULL;
71                 }
72         }
73
74         /* ED_object_modifier_remove may have freed this first before calling
75          * modifier_free (which calls this function) */
76         if (psmd->psys)
77                 psmd->psys->flag |= PSYS_DELETE;
78 }
79 static void copyData(ModifierData *md, ModifierData *target)
80 {
81 #if 0
82         ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
83 #endif
84         ParticleSystemModifierData *tpsmd = (ParticleSystemModifierData *) target;
85
86         modifier_copyData_generic(md, target);
87
88         tpsmd->dm_final = NULL;
89         tpsmd->dm_deformed = NULL;
90         tpsmd->totdmvert = tpsmd->totdmedge = tpsmd->totdmface = 0;
91 }
92
93 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
94 {
95         ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
96         return psys_emitter_customdata_mask(psmd->psys);
97 }
98
99 /* saves the current emitter state for a particle system and calculates particles */
100 static void deformVerts(ModifierData *md, const ModifierEvalContext *ctx,
101                         DerivedMesh *derivedData,
102                         float (*vertexCos)[3],
103                         int UNUSED(numVerts))
104 {
105         DerivedMesh *dm = derivedData;
106         ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
107         ParticleSystem *psys = NULL;
108         bool needsFree = false;
109         /* float cfra = BKE_scene_frame_get(md->scene); */  /* UNUSED */
110
111         if (ctx->object->particlesystem.first)
112                 psys = psmd->psys;
113         else
114                 return;
115         
116         if (!psys_check_enabled(ctx->object, psys, (ctx->flag & MOD_APPLY_RENDER) != 0))
117                 return;
118
119         if (dm == NULL) {
120                 dm = get_dm(ctx->object, NULL, NULL, vertexCos, false, true);
121
122                 if (!dm)
123                         return;
124
125                 needsFree = true;
126         }
127
128         /* clear old dm */
129         if (psmd->dm_final) {
130                 psmd->dm_final->needsFree = true;
131                 psmd->dm_final->release(psmd->dm_final);
132                 if (psmd->dm_deformed) {
133                         psmd->dm_deformed->needsFree = 1;
134                         psmd->dm_deformed->release(psmd->dm_deformed);
135                         psmd->dm_deformed = NULL;
136                 }
137         }
138         else if (psmd->flag & eParticleSystemFlag_file_loaded) {
139                 /* in file read dm just wasn't saved in file so no need to reset everything */
140                 psmd->flag &= ~eParticleSystemFlag_file_loaded;
141         }
142         else {
143                 /* no dm before, so recalc particles fully */
144                 psys->recalc |= PSYS_RECALC_RESET;
145         }
146
147         /* make new dm */
148         psmd->dm_final = CDDM_copy(dm);
149         CDDM_apply_vert_coords(psmd->dm_final, vertexCos);
150         CDDM_calc_normals(psmd->dm_final);
151
152         if (needsFree) {
153                 dm->needsFree = true;
154                 dm->release(dm);
155         }
156
157         /* protect dm */
158         psmd->dm_final->needsFree = false;
159
160         DM_ensure_tessface(psmd->dm_final);
161
162         if (!psmd->dm_final->deformedOnly) {
163                 /* XXX Think we can assume here that if current DM is not only-deformed, ob->deformedOnly has been set.
164                  *     This is awfully weak though. :| */
165                 if (ctx->object->derivedDeform) {
166                         psmd->dm_deformed = CDDM_copy(ctx->object->derivedDeform);
167                 }
168                 else {  /* Can happen in some cases, e.g. when rendering from Edit mode... */
169                         psmd->dm_deformed = CDDM_from_mesh((Mesh *)ctx->object->data);
170                 }
171                 DM_ensure_tessface(psmd->dm_deformed);
172         }
173
174         /* report change in mesh structure */
175         if (psmd->dm_final->getNumVerts(psmd->dm_final) != psmd->totdmvert ||
176             psmd->dm_final->getNumEdges(psmd->dm_final) != psmd->totdmedge ||
177             psmd->dm_final->getNumTessFaces(psmd->dm_final) != psmd->totdmface)
178         {
179                 psys->recalc |= PSYS_RECALC_RESET;
180
181                 psmd->totdmvert = psmd->dm_final->getNumVerts(psmd->dm_final);
182                 psmd->totdmedge = psmd->dm_final->getNumEdges(psmd->dm_final);
183                 psmd->totdmface = psmd->dm_final->getNumTessFaces(psmd->dm_final);
184         }
185
186         if (!(ctx->object->transflag & OB_NO_PSYS_UPDATE)) {
187                 psmd->flag &= ~eParticleSystemFlag_psys_updated;
188                 particle_system_update(ctx->depsgraph, md->scene, ctx->object, psys, (ctx->flag & MOD_APPLY_RENDER) != 0);
189                 psmd->flag |= eParticleSystemFlag_psys_updated;
190         }
191 }
192
193 /* disabled particles in editmode for now, until support for proper derivedmesh
194  * updates is coded */
195 #if 0
196 static void deformVertsEM(
197         ModifierData *md, Object *ob, EditMesh *editData,
198         DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
199 {
200         DerivedMesh *dm = derivedData;
201
202         if (!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
203
204         deformVerts(md, ob, dm, vertexCos, numVerts);
205
206         if (!derivedData) dm->release(dm);
207 }
208 #endif
209
210
211 ModifierTypeInfo modifierType_ParticleSystem = {
212         /* name */              "ParticleSystem",
213         /* structName */        "ParticleSystemModifierData",
214         /* structSize */        sizeof(ParticleSystemModifierData),
215         /* type */              eModifierTypeType_OnlyDeform,
216         /* flags */             eModifierTypeFlag_AcceptsMesh |
217                                 eModifierTypeFlag_SupportsMapping |
218                                 eModifierTypeFlag_UsesPointCache /* |
219                                 eModifierTypeFlag_SupportsEditmode |
220                                 eModifierTypeFlag_EnableInEditmode */,
221
222         /* copyData */          copyData,
223
224         /* deformVerts_DM */    deformVerts,
225         /* deformVertsEM_DM */  NULL,
226         /* deformMatrices_DM */ NULL,
227         /* deformMatricesEM_DM*/NULL,
228         /* applyModifier_DM */  NULL,
229         /* applyModifierEM_DM */NULL,
230
231         /* deformVerts */       NULL,
232         /* deformMatrices */    NULL,
233         /* deformVertsEM */     NULL,
234         /* deformMatricesEM */  NULL,
235         /* applyModifier */     NULL,
236         /* applyModifierEM */   NULL,
237
238         /* initData */          initData,
239         /* requiredDataMask */  requiredDataMask,
240         /* freeData */          freeData,
241         /* isDisabled */        NULL,
242         /* updateDepsgraph */   NULL,
243         /* dependsOnTime */     NULL,
244         /* dependsOnNormals */  NULL,
245         /* foreachObjectLink */ NULL,
246         /* foreachIDLink */     NULL,
247         /* foreachTexLink */    NULL,
248 };