UV: add UV orientation overlay to UV editor #119329

Open
Samuel Bilek wants to merge 5 commits from Samuel-Bilek-1/blender:add_uv_orientation_overlay into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
20 changed files with 465 additions and 83 deletions

View File

@ -1579,10 +1579,10 @@ class IMAGE_PT_overlay_guides(Panel):
layout.prop(uvedit, "tile_grid_shape", text="Tiles")
class IMAGE_PT_overlay_uv_stretch(Panel):
class IMAGE_PT_overlay_uv_color(Panel):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'HEADER'
bl_label = "UV Stretch"
bl_label = "UV Color"
bl_parent_id = "IMAGE_PT_overlay"
@classmethod
@ -1600,11 +1600,11 @@ class IMAGE_PT_overlay_uv_stretch(Panel):
layout.active = overlay.show_overlays
row = layout.row(align=True)
row.row().prop(uvedit, "show_stretch", text="")
row.row().prop(uvedit, "show_color", text="")
subrow = row.row()
subrow.active = uvedit.show_stretch
subrow.prop(uvedit, "display_stretch_type", text="")
subrow.prop(uvedit, "stretch_opacity", text="Opacity")
subrow.active = uvedit.show_color
subrow.prop(uvedit, "display_color_type", text="")
subrow.prop(uvedit, "color_opacity", text="Opacity")
class IMAGE_PT_overlay_uv_edit_geometry(Panel):
@ -1635,7 +1635,7 @@ class IMAGE_PT_overlay_uv_edit_geometry(Panel):
# Faces
row = col.row()
row.active = not uvedit.show_stretch
row.active = not uvedit.show_color
row.prop(uvedit, "show_faces", text="Faces")
@ -1756,7 +1756,7 @@ classes = (
IMAGE_PT_gizmo_display,
IMAGE_PT_overlay,
IMAGE_PT_overlay_guides,
IMAGE_PT_overlay_uv_stretch,
IMAGE_PT_overlay_uv_color,
IMAGE_PT_overlay_uv_edit_geometry,
IMAGE_PT_overlay_texture_paint,
IMAGE_PT_overlay_image,

View File

@ -2947,13 +2947,13 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
}
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 4)) {
if (!DNA_struct_member_exists(fd->filesdna, "SpaceImage", "float", "stretch_opacity")) {
if (!DNA_struct_member_exists(fd->filesdna, "SpaceImage", "float", "color_opacity")) {
LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
if (sl->spacetype == SPACE_IMAGE) {
SpaceImage *sima = reinterpret_cast<SpaceImage *>(sl);
sima->stretch_opacity = 0.9f;
sima->color_opacity = 0.9f;
}
}
}

View File

@ -50,6 +50,7 @@ set(SRC
intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc
intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc
intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc
intern/mesh_extractors/extract_mesh_vbo_edituv_nor.cc
intern/mesh_extractors/extract_mesh_vbo_fdots_edituv_data.cc
intern/mesh_extractors/extract_mesh_vbo_fdots_nor.cc
intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc
@ -691,6 +692,7 @@ set(GLSL_SRC
intern/shaders/common_subdiv_vbo_edge_fac_comp.glsl
intern/shaders/common_subdiv_vbo_edituv_strech_angle_comp.glsl
intern/shaders/common_subdiv_vbo_edituv_strech_area_comp.glsl
intern/shaders/common_subdiv_vbo_edituv_nor_comp.glsl
intern/shaders/common_subdiv_vbo_lnor_comp.glsl
intern/shaders/common_subdiv_vbo_sculpt_data_comp.glsl
intern/shaders/common_view_clipping_lib.glsl
@ -800,7 +802,7 @@ set(GLSL_SRC
engines/overlay/shaders/overlay_edit_uv_faces_vert.glsl
engines/overlay/shaders/overlay_edit_uv_image_mask_frag.glsl
engines/overlay/shaders/overlay_edit_uv_image_vert.glsl
engines/overlay/shaders/overlay_edit_uv_stretching_vert.glsl
engines/overlay/shaders/overlay_edit_uv_color_vert.glsl
engines/overlay/shaders/overlay_edit_uv_tiled_image_borders_vert.glsl
engines/overlay/shaders/overlay_edit_uv_verts_frag.glsl
engines/overlay/shaders/overlay_edit_uv_verts_vert.glsl

View File

@ -130,15 +130,15 @@ void OVERLAY_edit_uv_init(OVERLAY_Data *vedata)
const bool do_face_dots = (ts->uv_flag & UV_SYNC_SELECTION) ?
(ts->selectmode & SCE_SELECT_FACE) != 0 :
(ts->uv_selectmode == UV_SELECT_FACE);
const bool do_uvstretching_overlay = is_image_type && is_uv_editor && is_edit_mode &&
((sima->flag & SI_DRAW_STRETCH) != 0);
const bool do_uvcolor_overlay = is_image_type && is_uv_editor && is_edit_mode &&
((sima->flag & SI_DRAW_COLOR) != 0);
const bool do_tex_paint_shadows = (sima->flag & SI_NO_DRAW_TEXPAINT) == 0;
const bool do_stencil_overlay = is_paint_mode && is_image_type && brush &&
(brush->imagepaint_tool == PAINT_TOOL_CLONE) &&
brush->clone.image;
pd->edit_uv.do_verts = show_overlays && (!do_edges_only);
pd->edit_uv.do_faces = show_overlays && do_faces && !do_uvstretching_overlay;
pd->edit_uv.do_faces = show_overlays && do_faces && !do_uvcolor_overlay;
pd->edit_uv.do_face_dots = show_overlays && do_faces && do_face_dots;
pd->edit_uv.do_uv_overlay = show_overlays && do_uv_overlay;
pd->edit_uv.do_uv_shadow_overlay = show_overlays && is_image_type &&
@ -159,9 +159,9 @@ void OVERLAY_edit_uv_init(OVERLAY_Data *vedata)
draw_ctx->depsgraph, &sima->mask_info.mask->id) :
nullptr;
pd->edit_uv.do_uv_stretching_overlay = show_overlays && do_uvstretching_overlay;
pd->edit_uv.do_uv_color_overlay = show_overlays && do_uvcolor_overlay;
pd->edit_uv.uv_opacity = sima->uv_opacity;
pd->edit_uv.stretch_opacity = sima->stretch_opacity;
pd->edit_uv.color_opacity = sima->color_opacity;
pd->edit_uv.do_tiled_image_overlay = show_overlays && is_image_type && is_tiled_image;
pd->edit_uv.do_tiled_image_border_overlay = is_image_type && is_tiled_image;
pd->edit_uv.dash_length = 4.0f * UI_SCALE_FAC;
@ -169,7 +169,7 @@ void OVERLAY_edit_uv_init(OVERLAY_Data *vedata)
pd->edit_uv.do_smooth_wire = ((U.gpu_flag & USER_GPU_FLAG_OVERLAY_SMOOTH_WIRE) != 0);
pd->edit_uv.do_stencil_overlay = show_overlays && do_stencil_overlay;
pd->edit_uv.draw_type = eSpaceImage_UVDT_Stretch(sima->dt_uvstretch);
pd->edit_uv.draw_type = eSpaceImage_UVDT_Color(sima->dt_uvcolor);
BLI_listbase_clear(&pd->edit_uv.totals);
pd->edit_uv.total_area_ratio = 0.0f;
@ -277,25 +277,33 @@ void OVERLAY_edit_uv_cache_init(OVERLAY_Data *vedata)
}
/* uv stretching */
if (pd->edit_uv.do_uv_stretching_overlay) {
DRW_PASS_CREATE(psl->edit_uv_stretching_ps,
if (pd->edit_uv.do_uv_color_overlay) {
DRW_PASS_CREATE(psl->edit_uv_color_ps,
DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_ALWAYS | DRW_STATE_BLEND_ALPHA);
if (pd->edit_uv.draw_type == SI_UVDT_STRETCH_ANGLE) {
GPUShader *sh = OVERLAY_shader_edit_uv_stretching_angle_get();
pd->edit_uv_stretching_grp = DRW_shgroup_create(sh, psl->edit_uv_stretching_ps);
DRW_shgroup_uniform_block(pd->edit_uv_stretching_grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_vec2_copy(pd->edit_uv_stretching_grp, "aspect", pd->edit_uv.uv_aspect);
pd->edit_uv_color_grp = DRW_shgroup_create(sh, psl->edit_uv_color_ps);
DRW_shgroup_uniform_block(pd->edit_uv_color_grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_vec2_copy(pd->edit_uv_color_grp, "aspect", pd->edit_uv.uv_aspect);
DRW_shgroup_uniform_float_copy(
pd->edit_uv_stretching_grp, "stretch_opacity", pd->edit_uv.stretch_opacity);
pd->edit_uv_color_grp, "color_opacity", pd->edit_uv.color_opacity);
}
else /* SI_UVDT_STRETCH_AREA */ {
else if (pd->edit_uv.draw_type == SI_UVDT_STRETCH_AREA) {
GPUShader *sh = OVERLAY_shader_edit_uv_stretching_area_get();
pd->edit_uv_stretching_grp = DRW_shgroup_create(sh, psl->edit_uv_stretching_ps);
DRW_shgroup_uniform_block(pd->edit_uv_stretching_grp, "globalsBlock", G_draw.block_ubo);
pd->edit_uv_color_grp = DRW_shgroup_create(sh, psl->edit_uv_color_ps);
DRW_shgroup_uniform_block(pd->edit_uv_color_grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_float(
pd->edit_uv_stretching_grp, "totalAreaRatio", &pd->edit_uv.total_area_ratio, 1);
pd->edit_uv_color_grp, "totalAreaRatio", &pd->edit_uv.total_area_ratio, 1);
DRW_shgroup_uniform_float_copy(
pd->edit_uv_stretching_grp, "stretch_opacity", pd->edit_uv.stretch_opacity);
pd->edit_uv_color_grp, "color_opacity", pd->edit_uv.color_opacity);
}
else /* SI_UVDT_ORIENTATION */ {
GPUShader *sh = OVERLAY_shader_edit_uv_orientation_get();
pd->edit_uv_color_grp = DRW_shgroup_create(sh, psl->edit_uv_color_ps);
DRW_shgroup_uniform_block(pd->edit_uv_color_grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_vec2_copy(pd->edit_uv_color_grp, "aspect", pd->edit_uv.uv_aspect);
DRW_shgroup_uniform_float_copy(
pd->edit_uv_color_grp, "color_opacity", pd->edit_uv.color_opacity);
}
}
@ -475,19 +483,22 @@ static void overlay_edit_uv_cache_populate(OVERLAY_Data *vedata, Object *ob)
}
}
if (pd->edit_uv.do_uv_stretching_overlay) {
if (pd->edit_uv.do_uv_color_overlay) {
if (pd->edit_uv.draw_type == SI_UVDT_STRETCH_ANGLE) {
geom = DRW_mesh_batch_cache_get_edituv_faces_stretch_angle(ob, mesh);
}
else /* SI_UVDT_STRETCH_AREA */ {
else if (pd->edit_uv.draw_type == SI_UVDT_STRETCH_AREA) {
OVERLAY_StretchingAreaTotals *totals = static_cast<OVERLAY_StretchingAreaTotals *>(
MEM_mallocN(sizeof(OVERLAY_StretchingAreaTotals), __func__));
BLI_addtail(&pd->edit_uv.totals, totals);
geom = DRW_mesh_batch_cache_get_edituv_faces_stretch_area(
ob, mesh, &totals->total_area, &totals->total_area_uv);
}
else /* SI_UVDT_ORIENTATION */ {
geom = DRW_mesh_batch_cache_get_edituv_faces_orientation(ob, mesh);
}
if (geom) {
DRW_shgroup_call_obmat(pd->edit_uv_stretching_grp, geom, nullptr);
DRW_shgroup_call_obmat(pd->edit_uv_color_grp, geom, nullptr);
}
}
}
@ -528,7 +539,7 @@ void OVERLAY_edit_uv_cache_finish(OVERLAY_Data *vedata)
OVERLAY_StorageList *stl = vedata->stl;
OVERLAY_PrivateData *pd = stl->pd;
if (pd->edit_uv.do_uv_stretching_overlay) {
if (pd->edit_uv.do_uv_color_overlay) {
edit_uv_stretching_update_ratios(vedata);
}
}
@ -566,8 +577,8 @@ void OVERLAY_edit_uv_draw(OVERLAY_Data *vedata)
}
}
if (pd->edit_uv.do_uv_stretching_overlay) {
DRW_draw_pass(psl->edit_uv_stretching_ps);
if (pd->edit_uv.do_uv_color_overlay) {
DRW_draw_pass(psl->edit_uv_color_ps);
}
if (pd->edit_uv.do_uv_overlay) {

View File

@ -25,7 +25,7 @@
# define USE_GEOM_SHADER_WORKAROUND 0
#endif
/* Needed for eSpaceImage_UVDT_Stretch and eMaskOverlayMode */
/* Needed for eSpaceImage_UVDT_Color and eMaskOverlayMode */
#include "DNA_mask_types.h"
#include "DNA_space_types.h"
/* Forward declarations */
@ -92,7 +92,7 @@ struct OVERLAY_PassList {
DRWPass *edit_uv_edges_ps;
DRWPass *edit_uv_verts_ps;
DRWPass *edit_uv_faces_ps;
DRWPass *edit_uv_stretching_ps;
DRWPass *edit_uv_color_ps;
DRWPass *edit_uv_tiled_image_borders_ps;
DRWPass *edit_uv_stencil_ps;
DRWPass *edit_uv_mask_ps;
@ -274,7 +274,7 @@ struct OVERLAY_PrivateData {
DRWShadingGroup *edit_uv_shadow_edges_grp;
DRWShadingGroup *edit_uv_faces_grp;
DRWShadingGroup *edit_uv_face_dots_grp;
DRWShadingGroup *edit_uv_stretching_grp;
DRWShadingGroup *edit_uv_color_grp;
DRWShadingGroup *edit_curves_points_grp[2];
DRWShadingGroup *edit_curves_lines_grp[2];
DRWShadingGroup *extra_grid_grp;
@ -383,7 +383,7 @@ struct OVERLAY_PrivateData {
struct {
bool do_uv_overlay;
bool do_uv_shadow_overlay;
bool do_uv_stretching_overlay;
bool do_uv_color_overlay;
bool do_tiled_image_overlay;
bool do_tiled_image_border_overlay;
bool do_stencil_overlay;
@ -395,7 +395,7 @@ struct OVERLAY_PrivateData {
float uv_opacity;
float stretch_opacity;
float color_opacity;
int image_size[2];
float image_aspect[2];
@ -407,7 +407,7 @@ struct OVERLAY_PrivateData {
/* stretching overlay */
float uv_aspect[2];
eSpaceImage_UVDT_Stretch draw_type;
eSpaceImage_UVDT_Color draw_type;
ListBase totals;
float total_area_ratio;
@ -759,6 +759,7 @@ GPUShader *OVERLAY_shader_edit_uv_face_dots_get();
GPUShader *OVERLAY_shader_edit_uv_verts_get();
GPUShader *OVERLAY_shader_edit_uv_stretching_area_get();
GPUShader *OVERLAY_shader_edit_uv_stretching_angle_get();
GPUShader *OVERLAY_shader_edit_uv_orientation_get();
GPUShader *OVERLAY_shader_edit_uv_tiled_image_borders_get();
GPUShader *OVERLAY_shader_edit_uv_stencil_image();
GPUShader *OVERLAY_shader_edit_uv_mask_image();

View File

@ -60,6 +60,7 @@ struct OVERLAY_Shaders {
GPUShader *edit_uv_face_dots;
GPUShader *edit_uv_stretching_angle;
GPUShader *edit_uv_stretching_area;
GPUShader *edit_uv_orientation;
GPUShader *edit_uv_tiled_image_borders;
GPUShader *edit_uv_stencil_image;
GPUShader *edit_uv_mask_image;
@ -1099,7 +1100,7 @@ GPUShader *OVERLAY_shader_edit_uv_stretching_area_get()
OVERLAY_Shaders *sh_data = &e_data.sh_data[0];
if (!sh_data->edit_uv_stretching_area) {
sh_data->edit_uv_stretching_area = GPU_shader_create_from_info_name(
"overlay_edit_uv_stretching_area");
"overlay_edit_uv_color_stretching_area");
}
return sh_data->edit_uv_stretching_area;
@ -1110,12 +1111,23 @@ GPUShader *OVERLAY_shader_edit_uv_stretching_angle_get()
OVERLAY_Shaders *sh_data = &e_data.sh_data[0];
if (!sh_data->edit_uv_stretching_angle) {
sh_data->edit_uv_stretching_angle = GPU_shader_create_from_info_name(
"overlay_edit_uv_stretching_angle");
"overlay_edit_uv_color_stretching_angle");
}
return sh_data->edit_uv_stretching_angle;
}
GPUShader *OVERLAY_shader_edit_uv_orientation_get()
{
OVERLAY_Shaders *sh_data = &e_data.sh_data[0];
if (!sh_data->edit_uv_orientation) {
sh_data->edit_uv_orientation = GPU_shader_create_from_info_name(
"overlay_edit_uv_color_orientation");
}
return sh_data->edit_uv_orientation;
}
GPUShader *OVERLAY_shader_edit_uv_tiled_image_borders_get()
{
OVERLAY_Shaders *sh_data = &e_data.sh_data[0];

View File

@ -376,28 +376,34 @@ GPU_SHADER_CREATE_INFO(overlay_edit_uv_mask_image)
/** \name UV Stretching
* \{ */
GPU_SHADER_CREATE_INFO(overlay_edit_uv_stretching)
GPU_SHADER_CREATE_INFO(overlay_edit_uv_color)
.vertex_in(0, Type::VEC2, "pos")
.push_constant(Type::VEC2, "aspect")
.push_constant(Type::FLOAT, "stretch_opacity")
.push_constant(Type::FLOAT, "color_opacity")
.vertex_out(overlay_edit_nopersp_color_iface)
.fragment_out(0, Type::VEC4, "fragColor")
.vertex_source("overlay_edit_uv_stretching_vert.glsl")
.vertex_source("overlay_edit_uv_color_vert.glsl")
.fragment_source("overlay_varying_color.glsl")
.additional_info("draw_mesh", "draw_globals");
GPU_SHADER_CREATE_INFO(overlay_edit_uv_stretching_area)
GPU_SHADER_CREATE_INFO(overlay_edit_uv_color_stretching_area)
.do_static_compilation(true)
.define("STRETCH_AREA")
.vertex_in(1, Type::FLOAT, "ratio")
.push_constant(Type::FLOAT, "totalAreaRatio")
.additional_info("overlay_edit_uv_stretching");
.additional_info("overlay_edit_uv_color");
GPU_SHADER_CREATE_INFO(overlay_edit_uv_stretching_angle)
GPU_SHADER_CREATE_INFO(overlay_edit_uv_color_stretching_angle)
.do_static_compilation(true)
.define("STRETCH_ANGLE")
.vertex_in(1, Type::VEC2, "uv_angles")
.vertex_in(2, Type::FLOAT, "angle")
.additional_info("overlay_edit_uv_stretching");
.additional_info("overlay_edit_uv_color");
GPU_SHADER_CREATE_INFO(overlay_edit_uv_color_orientation)
.do_static_compilation(true)
.vertex_in(1, Type::VEC3, "uv_nor")
.additional_info("overlay_edit_uv_color");
/** \} */

View File

@ -70,17 +70,18 @@ void main()
vec3 world_pos = point_object_to_world(vec3(pos, 0.0));
gl_Position = point_world_to_ndc(world_pos);
#ifdef STRETCH_ANGLE
#if defined(STRETCH_ANGLE)
vec2 v1 = angle_to_v2(uv_angles.x * M_PI);
vec2 v2 = angle_to_v2(uv_angles.y * M_PI);
float uv_angle = angle_normalized_v2v2(v1, v2) / M_PI;
float stretch = 1.0 - abs(uv_angle - angle);
stretch = stretch;
stretch = 1.0 - stretch * stretch;
float weight = 1.0 - abs(uv_angle - angle);
weight = 1.0 - weight * weight;
#elif defined(STRETCH_AREA)
float weight = 1.0 - area_ratio_to_stretch(ratio, totalAreaRatio);
#else
float stretch = 1.0 - area_ratio_to_stretch(ratio, totalAreaRatio);
float weight = (uv_nor.z + 1.0) / 2.0;
#endif
finalColor = vec4(weight_to_rgb(stretch), stretch_opacity);
finalColor = vec4(weight_to_rgb(weight), color_opacity);
}

View File

@ -88,6 +88,7 @@ struct MeshBufferList {
GPUVertBuf *edituv_data;
GPUVertBuf *edituv_stretch_area;
GPUVertBuf *edituv_stretch_angle;
GPUVertBuf *edituv_orientation;
GPUVertBuf *mesh_analysis;
GPUVertBuf *fdots_pos;
GPUVertBuf *fdots_nor;
@ -143,6 +144,7 @@ struct MeshBatchList {
/* Edit UVs */
GPUBatch *edituv_faces_stretch_area;
GPUBatch *edituv_faces_stretch_angle;
GPUBatch *edituv_faces_orientation;
GPUBatch *edituv_faces;
GPUBatch *edituv_edges;
GPUBatch *edituv_verts;
@ -186,6 +188,7 @@ enum DRWBatchFlag {
MBC_SKIN_ROOTS = (1u << MBC_BATCH_INDEX(edit_skin_roots)),
MBC_EDITUV_FACES_STRETCH_AREA = (1u << MBC_BATCH_INDEX(edituv_faces_stretch_area)),
MBC_EDITUV_FACES_STRETCH_ANGLE = (1u << MBC_BATCH_INDEX(edituv_faces_stretch_angle)),
MBC_EDITUV_FACES_ORIENTATION = (1u << MBC_BATCH_INDEX(edituv_faces_orientation)),
MBC_EDITUV_FACES = (1u << MBC_BATCH_INDEX(edituv_faces)),
MBC_EDITUV_EDGES = (1u << MBC_BATCH_INDEX(edituv_edges)),
MBC_EDITUV_VERTS = (1u << MBC_BATCH_INDEX(edituv_verts)),
@ -295,8 +298,9 @@ struct MeshBatchCache {
};
#define MBC_EDITUV \
(MBC_EDITUV_FACES_STRETCH_AREA | MBC_EDITUV_FACES_STRETCH_ANGLE | MBC_EDITUV_FACES | \
MBC_EDITUV_EDGES | MBC_EDITUV_VERTS | MBC_EDITUV_FACEDOTS | MBC_WIRE_LOOPS_UVS)
(MBC_EDITUV_FACES_STRETCH_AREA | MBC_EDITUV_FACES_STRETCH_ANGLE | \
MBC_EDITUV_FACES_ORIENTATION | MBC_EDITUV_FACES | MBC_EDITUV_EDGES | MBC_EDITUV_VERTS | \
MBC_EDITUV_FACEDOTS | MBC_WIRE_LOOPS_UVS)
void mesh_buffer_cache_create_requested(TaskGraph *task_graph,
MeshBatchCache &cache,

View File

@ -639,6 +639,7 @@ void mesh_buffer_cache_create_requested(TaskGraph *task_graph,
EXTRACT_ADD_REQUESTED(vbo, edituv_data);
EXTRACT_ADD_REQUESTED(vbo, edituv_stretch_area);
EXTRACT_ADD_REQUESTED(vbo, edituv_stretch_angle);
EXTRACT_ADD_REQUESTED(vbo, edituv_orientation);
EXTRACT_ADD_REQUESTED(vbo, mesh_analysis);
EXTRACT_ADD_REQUESTED(vbo, fdots_pos);
EXTRACT_ADD_REQUESTED(vbo, fdots_nor);
@ -868,6 +869,7 @@ void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache &cache,
EXTRACT_ADD_REQUESTED(vbo, tan);
EXTRACT_ADD_REQUESTED(vbo, edituv_stretch_area);
EXTRACT_ADD_REQUESTED(vbo, edituv_stretch_angle);
EXTRACT_ADD_REQUESTED(vbo, edituv_orientation);
EXTRACT_ADD_REQUESTED(ibo, lines_paint_mask);
EXTRACT_ADD_REQUESTED(ibo, lines_adjacency);
EXTRACT_ADD_REQUESTED(vbo, weights);

View File

@ -252,6 +252,7 @@ GPUBatch *DRW_mesh_batch_cache_get_edituv_faces_stretch_area(Object *object,
float **tot_area,
float **tot_uv_area);
GPUBatch *DRW_mesh_batch_cache_get_edituv_faces_stretch_angle(Object *object, Mesh *mesh);
GPUBatch *DRW_mesh_batch_cache_get_edituv_faces_orientation(Object *object, Mesh *mesh);
GPUBatch *DRW_mesh_batch_cache_get_edituv_faces(Object *object, Mesh *mesh);
GPUBatch *DRW_mesh_batch_cache_get_edituv_edges(Object *object, Mesh *mesh);
GPUBatch *DRW_mesh_batch_cache_get_edituv_verts(Object *object, Mesh *mesh);

View File

@ -87,6 +87,7 @@ namespace blender::draw {
#define _BATCH_MAP8(a, b, c, d, e, f, g, h) _BATCH_MAP7(a, b, c, d, e, f, g) | _BATCH_MAP1(h)
#define _BATCH_MAP9(a, b, c, d, e, f, g, h, i) _BATCH_MAP8(a, b, c, d, e, f, g, h) | _BATCH_MAP1(i)
#define _BATCH_MAP10(a, b, c, d, e, f, g, h, i, j) _BATCH_MAP9(a, b, c, d, e, f, g, h, i) | _BATCH_MAP1(j)
#define _BATCH_MAP11(a, b, c, d, e, f, g, h, i, j, k) _BATCH_MAP10(a, b, c, d, e, f, g, h, i, j) | _BATCH_MAP1(k)
#define BATCH_MAP(...) VA_NARGS_CALL_OVERLOAD(_BATCH_MAP, __VA_ARGS__)
@ -112,8 +113,8 @@ static constexpr DRWBatchFlag batches_that_use_buffer(const int buffer_index)
return MBC_SURFACE_WEIGHTS;
case BUFFER_INDEX(vbo.uv):
return MBC_SURFACE | MBC_EDITUV_FACES_STRETCH_AREA | MBC_EDITUV_FACES_STRETCH_ANGLE |
MBC_EDITUV_FACES | MBC_EDITUV_EDGES | MBC_EDITUV_VERTS | MBC_WIRE_LOOPS_UVS |
MBC_SURFACE_PER_MAT;
MBC_EDITUV_FACES_ORIENTATION | MBC_EDITUV_FACES | MBC_EDITUV_EDGES |
MBC_EDITUV_VERTS | MBC_WIRE_LOOPS_UVS | MBC_SURFACE_PER_MAT;
case BUFFER_INDEX(vbo.tan):
return MBC_SURFACE_PER_MAT;
case BUFFER_INDEX(vbo.sculpt_data):
@ -124,11 +125,13 @@ static constexpr DRWBatchFlag batches_that_use_buffer(const int buffer_index)
return MBC_EDIT_TRIANGLES | MBC_EDIT_EDGES | MBC_EDIT_VERTICES;
case BUFFER_INDEX(vbo.edituv_data):
return MBC_EDITUV_FACES | MBC_EDITUV_FACES_STRETCH_AREA | MBC_EDITUV_FACES_STRETCH_ANGLE |
MBC_EDITUV_EDGES | MBC_EDITUV_VERTS;
MBC_EDITUV_FACES_ORIENTATION | MBC_EDITUV_EDGES | MBC_EDITUV_VERTS;
case BUFFER_INDEX(vbo.edituv_stretch_area):
return MBC_EDITUV_FACES_STRETCH_AREA;
case BUFFER_INDEX(vbo.edituv_stretch_angle):
return MBC_EDITUV_FACES_STRETCH_ANGLE;
case BUFFER_INDEX(vbo.edituv_orientation):
return MBC_EDITUV_FACES_ORIENTATION;
case BUFFER_INDEX(vbo.mesh_analysis):
return MBC_EDIT_MESH_ANALYSIS;
case BUFFER_INDEX(vbo.fdots_pos):
@ -186,7 +189,8 @@ static constexpr DRWBatchFlag batches_that_use_buffer(const int buffer_index)
case BUFFER_INDEX(ibo.lines_adjacency):
return MBC_EDGE_DETECTION;
case BUFFER_INDEX(ibo.edituv_tris):
return MBC_EDITUV_FACES | MBC_EDITUV_FACES_STRETCH_AREA | MBC_EDITUV_FACES_STRETCH_ANGLE;
return MBC_EDITUV_FACES | MBC_EDITUV_FACES_STRETCH_AREA | MBC_EDITUV_FACES_STRETCH_ANGLE |
MBC_EDITUV_FACES_ORIENTATION;
case BUFFER_INDEX(ibo.edituv_lines):
return MBC_EDITUV_EDGES | MBC_WIRE_LOOPS_UVS;
case BUFFER_INDEX(ibo.edituv_points):
@ -676,6 +680,7 @@ static void mesh_batch_cache_discard_uvedit(MeshBatchCache &cache)
FOREACH_MESH_BUFFER_CACHE (cache, mbc) {
GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.edituv_stretch_angle);
GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.edituv_stretch_area);
GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.edituv_orientation);
GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.uv);
GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.edituv_data);
GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.fdots_uv);
@ -687,6 +692,7 @@ static void mesh_batch_cache_discard_uvedit(MeshBatchCache &cache)
}
DRWBatchFlag batch_map = BATCH_MAP(vbo.edituv_stretch_angle,
vbo.edituv_stretch_area,
vbo.edituv_orientation,
vbo.uv,
vbo.edituv_data,
vbo.fdots_uv,
@ -1211,6 +1217,14 @@ GPUBatch *DRW_mesh_batch_cache_get_edituv_faces_stretch_angle(Object *object, Me
return DRW_batch_request(&cache.batch.edituv_faces_stretch_angle);
}
GPUBatch *DRW_mesh_batch_cache_get_edituv_faces_orientation(Object *object, Mesh *mesh)
{
MeshBatchCache &cache = *mesh_batch_cache_get(mesh);
edituv_request_active_uv(cache, object, mesh);
mesh_batch_cache_add_request(cache, MBC_EDITUV_FACES_ORIENTATION);
return DRW_batch_request(&cache.batch.edituv_faces_orientation);
}
GPUBatch *DRW_mesh_batch_cache_get_edituv_faces(Object *object, Mesh *mesh)
{
MeshBatchCache &cache = *mesh_batch_cache_get(mesh);
@ -1400,9 +1414,9 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph *task_graph,
}
}
if (batch_requested &
(MBC_SURFACE | MBC_WIRE_LOOPS_UVS | MBC_EDITUV_FACES_STRETCH_AREA |
MBC_EDITUV_FACES_STRETCH_ANGLE | MBC_EDITUV_FACES | MBC_EDITUV_EDGES | MBC_EDITUV_VERTS))
if (batch_requested & (MBC_SURFACE | MBC_WIRE_LOOPS_UVS | MBC_EDITUV_FACES_STRETCH_AREA |
MBC_EDITUV_FACES_STRETCH_ANGLE | MBC_EDITUV_FACES_ORIENTATION |
MBC_EDITUV_FACES | MBC_EDITUV_EDGES | MBC_EDITUV_VERTS))
{
/* Modifiers will only generate an orco layer if the mesh is deformed. */
if (cache.cd_needed.orco != 0) {
@ -1481,6 +1495,7 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph *task_graph,
GPU_BATCH_CLEAR_SAFE(cache.batch.wire_loops_uvs);
GPU_BATCH_CLEAR_SAFE(cache.batch.edituv_faces_stretch_area);
GPU_BATCH_CLEAR_SAFE(cache.batch.edituv_faces_stretch_angle);
GPU_BATCH_CLEAR_SAFE(cache.batch.edituv_faces_orientation);
GPU_BATCH_CLEAR_SAFE(cache.batch.edituv_faces);
GPU_BATCH_CLEAR_SAFE(cache.batch.edituv_edges);
GPU_BATCH_CLEAR_SAFE(cache.batch.edituv_verts);
@ -1779,6 +1794,17 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph *task_graph,
DRW_vbo_request(cache.batch.edituv_faces_stretch_angle, &mbuflist->vbo.edituv_data);
DRW_vbo_request(cache.batch.edituv_faces_stretch_angle, &mbuflist->vbo.edituv_stretch_angle);
}
assert_deps_valid(MBC_EDITUV_FACES_ORIENTATION,
{BUFFER_INDEX(ibo.edituv_tris),
BUFFER_INDEX(vbo.uv),
BUFFER_INDEX(vbo.edituv_data),
BUFFER_INDEX(vbo.edituv_orientation)});
if (DRW_batch_requested(cache.batch.edituv_faces_orientation, GPU_PRIM_TRIS)) {
DRW_ibo_request(cache.batch.edituv_faces_orientation, &mbuflist->ibo.edituv_tris);
DRW_vbo_request(cache.batch.edituv_faces_orientation, &mbuflist->vbo.uv);
DRW_vbo_request(cache.batch.edituv_faces_orientation, &mbuflist->vbo.edituv_data);
DRW_vbo_request(cache.batch.edituv_faces_orientation, &mbuflist->vbo.edituv_orientation);
}
assert_deps_valid(
MBC_EDITUV_EDGES,
{BUFFER_INDEX(ibo.edituv_lines), BUFFER_INDEX(vbo.uv), BUFFER_INDEX(vbo.edituv_data)});
@ -1838,6 +1864,7 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph *task_graph,
assert_final_deps_valid(BUFFER_INDEX(vbo.edituv_data));
assert_final_deps_valid(BUFFER_INDEX(vbo.edituv_stretch_area));
assert_final_deps_valid(BUFFER_INDEX(vbo.edituv_stretch_angle));
assert_final_deps_valid(BUFFER_INDEX(vbo.edituv_orientation));
assert_final_deps_valid(BUFFER_INDEX(vbo.fdots_uv));
assert_final_deps_valid(BUFFER_INDEX(vbo.fdots_edituv_data));
for (const int i : IndexRange(GPU_MAX_ATTR)) {

View File

@ -59,6 +59,7 @@ extern "C" char datatoc_common_subdiv_vbo_lnor_comp_glsl[];
extern "C" char datatoc_common_subdiv_vbo_sculpt_data_comp_glsl[];
extern "C" char datatoc_common_subdiv_vbo_edituv_strech_angle_comp_glsl[];
extern "C" char datatoc_common_subdiv_vbo_edituv_strech_area_comp_glsl[];
extern "C" char datatoc_common_subdiv_vbo_edituv_nor_comp_glsl[];
namespace blender::draw {
@ -84,6 +85,7 @@ enum {
SHADER_BUFFER_SCULPT_DATA,
SHADER_BUFFER_UV_STRETCH_ANGLE,
SHADER_BUFFER_UV_STRETCH_AREA,
SHADER_BUFFER_UV_ORIENTATION,
NUM_SHADERS,
};
@ -140,6 +142,9 @@ static const char *get_shader_code(int shader_type)
case SHADER_BUFFER_UV_STRETCH_AREA: {
return datatoc_common_subdiv_vbo_edituv_strech_area_comp_glsl;
}
case SHADER_BUFFER_UV_ORIENTATION: {
return datatoc_common_subdiv_vbo_edituv_nor_comp_glsl;
}
}
return nullptr;
}
@ -205,6 +210,9 @@ static const char *get_shader_name(int shader_type)
case SHADER_BUFFER_UV_STRETCH_AREA: {
return "subdiv uv stretch area";
}
case SHADER_BUFFER_UV_ORIENTATION: {
return "subdiv uv orientation";
}
}
return nullptr;
}
@ -1983,6 +1991,31 @@ void draw_subdiv_build_edituv_stretch_angle_buffer(const DRWSubdivCache &cache,
GPU_shader_unbind();
}
void draw_subdiv_build_edituv_orientation_buffer(const DRWSubdivCache &cache,
GPUVertBuf *uvs,
int uvs_offset,
GPUVertBuf *orientations)
{
GPUShader *shader = get_subdiv_shader(SHADER_BUFFER_UV_ORIENTATION);
GPU_shader_bind(shader);
int binding_point = 0;
/* Inputs */
GPU_vertbuf_bind_as_ssbo(uvs, binding_point++);
/* Outputs */
GPU_vertbuf_bind_as_ssbo(orientations, binding_point++);
BLI_assert(binding_point <= MAX_GPU_SUBDIV_SSBOS);
drw_subdiv_compute_dispatch(cache, shader, uvs_offset, 0, cache.num_subdiv_quads);
/* This generates a vertex buffer, so we need to put a barrier on the vertex attribute array. */
GPU_memory_barrier(GPU_BARRIER_VERTEX_ATTRIB_ARRAY);
/* Cleanup. */
GPU_shader_unbind();
}
/* -------------------------------------------------------------------- */
/**

View File

@ -294,6 +294,11 @@ void draw_subdiv_build_edituv_stretch_angle_buffer(const DRWSubdivCache &cache,
int uvs_offset,
GPUVertBuf *stretch_angles);
void draw_subdiv_build_edituv_orientation_buffer(const DRWSubdivCache &cache,
GPUVertBuf *uvs,
int uvs_offset,
GPUVertBuf *orientations);
/** Return the format used for the positions and normals VBO. */
GPUVertFormat *draw_subdiv_get_pos_nor_format();

View File

@ -362,6 +362,7 @@ extern const MeshExtract extract_edit_data;
extern const MeshExtract extract_edituv_data;
extern const MeshExtract extract_edituv_stretch_area;
extern const MeshExtract extract_edituv_stretch_angle;
extern const MeshExtract extract_edituv_orientation;
extern const MeshExtract extract_mesh_analysis;
extern const MeshExtract extract_fdots_pos;
extern const MeshExtract extract_fdots_nor;

View File

@ -0,0 +1,202 @@
/* SPDX-FileCopyrightText: 2021 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup draw
*/
#include "MEM_guardedalloc.h"
#include "BKE_mesh.hh"
#include "BKE_editmesh.hh"
#include "BLI_math_vector_types.hh"
#include "extract_mesh.hh"
#include "draw_subdivision.hh"
namespace blender::draw {
/* ---------------------------------------------------------------------- */
/** \name Extract Edit UV normals
* \{ */
struct MeshExtract_UVNormal_Data {
float3 *vbo_data;
const float2 *uv;
int cd_ofs;
};
static void extract_edituv_uv_nor_init(const MeshRenderData &mr,
MeshBatchCache & /*cache*/,
void *buf,
void *tls_data)
{
GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
GPU_vertformat_attr_add(&format, "uv_nor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, mr.loop_len);
MeshExtract_UVNormal_Data *data = static_cast<MeshExtract_UVNormal_Data *>(tls_data);
data->vbo_data = (float3 *)GPU_vertbuf_get_data(vbo);
/* Special iterator needed to save about half of the computing cost. */
if (mr.extract_type == MR_EXTRACT_BMESH) {
data->cd_ofs = CustomData_get_offset(&mr.bm->ldata, CD_PROP_FLOAT2);
}
else {
BLI_assert(mr.extract_type == MR_EXTRACT_MESH);
data->uv = (const float2 *)CustomData_get_layer(&mr.mesh->corner_data, CD_PROP_FLOAT2);
}
}
static void extract_edituv_uv_nor_iter_face_bm(const MeshRenderData &mr,
const BMFace *f,
const int f_index,
void *_data)
{
MeshExtract_UVNormal_Data *data = static_cast<MeshExtract_UVNormal_Data *>(_data);
int tri_first_index_real = poly_to_tri_count(f_index, BM_elem_index_get(f->l_first));
for (int i = 0; i < f->len; i++) {
data->vbo_data[BM_elem_index_get(f->l_first) + i] = {0.0f, 0.0f, -1.0f};
}
BMLoop *(*looptris)[3] = mr.edit_bmesh->looptris;
int tri_len = f->len - 2;
for (int offs = 0; offs < tri_len; offs++) {
BMLoop **elt = looptris[tri_first_index_real + offs];
const float(*luv_0)[2], (*luv_1)[2], (*luv_2)[2];
luv_0 = BM_ELEM_CD_GET_FLOAT2_P(elt[0], data->cd_ofs);
luv_1 = BM_ELEM_CD_GET_FLOAT2_P(elt[1], data->cd_ofs);
luv_2 = BM_ELEM_CD_GET_FLOAT2_P(elt[2], data->cd_ofs);
float3 e1 = {luv_0[0][0] - luv_1[0][0], luv_0[0][1] - luv_1[0][1], 0.0f};
float3 e2 = {luv_2[0][0] - luv_0[0][0], luv_2[0][1] - luv_0[0][1], 0.0f};
float3 normal = {e1[1] * e2[2] - e1[2] * e2[1],
e1[2] * e2[0] - e1[0] * e2[2],
e1[0] * e2[1] - e1[1] * e2[0]};
normalize_v3(normal);
if (normal.z > 0.0f) {
data->vbo_data[BM_elem_index_get(elt[0])] = normal;
data->vbo_data[BM_elem_index_get(elt[1])] = normal;
data->vbo_data[BM_elem_index_get(elt[2])] = normal;
}
}
}
static void extract_edituv_uv_nor_iter_face_mesh(const MeshRenderData &mr,
const int face_index,
void *_data)
{
MeshExtract_UVNormal_Data *data = static_cast<MeshExtract_UVNormal_Data *>(_data);
const IndexRange face = mr.faces[face_index];
int face_end = face.start() + face.size();
for (int i = face.start(); i < face_end; i++) {
data->vbo_data[i] = {0.0f, 0.0f, -1.0f};
}
int tri_first_index_real = poly_to_tri_count(face_index, face.start());
int tri_len = face.size() - 2;
for (int offs = 0; offs < tri_len; offs++) {
const int3 &tri = mr.corner_tris[tri_first_index_real + offs];
float2 luv_0 = data->uv[tri[0]];
float2 luv_1 = data->uv[tri[1]];
float2 luv_2 = data->uv[tri[2]];
float3 e1 = {luv_0[0] - luv_1[0], luv_0[1] - luv_1[1], 0.0f};
float3 e2 = {luv_2[0] - luv_0[0], luv_2[1] - luv_0[1], 0.0f};
float3 normal = {e1[1] * e2[2] - e1[2] * e2[1],
e1[2] * e2[0] - e1[0] * e2[2],
e1[0] * e2[1] - e1[1] * e2[0]};
normalize_v3(normal);
if (normal.z > 0.0f) {
data->vbo_data[tri[0]] = normal;
data->vbo_data[tri[1]] = normal;
data->vbo_data[tri[2]] = normal;
}
}
}
static GPUVertFormat *get_edituv_stretch_uv_nor_subdiv()
{
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
GPU_vertformat_attr_add(&format, "uv_nor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
return &format;
}
static void extract_edituv_uv_nor_init_subdiv(const DRWSubdivCache &subdiv_cache,
const MeshRenderData &mr,
MeshBatchCache &cache,
void *buffer,
void * /*tls_data*/)
{
GPUVertBuf *refined_vbo = static_cast<GPUVertBuf *>(buffer);
GPU_vertbuf_init_build_on_device(
refined_vbo, get_edituv_stretch_uv_nor_subdiv(), subdiv_cache.num_subdiv_loops);
GPUVertBuf *uvs = cache.final.buff.vbo.uv;
/* UVs are stored contiguously so we need to compute the offset in the UVs buffer for the active
* UV layer. */
CustomData *cd_ldata = (mr.extract_type == MR_EXTRACT_MESH) ? &mr.mesh->corner_data :
&mr.bm->ldata;
uint32_t uv_layers = cache.cd_used.uv;
/* HACK to fix #68857 */
if (mr.extract_type == MR_EXTRACT_BMESH && cache.cd_used.edit_uv == 1) {
int layer = CustomData_get_active_layer(cd_ldata, CD_PROP_FLOAT2);
if (layer != -1 && !CustomData_layer_is_anonymous(cd_ldata, CD_PROP_FLOAT2, layer)) {
uv_layers |= (1 << layer);
}
}
int uvs_offset = 0;
for (int i = 0; i < MAX_MTFACE; i++) {
if (uv_layers & (1 << i)) {
if (i == CustomData_get_active_layer(cd_ldata, CD_PROP_FLOAT2)) {
break;
}
uvs_offset += 1;
}
}
/* The data is at `offset * num loops`, and we have 2 values per index. */
uvs_offset *= subdiv_cache.num_subdiv_loops * 2;
draw_subdiv_build_edituv_orientation_buffer(subdiv_cache, uvs, uvs_offset, refined_vbo);
}
constexpr MeshExtract create_extractor_edituv_orientation()
{
MeshExtract extractor = {nullptr};
extractor.init = extract_edituv_uv_nor_init;
extractor.iter_face_bm = extract_edituv_uv_nor_iter_face_bm;
extractor.iter_face_mesh = extract_edituv_uv_nor_iter_face_mesh;
extractor.init_subdiv = extract_edituv_uv_nor_init_subdiv;
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(MeshExtract_UVNormal_Data);
extractor.use_threading = false;
extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.edituv_orientation);
return extractor;
}
/** \} */
const MeshExtract extract_edituv_orientation = create_extractor_edituv_orientation();
} // namespace blender::draw

View File

@ -0,0 +1,58 @@
/* SPDX-FileCopyrightText: 2021-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/* To be compiled with common_subdiv_lib.glsl */
layout(std430, binding = 0) readonly buffer inputUVs
{
vec2 uvs[];
};
layout(std430, binding = 1) writeonly buffer outputNormals
{
vec3 uv_normals[];
};
void main()
{
/* We execute for each quad. */
uint quad_index = get_global_invocation_index();
if (quad_index >= total_dispatch_size) {
return;
}
/* The start index of the loop is quad_index * 4. */
uint start_loop_index = quad_index * 4;
uint triangle_loop_index = quad_index * 6;
uint loop_0 = start_loop_index;
uint loop_1 = start_loop_index + 1;
uint loop_2 = start_loop_index + 2;
uint loop_3 = start_loop_index + 3;
vec2 luv_0= uvs[src_offset + loop_0];
vec2 luv_1= uvs[src_offset + loop_1];
vec2 luv_2= uvs[src_offset + loop_2];
vec2 luv_3= uvs[src_offset + loop_3];
vec3 e1 = vec3(luv_0 - luv_1, 0.0);
vec3 e2 = vec3(luv_2 - luv_0, 0.0);
vec3 e3 = vec3(luv_3 - luv_2, 0.0);
vec3 normal_1 = normalize(cross(e1, e2));
vec3 normal_2 = normalize(cross(e2, e3));
uv_normals[loop_1] = normal_1;
uv_normals[loop_3] = normal_2;
if (normal_1.z > 0.0) {
uv_normals[loop_0] = normal_1;
uv_normals[loop_2] = normal_1;
}
else {
uv_normals[loop_0] = normal_2;
uv_normals[loop_2] = normal_2;
}
}

View File

@ -101,7 +101,7 @@ static SpaceLink *image_create(const ScrArea * /*area*/, const Scene * /*scene*/
simage->lock = true;
simage->flag = SI_SHOW_GPENCIL | SI_USE_ALPHA | SI_COORDFLOATS;
simage->uv_opacity = 1.0f;
simage->stretch_opacity = 1.0f;
simage->color_opacity = 1.0f;
simage->overlay.flag = SI_OVERLAY_SHOW_OVERLAYS | SI_OVERLAY_SHOW_GRID_BACKGROUND;
BKE_imageuser_default(&simage->iuser);

View File

@ -1261,7 +1261,7 @@ typedef struct SpaceImage {
/** UV draw type. */
char dt_uv;
/** Sticky selection type. */
char dt_uvstretch;
char dt_uvcolor;
char around;
char gizmo_flag;
@ -1273,7 +1273,7 @@ typedef struct SpaceImage {
float uv_opacity;
float stretch_opacity;
float color_opacity;
int tile_grid_shape[2];
/**
@ -1294,11 +1294,12 @@ typedef enum eSpaceImage_UVDT {
SI_UVDT_WHITE = 3,
} eSpaceImage_UVDT;
/** #SpaceImage.dt_uvstretch */
typedef enum eSpaceImage_UVDT_Stretch {
/** #SpaceImage.dt_uvcolor */
typedef enum eSpaceImage_UVDT_Color {
SI_UVDT_STRETCH_ANGLE = 0,
SI_UVDT_STRETCH_AREA = 1,
} eSpaceImage_UVDT_Stretch;
SI_UVDT_ORIENTATION = 2,
} eSpaceImage_UVDT_Color;
/** #SpaceImage.pixel_round_mode */
typedef enum eSpaceImage_PixelRoundMode {
@ -1347,7 +1348,7 @@ typedef enum eSpaceImage_Flag {
*/
SI_DRAW_TILE = (1 << 19),
SI_FLAG_UNUSED_20 = (1 << 20), /* cleared */
SI_DRAW_STRETCH = (1 << 21),
SI_DRAW_COLOR = (1 << 21),
SI_SHOW_GPENCIL = (1 << 22),
SI_FLAG_UNUSED_23 = (1 << 23), /* cleared */

View File

@ -3618,9 +3618,24 @@ static void rna_def_space_image_uv(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
static const EnumPropertyItem dt_uvstretch_items[] = {
{SI_UVDT_STRETCH_ANGLE, "ANGLE", 0, "Angle", "Angular distortion between UV and 3D angles"},
{SI_UVDT_STRETCH_AREA, "AREA", 0, "Area", "Area distortion between UV and 3D faces"},
static const EnumPropertyItem dt_uvcolor_items[] = {
{SI_UVDT_STRETCH_ANGLE,
"ANGLE",
0,
"Angle Stretch",
"Angular distortion between UV and 3D angles (blue for low distortion, red for high "
"distortion)"},
{SI_UVDT_STRETCH_AREA,
"AREA",
0,
"Area Stretch",
"Area distortion between UV and 3D faces (blue for low distortion, red for high "
"distortion)"},
{SI_UVDT_ORIENTATION,
"UV_ORIENTATION",
0,
"UV Orientation",
"Orientation of UVs (blue for negative, red for positive)"},
{0, nullptr, 0, nullptr, nullptr},
};
@ -3651,8 +3666,8 @@ static void rna_def_space_image_uv(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Display As", "Display style for UV edges");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, nullptr);
prop = RNA_def_property(srna, "show_stretch", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "flag", SI_DRAW_STRETCH);
prop = RNA_def_property(srna, "show_color", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "flag", SI_DRAW_COLOR);
RNA_def_property_ui_text(
prop,
"Display Stretch",
@ -3660,10 +3675,10 @@ static void rna_def_space_image_uv(BlenderRNA *brna)
"their 3D coordinates (blue for low distortion, red for high distortion)");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, nullptr);
prop = RNA_def_property(srna, "display_stretch_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, nullptr, "dt_uvstretch");
RNA_def_property_enum_items(prop, dt_uvstretch_items);
RNA_def_property_ui_text(prop, "Display Stretch Type", "Type of stretch to display");
prop = RNA_def_property(srna, "display_color_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, nullptr, "dt_uvcolor");
RNA_def_property_enum_items(prop, dt_uvcolor_items);
RNA_def_property_ui_text(prop, "Display Color Overlay Type", "Type of color overlay to display");
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_MESH);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, nullptr);
@ -3732,10 +3747,10 @@ static void rna_def_space_image_uv(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "UV Opacity", "Opacity of UV overlays");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, nullptr);
prop = RNA_def_property(srna, "stretch_opacity", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, nullptr, "stretch_opacity");
prop = RNA_def_property(srna, "color_opacity", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, nullptr, "color_opacity");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Stretch Opacity", "Opacity of the UV Stretch overlay");
RNA_def_property_ui_text(prop, "Color Opacity", "Opacity of the UV Color overlay");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, nullptr);
prop = RNA_def_property(srna, "pixel_round_mode", PROP_ENUM, PROP_NONE);