Blender  V2.93
MOD_uvwarp.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
21 #include <string.h>
22 
23 #include "BLI_utildefines.h"
24 
25 #include "BLI_math.h"
26 #include "BLI_task.h"
27 
28 #include "BLT_translation.h"
29 
30 #include "DNA_defaults.h"
31 #include "DNA_mesh_types.h"
32 #include "DNA_meshdata_types.h"
33 #include "DNA_object_types.h"
34 #include "DNA_screen_types.h"
35 
36 #include "BKE_action.h" /* BKE_pose_channel_find_name */
37 #include "BKE_context.h"
38 #include "BKE_deform.h"
39 #include "BKE_lib_query.h"
40 #include "BKE_modifier.h"
41 #include "BKE_screen.h"
42 
43 #include "UI_interface.h"
44 #include "UI_resources.h"
45 
46 #include "RNA_access.h"
47 
48 #include "DEG_depsgraph_query.h"
49 
50 #include "MOD_ui_common.h"
51 #include "MOD_util.h"
52 
53 static void uv_warp_from_mat4_pair(float uv_dst[2],
54  const float uv_src[2],
55  const float warp_mat[4][4])
56 {
57  float tuv[3] = {0.0f};
58 
59  copy_v2_v2(tuv, uv_src);
60  mul_m4_v3(warp_mat, tuv);
61  copy_v2_v2(uv_dst, tuv);
62 }
63 
64 static void initData(ModifierData *md)
65 {
67 
69 
71 }
72 
73 static void requiredDataMask(Object *UNUSED(ob),
74  ModifierData *md,
75  CustomData_MeshMasks *r_cddata_masks)
76 {
78 
79  /* ask for vertexgroups if we need them */
80  if (umd->vgroup_name[0] != '\0') {
81  r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
82  }
83 }
84 
85 static void matrix_from_obj_pchan(float mat[4][4], Object *ob, const char *bonename)
86 {
87  bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, bonename);
88  if (pchan) {
89  mul_m4_m4m4(mat, ob->obmat, pchan->pose_mat);
90  }
91  else {
92  copy_m4_m4(mat, ob->obmat);
93  }
94 }
95 
96 typedef struct UVWarpData {
100 
103 
107 
108 static void uv_warp_compute(void *__restrict userdata,
109  const int i,
110  const TaskParallelTLS *__restrict UNUSED(tls))
111 {
112  const UVWarpData *data = userdata;
113 
114  const MPoly *mp = &data->mpoly[i];
115  const MLoop *ml = &data->mloop[mp->loopstart];
116  MLoopUV *mluv = &data->mloopuv[mp->loopstart];
117 
118  const MDeformVert *dvert = data->dvert;
119  const int defgrp_index = data->defgrp_index;
120 
121  float(*warp_mat)[4] = data->warp_mat;
122 
123  int l;
124 
125  if (dvert) {
126  for (l = 0; l < mp->totloop; l++, ml++, mluv++) {
127  float uv[2];
128  const float weight = data->invert_vgroup ?
129  1.0f - BKE_defvert_find_weight(&dvert[ml->v], defgrp_index) :
130  BKE_defvert_find_weight(&dvert[ml->v], defgrp_index);
131 
132  uv_warp_from_mat4_pair(uv, mluv->uv, warp_mat);
133  interp_v2_v2v2(mluv->uv, mluv->uv, uv, weight);
134  }
135  }
136  else {
137  for (l = 0; l < mp->totloop; l++, ml++, mluv++) {
138  uv_warp_from_mat4_pair(mluv->uv, mluv->uv, warp_mat);
139  }
140  }
141 }
142 
144 {
146  int numPolys, numLoops;
147  MPoly *mpoly;
148  MLoop *mloop;
149  MLoopUV *mloopuv;
150  MDeformVert *dvert;
151  int defgrp_index;
152  char uvname[MAX_CUSTOMDATA_LAYER_NAME];
153  float warp_mat[4][4];
154  const int axis_u = umd->axis_u;
155  const int axis_v = umd->axis_v;
156  const bool invert_vgroup = (umd->flag & MOD_UVWARP_INVERT_VGROUP) != 0;
157 
158  /* make sure there are UV Maps available */
160  return mesh;
161  }
162 
163  if (!ELEM(NULL, umd->object_src, umd->object_dst)) {
164  float mat_src[4][4];
165  float mat_dst[4][4];
166  float imat_dst[4][4];
167  float shuf_mat[4][4];
168 
169  /* make sure anything moving UVs is available */
170  matrix_from_obj_pchan(mat_src, umd->object_src, umd->bone_src);
171  matrix_from_obj_pchan(mat_dst, umd->object_dst, umd->bone_dst);
172 
173  invert_m4_m4(imat_dst, mat_dst);
174  mul_m4_m4m4(warp_mat, imat_dst, mat_src);
175 
176  /* apply warp */
177  if (!is_zero_v2(umd->center)) {
178  float mat_cent[4][4];
179  float imat_cent[4][4];
180 
181  unit_m4(mat_cent);
182  mat_cent[3][axis_u] = umd->center[0];
183  mat_cent[3][axis_v] = umd->center[1];
184 
185  invert_m4_m4(imat_cent, mat_cent);
186 
187  mul_m4_m4m4(warp_mat, warp_mat, imat_cent);
188  mul_m4_m4m4(warp_mat, mat_cent, warp_mat);
189  }
190 
191  const int shuf_indices[4] = {axis_u, axis_v, -1, 3};
192  shuffle_m4(shuf_mat, shuf_indices);
193  mul_m4_m4m4(warp_mat, shuf_mat, warp_mat);
194  transpose_m4(shuf_mat);
195  mul_m4_m4m4(warp_mat, warp_mat, shuf_mat);
196  }
197  else {
198  unit_m4(warp_mat);
199  }
200 
201  /* Apply direct 2d transform. */
202  translate_m4(warp_mat, umd->center[0], umd->center[1], 0.0f);
203  const float scale[3] = {umd->scale[0], umd->scale[1], 1.0f};
204  rescale_m4(warp_mat, scale);
205  rotate_m4(warp_mat, 'Z', umd->rotation);
206  translate_m4(warp_mat, umd->offset[0], umd->offset[1], 0.0f);
207  translate_m4(warp_mat, -umd->center[0], -umd->center[1], 0.0f);
208 
209  /* make sure we're using an existing layer */
211 
212  numPolys = mesh->totpoly;
213  numLoops = mesh->totloop;
214 
215  mpoly = mesh->mpoly;
216  mloop = mesh->mloop;
217  /* make sure we are not modifying the original UV map */
219  &mesh->ldata, CD_MLOOPUV, uvname, numLoops);
220  MOD_get_vgroup(ctx->object, mesh, umd->vgroup_name, &dvert, &defgrp_index);
221 
222  UVWarpData data = {
223  .mpoly = mpoly,
224  .mloop = mloop,
225  .mloopuv = mloopuv,
226  .dvert = dvert,
227  .defgrp_index = defgrp_index,
228  .warp_mat = warp_mat,
229  .invert_vgroup = invert_vgroup,
230  };
231  TaskParallelSettings settings;
233  settings.use_threading = (numPolys > 1000);
234  BLI_task_parallel_range(0, numPolys, &data, uv_warp_compute, &settings);
235 
236  /* XXX TODO is this still needed? */
237  // me_eval->dirty |= DM_DIRTY_TESS_CDLAYERS;
238 
239  mesh->runtime.is_original = false;
240 
241  return mesh;
242 }
243 
244 static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
245 {
247 
248  walk(userData, ob, (ID **)&umd->object_dst, IDWALK_CB_NOP);
249  walk(userData, ob, (ID **)&umd->object_src, IDWALK_CB_NOP);
250 }
251 
253 {
255 
257  ctx->node, umd->object_src, umd->bone_src, "UVWarp Modifier");
259  ctx->node, umd->object_dst, umd->bone_dst, "UVWarp Modifier");
260 
261  DEG_add_modifier_to_transform_relation(ctx->node, "UVWarp Modifier");
262 }
263 
264 static void panel_draw(const bContext *UNUSED(C), Panel *panel)
265 {
266  uiLayout *col;
267  uiLayout *layout = panel->layout;
268 
269  PointerRNA ob_ptr;
271 
272  PointerRNA warp_obj_ptr;
273  PointerRNA obj_data_ptr = RNA_pointer_get(&ob_ptr, "data");
274 
275  uiLayoutSetPropSep(layout, true);
276 
277  uiItemPointerR(layout, ptr, "uv_layer", &obj_data_ptr, "uv_layers", NULL, ICON_NONE);
278 
279  col = uiLayoutColumn(layout, false);
280  uiItemR(col, ptr, "center", 0, NULL, ICON_NONE);
281 
282  col = uiLayoutColumn(layout, false);
283  uiItemR(col, ptr, "axis_u", 0, IFACE_("Axis U"), ICON_NONE);
284  uiItemR(col, ptr, "axis_v", 0, IFACE_("V"), ICON_NONE);
285 
286  col = uiLayoutColumn(layout, false);
287  uiItemR(col, ptr, "object_from", 0, NULL, ICON_NONE);
288  warp_obj_ptr = RNA_pointer_get(ptr, "object_from");
289  if (!RNA_pointer_is_null(&warp_obj_ptr) && RNA_enum_get(&warp_obj_ptr, "type") == OB_ARMATURE) {
290  PointerRNA warp_obj_data_ptr = RNA_pointer_get(&warp_obj_ptr, "data");
291  uiItemPointerR(col, ptr, "bone_from", &warp_obj_data_ptr, "bones", NULL, ICON_NONE);
292  }
293 
294  uiItemR(col, ptr, "object_to", 0, IFACE_("To"), ICON_NONE);
295  warp_obj_ptr = RNA_pointer_get(ptr, "object_to");
296  if (!RNA_pointer_is_null(&warp_obj_ptr) && RNA_enum_get(&warp_obj_ptr, "type") == OB_ARMATURE) {
297  PointerRNA warp_obj_data_ptr = RNA_pointer_get(&warp_obj_ptr, "data");
298  uiItemPointerR(col, ptr, "bone_to", &warp_obj_data_ptr, "bones", NULL, ICON_NONE);
299  }
300 
301  modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
302 
303  modifier_panel_end(layout, ptr);
304 }
305 
306 static void transform_panel_draw(const bContext *UNUSED(C), Panel *panel)
307 {
308  uiLayout *layout = panel->layout;
309 
311 
312  uiLayoutSetPropSep(layout, true);
313 
314  uiItemR(layout, ptr, "offset", 0, NULL, ICON_NONE);
315  uiItemR(layout, ptr, "scale", 0, NULL, ICON_NONE);
316  uiItemR(layout, ptr, "rotation", 0, NULL, ICON_NONE);
317 }
318 
319 static void panelRegister(ARegionType *region_type)
320 {
323  region_type, "offset", "Transform", NULL, transform_panel_draw, panel_type);
324 }
325 
327  /* name */ "UVWarp",
328  /* structName */ "UVWarpModifierData",
329  /* structSize */ sizeof(UVWarpModifierData),
330  /* srna */ &RNA_UVWarpModifier,
334  /* icon */ ICON_MOD_UVPROJECT, /* TODO: Use correct icon. */
335 
336  /* copyData */ BKE_modifier_copydata_generic,
337 
338  /* deformVerts */ NULL,
339  /* deformMatrices */ NULL,
340  /* deformVertsEM */ NULL,
341  /* deformMatricesEM */ NULL,
342  /* modifyMesh */ modifyMesh,
343  /* modifyHair */ NULL,
344  /* modifyGeometrySet */ NULL,
345  /* modifyVolume */ NULL,
346 
347  /* initData */ initData,
348  /* requiredDataMask */ requiredDataMask,
349  /* freeData */ NULL,
350  /* isDisabled */ NULL,
351  /* updateDepsgraph */ updateDepsgraph,
352  /* dependsOnTime */ NULL,
353  /* dependsOnNormals */ NULL,
354  /* foreachIDLink */ foreachIDLink,
355  /* foreachTexLink */ NULL,
356  /* freeRuntimeData */ NULL,
357  /* panelRegister */ panelRegister,
358  /* blendWrite */ NULL,
359  /* blendRead */ NULL,
360 };
typedef float(TangentPoint)[2]
Blender kernel action and pose functionality.
struct bPoseChannel * BKE_pose_channel_find_name(const struct bPose *pose, const char *name)
bool CustomData_has_layer(const struct CustomData *data, int type)
void * CustomData_duplicate_referenced_layer_named(struct CustomData *data, const int type, const char *name, const int totelem)
Definition: customdata.c:2807
void CustomData_validate_layer_name(const struct CustomData *data, int type, const char *name, char *outname)
support for deformation groups and hooks.
float BKE_defvert_find_weight(const struct MDeformVert *dvert, const int defgroup)
Definition: deform.c:632
@ IDWALK_CB_NOP
Definition: BKE_lib_query.h:47
void(* IDWalkFunc)(void *userData, struct Object *ob, struct ID **idpoin, int cb_flag)
Definition: BKE_modifier.h:120
@ eModifierTypeFlag_EnableInEditmode
Definition: BKE_modifier.h:92
@ eModifierTypeFlag_SupportsEditmode
Definition: BKE_modifier.h:83
@ eModifierTypeFlag_AcceptsMesh
Definition: BKE_modifier.h:80
void BKE_modifier_copydata_generic(const struct ModifierData *md, struct ModifierData *md_dst, const int flag)
@ eModifierTypeType_NonGeometrical
Definition: BKE_modifier.h:76
#define BLI_assert(a)
Definition: BLI_assert.h:58
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:262
void unit_m4(float m[4][4])
Definition: rct.c:1140
void translate_m4(float mat[4][4], float tx, float ty, float tz)
Definition: math_matrix.c:2325
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1278
void rescale_m4(float mat[4][4], const float scale[3])
Definition: math_matrix.c:2396
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:732
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:95
void shuffle_m4(float R[4][4], const int index[4])
Definition: math_matrix.c:250
void transpose_m4(float R[4][4])
Definition: math_matrix.c:1358
void rotate_m4(float mat[4][4], const char axis, const float angle)
Definition: math_matrix.c:2352
void interp_v2_v2v2(float r[2], const float a[2], const float b[2], const float t)
Definition: math_vector.c:32
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE bool is_zero_v2(const float a[3]) ATTR_WARN_UNUSED_RESULT
void BLI_task_parallel_range(const int start, const int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition: task_range.cc:110
BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings)
Definition: BLI_task.h:231
#define UNUSED(x)
#define ELEM(...)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define IFACE_(msgid)
void DEG_add_modifier_to_transform_relation(struct DepsNodeHandle *node_handle, const char *description)
#define MAX_CUSTOMDATA_LAYER_NAME
#define CD_MASK_MDEFORMVERT
@ CD_MLOOPUV
#define DNA_struct_default_get(struct_name)
Definition: DNA_defaults.h:44
@ MOD_UVWARP_INVERT_VGROUP
@ eModifierType_UVWarp
struct UVWarpModifierData UVWarpModifierData
Object is a sort of wrapper for general info.
@ OB_ARMATURE
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
void modifier_vgroup_ui(uiLayout *layout, PointerRNA *ptr, PointerRNA *ob_ptr, const char *vgroup_prop, const char *invert_vgroup_prop, const char *text)
PanelType * modifier_subpanel_register(ARegionType *region_type, const char *name, const char *label, PanelDrawFn draw_header, PanelDrawFn draw, PanelType *parent)
void MOD_depsgraph_update_object_bone_relation(struct DepsNodeHandle *node, Object *object, const char *bonename, const char *description)
Definition: MOD_util.c:270
void MOD_get_vgroup(Object *ob, struct Mesh *mesh, const char *name, MDeformVert **dvert, int *defgrp_index)
Definition: MOD_util.c:254
static Mesh * modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
Definition: MOD_uvwarp.c:143
static void transform_panel_draw(const bContext *UNUSED(C), Panel *panel)
Definition: MOD_uvwarp.c:306
static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
Definition: MOD_uvwarp.c:252
static void matrix_from_obj_pchan(float mat[4][4], Object *ob, const char *bonename)
Definition: MOD_uvwarp.c:85
static void uv_warp_compute(void *__restrict userdata, const int i, const TaskParallelTLS *__restrict UNUSED(tls))
Definition: MOD_uvwarp.c:108
static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
Definition: MOD_uvwarp.c:244
static void uv_warp_from_mat4_pair(float uv_dst[2], const float uv_src[2], const float warp_mat[4][4])
Definition: MOD_uvwarp.c:53
struct UVWarpData UVWarpData
ModifierTypeInfo modifierType_UVWarp
Definition: MOD_uvwarp.c:326
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
Definition: MOD_uvwarp.c:264
static void initData(ModifierData *md)
Definition: MOD_uvwarp.c:64
static void panelRegister(ARegionType *region_type)
Definition: MOD_uvwarp.c:319
static void requiredDataMask(Object *UNUSED(ob), ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
Definition: MOD_uvwarp.c:73
StructRNA RNA_UVWarpModifier
#define C
Definition: RandGen.cpp:39
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, struct PointerRNA *searchptr, const char *searchpropname, const char *name, int icon)
ATTR_WARN_UNUSED_RESULT const BMLoop * l
uint col
PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6562
bool RNA_pointer_is_null(const PointerRNA *ptr)
Definition: rna_access.c:174
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
Definition: DNA_ID.h:273
struct CustomData pdata ldata
struct MLoop * mloop
Mesh_Runtime runtime
int totpoly
int totloop
struct MPoly * mpoly
struct Object * object
Definition: BKE_modifier.h:154
struct DepsNodeHandle * node
Definition: BKE_modifier.h:147
struct bPose * pose
float obmat[4][4]
struct uiLayout * layout
MLoop * mloop
Definition: MOD_uvwarp.c:98
MPoly * mpoly
Definition: MOD_uvwarp.c:97
MLoopUV * mloopuv
Definition: MOD_uvwarp.c:99
MDeformVert * dvert
Definition: MOD_uvwarp.c:101
bool invert_vgroup
Definition: MOD_uvwarp.c:105
int defgrp_index
Definition: MOD_uvwarp.c:102
float(* warp_mat)[4]
Definition: MOD_uvwarp.c:104
struct Object * object_dst
struct Object * object_src
float pose_mat[4][4]
PointerRNA * ptr
Definition: wm_files.c:3157