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