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