Fix T47038: Particles in Particle Edit Mode get added in completely wrong location.
[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_final = NULL;
55         psmd->dm_deformed = NULL;
56         psmd->totdmvert = psmd->totdmedge = psmd->totdmface = 0;
57 }
58 static void freeData(ModifierData *md)
59 {
60         ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
61
62         if (psmd->dm_final) {
63                 psmd->dm_final->needsFree = 1;
64                 psmd->dm_final->release(psmd->dm_final);
65                 psmd->dm_final = NULL;
66                 if (psmd->dm_deformed) {
67                         psmd->dm_deformed->needsFree = 1;
68                         psmd->dm_deformed->release(psmd->dm_deformed);
69                         psmd->dm_deformed = NULL;
70                 }
71         }
72
73         /* ED_object_modifier_remove may have freed this first before calling
74          * modifier_free (which calls this function) */
75         if (psmd->psys)
76                 psmd->psys->flag |= PSYS_DELETE;
77 }
78 static void copyData(ModifierData *md, ModifierData *target)
79 {
80 #if 0
81         ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
82 #endif
83         ParticleSystemModifierData *tpsmd = (ParticleSystemModifierData *) target;
84
85         modifier_copyData_generic(md, target);
86
87         tpsmd->dm_final = NULL;
88         tpsmd->dm_deformed = NULL;
89         tpsmd->totdmvert = tpsmd->totdmedge = tpsmd->totdmface = 0;
90 }
91
92 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
93 {
94         ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
95         return psys_emitter_customdata_mask(psmd->psys);
96 }
97
98 /* saves the current emitter state for a particle system and calculates particles */
99 static void deformVerts(ModifierData *md, Object *ob,
100                         DerivedMesh *derivedData,
101                         float (*vertexCos)[3],
102                         int UNUSED(numVerts),
103                         ModifierApplyFlag UNUSED(flag))
104 {
105         DerivedMesh *dm = derivedData;
106         ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
107         ParticleSystem *psys = NULL;
108         int needsFree = 0;
109         /* float cfra = BKE_scene_frame_get(md->scene); */  /* UNUSED */
110
111         if (ob->particlesystem.first)
112                 psys = psmd->psys;
113         else
114                 return;
115         
116         if (!psys_check_enabled(ob, psys))
117                 return;
118
119         if (dm == NULL) {
120                 dm = get_dm(ob, NULL, NULL, vertexCos, false, true);
121
122                 if (!dm)
123                         return;
124
125                 needsFree = 1;
126         }
127
128         /* clear old dm */
129         if (psmd->dm_final) {
130                 psmd->dm_final->needsFree = 1;
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 = 1;
154                 dm->release(dm);
155         }
156
157         /* protect dm */
158         psmd->dm_final->needsFree = 0;
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                 psmd->dm_deformed = CDDM_copy(ob->derivedDeform);
166                 DM_ensure_tessface(psmd->dm_deformed);
167         }
168
169         /* report change in mesh structure */
170         if (psmd->dm_final->getNumVerts(psmd->dm_final) != psmd->totdmvert ||
171             psmd->dm_final->getNumEdges(psmd->dm_final) != psmd->totdmedge ||
172             psmd->dm_final->getNumTessFaces(psmd->dm_final) != psmd->totdmface)
173         {
174                 psys->recalc |= PSYS_RECALC_RESET;
175
176                 psmd->totdmvert = psmd->dm_final->getNumVerts(psmd->dm_final);
177                 psmd->totdmedge = psmd->dm_final->getNumEdges(psmd->dm_final);
178                 psmd->totdmface = psmd->dm_final->getNumTessFaces(psmd->dm_final);
179         }
180
181         if (!(ob->transflag & OB_NO_PSYS_UPDATE)) {
182                 psmd->flag &= ~eParticleSystemFlag_psys_updated;
183                 particle_system_update(md->scene, ob, psys);
184                 psmd->flag |= eParticleSystemFlag_psys_updated;
185         }
186 }
187
188 /* disabled particles in editmode for now, until support for proper derivedmesh
189  * updates is coded */
190 #if 0
191 static void deformVertsEM(
192         ModifierData *md, Object *ob, EditMesh *editData,
193         DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
194 {
195         DerivedMesh *dm = derivedData;
196
197         if (!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
198
199         deformVerts(md, ob, dm, vertexCos, numVerts);
200
201         if (!derivedData) dm->release(dm);
202 }
203 #endif
204
205
206 ModifierTypeInfo modifierType_ParticleSystem = {
207         /* name */              "ParticleSystem",
208         /* structName */        "ParticleSystemModifierData",
209         /* structSize */        sizeof(ParticleSystemModifierData),
210         /* type */              eModifierTypeType_OnlyDeform,
211         /* flags */             eModifierTypeFlag_AcceptsMesh |
212                                 eModifierTypeFlag_SupportsMapping |
213                                 eModifierTypeFlag_UsesPointCache /* |
214                                 eModifierTypeFlag_SupportsEditmode |
215                                 eModifierTypeFlag_EnableInEditmode */,
216
217         /* copyData */          copyData,
218         /* deformVerts */       deformVerts,
219         /* deformVertsEM */     NULL,
220         /* deformMatrices */    NULL,
221         /* deformMatricesEM */  NULL,
222         /* applyModifier */     NULL,
223         /* applyModifierEM */   NULL,
224         /* initData */          initData,
225         /* requiredDataMask */  requiredDataMask,
226         /* freeData */          freeData,
227         /* isDisabled */        NULL,
228         /* updateDepgraph */    NULL,
229         /* updateDepsgraph */   NULL,
230         /* dependsOnTime */     NULL,
231         /* dependsOnNormals */  NULL,
232         /* foreachObjectLink */ NULL,
233         /* foreachIDLink */     NULL,
234         /* foreachTexLink */    NULL,
235 };