Depsgrapgh: Use more distinctive opcode for texture and image evaluation
[blender.git] / source / blender / modifiers / intern / MOD_warp.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  * Contributor(s): Campbell Barton
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  *
22  */
23
24 /** \file blender/modifiers/intern/MOD_warp.c
25  *  \ingroup modifiers
26  */
27
28 #include <string.h>
29
30 #include "MEM_guardedalloc.h"
31
32 #include "DNA_mesh_types.h"
33 #include "DNA_meshdata_types.h"
34 #include "DNA_object_types.h"
35
36 #include "BLI_math.h"
37 #include "BLI_utildefines.h"
38
39 #include "BKE_editmesh.h"
40 #include "BKE_library.h"
41 #include "BKE_library_query.h"
42 #include "BKE_mesh.h"
43 #include "BKE_modifier.h"
44 #include "BKE_deform.h"
45 #include "BKE_texture.h"
46 #include "BKE_colortools.h"
47
48 #include "DEG_depsgraph.h"
49 #include "DEG_depsgraph_query.h"
50
51 #include "RE_shader_ext.h"
52
53 #include "MOD_util.h"
54
55
56 static void initData(ModifierData *md)
57 {
58         WarpModifierData *wmd = (WarpModifierData *) md;
59
60         wmd->curfalloff = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
61         wmd->texture = NULL;
62         wmd->strength = 1.0f;
63         wmd->falloff_radius = 1.0f;
64         wmd->falloff_type = eWarp_Falloff_Smooth;
65         wmd->flag = 0;
66 }
67
68 static void copyData(const ModifierData *md, ModifierData *target, const int flag)
69 {
70         const WarpModifierData *wmd = (const WarpModifierData *) md;
71         WarpModifierData *twmd = (WarpModifierData *) target;
72
73         modifier_copyData_generic(md, target, flag);
74
75         twmd->curfalloff = curvemapping_copy(wmd->curfalloff);
76 }
77
78 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
79 {
80         WarpModifierData *wmd = (WarpModifierData *)md;
81         CustomDataMask dataMask = 0;
82
83         /* ask for vertexgroups if we need them */
84         if (wmd->defgrp_name[0]) dataMask |= (CD_MASK_MDEFORMVERT);
85         dataMask |= (CD_MASK_MDEFORMVERT);
86
87         /* ask for UV coordinates if we need them */
88         if (wmd->texmapping == MOD_DISP_MAP_UV) dataMask |= (1 << CD_MTFACE);
89
90         return dataMask;
91 }
92
93 static bool dependsOnTime(ModifierData *md)
94 {
95         WarpModifierData *wmd = (WarpModifierData *)md;
96
97         if (wmd->texture) {
98                 return BKE_texture_dependsOnTime(wmd->texture);
99         }
100         else {
101                 return false;
102         }
103 }
104
105 static void freeData(ModifierData *md)
106 {
107         WarpModifierData *wmd = (WarpModifierData *) md;
108         curvemapping_free(wmd->curfalloff);
109 }
110
111
112 static bool isDisabled(const struct Scene *UNUSED(scene), ModifierData *md, bool UNUSED(userRenderParams))
113 {
114         WarpModifierData *wmd = (WarpModifierData *) md;
115
116         return !(wmd->object_from && wmd->object_to);
117 }
118
119 static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
120 {
121         WarpModifierData *wmd = (WarpModifierData *) md;
122
123         walk(userData, ob, &wmd->object_from, IDWALK_CB_NOP);
124         walk(userData, ob, &wmd->object_to, IDWALK_CB_NOP);
125         walk(userData, ob, &wmd->map_object, IDWALK_CB_NOP);
126 }
127
128 static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
129 {
130         WarpModifierData *wmd = (WarpModifierData *) md;
131
132         walk(userData, ob, (ID **)&wmd->texture, IDWALK_CB_USER);
133
134         foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
135 }
136
137 static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void *userData)
138 {
139         walk(userData, ob, md, "texture");
140 }
141
142 static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
143 {
144         WarpModifierData *wmd = (WarpModifierData *) md;
145         if (wmd->object_from != NULL && wmd->object_to != NULL) {
146                 DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Warplace Modifier");
147                 DEG_add_object_relation(ctx->node, wmd->object_from, DEG_OB_COMP_TRANSFORM, "Warp Modifier from");
148                 DEG_add_object_relation(ctx->node, wmd->object_to, DEG_OB_COMP_TRANSFORM, "Warp Modifier to");
149         }
150         if ((wmd->texmapping == MOD_DISP_MAP_OBJECT) && wmd->map_object != NULL) {
151                 DEG_add_object_relation(ctx->node, wmd->map_object, DEG_OB_COMP_TRANSFORM, "Warp Modifier map");
152         }
153 }
154
155 static void warpModifier_do(
156         WarpModifierData *wmd, const ModifierEvalContext *ctx,
157         Mesh *mesh, float (*vertexCos)[3], int numVerts)
158 {
159         Object *ob = ctx->object;
160         Depsgraph *depsgraph = ctx->depsgraph;
161         float obinv[4][4];
162         float mat_from[4][4];
163         float mat_from_inv[4][4];
164         float mat_to[4][4];
165         float mat_unit[4][4];
166         float mat_final[4][4];
167
168         float tmat[4][4];
169
170         const float falloff_radius_sq = SQUARE(wmd->falloff_radius);
171         float strength = wmd->strength;
172         float fac = 1.0f, weight;
173         int i;
174         int defgrp_index;
175         MDeformVert *dvert, *dv = NULL;
176
177         float (*tex_co)[3] = NULL;
178
179         if (!(wmd->object_from && wmd->object_to))
180                 return;
181
182         MOD_get_vgroup(ob, mesh, wmd->defgrp_name, &dvert, &defgrp_index);
183         if (dvert == NULL) {
184                 defgrp_index = -1;
185         }
186
187         if (wmd->curfalloff == NULL) /* should never happen, but bad lib linking could cause it */
188                 wmd->curfalloff = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
189
190         if (wmd->curfalloff) {
191                 curvemapping_initialize(wmd->curfalloff);
192         }
193
194         invert_m4_m4(obinv, ob->obmat);
195
196         mul_m4_m4m4(mat_from, obinv, wmd->object_from->obmat);
197         mul_m4_m4m4(mat_to, obinv, wmd->object_to->obmat);
198
199         invert_m4_m4(tmat, mat_from); // swap?
200         mul_m4_m4m4(mat_final, tmat, mat_to);
201
202         invert_m4_m4(mat_from_inv, mat_from);
203
204         unit_m4(mat_unit);
205
206         if (strength < 0.0f) {
207                 float loc[3];
208                 strength = -strength;
209
210                 /* inverted location is not useful, just use the negative */
211                 copy_v3_v3(loc, mat_final[3]);
212                 invert_m4(mat_final);
213                 negate_v3_v3(mat_final[3], loc);
214
215         }
216         weight = strength;
217
218         if (mesh != NULL && wmd->texture) {
219                 tex_co = MEM_malloc_arrayN(numVerts, sizeof(*tex_co), "warpModifier_do tex_co");
220                 MOD_get_texture_coords((MappingInfoModifierData *)wmd, ob, mesh, vertexCos, tex_co);
221
222                 MOD_init_texture(depsgraph, wmd->texture);
223         }
224
225         for (i = 0; i < numVerts; i++) {
226                 float *co = vertexCos[i];
227
228                 if (wmd->falloff_type == eWarp_Falloff_None ||
229                     ((fac = len_squared_v3v3(co, mat_from[3])) < falloff_radius_sq &&
230                      (fac = (wmd->falloff_radius - sqrtf(fac)) / wmd->falloff_radius)))
231                 {
232                         /* skip if no vert group found */
233                         if (defgrp_index != -1) {
234                                 dv = &dvert[i];
235                                 weight = defvert_find_weight(dv, defgrp_index) * strength;
236                                 if (weight <= 0.0f) {
237                                         continue;
238                                 }
239                         }
240
241
242                         /* closely match PROP_SMOOTH and similar */
243                         switch (wmd->falloff_type) {
244                                 case eWarp_Falloff_None:
245                                         fac = 1.0f;
246                                         break;
247                                 case eWarp_Falloff_Curve:
248                                         fac = curvemapping_evaluateF(wmd->curfalloff, 0, fac);
249                                         break;
250                                 case eWarp_Falloff_Sharp:
251                                         fac = fac * fac;
252                                         break;
253                                 case eWarp_Falloff_Smooth:
254                                         fac = 3.0f * fac * fac - 2.0f * fac * fac * fac;
255                                         break;
256                                 case eWarp_Falloff_Root:
257                                         fac = sqrtf(fac);
258                                         break;
259                                 case eWarp_Falloff_Linear:
260                                         /* pass */
261                                         break;
262                                 case eWarp_Falloff_Const:
263                                         fac = 1.0f;
264                                         break;
265                                 case eWarp_Falloff_Sphere:
266                                         fac = sqrtf(2 * fac - fac * fac);
267                                         break;
268                                 case eWarp_Falloff_InvSquare:
269                                         fac = fac * (2.0f - fac);
270                                         break;
271                         }
272
273                         fac *= weight;
274
275                         if (tex_co) {
276                                 struct Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
277                                 TexResult texres;
278                                 texres.nor = NULL;
279                                 BKE_texture_get_value(scene, wmd->texture, tex_co[i], &texres, false);
280                                 fac *= texres.tin;
281                         }
282
283                         if (fac != 0.0f) {
284                                 /* into the 'from' objects space */
285                                 mul_m4_v3(mat_from_inv, co);
286
287                                 if (fac == 1.0f) {
288                                         mul_m4_v3(mat_final, co);
289                                 }
290                                 else {
291                                         if (wmd->flag & MOD_WARP_VOLUME_PRESERVE) {
292                                                 /* interpolate the matrix for nicer locations */
293                                                 blend_m4_m4m4(tmat, mat_unit, mat_final, fac);
294                                                 mul_m4_v3(tmat, co);
295                                         }
296                                         else {
297                                                 float tvec[3];
298                                                 mul_v3_m4v3(tvec, mat_final, co);
299                                                 interp_v3_v3v3(co, co, tvec, fac);
300                                         }
301                                 }
302
303                                 /* out of the 'from' objects space */
304                                 mul_m4_v3(mat_from, co);
305                         }
306                 }
307         }
308
309         if (tex_co) {
310                 MEM_freeN(tex_co);
311         }
312 }
313
314 static void deformVerts(
315         ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh,
316         float (*vertexCos)[3], int numVerts)
317 {
318         WarpModifierData *wmd = (WarpModifierData *)md;
319         Mesh *mesh_src = NULL;
320
321         if (wmd->defgrp_name[0] != '\0' || wmd->texture != NULL) {
322                 /* mesh_src is only needed for vgroups and textures. */
323                 mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false);
324         }
325
326         warpModifier_do(wmd, ctx, mesh_src, vertexCos, numVerts);
327
328         if (!ELEM(mesh_src, NULL, mesh)) {
329                 BKE_id_free(NULL, mesh_src);
330         }
331 }
332
333 static void deformVertsEM(
334         ModifierData *md, const ModifierEvalContext *ctx, struct BMEditMesh *em,
335         Mesh *mesh, float (*vertexCos)[3], int numVerts)
336 {
337         WarpModifierData *wmd = (WarpModifierData *)md;
338         Mesh *mesh_src = NULL;
339
340         if (wmd->defgrp_name[0] != '\0' || wmd->texture != NULL) {
341                 /* mesh_src is only needed for vgroups and textures. */
342                 mesh_src = MOD_deform_mesh_eval_get(ctx->object, em, mesh, NULL, numVerts, false, false);
343         }
344
345         warpModifier_do(wmd, ctx, mesh_src, vertexCos, numVerts);
346
347         if (!ELEM(mesh_src, NULL, mesh)) {
348                 BKE_id_free(NULL, mesh_src);
349         }
350 }
351
352
353 ModifierTypeInfo modifierType_Warp = {
354         /* name */              "Warp",
355         /* structName */        "WarpModifierData",
356         /* structSize */        sizeof(WarpModifierData),
357         /* type */              eModifierTypeType_OnlyDeform,
358         /* flags */             eModifierTypeFlag_AcceptsCVs |
359                                 eModifierTypeFlag_AcceptsLattice |
360                                 eModifierTypeFlag_SupportsEditmode,
361         /* copyData */          copyData,
362
363         /* deformVerts_DM */    NULL,
364         /* deformMatrices_DM */ NULL,
365         /* deformVertsEM_DM */  NULL,
366         /* deformMatricesEM_DM*/NULL,
367         /* applyModifier_DM */  NULL,
368
369         /* deformVerts */       deformVerts,
370         /* deformMatrices */    NULL,
371         /* deformVertsEM */     deformVertsEM,
372         /* deformMatricesEM */  NULL,
373         /* applyModifier */     NULL,
374
375         /* initData */          initData,
376         /* requiredDataMask */  requiredDataMask,
377         /* freeData */          freeData,
378         /* isDisabled */        isDisabled,
379         /* updateDepsgraph */   updateDepsgraph,
380         /* dependsOnTime */     dependsOnTime,
381         /* dependsOnNormals */  NULL,
382         /* foreachObjectLink */ foreachObjectLink,
383         /* foreachIDLink */     foreachIDLink,
384         /* foreachTexLink */    foreachTexLink,
385 };