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