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