sphinx doc gen: multiple examples possible and include the scripts docstring inline...
[blender.git] / source / blender / modifiers / intern / MOD_particlesystem.c
1 /*
2 * $Id$
3 *
4 * ***** BEGIN GPL LICENSE BLOCK *****
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software  Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 *
20 * The Original Code is Copyright (C) 2005 by the Blender Foundation.
21 * All rights reserved.
22 *
23 * Contributor(s): Daniel Dunbar
24 *                 Ton Roosendaal,
25 *                 Ben Batt,
26 *                 Brecht Van Lommel,
27 *                 Campbell Barton
28 *
29 * ***** END GPL LICENSE BLOCK *****
30 *
31 */
32
33 #include "stddef.h"
34
35 #include "DNA_material_types.h"
36
37 #include "BLI_utildefines.h"
38
39
40 #include "BKE_cdderivedmesh.h"
41 #include "BKE_material.h"
42 #include "BKE_modifier.h"
43 #include "BKE_particle.h"
44
45 #include "MOD_util.h"
46
47
48 static void initData(ModifierData *md) 
49 {
50         ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md;
51         psmd->psys= 0;
52         psmd->dm=0;
53         psmd->totdmvert= psmd->totdmedge= psmd->totdmface= 0;
54 }
55 static void freeData(ModifierData *md)
56 {
57         ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md;
58
59         if(psmd->dm){
60                 psmd->dm->needsFree = 1;
61                 psmd->dm->release(psmd->dm);
62                 psmd->dm=0;
63         }
64
65         /* ED_object_modifier_remove may have freed this first before calling
66          * modifier_free (which calls this function) */
67         if(psmd->psys)
68                 psmd->psys->flag |= PSYS_DELETE;
69 }
70 static void copyData(ModifierData *md, ModifierData *target)
71 {
72         ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md;
73         ParticleSystemModifierData *tpsmd= (ParticleSystemModifierData*) target;
74
75         tpsmd->dm = 0;
76         tpsmd->totdmvert = tpsmd->totdmedge = tpsmd->totdmface = 0;
77         //tpsmd->facepa = 0;
78         tpsmd->flag = psmd->flag;
79         /* need to keep this to recognise a bit later in copy_object */
80         tpsmd->psys = psmd->psys;
81 }
82
83 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
84 {
85         ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md;
86         CustomDataMask dataMask = 0;
87         MTex *mtex;
88         int i;
89
90         if(!psmd->psys->part)
91                 return 0;
92
93         for(i=0; i<MAX_MTEX; i++) {
94                 mtex = psmd->psys->part->mtex[i];
95                 if(mtex && mtex->mapto && (mtex->texco & TEXCO_UV))
96                         dataMask |= CD_MASK_MTFACE;
97         }
98
99         if(psmd->psys->part->tanfac!=0.0)
100                 dataMask |= CD_MASK_MTFACE;
101
102         /* ask for vertexgroups if we need them */
103         for(i=0; i<PSYS_TOT_VG; i++){
104                 if(psmd->psys->vgroup[i]){
105                         dataMask |= CD_MASK_MDEFORMVERT;
106                         break;
107                 }
108         }
109         
110         /* particles only need this if they are after a non deform modifier, and
111         * the modifier stack will only create them in that case. */
112         dataMask |= CD_MASK_ORIGSPACE|CD_MASK_ORIGINDEX;
113
114         dataMask |= CD_MASK_ORCO;
115         
116         return dataMask;
117 }
118
119 /* saves the current emitter state for a particle system and calculates particles */
120 static void deformVerts(ModifierData *md, Object *ob,
121                                                 DerivedMesh *derivedData,
122                                                 float (*vertexCos)[3],
123                                                 int UNUSED(numVerts),
124                                                 int UNUSED(useRenderParams),
125                                                 int UNUSED(isFinalCalc))
126 {
127         DerivedMesh *dm = derivedData;
128         ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md;
129         ParticleSystem * psys=0;
130         int needsFree=0;
131
132         if(ob->particlesystem.first)
133                 psys=psmd->psys;
134         else
135                 return;
136         
137         if(!psys_check_enabled(ob, psys))
138                 return;
139
140         if(dm==0) {
141                 dm= get_dm(ob, NULL, NULL, vertexCos, 1);
142
143                 if(!dm)
144                         return;
145
146                 needsFree= 1;
147         }
148
149         /* clear old dm */
150         if(psmd->dm){
151                 psmd->dm->needsFree = 1;
152                 psmd->dm->release(psmd->dm);
153         }
154         else if(psmd->flag & eParticleSystemFlag_file_loaded) {
155                 /* in file read dm just wasn't saved in file so no need to reset everything */
156                 psmd->flag &= ~eParticleSystemFlag_file_loaded;
157         }
158         else {
159                 /* no dm before, so recalc particles fully */
160                 psys->recalc |= PSYS_RECALC_RESET;
161         }
162
163         /* make new dm */
164         psmd->dm=CDDM_copy(dm);
165         CDDM_apply_vert_coords(psmd->dm, vertexCos);
166         CDDM_calc_normals(psmd->dm);
167
168         if(needsFree){
169                 dm->needsFree = 1;
170                 dm->release(dm);
171         }
172
173         /* protect dm */
174         psmd->dm->needsFree = 0;
175
176         /* report change in mesh structure */
177         if(psmd->dm->getNumVerts(psmd->dm)!=psmd->totdmvert ||
178                   psmd->dm->getNumEdges(psmd->dm)!=psmd->totdmedge ||
179                   psmd->dm->getNumFaces(psmd->dm)!=psmd->totdmface){
180
181                 psys->recalc |= PSYS_RECALC_RESET;
182
183                 psmd->totdmvert= psmd->dm->getNumVerts(psmd->dm);
184                 psmd->totdmedge= psmd->dm->getNumEdges(psmd->dm);
185                 psmd->totdmface= psmd->dm->getNumFaces(psmd->dm);
186         }
187
188         if(psys) {
189                 psmd->flag &= ~eParticleSystemFlag_psys_updated;
190                 particle_system_update(md->scene, ob, psys);
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         /* deformVerts */       deformVerts,
226         /* deformVertsEM */     0 /* deformVertsEM */ ,
227         /* deformMatrices */    0,
228         /* deformMatricesEM */  0,
229         /* applyModifier */     0,
230         /* applyModifierEM */   0,
231         /* initData */          initData,
232         /* requiredDataMask */  requiredDataMask,
233         /* freeData */          freeData,
234         /* isDisabled */        0,
235         /* updateDepgraph */    0,
236         /* dependsOnTime */     0,
237         /* dependsOnNormals */  0,
238         /* foreachObjectLink */ 0,
239         /* foreachIDLink */     0,
240 };