Modifiers: Add option to directly specify a 2D transform for UVWarp
Currently the only option is to warp based on the transform of other objects, which is inconvenient if you want to e.g. control it through a driver - you need to set up a dummy object and go through that, which is clunky and should be unneccessary. Reviewed By: brecht Differential Revision: https://developer.blender.org/D6690
This commit is contained in:
@@ -1455,6 +1455,19 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
|
||||
col.label(text="Bone:")
|
||||
col.prop_search(md, "bone_to", obj.data, "bones", text="")
|
||||
|
||||
split = layout.split()
|
||||
col = split.column()
|
||||
col.label(text="Offset:")
|
||||
col.prop(md, "offset", text="")
|
||||
|
||||
col = split.column()
|
||||
col.label(text="Scale:")
|
||||
col.prop(md, "scale", text="")
|
||||
|
||||
col = split.column()
|
||||
col.label(text="Rotate:")
|
||||
col.prop(md, "rotation", text="")
|
||||
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
|
||||
@@ -60,6 +60,9 @@ void copy_m4d_m4(double R[4][4], const float A[4][4]);
|
||||
void swap_m3m3(float A[3][3], float B[3][3]);
|
||||
void swap_m4m4(float A[4][4], float B[4][4]);
|
||||
|
||||
/* Build index shuffle matrix */
|
||||
void shuffle_m4(float R[4][4], int index[4]);
|
||||
|
||||
/******************************** Arithmetic *********************************/
|
||||
|
||||
void add_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3]);
|
||||
|
||||
@@ -210,6 +210,16 @@ void swap_m4m4(float m1[4][4], float m2[4][4])
|
||||
}
|
||||
}
|
||||
|
||||
void shuffle_m4(float R[4][4], int index[4])
|
||||
{
|
||||
zero_m4(R);
|
||||
for (int k = 0; k < 4; k++) {
|
||||
if (index[k] >= 0) {
|
||||
R[index[k]][k] = 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************** Arithmetic *********************************/
|
||||
|
||||
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
|
||||
|
||||
@@ -4482,5 +4482,17 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Add 2D transform to UV Warp modifier. */
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "UVWarpModifierData", "float", "scale[2]")) {
|
||||
for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
|
||||
for (ModifierData *md = ob->modifiers.first; md; md = md->next) {
|
||||
if (md->type == eModifierType_UVWarp) {
|
||||
UVWarpModifierData *umd = (UVWarpModifierData *)md;
|
||||
copy_v2_fl(umd->scale, 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1742,10 +1742,14 @@ typedef struct UVWarpModifierData {
|
||||
ModifierData modifier;
|
||||
|
||||
char axis_u, axis_v;
|
||||
char _pad[6];
|
||||
char _pad[2];
|
||||
/** Used for rotate/scale. */
|
||||
float center[2];
|
||||
|
||||
float offset[2];
|
||||
float scale[2];
|
||||
float rotation;
|
||||
|
||||
/** Source. */
|
||||
struct Object *object_src;
|
||||
/** Optional name of bone target, MAX_ID_NAME-2. */
|
||||
|
||||
@@ -4599,6 +4599,21 @@ static void rna_def_modifier_uvwarp(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "UV Center", "Center point for rotate/scale");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "offset", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "offset");
|
||||
RNA_def_property_ui_text(prop, "Offset", "2D Offset for the warp");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "scale");
|
||||
RNA_def_property_ui_text(prop, "Scale", "2D Scale for the warp");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_ANGLE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "rotation");
|
||||
RNA_def_property_ui_text(prop, "Rotation", "2D Rotation for the warp");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "object_from", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "object_src");
|
||||
RNA_def_property_ui_text(prop, "Object From", "Object defining offset");
|
||||
|
||||
@@ -38,18 +38,13 @@
|
||||
|
||||
#include "MOD_util.h"
|
||||
|
||||
static void uv_warp_from_mat4_pair(
|
||||
float uv_dst[2], const float uv_src[2], float warp_mat[4][4], int axis_u, int axis_v)
|
||||
static void uv_warp_from_mat4_pair(float uv_dst[2], const float uv_src[2], float warp_mat[4][4])
|
||||
{
|
||||
float tuv[3] = {0.0f};
|
||||
|
||||
tuv[axis_u] = uv_src[0];
|
||||
tuv[axis_v] = uv_src[1];
|
||||
|
||||
copy_v2_v2(tuv, uv_src);
|
||||
mul_m4_v3(warp_mat, tuv);
|
||||
|
||||
uv_dst[0] = tuv[axis_u];
|
||||
uv_dst[1] = tuv[axis_v];
|
||||
copy_v2_v2(uv_dst, tuv);
|
||||
}
|
||||
|
||||
static void initData(ModifierData *md)
|
||||
@@ -58,6 +53,7 @@ static void initData(ModifierData *md)
|
||||
umd->axis_u = 0;
|
||||
umd->axis_v = 1;
|
||||
copy_v2_fl(umd->center, 0.5f);
|
||||
copy_v2_fl(umd->scale, 1.0f);
|
||||
}
|
||||
|
||||
static void requiredDataMask(Object *UNUSED(ob),
|
||||
@@ -92,8 +88,6 @@ typedef struct UVWarpData {
|
||||
int defgrp_index;
|
||||
|
||||
float (*warp_mat)[4];
|
||||
int axis_u;
|
||||
int axis_v;
|
||||
} UVWarpData;
|
||||
|
||||
static void uv_warp_compute(void *__restrict userdata,
|
||||
@@ -110,8 +104,6 @@ static void uv_warp_compute(void *__restrict userdata,
|
||||
const int defgrp_index = data->defgrp_index;
|
||||
|
||||
float(*warp_mat)[4] = data->warp_mat;
|
||||
const int axis_u = data->axis_u;
|
||||
const int axis_v = data->axis_v;
|
||||
|
||||
int l;
|
||||
|
||||
@@ -120,13 +112,13 @@ static void uv_warp_compute(void *__restrict userdata,
|
||||
float uv[2];
|
||||
const float weight = defvert_find_weight(&dvert[ml->v], defgrp_index);
|
||||
|
||||
uv_warp_from_mat4_pair(uv, mluv->uv, warp_mat, axis_u, axis_v);
|
||||
uv_warp_from_mat4_pair(uv, mluv->uv, warp_mat);
|
||||
interp_v2_v2v2(mluv->uv, mluv->uv, uv, weight);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (l = 0; l < mp->totloop; l++, ml++, mluv++) {
|
||||
uv_warp_from_mat4_pair(mluv->uv, mluv->uv, warp_mat, axis_u, axis_v);
|
||||
uv_warp_from_mat4_pair(mluv->uv, mluv->uv, warp_mat);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -141,9 +133,6 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
|
||||
MDeformVert *dvert;
|
||||
int defgrp_index;
|
||||
char uvname[MAX_CUSTOMDATA_LAYER_NAME];
|
||||
float mat_src[4][4];
|
||||
float mat_dst[4][4];
|
||||
float imat_dst[4][4];
|
||||
float warp_mat[4][4];
|
||||
const int axis_u = umd->axis_u;
|
||||
const int axis_v = umd->axis_v;
|
||||
@@ -152,32 +141,52 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
|
||||
if (!CustomData_has_layer(&mesh->ldata, CD_MLOOPUV)) {
|
||||
return mesh;
|
||||
}
|
||||
else if (ELEM(NULL, umd->object_src, umd->object_dst)) {
|
||||
modifier_setError(md, "From/To objects must be set");
|
||||
return mesh;
|
||||
|
||||
if (!ELEM(NULL, umd->object_src, umd->object_dst)) {
|
||||
float mat_src[4][4];
|
||||
float mat_dst[4][4];
|
||||
float imat_dst[4][4];
|
||||
float shuf_mat[4][4];
|
||||
|
||||
/* make sure anything moving UVs is available */
|
||||
matrix_from_obj_pchan(mat_src, umd->object_src, umd->bone_src);
|
||||
matrix_from_obj_pchan(mat_dst, umd->object_dst, umd->bone_dst);
|
||||
|
||||
invert_m4_m4(imat_dst, mat_dst);
|
||||
mul_m4_m4m4(warp_mat, imat_dst, mat_src);
|
||||
|
||||
/* apply warp */
|
||||
if (!is_zero_v2(umd->center)) {
|
||||
float mat_cent[4][4];
|
||||
float imat_cent[4][4];
|
||||
|
||||
unit_m4(mat_cent);
|
||||
mat_cent[3][axis_u] = umd->center[0];
|
||||
mat_cent[3][axis_v] = umd->center[1];
|
||||
|
||||
invert_m4_m4(imat_cent, mat_cent);
|
||||
|
||||
mul_m4_m4m4(warp_mat, warp_mat, imat_cent);
|
||||
mul_m4_m4m4(warp_mat, mat_cent, warp_mat);
|
||||
}
|
||||
|
||||
int shuf_indices[4] = {axis_u, axis_v, -1, 3};
|
||||
shuffle_m4(shuf_mat, shuf_indices);
|
||||
mul_m4_m4m4(warp_mat, shuf_mat, warp_mat);
|
||||
transpose_m4(shuf_mat);
|
||||
mul_m4_m4m4(warp_mat, warp_mat, shuf_mat);
|
||||
}
|
||||
else {
|
||||
unit_m4(warp_mat);
|
||||
}
|
||||
|
||||
/* make sure anything moving UVs is available */
|
||||
matrix_from_obj_pchan(mat_src, umd->object_src, umd->bone_src);
|
||||
matrix_from_obj_pchan(mat_dst, umd->object_dst, umd->bone_dst);
|
||||
|
||||
invert_m4_m4(imat_dst, mat_dst);
|
||||
mul_m4_m4m4(warp_mat, imat_dst, mat_src);
|
||||
|
||||
/* apply warp */
|
||||
if (!is_zero_v2(umd->center)) {
|
||||
float mat_cent[4][4];
|
||||
float imat_cent[4][4];
|
||||
|
||||
unit_m4(mat_cent);
|
||||
mat_cent[3][axis_u] = umd->center[0];
|
||||
mat_cent[3][axis_v] = umd->center[1];
|
||||
|
||||
invert_m4_m4(imat_cent, mat_cent);
|
||||
|
||||
mul_m4_m4m4(warp_mat, warp_mat, imat_cent);
|
||||
mul_m4_m4m4(warp_mat, mat_cent, warp_mat);
|
||||
}
|
||||
/* Apply direct 2d transform. */
|
||||
translate_m4(warp_mat, umd->center[0], umd->center[1], 0.0f);
|
||||
const float scale[3] = {umd->scale[0], umd->scale[1], 1.0f};
|
||||
rescale_m4(warp_mat, scale);
|
||||
rotate_m4(warp_mat, 'Z', umd->rotation);
|
||||
translate_m4(warp_mat, umd->offset[0], umd->offset[1], 0.0f);
|
||||
translate_m4(warp_mat, -umd->center[0], -umd->center[1], 0.0f);
|
||||
|
||||
/* make sure we're using an existing layer */
|
||||
CustomData_validate_layer_name(&mesh->ldata, CD_MLOOPUV, umd->uvlayer_name, uvname);
|
||||
@@ -199,8 +208,6 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
|
||||
.dvert = dvert,
|
||||
.defgrp_index = defgrp_index,
|
||||
.warp_mat = warp_mat,
|
||||
.axis_u = axis_u,
|
||||
.axis_v = axis_v,
|
||||
};
|
||||
TaskParallelSettings settings;
|
||||
BLI_parallel_range_settings_defaults(&settings);
|
||||
|
||||
Reference in New Issue
Block a user