style cleanup
[blender.git] / source / blender / modifiers / intern / MOD_wave.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_wave.c
32  *  \ingroup modifiers
33  */
34
35
36 #include "BLI_math.h"
37
38 #include "DNA_meshdata_types.h"
39 #include "DNA_scene_types.h"
40 #include "DNA_object_types.h"
41
42 #include "BLI_utildefines.h"
43 #include "BLI_string.h"
44
45
46 #include "BKE_DerivedMesh.h"
47 #include "BKE_object.h"
48 #include "BKE_deform.h"
49 #include "BKE_scene.h"
50
51 #include "depsgraph_private.h"
52
53 #include "MEM_guardedalloc.h"
54 #include "RE_shader_ext.h"
55
56 #include "MOD_modifiertypes.h"
57 #include "MOD_util.h"
58
59 static void initData(ModifierData *md)
60 {
61         WaveModifierData *wmd = (WaveModifierData *) md; // whadya know, moved here from Iraq
62
63         wmd->flag |= (MOD_WAVE_X | MOD_WAVE_Y | MOD_WAVE_CYCL |
64                       MOD_WAVE_NORM_X | MOD_WAVE_NORM_Y | MOD_WAVE_NORM_Z);
65
66         wmd->objectcenter = NULL;
67         wmd->texture = NULL;
68         wmd->map_object = NULL;
69         wmd->height = 0.5f;
70         wmd->width = 1.5f;
71         wmd->speed = 0.25f;
72         wmd->narrow = 1.5f;
73         wmd->lifetime = 0.0f;
74         wmd->damp = 10.0f;
75         wmd->falloff = 0.0f;
76         wmd->texmapping = MOD_DISP_MAP_LOCAL;
77         wmd->defgrp_name[0] = 0;
78 }
79
80 static void copyData(ModifierData *md, ModifierData *target)
81 {
82         WaveModifierData *wmd = (WaveModifierData *) md;
83         WaveModifierData *twmd = (WaveModifierData *) target;
84
85         twmd->damp = wmd->damp;
86         twmd->flag = wmd->flag;
87         twmd->height = wmd->height;
88         twmd->lifetime = wmd->lifetime;
89         twmd->narrow = wmd->narrow;
90         twmd->speed = wmd->speed;
91         twmd->startx = wmd->startx;
92         twmd->starty = wmd->starty;
93         twmd->timeoffs = wmd->timeoffs;
94         twmd->width = wmd->width;
95         twmd->falloff = wmd->falloff;
96         twmd->objectcenter = wmd->objectcenter;
97         twmd->texture = wmd->texture;
98         twmd->map_object = wmd->map_object;
99         twmd->texmapping = wmd->texmapping;
100         BLI_strncpy(twmd->defgrp_name, wmd->defgrp_name, sizeof(twmd->defgrp_name));
101 }
102
103 static int dependsOnTime(ModifierData *UNUSED(md))
104 {
105         return 1;
106 }
107
108 static void foreachObjectLink(
109         ModifierData *md, Object *ob,
110         ObjectWalkFunc walk, void *userData)
111 {
112         WaveModifierData *wmd = (WaveModifierData *) md;
113
114         walk(userData, ob, &wmd->objectcenter);
115         walk(userData, ob, &wmd->map_object);
116 }
117
118 static void foreachIDLink(ModifierData *md, Object *ob,
119                           IDWalkFunc walk, void *userData)
120 {
121         WaveModifierData *wmd = (WaveModifierData *) md;
122
123         walk(userData, ob, (ID **)&wmd->texture);
124
125         foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
126 }
127
128 static void foreachTexLink(ModifierData *md, Object *ob,
129                            TexWalkFunc walk, void *userData)
130 {
131         walk(userData, ob, md, "texture");
132 }
133
134 static void updateDepgraph(ModifierData *md, DagForest *forest,
135                            Scene *UNUSED(scene),
136                            Object *UNUSED(ob),
137                            DagNode *obNode)
138 {
139         WaveModifierData *wmd = (WaveModifierData *) md;
140
141         if (wmd->objectcenter) {
142                 DagNode *curNode = dag_get_node(forest, wmd->objectcenter);
143
144                 dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA,
145                                  "Wave Modifier");
146         }
147
148         if (wmd->map_object) {
149                 DagNode *curNode = dag_get_node(forest, wmd->map_object);
150
151                 dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA,
152                                  "Wave Modifer");
153         }
154 }
155
156 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
157 {
158         WaveModifierData *wmd = (WaveModifierData *)md;
159         CustomDataMask dataMask = 0;
160
161
162         /* ask for UV coordinates if we need them */
163         if (wmd->texture && wmd->texmapping == MOD_DISP_MAP_UV)
164                 dataMask |= CD_MASK_MTFACE;
165
166         /* ask for vertexgroups if we need them */
167         if (wmd->defgrp_name[0])
168                 dataMask |= CD_MASK_MDEFORMVERT;
169
170         return dataMask;
171 }
172
173 static void waveModifier_do(WaveModifierData *md, 
174                             Scene *scene, Object *ob, DerivedMesh *dm,
175                             float (*vertexCos)[3], int numVerts)
176 {
177         WaveModifierData *wmd = (WaveModifierData *) md;
178         MVert *mvert = NULL;
179         MDeformVert *dvert;
180         int defgrp_index;
181         float ctime = BKE_scene_frame_get(scene);
182         float minfac = (float)(1.0 / exp(wmd->width * wmd->narrow * wmd->width * wmd->narrow));
183         float lifefac = wmd->height;
184         float (*tex_co)[3] = NULL;
185         const int wmd_axis = wmd->flag & (MOD_WAVE_X | MOD_WAVE_Y);
186         const float falloff = wmd->falloff;
187         float falloff_fac = 1.0f; /* when falloff == 0.0f this stays at 1.0f */
188
189         if ((wmd->flag & MOD_WAVE_NORM) && (ob->type == OB_MESH))
190                 mvert = dm->getVertArray(dm);
191
192         if (wmd->objectcenter) {
193                 float mat[4][4];
194                 /* get the control object's location in local coordinates */
195                 invert_m4_m4(ob->imat, ob->obmat);
196                 mult_m4_m4m4(mat, ob->imat, wmd->objectcenter->obmat);
197
198                 wmd->startx = mat[3][0];
199                 wmd->starty = mat[3][1];
200         }
201
202         /* get the index of the deform group */
203         modifier_get_vgroup(ob, dm, wmd->defgrp_name, &dvert, &defgrp_index);
204
205         if (wmd->damp == 0) wmd->damp = 10.0f;
206
207         if (wmd->lifetime != 0.0f) {
208                 float x = ctime - wmd->timeoffs;
209
210                 if (x > wmd->lifetime) {
211                         lifefac = x - wmd->lifetime;
212
213                         if (lifefac > wmd->damp) lifefac = 0.0;
214                         else lifefac = (float)(wmd->height * (1.0f - sqrtf(lifefac / wmd->damp)));
215                 }
216         }
217
218         if (wmd->texture) {
219                 tex_co = MEM_mallocN(sizeof(*tex_co) * numVerts,
220                                      "waveModifier_do tex_co");
221                 get_texture_coords((MappingInfoModifierData *)wmd, ob, dm, vertexCos, tex_co, numVerts);
222
223                 modifier_init_texture(wmd->modifier.scene, wmd->texture);
224         }
225
226         if (lifefac != 0.0f) {
227                 /* avoid divide by zero checks within the loop */
228                 float falloff_inv = falloff ? 1.0f / falloff : 1.0f;
229                 int i;
230
231                 for (i = 0; i < numVerts; i++) {
232                         float *co = vertexCos[i];
233                         float x = co[0] - wmd->startx;
234                         float y = co[1] - wmd->starty;
235                         float amplit = 0.0f;
236                         float def_weight = 1.0f;
237
238                         /* get weights */
239                         if (dvert) {
240                                 def_weight = defvert_find_weight(&dvert[i], defgrp_index);
241
242                                 /* if this vert isn't in the vgroup, don't deform it */
243                                 if (def_weight == 0.0f) {
244                                         continue;
245                                 }
246                         }
247
248                         switch (wmd_axis) {
249                                 case MOD_WAVE_X | MOD_WAVE_Y:
250                                         amplit = sqrtf(x * x + y * y);
251                                         break;
252                                 case MOD_WAVE_X:
253                                         amplit = x;
254                                         break;
255                                 case MOD_WAVE_Y:
256                                         amplit = y;
257                                         break;
258                         }
259
260                         /* this way it makes nice circles */
261                         amplit -= (ctime - wmd->timeoffs) * wmd->speed;
262
263                         if (wmd->flag & MOD_WAVE_CYCL) {
264                                 amplit = (float)fmodf(amplit - wmd->width, 2.0f * wmd->width) +
265                                          wmd->width;
266                         }
267
268                         if (falloff != 0.0f) {
269                                 float dist = 0.0f;
270
271                                 switch (wmd_axis) {
272                                         case MOD_WAVE_X | MOD_WAVE_Y:
273                                                 dist = sqrtf(x * x + y * y);
274                                                 break;
275                                         case MOD_WAVE_X:
276                                                 dist = fabsf(x);
277                                                 break;
278                                         case MOD_WAVE_Y:
279                                                 dist = fabsf(y);
280                                                 break;
281                                 }
282
283                                 falloff_fac = (1.0f - (dist * falloff_inv));
284                                 CLAMP(falloff_fac, 0.0f, 1.0f);
285                         }
286
287                         /* GAUSSIAN */
288                         if ((falloff_fac != 0.0f) && (amplit > -wmd->width) && (amplit < wmd->width)) {
289                                 amplit = amplit * wmd->narrow;
290                                 amplit = (float)(1.0f / expf(amplit * amplit) - minfac);
291
292                                 /*apply texture*/
293                                 if (wmd->texture) {
294                                         TexResult texres;
295                                         texres.nor = NULL;
296                                         get_texture_value(wmd->texture, tex_co[i], &texres);
297                                         amplit *= texres.tin;
298                                 }
299
300                                 /*apply weight & falloff */
301                                 amplit *= def_weight * falloff_fac;
302
303                                 if (mvert) {
304                                         /* move along normals */
305                                         if (wmd->flag & MOD_WAVE_NORM_X) {
306                                                 co[0] += (lifefac * amplit) * mvert[i].no[0] / 32767.0f;
307                                         }
308                                         if (wmd->flag & MOD_WAVE_NORM_Y) {
309                                                 co[1] += (lifefac * amplit) * mvert[i].no[1] / 32767.0f;
310                                         }
311                                         if (wmd->flag & MOD_WAVE_NORM_Z) {
312                                                 co[2] += (lifefac * amplit) * mvert[i].no[2] / 32767.0f;
313                                         }
314                                 }
315                                 else {
316                                         /* move along local z axis */
317                                         co[2] += lifefac * amplit;
318                                 }
319                         }
320                 }
321         }
322
323         if (wmd->texture) MEM_freeN(tex_co);
324 }
325
326 static void deformVerts(ModifierData *md, Object *ob,
327                         DerivedMesh *derivedData,
328                         float (*vertexCos)[3],
329                         int numVerts,
330                         ModifierApplyFlag UNUSED(flag))
331 {
332         DerivedMesh *dm = derivedData;
333         WaveModifierData *wmd = (WaveModifierData *)md;
334
335         if (wmd->flag & MOD_WAVE_NORM)
336                 dm = get_cddm(ob, NULL, dm, vertexCos);
337         else if (wmd->texture || wmd->defgrp_name[0])
338                 dm = get_dm(ob, NULL, dm, NULL, 0);
339
340         waveModifier_do(wmd, md->scene, ob, dm, vertexCos, numVerts);
341
342         if (dm != derivedData)
343                 dm->release(dm);
344 }
345
346 static void deformVertsEM(
347         ModifierData *md, Object *ob, struct BMEditMesh *editData,
348         DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
349 {
350         DerivedMesh *dm = derivedData;
351         WaveModifierData *wmd = (WaveModifierData *)md;
352
353         if (wmd->flag & MOD_WAVE_NORM)
354                 dm = get_cddm(ob, editData, dm, vertexCos);
355         else if (wmd->texture || wmd->defgrp_name[0])
356                 dm = get_dm(ob, editData, dm, NULL, 0);
357
358         waveModifier_do(wmd, md->scene, ob, dm, vertexCos, numVerts);
359
360         if (dm != derivedData)
361                 dm->release(dm);
362 }
363
364
365 ModifierTypeInfo modifierType_Wave = {
366         /* name */              "Wave",
367         /* structName */        "WaveModifierData",
368         /* structSize */        sizeof(WaveModifierData),
369         /* type */              eModifierTypeType_OnlyDeform,
370         /* flags */             eModifierTypeFlag_AcceptsCVs |
371                                 eModifierTypeFlag_SupportsEditmode,
372         /* copyData */          copyData,
373         /* deformVerts */       deformVerts,
374         /* deformMatrices */    NULL,
375         /* deformVertsEM */     deformVertsEM,
376         /* deformMatricesEM */  NULL,
377         /* applyModifier */     NULL,
378         /* applyModifierEM */   NULL,
379         /* initData */          initData,
380         /* requiredDataMask */  requiredDataMask,
381         /* freeData */          NULL,
382         /* isDisabled */        NULL,
383         /* updateDepgraph */    updateDepgraph,
384         /* dependsOnTime */     dependsOnTime,
385         /* dependsOnNormals */  NULL,
386         /* foreachObjectLink */ foreachObjectLink,
387         /* foreachIDLink */     foreachIDLink,
388         /* foreachTexLink */    foreachTexLink,
389 };