Depsgraph: remove EvaluationContext, pass Depsgraph instead.
[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_meshdata_types.h"
37 #include "DNA_object_types.h"
38
39 #include "BLI_utildefines.h"
40 #include "BLI_math.h"
41 #include "BLI_task.h"
42
43 #include "BKE_cdderivedmesh.h"
44 #include "BKE_library.h"
45 #include "BKE_library_query.h"
46 #include "BKE_image.h"
47 #include "BKE_mesh.h"
48 #include "BKE_modifier.h"
49 #include "BKE_texture.h"
50 #include "BKE_deform.h"
51 #include "BKE_object.h"
52
53 #include "MEM_guardedalloc.h"
54
55 #include "MOD_util.h"
56
57 #include "RE_shader_ext.h"
58
59
60 /* Displace */
61
62 static void initData(ModifierData *md)
63 {
64         DisplaceModifierData *dmd = (DisplaceModifierData *) md;
65
66         dmd->texture = NULL;
67         dmd->strength = 1;
68         dmd->direction = MOD_DISP_DIR_NOR;
69         dmd->midlevel = 0.5;
70         dmd->space = MOD_DISP_SPACE_LOCAL;
71 }
72
73 static void copyData(ModifierData *md, ModifierData *target)
74 {
75 #if 0
76         DisplaceModifierData *dmd = (DisplaceModifierData *) md;
77         DisplaceModifierData *tdmd = (DisplaceModifierData *) target;
78 #endif
79
80         modifier_copyData_generic(md, target);
81 }
82
83 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
84 {
85         DisplaceModifierData *dmd = (DisplaceModifierData *)md;
86         CustomDataMask dataMask = 0;
87
88         /* ask for vertexgroups if we need them */
89         if (dmd->defgrp_name[0]) dataMask |= CD_MASK_MDEFORMVERT;
90
91         /* ask for UV coordinates if we need them */
92         if (dmd->texmapping == MOD_DISP_MAP_UV) dataMask |= CD_MASK_MTFACE;
93
94         if (dmd->direction == MOD_DISP_DIR_CLNOR) {
95                 dataMask |= CD_MASK_CUSTOMLOOPNORMAL;
96         }
97
98         return dataMask;
99 }
100
101 static bool dependsOnTime(ModifierData *md)
102 {
103         DisplaceModifierData *dmd = (DisplaceModifierData *)md;
104
105         if (dmd->texture) {
106                 return BKE_texture_dependsOnTime(dmd->texture);
107         }
108         else {
109                 return false;
110         }
111 }
112
113 static bool dependsOnNormals(ModifierData *md)
114 {
115         DisplaceModifierData *dmd = (DisplaceModifierData *)md;
116         return ELEM(dmd->direction, MOD_DISP_DIR_NOR, MOD_DISP_DIR_CLNOR);
117 }
118
119 static void foreachObjectLink(ModifierData *md, Object *ob,
120                               ObjectWalkFunc walk, void *userData)
121 {
122         DisplaceModifierData *dmd = (DisplaceModifierData *) md;
123
124         walk(userData, ob, &dmd->map_object, IDWALK_CB_NOP);
125 }
126
127 static void foreachIDLink(ModifierData *md, Object *ob,
128                           IDWalkFunc walk, void *userData)
129 {
130         DisplaceModifierData *dmd = (DisplaceModifierData *) md;
131
132         walk(userData, ob, (ID **)&dmd->texture, IDWALK_CB_USER);
133
134         foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
135 }
136
137 static void foreachTexLink(ModifierData *md, Object *ob,
138                            TexWalkFunc walk, void *userData)
139 {
140         walk(userData, ob, md, "texture");
141 }
142
143 static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
144 {
145         DisplaceModifierData *dmd = (DisplaceModifierData *) md;
146         return ((!dmd->texture && dmd->direction == MOD_DISP_DIR_RGB_XYZ) || dmd->strength == 0.0f);
147 }
148
149 static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
150 {
151         DisplaceModifierData *dmd = (DisplaceModifierData *)md;
152         if (dmd->map_object != NULL && dmd->texmapping == MOD_DISP_MAP_OBJECT) {
153                 DEG_add_object_relation(ctx->node, dmd->map_object, DEG_OB_COMP_TRANSFORM, "Displace Modifier");
154         }
155         if (dmd->texmapping == MOD_DISP_MAP_GLOBAL ||
156             (ELEM(dmd->direction, MOD_DISP_DIR_X, MOD_DISP_DIR_Y, MOD_DISP_DIR_Z, MOD_DISP_DIR_RGB_XYZ) &&
157             dmd->space == MOD_DISP_SPACE_GLOBAL))
158         {
159                 DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Displace Modifier");
160         }
161 }
162
163 typedef struct DisplaceUserdata {
164         /*const*/ DisplaceModifierData *dmd;
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(dmd->modifier.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 /* dm must be a CDDerivedMesh */
278 static void displaceModifier_do(
279         DisplaceModifierData *dmd, Object *ob,
280         DerivedMesh *dm, float (*vertexCos)[3], int numVerts)
281 {
282         MVert *mvert;
283         MDeformVert *dvert;
284         int direction = dmd->direction;
285         int defgrp_index;
286         float (*tex_co)[3];
287         float weight = 1.0f; /* init value unused but some compilers may complain */
288         float (*vert_clnors)[3] = NULL;
289         float local_mat[4][4] = {{0}};
290         const bool use_global_direction = dmd->space == MOD_DISP_SPACE_GLOBAL;
291
292         if (!dmd->texture && dmd->direction == MOD_DISP_DIR_RGB_XYZ) return;
293         if (dmd->strength == 0.0f) return;
294
295         mvert = CDDM_get_verts(dm);
296         modifier_get_vgroup(ob, dm, dmd->defgrp_name, &dvert, &defgrp_index);
297
298         if (dmd->texture) {
299                 tex_co = MEM_calloc_arrayN((size_t)numVerts, sizeof(*tex_co),
300                                      "displaceModifier_do tex_co");
301                 get_texture_coords((MappingInfoModifierData *)dmd, ob, dm, vertexCos, tex_co, numVerts);
302
303                 modifier_init_texture(dmd->modifier.scene, dmd->texture);
304         }
305         else {
306                 tex_co = NULL;
307         }
308
309         if (direction == MOD_DISP_DIR_CLNOR) {
310                 CustomData *ldata = dm->getLoopDataLayout(dm);
311
312                 if (CustomData_has_layer(ldata, CD_CUSTOMLOOPNORMAL)) {
313                         float (*clnors)[3] = NULL;
314
315                         if ((dm->dirty & DM_DIRTY_NORMALS) || !CustomData_has_layer(ldata, CD_NORMAL)) {
316                                 dm->calcLoopNormals(dm, true, (float)M_PI);
317                         }
318
319                         clnors = CustomData_get_layer(ldata, CD_NORMAL);
320                         vert_clnors = MEM_malloc_arrayN(numVerts, sizeof(*vert_clnors), __func__);
321                         BKE_mesh_normals_loop_to_vertex(numVerts, dm->getLoopArray(dm), dm->getNumLoops(dm),
322                                                         (const float (*)[3])clnors, vert_clnors);
323                 }
324                 else {
325                         direction = MOD_DISP_DIR_NOR;
326                 }
327         }
328         else if (ELEM(direction, MOD_DISP_DIR_X, MOD_DISP_DIR_Y, MOD_DISP_DIR_Z, MOD_DISP_DIR_RGB_XYZ) &&
329                  use_global_direction)
330         {
331                 copy_m4_m4(local_mat, ob->obmat);
332         }
333
334         DisplaceUserdata data = {NULL};
335         data.dmd = dmd;
336         data.dvert = dvert;
337         data.weight = weight;
338         data.defgrp_index = defgrp_index;
339         data.direction = direction;
340         data.use_global_direction = use_global_direction;
341         data.tex_co = tex_co;
342         data.vertexCos = vertexCos;
343         copy_m4_m4(data.local_mat, local_mat);
344         data.mvert = mvert;
345         data.vert_clnors = vert_clnors;
346         if (dmd->texture != NULL) {
347                 data.pool = BKE_image_pool_new();
348                 BKE_texture_fetch_images_for_pool(dmd->texture, data.pool);
349         }
350         ParallelRangeSettings settings;
351         BLI_parallel_range_settings_defaults(&settings);
352         settings.use_threading = (numVerts > 512);
353         BLI_task_parallel_range(0, numVerts,
354                                 &data,
355                                 displaceModifier_do_task,
356                                 &settings);
357
358         if (data.pool != NULL) {
359                 BKE_image_pool_free(data.pool);
360         }
361
362         if (tex_co) {
363                 MEM_freeN(tex_co);
364         }
365
366         if (vert_clnors) {
367                 MEM_freeN(vert_clnors);
368         }
369 }
370
371 static void deformVerts(ModifierData *md, struct Depsgraph *UNUSED(depsgraph),
372                         Object *ob, DerivedMesh *derivedData,
373                         float (*vertexCos)[3],
374                         int numVerts,
375                         ModifierApplyFlag UNUSED(flag))
376 {
377         DerivedMesh *dm = get_cddm(ob, NULL, derivedData, vertexCos, dependsOnNormals(md));
378
379         displaceModifier_do((DisplaceModifierData *)md, ob, dm,
380                             vertexCos, numVerts);
381
382         if (dm != derivedData)
383                 dm->release(dm);
384 }
385
386 static void deformVertsEM(
387         ModifierData *md, struct Depsgraph *UNUSED(depsgraph), Object *ob, struct BMEditMesh *editData,
388         DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
389 {
390         DerivedMesh *dm = get_cddm(ob, editData, derivedData, vertexCos, dependsOnNormals(md));
391
392         displaceModifier_do((DisplaceModifierData *)md, ob, dm,
393                             vertexCos, numVerts);
394
395         if (dm != derivedData)
396                 dm->release(dm);
397 }
398
399
400 ModifierTypeInfo modifierType_Displace = {
401         /* name */              "Displace",
402         /* structName */        "DisplaceModifierData",
403         /* structSize */        sizeof(DisplaceModifierData),
404         /* type */              eModifierTypeType_OnlyDeform,
405         /* flags */             eModifierTypeFlag_AcceptsMesh |
406                                 eModifierTypeFlag_SupportsEditmode,
407
408         /* copyData */          copyData,
409         /* deformVerts */       deformVerts,
410         /* deformMatrices */    NULL,
411         /* deformVertsEM */     deformVertsEM,
412         /* deformMatricesEM */  NULL,
413         /* applyModifier */     NULL,
414         /* applyModifierEM */   NULL,
415         /* initData */          initData,
416         /* requiredDataMask */  requiredDataMask,
417         /* freeData */          NULL,
418         /* isDisabled */        isDisabled,
419         /* updateDepsgraph */   updateDepsgraph,
420         /* dependsOnTime */     dependsOnTime,
421         /* dependsOnNormals */  dependsOnNormals,
422         /* foreachObjectLink */ foreachObjectLink,
423         /* foreachIDLink */     foreachIDLink,
424         /* foreachTexLink */    foreachTexLink,
425 };