Minor tweaks to some UI messages...
[blender.git] / source / blender / modifiers / intern / MOD_uvwarp.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): Pawel Kowal, Campbell Barton
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  *
22  */
23
24 /** \file blender/modifiers/intern/MOD_uvwarp.c
25  *  \ingroup modifiers
26  */
27
28 #include <string.h>
29
30 #include "DNA_meshdata_types.h"
31 #include "DNA_object_types.h"
32
33 #include "BLI_math.h"
34 #include "BLI_string.h"
35 #include "BLI_utildefines.h"
36
37 #include "BKE_action.h"  /* BKE_pose_channel_find_name */
38 #include "BKE_cdderivedmesh.h"
39 #include "BKE_deform.h"
40 #include "BKE_modifier.h"
41
42 #include "depsgraph_private.h"
43
44 #include "MOD_util.h"
45
46
47 static void uv_warp_from_mat4_pair(float uv_dst[2], const float uv_src[2], float warp_mat[4][4],
48                                    int axis_u, int axis_v)
49 {
50         float tuv[3] = {0.0f};
51
52         tuv[axis_u] = uv_src[0];
53         tuv[axis_v] = uv_src[1];
54
55         mul_m4_v3(warp_mat, tuv);
56
57         uv_dst[0] = tuv[axis_u];
58         uv_dst[1] = tuv[axis_v];
59 }
60
61 static void initData(ModifierData *md)
62 {
63         UVWarpModifierData *umd = (UVWarpModifierData *) md;
64         umd->axis_u = 0;
65         umd->axis_v = 1;
66         copy_v2_fl(umd->center, 0.5f);
67 }
68
69 static void copyData(ModifierData *md, ModifierData *target)
70 {
71         UVWarpModifierData *umd  = (UVWarpModifierData *)md;
72         UVWarpModifierData *tumd = (UVWarpModifierData *)target;
73
74         tumd->axis_u = umd->axis_u;
75         tumd->axis_v = umd->axis_v;
76         copy_v2_v2(tumd->center, umd->center);
77         tumd->object_src = umd->object_src;
78         BLI_strncpy(tumd->bone_src, umd->bone_src, sizeof(tumd->bone_src));
79         tumd->object_dst = umd->object_dst;
80         BLI_strncpy(tumd->bone_dst, umd->bone_dst, sizeof(tumd->bone_dst));
81         BLI_strncpy(tumd->vgroup_name, umd->vgroup_name, sizeof(tumd->vgroup_name));
82         BLI_strncpy(tumd->uvlayer_name, umd->uvlayer_name, sizeof(umd->uvlayer_name));
83 }
84
85 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
86 {
87         UVWarpModifierData *umd = (UVWarpModifierData *)md;
88         CustomDataMask dataMask = 0;
89
90         /* ask for vertexgroups if we need them */
91         if (umd->vgroup_name[0])
92                 dataMask |= CD_MASK_MDEFORMVERT;
93
94         return dataMask;
95 }
96
97 static void matrix_from_obj_pchan(float mat[4][4], Object *ob, const char *bonename)
98 {
99         bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, bonename);
100         if (pchan) {
101                 mult_m4_m4m4(mat, ob->obmat, pchan->pose_mat);
102         }
103         else {
104                 copy_m4_m4(mat, ob->obmat);
105         }
106 }
107
108 #define OMP_LIMIT 1000
109 static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
110                                   DerivedMesh *dm,
111                                   ModifierApplyFlag UNUSED(flag))
112 {
113         UVWarpModifierData *umd = (UVWarpModifierData *) md;
114         int i, numPolys, numLoops;
115         MPoly *mpoly;
116         MLoop *mloop;
117         MLoopUV *mloopuv;
118         MDeformVert *dvert;
119         int defgrp_index;
120         char uvname[MAX_CUSTOMDATA_LAYER_NAME];
121         float mat_src[4][4];
122         float mat_dst[4][4];
123         float imat_dst[4][4];
124         float warp_mat[4][4];
125         const int axis_u = umd->axis_u;
126         const int axis_v = umd->axis_v;
127
128         /* make sure there are UV Maps available */
129         if (!CustomData_has_layer(&dm->loopData, CD_MLOOPUV)) {
130                 return dm;
131         }
132         else if (ELEM(NULL, umd->object_src, umd->object_dst)) {
133                 modifier_setError(md, "From/To objects must be set");
134                 return dm;
135         }
136
137         /* make sure anything moving UVs is available */
138         matrix_from_obj_pchan(mat_src, umd->object_src, umd->bone_src);
139         matrix_from_obj_pchan(mat_dst, umd->object_dst, umd->bone_dst);
140
141         invert_m4_m4(imat_dst, mat_dst);
142         mult_m4_m4m4(warp_mat, imat_dst, mat_src);
143
144         /* apply warp */
145         if (!is_zero_v2(umd->center)) {
146                 float mat_cent[4][4];
147                 float imat_cent[4][4];
148
149                 unit_m4(mat_cent);
150                 mat_cent[3][axis_u] = umd->center[0];
151                 mat_cent[3][axis_v] = umd->center[1];
152
153                 invert_m4_m4(imat_cent, mat_cent);
154
155                 mult_m4_m4m4(warp_mat, warp_mat, imat_cent);
156                 mult_m4_m4m4(warp_mat, mat_cent, warp_mat);
157         }
158
159         /* make sure we're using an existing layer */
160         CustomData_validate_layer_name(&dm->loopData, CD_MLOOPUV, umd->uvlayer_name, uvname);
161
162         numPolys = dm->getNumPolys(dm);
163         numLoops = dm->getNumLoops(dm);
164
165         mpoly = dm->getPolyArray(dm);
166         mloop = dm->getLoopArray(dm);
167         /* make sure we are not modifying the original UV map */
168         mloopuv = CustomData_duplicate_referenced_layer_named(&dm->loopData, CD_MLOOPUV, uvname, numLoops);
169         modifier_get_vgroup(ob, dm, umd->vgroup_name, &dvert, &defgrp_index);
170
171         if (dvert) {
172 #pragma omp parallel for if (numPolys > OMP_LIMIT)
173                 for (i = 0; i < numPolys; i++) {
174                         float uv[2];
175                         MPoly *mp     = &mpoly[i];
176                         MLoop *ml     = &mloop[mp->loopstart];
177                         MLoopUV *mluv = &mloopuv[mp->loopstart];
178                         int l;
179                         for (l = 0; l < mp->totloop; l++, ml++, mluv++) {
180                                 const float weight = defvert_find_weight(&dvert[ml->v], defgrp_index);
181                                 uv_warp_from_mat4_pair(uv, mluv->uv, warp_mat, axis_u, axis_v);
182                                 interp_v2_v2v2(mluv->uv, mluv->uv, uv, weight);
183                         }
184                 }
185         }
186         else {
187 #pragma omp parallel for if (numPolys > OMP_LIMIT)
188                 for (i = 0; i < numPolys; i++) {
189                         MPoly *mp     = &mpoly[i];
190                         // MLoop *ml     = &mloop[mp->loopstart];
191                         MLoopUV *mluv = &mloopuv[mp->loopstart];
192                         int l;
193                         for (l = 0; l < mp->totloop; l++, /* ml++, */ mluv++) {
194                                 uv_warp_from_mat4_pair(mluv->uv, mluv->uv, warp_mat, axis_u, axis_v);
195                         }
196                 }
197         }
198
199         dm->dirty |= DM_DIRTY_TESS_CDLAYERS;
200
201         return dm;
202 }
203
204 static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
205                                     struct BMEditMesh *UNUSED(editData),
206                                     DerivedMesh *derivedData)
207 {
208         return applyModifier(md, ob, derivedData, MOD_APPLY_USECACHE);
209 }
210
211 static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
212 {
213         UVWarpModifierData *umd = (UVWarpModifierData *) md;
214
215         walk(userData, ob, &umd->object_dst);
216         walk(userData, ob, &umd->object_src);
217 }
218
219 static void uv_warp_deps_object_bone(DagForest *forest, DagNode *obNode,
220                                 Object *obj, const char *bonename)
221 {
222         if (obj) {
223                 DagNode *curNode = dag_get_node(forest, obj);
224
225                 if (bonename[0])
226                         dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA | DAG_RL_DATA_DATA, "UVWarp Modifier");
227                 else
228                         dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA, "UVWarp Modifier");
229         }
230 }
231
232 static void updateDepgraph(ModifierData *md, DagForest *forest,
233                            struct Scene *UNUSED(scene),
234                            Object *UNUSED(ob),
235                            DagNode *obNode)
236 {
237         UVWarpModifierData *umd = (UVWarpModifierData *) md;
238
239         uv_warp_deps_object_bone(forest, obNode, umd->object_src, umd->bone_src);
240         uv_warp_deps_object_bone(forest, obNode, umd->object_dst, umd->bone_dst);
241 }
242
243 ModifierTypeInfo modifierType_UVWarp = {
244         /* name */              "UVWarp",
245         /* structName */        "UVWarpModifierData",
246         /* structSize */        sizeof(UVWarpModifierData),
247         /* type */              eModifierTypeType_NonGeometrical,
248         /* flags */             eModifierTypeFlag_AcceptsMesh |
249                                 eModifierTypeFlag_SupportsEditmode |
250                                 eModifierTypeFlag_EnableInEditmode,
251         /* copyData */          copyData,
252         /* deformVerts */       NULL,
253         /* deformMatrices */    NULL,
254         /* deformVertsEM */     NULL,
255         /* deformMatricesEM */  NULL,
256         /* applyModifier */     applyModifier,
257         /* applyModifierEM */   applyModifierEM,
258         /* initData */          initData,
259         /* requiredDataMask */  requiredDataMask,
260         /* freeData */          NULL,
261         /* isDisabled */        NULL,
262         /* updateDepgraph */    updateDepgraph,
263         /* dependsOnTime */     NULL,
264         /* dependsOnNormals */  NULL,
265         /* foreachObjectLink */ foreachObjectLink,
266         /* foreachIDLink */     NULL,
267         /* foreachTexLink */    NULL,
268 };