From 9c2e768f5baf492bd5cedb59c218a7dfc8a7a761 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Fri, 1 Sep 2023 17:08:07 +0200 Subject: [PATCH] Snap: Show different symbols for different types Add a set of symbols to improve visualization of different snap types. - Circle: Represents snapping to a vertex. - Two Aligned Lines: Represent snapping to an edge. - Closed Aligned Square: Represents snapping to a specific part of an edge (center or perpendicular). - Face-Aligned Circle with Midline: Represents snapping to a face. Pull Request: https://projects.blender.org/blender/blender/pulls/109387 --- .../space_view3d/view3d_cursor_snap.cc | 172 ++++++++++++------ .../editors/transform/transform_snap.cc | 30 ++- 2 files changed, 139 insertions(+), 63 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_cursor_snap.cc b/source/blender/editors/space_view3d/view3d_cursor_snap.cc index dab1121576f..f7c6745cc82 100644 --- a/source/blender/editors/space_view3d/view3d_cursor_snap.cc +++ b/source/blender/editors/space_view3d/view3d_cursor_snap.cc @@ -374,6 +374,99 @@ static void cursor_box_draw(const float dimensions[3], uchar color[4]) GPU_blend(GPU_BLEND_NONE); } +static void cursor_point_draw(uint attr_pos, + const float loc[3], + const float nor[3], + const float size, + eSnapMode snap_type, + const uchar color[4], + bool is_persp) +{ + immUniformColor4ubv(color); + + GPU_matrix_push(); + + float rotate_view[3][3], model_view_new[4][4]; + GPU_matrix_model_view_get(model_view_new); + copy_m3_m4(rotate_view, model_view_new); + translate_m4(model_view_new, UNPACK3(loc)); + copy_v3_fl3(model_view_new[0], size, 0.0f, 0.0f); + copy_v3_fl3(model_view_new[1], 0.0f, size, 0.0f); + copy_v3_fl3(model_view_new[2], 0.0f, 0.0f, size); + GPU_matrix_set(model_view_new); + + float size_b = 0.8f; + switch (snap_type) { + case SCE_SNAP_TO_NONE: + immBegin(GPU_PRIM_LINES, 4); + immVertex3f(attr_pos, -size_b, -size_b, 0.0f); + immVertex3f(attr_pos, +size_b, +size_b, 0.0f); + immVertex3f(attr_pos, -size_b, +size_b, 0.0f); + immVertex3f(attr_pos, +size_b, -size_b, 0.0f); + immEnd(); + break; + case SCE_SNAP_TO_EDGE_MIDPOINT: + case SCE_SNAP_TO_EDGE_PERPENDICULAR: + case SCE_SNAP_TO_EDGE: { + float x_dir[3]; + mul_v3_m3v3(x_dir, rotate_view, nor); + if (is_persp) { + float *translation = model_view_new[3]; + add_v3_v3(x_dir, translation); + float fac = translation[2] / x_dir[2]; + x_dir[0] *= fac; + x_dir[1] *= fac; + sub_v2_v2(x_dir, translation); + } + normalize_v2_length(x_dir, size); + model_view_new[0][0] = x_dir[0]; + model_view_new[0][1] = x_dir[1]; + model_view_new[1][0] = x_dir[1]; + model_view_new[1][1] = -x_dir[0]; + GPU_matrix_set(model_view_new); + + immBegin(GPU_PRIM_LINES, 4); + immVertex3f(attr_pos, -size_b, -size_b, 0.0f); + immVertex3f(attr_pos, +size_b, -size_b, 0.0f); + immVertex3f(attr_pos, -size_b, +size_b, 0.0f); + immVertex3f(attr_pos, +size_b, +size_b, 0.0f); + immEnd(); + if (snap_type == SCE_SNAP_TO_EDGE) { + break; + } + immBegin(GPU_PRIM_LINES, 4); + immVertex3f(attr_pos, -size_b, -size_b, 0.0f); + immVertex3f(attr_pos, -size_b, +size_b, 0.0f); + immVertex3f(attr_pos, +size_b, -size_b, 0.0f); + immVertex3f(attr_pos, +size_b, +size_b, 0.0f); + immEnd(); + break; + } + case SCE_SNAP_TO_FACE: { + float z_dir[3]; + mul_v3_m3v3(z_dir, rotate_view, nor); + copy_v3_v3(model_view_new[2], z_dir); + ortho_basis_v3v3_v3(model_view_new[0], model_view_new[1], model_view_new[2]); + mul_mat3_m4_fl(model_view_new, size * 1.4); + GPU_matrix_set(model_view_new); + + immBegin(GPU_PRIM_LINES, 2); + immVertex3f(attr_pos, 0.0f, 0.0f, 0.0f); + immVertex3f(attr_pos, 0.0f, 0.0f, size_b); + immEnd(); + + ATTR_FALLTHROUGH; + } + case SCE_SNAP_TO_POINT: + /* case SCE_SNAP_TO_EDGE_ENDPOINT: */ + default: + imm_draw_circle_wire_3d(attr_pos, 0.0f, 0.0f, 1.0f, 24); + break; + } + + GPU_matrix_pop(); +} + void ED_view3d_cursor_snap_draw_util(RegionView3D *rv3d, const float source_loc[3], const float target_loc[3], @@ -386,64 +479,34 @@ void ED_view3d_cursor_snap_draw_util(RegionView3D *rv3d, return; } - float view_inv[4][4]; - copy_m4_m4(view_inv, rv3d->viewinv); - - /* The size of the circle is larger than the vertex size. - * This prevents a drawing overlaps the other. */ + /* The size of the symbol is larger than the vertex size. + * This prevents overlaps. */ float radius = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE); uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + GPU_blend(GPU_BLEND_ALPHA); + GPU_line_smooth(true); + GPU_line_width(1.5f); immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); if (target_loc) { - immUniformColor4ubv(target_color); - imm_drawcircball(target_loc, ED_view3d_pixel_size(rv3d, target_loc) * radius, view_inv, pos); - - /* draw normal if needed */ - if (target_normal) { - immBegin(GPU_PRIM_LINES, 2); - immVertex3fv(pos, target_loc); - immVertex3f(pos, - target_loc[0] + target_normal[0], - target_loc[1] + target_normal[1], - target_loc[2] + target_normal[2]); - immEnd(); - } + cursor_point_draw(pos, + target_loc, + target_normal, + radius * ED_view3d_pixel_size(rv3d, target_loc), + target_type, + target_color, + rv3d->is_persp); } if (source_loc) { - /* Draw an "X" indicating where the previous snap point is. - * This is useful for indicating perpendicular snap. */ - - /* v1, v2, v3 and v4 indicate the coordinates of the ends of the "X". */ - float vx[3], vy[3], v1[3], v2[3], v3[3], v4[4]; - - /* Multiply by 0.75f so that the final size of the "X" is close to that of - * the circle. - * (A closer value is 0.7071f, but we don't need to be exact here). */ - float x_size = 0.75f * radius * ED_view3d_pixel_size(rv3d, source_loc); - - mul_v3_v3fl(vx, view_inv[0], x_size); - mul_v3_v3fl(vy, view_inv[1], x_size); - - add_v3_v3v3(v1, vx, vy); - sub_v3_v3v3(v2, vx, vy); - negate_v3_v3(v3, v1); - negate_v3_v3(v4, v2); - - add_v3_v3(v1, source_loc); - add_v3_v3(v2, source_loc); - add_v3_v3(v3, source_loc); - add_v3_v3(v4, source_loc); - - immUniformColor4ubv(source_color); - immBegin(GPU_PRIM_LINES, 4); - immVertex3fv(pos, v3); - immVertex3fv(pos, v1); - immVertex3fv(pos, v4); - immVertex3fv(pos, v2); - immEnd(); + cursor_point_draw(pos, + source_loc, + target_normal, + radius * ED_view3d_pixel_size(rv3d, source_loc), + SCE_SNAP_TO_NONE, + source_color, + rv3d->is_persp); if (target_loc && (target_type & SCE_SNAP_TO_EDGE_PERPENDICULAR)) { /* Dashed line. */ @@ -464,6 +527,8 @@ void ED_view3d_cursor_snap_draw_util(RegionView3D *rv3d, } } + GPU_line_smooth(false); + GPU_blend(GPU_BLEND_NONE); immUnbindProgram(); } @@ -884,17 +949,14 @@ static void v3d_cursor_snap_draw_fn(bContext *C, int x, int y, void * /*customda } if (snap_data->snap_elem != SCE_SNAP_TO_NONE && (state->draw_point || state->draw_box)) { - const float *prev_point = (snap_data->snap_elem & SCE_SNAP_TO_EDGE_PERPENDICULAR) ? + const float *source_loc = (snap_data->snap_elem & SCE_SNAP_TO_EDGE_PERPENDICULAR) ? state->prevpoint : nullptr; - GPU_line_smooth(false); - GPU_line_width(1.0f); - ED_view3d_cursor_snap_draw_util(rv3d, - prev_point, + source_loc, snap_data->loc, - nullptr, + snap_data->nor, state->source_color, state->target_color, snap_data->snap_elem); diff --git a/source/blender/editors/transform/transform_snap.cc b/source/blender/editors/transform/transform_snap.cc index 7638ed6fea0..34736c718a7 100644 --- a/source/blender/editors/transform/transform_snap.cc +++ b/source/blender/editors/transform/transform_snap.cc @@ -205,7 +205,6 @@ void drawSnapping(TransInfo *t) if (t->spacetype == SPACE_VIEW3D) { const float *source_loc = nullptr; const float *target_loc = nullptr; - const float *target_normal = nullptr; GPU_depth_test(GPU_DEPTH_NONE); @@ -237,11 +236,6 @@ void drawSnapping(TransInfo *t) immUnbindProgram(); } - /* draw normal if needed */ - if (usingSnappingNormal(t) && validSnappingNormal(t)) { - target_normal = t->tsnap.snapNormal; - } - if (draw_source) { source_loc = t->tsnap.snap_source; } @@ -250,8 +244,28 @@ void drawSnapping(TransInfo *t) target_loc = t->tsnap.snap_target; } - ED_view3d_cursor_snap_draw_util( - rv3d, source_loc, target_loc, target_normal, col, activeCol, t->tsnap.target_type); + ED_view3d_cursor_snap_draw_util(rv3d, + source_loc, + target_loc, + t->tsnap.snapNormal, + col, activeCol, t->tsnap.target_type); + + /* Draw normal if needed. */ + if (usingSnappingNormal(t) && validSnappingNormal(t)) { + uint pos = GPU_vertformat_attr_add( + immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor4ubv(activeCol); + immBegin(GPU_PRIM_LINES, 2); + immVertex3fv(pos, target_loc); + immVertex3f(pos, + target_loc[0] + t->tsnap.snapNormal[0], + target_loc[1] + t->tsnap.snapNormal[1], + target_loc[2] + t->tsnap.snapNormal[2]); + immEnd(); + immUnbindProgram(); + } GPU_depth_test(GPU_DEPTH_LESS_EQUAL); }