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