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