Depsgrapgh: Use more distinctive opcode for texture and image evaluation
[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 }
161
162 typedef struct DisplaceUserdata {
163         /*const*/ DisplaceModifierData *dmd;
164         struct Scene *scene;
165         struct ImagePool *pool;
166         MDeformVert *dvert;
167         float weight;
168         int defgrp_index;
169         int direction;
170         bool use_global_direction;
171         float (*tex_co)[3];
172         float (*vertexCos)[3];
173         float local_mat[4][4];
174         MVert *mvert;
175         float (*vert_clnors)[3];
176 } DisplaceUserdata;
177
178 static void displaceModifier_do_task(
179         void *__restrict userdata,
180         const int iter,
181         const ParallelRangeTLS *__restrict UNUSED(tls))
182 {
183         DisplaceUserdata *data = (DisplaceUserdata *)userdata;
184         DisplaceModifierData *dmd = data->dmd;
185         MDeformVert *dvert = data->dvert;
186         float weight = data->weight;
187         int defgrp_index = data->defgrp_index;
188         int direction = data->direction;
189         bool use_global_direction = data->use_global_direction;
190         float (*tex_co)[3] = data->tex_co;
191         float (*vertexCos)[3] = data->vertexCos;
192         MVert *mvert = data->mvert;
193         float (*vert_clnors)[3] = data->vert_clnors;
194
195         const float delta_fixed = 1.0f - dmd->midlevel;  /* when no texture is used, we fallback to white */
196
197         TexResult texres;
198         float strength = dmd->strength;
199         float delta;
200         float local_vec[3];
201
202         if (dvert) {
203                 weight = defvert_find_weight(dvert + iter, defgrp_index);
204                 if (weight == 0.0f) {
205                         return;
206                 }
207         }
208
209         if (dmd->texture) {
210                 texres.nor = NULL;
211                 BKE_texture_get_value_ex(data->scene, dmd->texture, tex_co[iter], &texres, data->pool, false);
212                 delta = texres.tin - dmd->midlevel;
213         }
214         else {
215                 delta = delta_fixed;  /* (1.0f - dmd->midlevel) */  /* never changes */
216         }
217
218         if (dvert) {
219                 strength *= weight;
220         }
221
222         delta *= strength;
223         CLAMP(delta, -10000, 10000);
224
225         switch (direction) {
226                 case MOD_DISP_DIR_X:
227                         if (use_global_direction) {
228                                 vertexCos[iter][0] += delta * data->local_mat[0][0];
229                                 vertexCos[iter][1] += delta * data->local_mat[1][0];
230                                 vertexCos[iter][2] += delta * data->local_mat[2][0];
231                         }
232                         else {
233                                 vertexCos[iter][0] += delta;
234                         }
235                         break;
236                 case MOD_DISP_DIR_Y:
237                         if (use_global_direction) {
238                                 vertexCos[iter][0] += delta * data->local_mat[0][1];
239                                 vertexCos[iter][1] += delta * data->local_mat[1][1];
240                                 vertexCos[iter][2] += delta * data->local_mat[2][1];
241                         }
242                         else {
243                                 vertexCos[iter][1] += delta;
244                         }
245                         break;
246                 case MOD_DISP_DIR_Z:
247                         if (use_global_direction) {
248                                 vertexCos[iter][0] += delta * data->local_mat[0][2];
249                                 vertexCos[iter][1] += delta * data->local_mat[1][2];
250                                 vertexCos[iter][2] += delta * data->local_mat[2][2];
251                         }
252                         else {
253                                 vertexCos[iter][2] += delta;
254                         }
255                         break;
256                 case MOD_DISP_DIR_RGB_XYZ:
257                         local_vec[0] = texres.tr - dmd->midlevel;
258                         local_vec[1] = texres.tg - dmd->midlevel;
259                         local_vec[2] = texres.tb - dmd->midlevel;
260                         if (use_global_direction) {
261                                 mul_transposed_mat3_m4_v3(data->local_mat, local_vec);
262                         }
263                         mul_v3_fl(local_vec, strength);
264                         add_v3_v3(vertexCos[iter], local_vec);
265                         break;
266                 case MOD_DISP_DIR_NOR:
267                         vertexCos[iter][0] += delta * (mvert[iter].no[0] / 32767.0f);
268                         vertexCos[iter][1] += delta * (mvert[iter].no[1] / 32767.0f);
269                         vertexCos[iter][2] += delta * (mvert[iter].no[2] / 32767.0f);
270                         break;
271                 case MOD_DISP_DIR_CLNOR:
272                         madd_v3_v3fl(vertexCos[iter], vert_clnors[iter], delta);
273                         break;
274         }
275 }
276
277 static void displaceModifier_do(
278         DisplaceModifierData *dmd, const ModifierEvalContext *ctx,
279         Mesh *mesh, float (*vertexCos)[3], const int numVerts)
280 {
281         Object *ob = ctx->object;
282         Depsgraph *depsgraph = ctx->depsgraph;
283         MVert *mvert;
284         MDeformVert *dvert;
285         int direction = dmd->direction;
286         int defgrp_index;
287         float (*tex_co)[3];
288         float weight = 1.0f; /* init value unused but some compilers may complain */
289         float (*vert_clnors)[3] = NULL;
290         float local_mat[4][4] = {{0}};
291         const bool use_global_direction = dmd->space == MOD_DISP_SPACE_GLOBAL;
292
293         if (!dmd->texture && dmd->direction == MOD_DISP_DIR_RGB_XYZ) return;
294         if (dmd->strength == 0.0f) return;
295
296         mvert = mesh->mvert;
297         MOD_get_vgroup(ob, mesh, dmd->defgrp_name, &dvert, &defgrp_index);
298
299         if (dmd->texture) {
300                 tex_co = MEM_calloc_arrayN((size_t)numVerts, sizeof(*tex_co),
301                                      "displaceModifier_do tex_co");
302                 MOD_get_texture_coords((MappingInfoModifierData *)dmd, ob, mesh, vertexCos, tex_co);
303
304                 MOD_init_texture(depsgraph, dmd->texture);
305         }
306         else {
307                 tex_co = NULL;
308         }
309
310         if (direction == MOD_DISP_DIR_CLNOR) {
311                 CustomData *ldata = &mesh->ldata;
312
313                 if (CustomData_has_layer(ldata, CD_CUSTOMLOOPNORMAL)) {
314                         float (*clnors)[3] = NULL;
315
316                         if ((mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) || !CustomData_has_layer(ldata, CD_NORMAL)) {
317                                 BKE_mesh_calc_normals_split(mesh);
318                         }
319
320                         clnors = CustomData_get_layer(ldata, CD_NORMAL);
321                         vert_clnors = MEM_malloc_arrayN(numVerts, sizeof(*vert_clnors), __func__);
322                         BKE_mesh_normals_loop_to_vertex(numVerts, mesh->mloop, mesh->totloop,
323                                                         (const float (*)[3])clnors, vert_clnors);
324                 }
325                 else {
326                         direction = MOD_DISP_DIR_NOR;
327                 }
328         }
329         else if (ELEM(direction, MOD_DISP_DIR_X, MOD_DISP_DIR_Y, MOD_DISP_DIR_Z, MOD_DISP_DIR_RGB_XYZ) &&
330                  use_global_direction)
331         {
332                 copy_m4_m4(local_mat, ob->obmat);
333         }
334
335         DisplaceUserdata data = {NULL};
336         data.scene = DEG_get_evaluated_scene(ctx->depsgraph);
337         data.dmd = dmd;
338         data.dvert = dvert;
339         data.weight = weight;
340         data.defgrp_index = defgrp_index;
341         data.direction = direction;
342         data.use_global_direction = use_global_direction;
343         data.tex_co = tex_co;
344         data.vertexCos = vertexCos;
345         copy_m4_m4(data.local_mat, local_mat);
346         data.mvert = mvert;
347         data.vert_clnors = vert_clnors;
348         if (dmd->texture != NULL) {
349                 data.pool = BKE_image_pool_new();
350                 BKE_texture_fetch_images_for_pool(dmd->texture, data.pool);
351         }
352         ParallelRangeSettings settings;
353         BLI_parallel_range_settings_defaults(&settings);
354         settings.use_threading = (numVerts > 512);
355         BLI_task_parallel_range(0, numVerts,
356                                 &data,
357                                 displaceModifier_do_task,
358                                 &settings);
359
360         if (data.pool != NULL) {
361                 BKE_image_pool_free(data.pool);
362         }
363
364         if (tex_co) {
365                 MEM_freeN(tex_co);
366         }
367
368         if (vert_clnors) {
369                 MEM_freeN(vert_clnors);
370         }
371 }
372
373 static void deformVerts(
374         ModifierData *md,
375         const ModifierEvalContext *ctx,
376         Mesh *mesh,
377         float (*vertexCos)[3],
378         int numVerts)
379 {
380         Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false);
381
382         displaceModifier_do((DisplaceModifierData *)md, ctx, mesh_src, vertexCos, numVerts);
383
384         if (!ELEM(mesh_src, NULL, mesh)) {
385                 BKE_id_free(NULL, mesh_src);
386         }
387 }
388
389 static void deformVertsEM(
390         ModifierData *md, const ModifierEvalContext *ctx, struct BMEditMesh *editData,
391         Mesh *mesh, float (*vertexCos)[3], int numVerts)
392 {
393         Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false);
394
395         displaceModifier_do((DisplaceModifierData *)md, ctx, mesh_src, vertexCos, numVerts);
396
397         if (!ELEM(mesh_src, NULL, mesh)) {
398                 BKE_id_free(NULL, mesh_src);
399         }
400 }
401
402
403 ModifierTypeInfo modifierType_Displace = {
404         /* name */              "Displace",
405         /* structName */        "DisplaceModifierData",
406         /* structSize */        sizeof(DisplaceModifierData),
407         /* type */              eModifierTypeType_OnlyDeform,
408         /* flags */             eModifierTypeFlag_AcceptsMesh |
409                                 eModifierTypeFlag_SupportsEditmode,
410
411         /* copyData */          modifier_copyData_generic,
412
413         /* deformVerts_DM */    NULL,
414         /* deformMatrices_DM */ NULL,
415         /* deformVertsEM_DM */  NULL,
416         /* deformMatricesEM_DM*/NULL,
417         /* applyModifier_DM */  NULL,
418
419         /* deformVerts */       deformVerts,
420         /* deformMatrices */    NULL,
421         /* deformVertsEM */     deformVertsEM,
422         /* deformMatricesEM */  NULL,
423         /* applyModifier */     NULL,
424
425         /* initData */          initData,
426         /* requiredDataMask */  requiredDataMask,
427         /* freeData */          NULL,
428         /* isDisabled */        isDisabled,
429         /* updateDepsgraph */   updateDepsgraph,
430         /* dependsOnTime */     dependsOnTime,
431         /* dependsOnNormals */  dependsOnNormals,
432         /* foreachObjectLink */ foreachObjectLink,
433         /* foreachIDLink */     foreachIDLink,
434         /* foreachTexLink */    foreachTexLink,
435 };