Fix T58679: Missing modifiers update on changes to texture
[blender.git] / source / blender / modifiers / intern / MOD_displace.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_displace.c
32  *  \ingroup modifiers
33  */
34
35
36 #include "DNA_mesh_types.h"
37 #include "DNA_meshdata_types.h"
38 #include "DNA_object_types.h"
39
40 #include "BLI_utildefines.h"
41 #include "BLI_math.h"
42 #include "BLI_task.h"
43
44 #include "BKE_customdata.h"
45 #include "BKE_editmesh.h"
46 #include "BKE_library.h"
47 #include "BKE_library_query.h"
48 #include "BKE_image.h"
49 #include "BKE_mesh.h"
50 #include "BKE_modifier.h"
51 #include "BKE_texture.h"
52 #include "BKE_deform.h"
53 #include "BKE_object.h"
54
55 #include "DEG_depsgraph.h"
56 #include "DEG_depsgraph_query.h"
57
58 #include "MEM_guardedalloc.h"
59
60 #include "MOD_util.h"
61
62 #include "RE_shader_ext.h"
63
64
65 /* Displace */
66
67 static void initData(ModifierData *md)
68 {
69         DisplaceModifierData *dmd = (DisplaceModifierData *) md;
70
71         dmd->texture = NULL;
72         dmd->strength = 1;
73         dmd->direction = MOD_DISP_DIR_NOR;
74         dmd->midlevel = 0.5;
75         dmd->space = MOD_DISP_SPACE_LOCAL;
76 }
77
78 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
79 {
80         DisplaceModifierData *dmd = (DisplaceModifierData *)md;
81         CustomDataMask dataMask = 0;
82
83         /* ask for vertexgroups if we need them */
84         if (dmd->defgrp_name[0]) dataMask |= CD_MASK_MDEFORMVERT;
85
86         /* ask for UV coordinates if we need them */
87         if (dmd->texmapping == MOD_DISP_MAP_UV) dataMask |= CD_MASK_MTFACE;
88
89         if (dmd->direction == MOD_DISP_DIR_CLNOR) {
90                 dataMask |= CD_MASK_CUSTOMLOOPNORMAL;
91         }
92
93         return dataMask;
94 }
95
96 static bool dependsOnTime(ModifierData *md)
97 {
98         DisplaceModifierData *dmd = (DisplaceModifierData *)md;
99
100         if (dmd->texture) {
101                 return BKE_texture_dependsOnTime(dmd->texture);
102         }
103         else {
104                 return false;
105         }
106 }
107
108 static bool dependsOnNormals(ModifierData *md)
109 {
110         DisplaceModifierData *dmd = (DisplaceModifierData *)md;
111         return ELEM(dmd->direction, MOD_DISP_DIR_NOR, MOD_DISP_DIR_CLNOR);
112 }
113
114 static void foreachObjectLink(
115         ModifierData *md, Object *ob,
116         ObjectWalkFunc walk, void *userData)
117 {
118         DisplaceModifierData *dmd = (DisplaceModifierData *) md;
119
120         walk(userData, ob, &dmd->map_object, IDWALK_CB_NOP);
121 }
122
123 static void foreachIDLink(
124         ModifierData *md, Object *ob,
125         IDWalkFunc walk, void *userData)
126 {
127         DisplaceModifierData *dmd = (DisplaceModifierData *) md;
128
129         walk(userData, ob, (ID **)&dmd->texture, IDWALK_CB_USER);
130
131         foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
132 }
133
134 static void foreachTexLink(
135         ModifierData *md, Object *ob,
136         TexWalkFunc walk, void *userData)
137 {
138         walk(userData, ob, md, "texture");
139 }
140
141 static bool isDisabled(const struct Scene *UNUSED(scene), ModifierData *md, bool UNUSED(useRenderParams))
142 {
143         DisplaceModifierData *dmd = (DisplaceModifierData *) md;
144         return ((!dmd->texture && dmd->direction == MOD_DISP_DIR_RGB_XYZ) || dmd->strength == 0.0f);
145 }
146
147 static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
148 {
149         DisplaceModifierData *dmd = (DisplaceModifierData *)md;
150         if (dmd->map_object != NULL && dmd->texmapping == MOD_DISP_MAP_OBJECT) {
151                 DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Displace Modifier");
152                 DEG_add_object_relation(ctx->node, dmd->map_object, DEG_OB_COMP_TRANSFORM, "Displace Modifier");
153         }
154         if (dmd->texmapping == MOD_DISP_MAP_GLOBAL ||
155             (ELEM(dmd->direction, MOD_DISP_DIR_X, MOD_DISP_DIR_Y, MOD_DISP_DIR_Z, MOD_DISP_DIR_RGB_XYZ) &&
156             dmd->space == MOD_DISP_SPACE_GLOBAL))
157         {
158                 DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Displace Modifier");
159         }
160         if (dmd->texture != NULL) {
161                 DEG_add_generic_id_relation(ctx->node, &dmd->texture->id, "Displace Modifier");
162         }
163 }
164
165 typedef struct DisplaceUserdata {
166         /*const*/ DisplaceModifierData *dmd;
167         struct Scene *scene;
168         struct ImagePool *pool;
169         MDeformVert *dvert;
170         float weight;
171         int defgrp_index;
172         int direction;
173         bool use_global_direction;
174         float (*tex_co)[3];
175         float (*vertexCos)[3];
176         float local_mat[4][4];
177         MVert *mvert;
178         float (*vert_clnors)[3];
179 } DisplaceUserdata;
180
181 static void displaceModifier_do_task(
182         void *__restrict userdata,
183         const int iter,
184         const ParallelRangeTLS *__restrict UNUSED(tls))
185 {
186         DisplaceUserdata *data = (DisplaceUserdata *)userdata;
187         DisplaceModifierData *dmd = data->dmd;
188         MDeformVert *dvert = data->dvert;
189         float weight = data->weight;
190         int defgrp_index = data->defgrp_index;
191         int direction = data->direction;
192         bool use_global_direction = data->use_global_direction;
193         float (*tex_co)[3] = data->tex_co;
194         float (*vertexCos)[3] = data->vertexCos;
195         MVert *mvert = data->mvert;
196         float (*vert_clnors)[3] = data->vert_clnors;
197
198         const float delta_fixed = 1.0f - dmd->midlevel;  /* when no texture is used, we fallback to white */
199
200         TexResult texres;
201         float strength = dmd->strength;
202         float delta;
203         float local_vec[3];
204
205         if (dvert) {
206                 weight = defvert_find_weight(dvert + iter, defgrp_index);
207                 if (weight == 0.0f) {
208                         return;
209                 }
210         }
211
212         if (dmd->texture) {
213                 texres.nor = NULL;
214                 BKE_texture_get_value_ex(data->scene, dmd->texture, tex_co[iter], &texres, data->pool, false);
215                 delta = texres.tin - dmd->midlevel;
216         }
217         else {
218                 delta = delta_fixed;  /* (1.0f - dmd->midlevel) */  /* never changes */
219         }
220
221         if (dvert) {
222                 strength *= weight;
223         }
224
225         delta *= strength;
226         CLAMP(delta, -10000, 10000);
227
228         switch (direction) {
229                 case MOD_DISP_DIR_X:
230                         if (use_global_direction) {
231                                 vertexCos[iter][0] += delta * data->local_mat[0][0];
232                                 vertexCos[iter][1] += delta * data->local_mat[1][0];
233                                 vertexCos[iter][2] += delta * data->local_mat[2][0];
234                         }
235                         else {
236                                 vertexCos[iter][0] += delta;
237                         }
238                         break;
239                 case MOD_DISP_DIR_Y:
240                         if (use_global_direction) {
241                                 vertexCos[iter][0] += delta * data->local_mat[0][1];
242                                 vertexCos[iter][1] += delta * data->local_mat[1][1];
243                                 vertexCos[iter][2] += delta * data->local_mat[2][1];
244                         }
245                         else {
246                                 vertexCos[iter][1] += delta;
247                         }
248                         break;
249                 case MOD_DISP_DIR_Z:
250                         if (use_global_direction) {
251                                 vertexCos[iter][0] += delta * data->local_mat[0][2];
252                                 vertexCos[iter][1] += delta * data->local_mat[1][2];
253                                 vertexCos[iter][2] += delta * data->local_mat[2][2];
254                         }
255                         else {
256                                 vertexCos[iter][2] += delta;
257                         }
258                         break;
259                 case MOD_DISP_DIR_RGB_XYZ:
260                         local_vec[0] = texres.tr - dmd->midlevel;
261                         local_vec[1] = texres.tg - dmd->midlevel;
262                         local_vec[2] = texres.tb - dmd->midlevel;
263                         if (use_global_direction) {
264                                 mul_transposed_mat3_m4_v3(data->local_mat, local_vec);
265                         }
266                         mul_v3_fl(local_vec, strength);
267                         add_v3_v3(vertexCos[iter], local_vec);
268                         break;
269                 case MOD_DISP_DIR_NOR:
270                         vertexCos[iter][0] += delta * (mvert[iter].no[0] / 32767.0f);
271                         vertexCos[iter][1] += delta * (mvert[iter].no[1] / 32767.0f);
272                         vertexCos[iter][2] += delta * (mvert[iter].no[2] / 32767.0f);
273                         break;
274                 case MOD_DISP_DIR_CLNOR:
275                         madd_v3_v3fl(vertexCos[iter], vert_clnors[iter], delta);
276                         break;
277         }
278 }
279
280 static void displaceModifier_do(
281         DisplaceModifierData *dmd, const ModifierEvalContext *ctx,
282         Mesh *mesh, float (*vertexCos)[3], const int numVerts)
283 {
284         Object *ob = ctx->object;
285         Depsgraph *depsgraph = ctx->depsgraph;
286         MVert *mvert;
287         MDeformVert *dvert;
288         int direction = dmd->direction;
289         int defgrp_index;
290         float (*tex_co)[3];
291         float weight = 1.0f; /* init value unused but some compilers may complain */
292         float (*vert_clnors)[3] = NULL;
293         float local_mat[4][4] = {{0}};
294         const bool use_global_direction = dmd->space == MOD_DISP_SPACE_GLOBAL;
295
296         if (!dmd->texture && dmd->direction == MOD_DISP_DIR_RGB_XYZ) return;
297         if (dmd->strength == 0.0f) return;
298
299         mvert = mesh->mvert;
300         MOD_get_vgroup(ob, mesh, dmd->defgrp_name, &dvert, &defgrp_index);
301
302         if (dmd->texture) {
303                 tex_co = MEM_calloc_arrayN((size_t)numVerts, sizeof(*tex_co),
304                                      "displaceModifier_do tex_co");
305                 MOD_get_texture_coords((MappingInfoModifierData *)dmd, ob, mesh, vertexCos, tex_co);
306
307                 MOD_init_texture(depsgraph, dmd->texture);
308         }
309         else {
310                 tex_co = NULL;
311         }
312
313         if (direction == MOD_DISP_DIR_CLNOR) {
314                 CustomData *ldata = &mesh->ldata;
315
316                 if (CustomData_has_layer(ldata, CD_CUSTOMLOOPNORMAL)) {
317                         float (*clnors)[3] = NULL;
318
319                         if ((mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) || !CustomData_has_layer(ldata, CD_NORMAL)) {
320                                 BKE_mesh_calc_normals_split(mesh);
321                         }
322
323                         clnors = CustomData_get_layer(ldata, CD_NORMAL);
324                         vert_clnors = MEM_malloc_arrayN(numVerts, sizeof(*vert_clnors), __func__);
325                         BKE_mesh_normals_loop_to_vertex(numVerts, mesh->mloop, mesh->totloop,
326                                                         (const float (*)[3])clnors, vert_clnors);
327                 }
328                 else {
329                         direction = MOD_DISP_DIR_NOR;
330                 }
331         }
332         else if (ELEM(direction, MOD_DISP_DIR_X, MOD_DISP_DIR_Y, MOD_DISP_DIR_Z, MOD_DISP_DIR_RGB_XYZ) &&
333                  use_global_direction)
334         {
335                 copy_m4_m4(local_mat, ob->obmat);
336         }
337
338         DisplaceUserdata data = {NULL};
339         data.scene = DEG_get_evaluated_scene(ctx->depsgraph);
340         data.dmd = dmd;
341         data.dvert = dvert;
342         data.weight = weight;
343         data.defgrp_index = defgrp_index;
344         data.direction = direction;
345         data.use_global_direction = use_global_direction;
346         data.tex_co = tex_co;
347         data.vertexCos = vertexCos;
348         copy_m4_m4(data.local_mat, local_mat);
349         data.mvert = mvert;
350         data.vert_clnors = vert_clnors;
351         if (dmd->texture != NULL) {
352                 data.pool = BKE_image_pool_new();
353                 BKE_texture_fetch_images_for_pool(dmd->texture, data.pool);
354         }
355         ParallelRangeSettings settings;
356         BLI_parallel_range_settings_defaults(&settings);
357         settings.use_threading = (numVerts > 512);
358         BLI_task_parallel_range(0, numVerts,
359                                 &data,
360                                 displaceModifier_do_task,
361                                 &settings);
362
363         if (data.pool != NULL) {
364                 BKE_image_pool_free(data.pool);
365         }
366
367         if (tex_co) {
368                 MEM_freeN(tex_co);
369         }
370
371         if (vert_clnors) {
372                 MEM_freeN(vert_clnors);
373         }
374 }
375
376 static void deformVerts(
377         ModifierData *md,
378         const ModifierEvalContext *ctx,
379         Mesh *mesh,
380         float (*vertexCos)[3],
381         int numVerts)
382 {
383         Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false);
384
385         displaceModifier_do((DisplaceModifierData *)md, ctx, mesh_src, vertexCos, numVerts);
386
387         if (!ELEM(mesh_src, NULL, mesh)) {
388                 BKE_id_free(NULL, mesh_src);
389         }
390 }
391
392 static void deformVertsEM(
393         ModifierData *md, const ModifierEvalContext *ctx, struct BMEditMesh *editData,
394         Mesh *mesh, float (*vertexCos)[3], int numVerts)
395 {
396         Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false);
397
398         displaceModifier_do((DisplaceModifierData *)md, ctx, mesh_src, vertexCos, numVerts);
399
400         if (!ELEM(mesh_src, NULL, mesh)) {
401                 BKE_id_free(NULL, mesh_src);
402         }
403 }
404
405
406 ModifierTypeInfo modifierType_Displace = {
407         /* name */              "Displace",
408         /* structName */        "DisplaceModifierData",
409         /* structSize */        sizeof(DisplaceModifierData),
410         /* type */              eModifierTypeType_OnlyDeform,
411         /* flags */             eModifierTypeFlag_AcceptsMesh |
412                                 eModifierTypeFlag_SupportsEditmode,
413
414         /* copyData */          modifier_copyData_generic,
415
416         /* deformVerts_DM */    NULL,
417         /* deformMatrices_DM */ NULL,
418         /* deformVertsEM_DM */  NULL,
419         /* deformMatricesEM_DM*/NULL,
420         /* applyModifier_DM */  NULL,
421
422         /* deformVerts */       deformVerts,
423         /* deformMatrices */    NULL,
424         /* deformVertsEM */     deformVertsEM,
425         /* deformMatricesEM */  NULL,
426         /* applyModifier */     NULL,
427
428         /* initData */          initData,
429         /* requiredDataMask */  requiredDataMask,
430         /* freeData */          NULL,
431         /* isDisabled */        isDisabled,
432         /* updateDepsgraph */   updateDepsgraph,
433         /* dependsOnTime */     dependsOnTime,
434         /* dependsOnNormals */  dependsOnNormals,
435         /* foreachObjectLink */ foreachObjectLink,
436         /* foreachIDLink */     foreachIDLink,
437         /* foreachTexLink */    foreachTexLink,
438 };