Mesh Modifiers: refactor copying using a generic function
[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 #if 0
72         UVWarpModifierData *umd  = (UVWarpModifierData *)md;
73         UVWarpModifierData *tumd = (UVWarpModifierData *)target;
74 #endif
75         modifier_copyData_generic(md, target);
76 }
77
78 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
79 {
80         UVWarpModifierData *umd = (UVWarpModifierData *)md;
81         CustomDataMask dataMask = 0;
82
83         /* ask for vertexgroups if we need them */
84         if (umd->vgroup_name[0])
85                 dataMask |= CD_MASK_MDEFORMVERT;
86
87         return dataMask;
88 }
89
90 static void matrix_from_obj_pchan(float mat[4][4], Object *ob, const char *bonename)
91 {
92         bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, bonename);
93         if (pchan) {
94                 mul_m4_m4m4(mat, ob->obmat, pchan->pose_mat);
95         }
96         else {
97                 copy_m4_m4(mat, ob->obmat);
98         }
99 }
100
101 #ifdef _OPENMP
102 #  define OMP_LIMIT 1000
103 #endif
104
105 static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
106                                   DerivedMesh *dm,
107                                   ModifierApplyFlag UNUSED(flag))
108 {
109         UVWarpModifierData *umd = (UVWarpModifierData *) md;
110         int i, numPolys, numLoops;
111         MPoly *mpoly;
112         MLoop *mloop;
113         MLoopUV *mloopuv;
114         MDeformVert *dvert;
115         int defgrp_index;
116         char uvname[MAX_CUSTOMDATA_LAYER_NAME];
117         float mat_src[4][4];
118         float mat_dst[4][4];
119         float imat_dst[4][4];
120         float warp_mat[4][4];
121         const int axis_u = umd->axis_u;
122         const int axis_v = umd->axis_v;
123
124         /* make sure there are UV Maps available */
125         if (!CustomData_has_layer(&dm->loopData, CD_MLOOPUV)) {
126                 return dm;
127         }
128         else if (ELEM(NULL, umd->object_src, umd->object_dst)) {
129                 modifier_setError(md, "From/To objects must be set");
130                 return dm;
131         }
132
133         /* make sure anything moving UVs is available */
134         matrix_from_obj_pchan(mat_src, umd->object_src, umd->bone_src);
135         matrix_from_obj_pchan(mat_dst, umd->object_dst, umd->bone_dst);
136
137         invert_m4_m4(imat_dst, mat_dst);
138         mul_m4_m4m4(warp_mat, imat_dst, mat_src);
139
140         /* apply warp */
141         if (!is_zero_v2(umd->center)) {
142                 float mat_cent[4][4];
143                 float imat_cent[4][4];
144
145                 unit_m4(mat_cent);
146                 mat_cent[3][axis_u] = umd->center[0];
147                 mat_cent[3][axis_v] = umd->center[1];
148
149                 invert_m4_m4(imat_cent, mat_cent);
150
151                 mul_m4_m4m4(warp_mat, warp_mat, imat_cent);
152                 mul_m4_m4m4(warp_mat, mat_cent, warp_mat);
153         }
154
155         /* make sure we're using an existing layer */
156         CustomData_validate_layer_name(&dm->loopData, CD_MLOOPUV, umd->uvlayer_name, uvname);
157
158         numPolys = dm->getNumPolys(dm);
159         numLoops = dm->getNumLoops(dm);
160
161         mpoly = dm->getPolyArray(dm);
162         mloop = dm->getLoopArray(dm);
163         /* make sure we are not modifying the original UV map */
164         mloopuv = CustomData_duplicate_referenced_layer_named(&dm->loopData, CD_MLOOPUV, uvname, numLoops);
165         modifier_get_vgroup(ob, dm, umd->vgroup_name, &dvert, &defgrp_index);
166
167         if (dvert) {
168 #pragma omp parallel for if (numPolys > OMP_LIMIT)
169                 for (i = 0; i < numPolys; i++) {
170                         float uv[2];
171                         MPoly *mp     = &mpoly[i];
172                         MLoop *ml     = &mloop[mp->loopstart];
173                         MLoopUV *mluv = &mloopuv[mp->loopstart];
174                         int l;
175                         for (l = 0; l < mp->totloop; l++, ml++, mluv++) {
176                                 const float weight = defvert_find_weight(&dvert[ml->v], defgrp_index);
177                                 uv_warp_from_mat4_pair(uv, mluv->uv, warp_mat, axis_u, axis_v);
178                                 interp_v2_v2v2(mluv->uv, mluv->uv, uv, weight);
179                         }
180                 }
181         }
182         else {
183 #pragma omp parallel for if (numPolys > OMP_LIMIT)
184                 for (i = 0; i < numPolys; i++) {
185                         MPoly *mp     = &mpoly[i];
186                         // MLoop *ml     = &mloop[mp->loopstart];
187                         MLoopUV *mluv = &mloopuv[mp->loopstart];
188                         int l;
189                         for (l = 0; l < mp->totloop; l++, /* ml++, */ mluv++) {
190                                 uv_warp_from_mat4_pair(mluv->uv, mluv->uv, warp_mat, axis_u, axis_v);
191                         }
192                 }
193         }
194
195         dm->dirty |= DM_DIRTY_TESS_CDLAYERS;
196
197         return dm;
198 }
199
200 static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
201 {
202         UVWarpModifierData *umd = (UVWarpModifierData *) md;
203
204         walk(userData, ob, &umd->object_dst);
205         walk(userData, ob, &umd->object_src);
206 }
207
208 static void uv_warp_deps_object_bone(DagForest *forest, DagNode *obNode,
209                                 Object *obj, const char *bonename)
210 {
211         if (obj) {
212                 DagNode *curNode = dag_get_node(forest, obj);
213
214                 if (bonename[0])
215                         dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA | DAG_RL_DATA_DATA, "UVWarp Modifier");
216                 else
217                         dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA, "UVWarp Modifier");
218         }
219 }
220
221 static void updateDepgraph(ModifierData *md, DagForest *forest,
222                            struct Scene *UNUSED(scene),
223                            Object *UNUSED(ob),
224                            DagNode *obNode)
225 {
226         UVWarpModifierData *umd = (UVWarpModifierData *) md;
227
228         uv_warp_deps_object_bone(forest, obNode, umd->object_src, umd->bone_src);
229         uv_warp_deps_object_bone(forest, obNode, umd->object_dst, umd->bone_dst);
230 }
231
232 ModifierTypeInfo modifierType_UVWarp = {
233         /* name */              "UVWarp",
234         /* structName */        "UVWarpModifierData",
235         /* structSize */        sizeof(UVWarpModifierData),
236         /* type */              eModifierTypeType_NonGeometrical,
237         /* flags */             eModifierTypeFlag_AcceptsMesh |
238                                 eModifierTypeFlag_SupportsEditmode |
239                                 eModifierTypeFlag_EnableInEditmode,
240         /* copyData */          copyData,
241         /* deformVerts */       NULL,
242         /* deformMatrices */    NULL,
243         /* deformVertsEM */     NULL,
244         /* deformMatricesEM */  NULL,
245         /* applyModifier */     applyModifier,
246         /* applyModifierEM */   NULL,
247         /* initData */          initData,
248         /* requiredDataMask */  requiredDataMask,
249         /* freeData */          NULL,
250         /* isDisabled */        NULL,
251         /* updateDepgraph */    updateDepgraph,
252         /* dependsOnTime */     NULL,
253         /* dependsOnNormals */  NULL,
254         /* foreachObjectLink */ foreachObjectLink,
255         /* foreachIDLink */     NULL,
256         /* foreachTexLink */    NULL,
257 };