Blender V4.3
overlay_edit_mesh.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2019 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "DRW_render.hh"
10
11#include "ED_view3d.hh"
12
13#include "DNA_mesh_types.h"
14
15#include "BKE_customdata.hh"
16#include "BKE_editmesh.hh"
17#include "BKE_mesh_types.hh"
18#include "BKE_object.hh"
19
20#include "draw_cache_impl.hh"
21#include "draw_manager_text.hh"
22
23#include "overlay_private.hh"
24
25#define OVERLAY_EDIT_TEXT \
26 (V3D_OVERLAY_EDIT_EDGE_LEN | V3D_OVERLAY_EDIT_FACE_AREA | V3D_OVERLAY_EDIT_FACE_ANG | \
27 V3D_OVERLAY_EDIT_EDGE_ANG | V3D_OVERLAY_EDIT_INDICES)
28
30{
31 OVERLAY_PrivateData *pd = vedata->stl->pd;
32 const DRWContextState *draw_ctx = DRW_context_state_get();
33
35
36 /* Create view with depth offset */
37 DRWView *default_view = (DRWView *)DRW_view_default_get();
38 pd->view_edit_faces = default_view;
39 pd->view_edit_faces_cage = DRW_view_create_with_zoffset(default_view, draw_ctx->rv3d, 0.5f);
40 pd->view_edit_edges = DRW_view_create_with_zoffset(default_view, draw_ctx->rv3d, 1.0f);
41 pd->view_edit_verts = DRW_view_create_with_zoffset(default_view, draw_ctx->rv3d, 1.5f);
42}
43
45{
46 using namespace blender::draw;
47 OVERLAY_TextureList *txl = vedata->txl;
48 OVERLAY_PassList *psl = vedata->psl;
49 OVERLAY_PrivateData *pd = vedata->stl->pd;
50 OVERLAY_ShadingData *shdata = &pd->shdata;
51 DRWShadingGroup *grp = nullptr;
52 GPUShader *sh = nullptr;
54
56
57 const DRWContextState *draw_ctx = DRW_context_state_get();
58 const View3DShading *shading = &draw_ctx->v3d->shading;
59 ToolSettings *tsettings = draw_ctx->scene->toolsettings;
60 View3D *v3d = draw_ctx->v3d;
61 bool select_vert = pd->edit_mesh.select_vert = (tsettings->selectmode & SCE_SELECT_VERTEX) != 0;
62 bool select_face = pd->edit_mesh.select_face = (tsettings->selectmode & SCE_SELECT_FACE) != 0;
63 bool select_edge = pd->edit_mesh.select_edge = (tsettings->selectmode & SCE_SELECT_EDGE) != 0;
64
65 bool show_face_dots = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT) != 0 ||
67
68 bool show_retopology = RETOPOLOGY_ENABLED(v3d);
69 float retopology_offset = RETOPOLOGY_OFFSET(v3d);
70
71 pd->edit_mesh.do_faces = true;
72
73 int *mask = shdata->data_mask;
74 mask[0] = 0xFF; /* Face Flag */
75 mask[1] = 0xFF; /* Edge Flag */
76
77 const int flag = pd->edit_mesh.flag = v3d->overlay.edit_flag;
78
79 SET_FLAG_FROM_TEST(mask[0], flag & V3D_OVERLAY_EDIT_FACES, VFLAG_FACE_SELECTED);
80 SET_FLAG_FROM_TEST(mask[0], flag & V3D_OVERLAY_EDIT_FREESTYLE_FACE, VFLAG_FACE_FREESTYLE);
81 SET_FLAG_FROM_TEST(mask[1], flag & V3D_OVERLAY_EDIT_FREESTYLE_EDGE, VFLAG_EDGE_FREESTYLE);
82 SET_FLAG_FROM_TEST(mask[1], flag & V3D_OVERLAY_EDIT_SEAMS, VFLAG_EDGE_SEAM);
83 SET_FLAG_FROM_TEST(mask[1], flag & V3D_OVERLAY_EDIT_SHARP, VFLAG_EDGE_SHARP);
86
87 if ((flag & V3D_OVERLAY_EDIT_FACES) == 0) {
88 pd->edit_mesh.do_faces = false;
89 }
90
91 const bool is_wire_shmode = (shading->type == OB_WIRE);
92
93 float backwire_opacity = (pd->edit_mesh.do_zbufclip) ? 0.5f : 1.0f;
94 float face_alpha = (!pd->edit_mesh.do_faces) ? 0.0f : 1.0f;
95 GPUTexture **depth_tex = (pd->edit_mesh.do_zbufclip) ? &dtxl->depth : &txl->dummy_depth_tx;
96
97 /* Run Twice for in-front passes. */
98 for (int i = 0; i < 2; i++) {
99 /* Complementary Depth Pass */
101 if (show_retopology) {
102 /* Do not cull back-faces for retopology depth pass.
103 * This prevents edit overlays from appearing behind any faces.
104 * Doing so reduces visual clutter. */
105 state &= ~DRW_STATE_CULL_BACK;
106 }
108
111 DRW_shgroup_uniform_float_copy(grp, "retopologyOffset", retopology_offset);
112 }
113 {
114 /* Normals */
118
121 DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
123 DRW_shgroup_uniform_float_copy(grp, "alpha", backwire_opacity);
124 DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tex);
126 "isConstantScreenSizeNormals",
129 grp, "normalScreenSize", v3d->overlay.normals_constant_screen_size);
130 DRW_shgroup_uniform_float_copy(grp, "retopologyOffset", retopology_offset);
131 }
132 {
133 /* Mesh Analysis Pass */
136
140 }
141 /* Run Twice for in-front passes. */
142 for (int i = 0; i < 2; i++) {
143 GPUShader *edge_sh = OVERLAY_shader_edit_mesh_edge(!select_vert);
145 const bool do_zbufclip = (i == 0 && pd->edit_mesh.do_zbufclip);
146 const bool do_smooth_wire = (U.gpu_flag & USER_GPU_FLAG_NO_EDIT_MODE_SMOOTH_WIRE) == 0;
149 /* Faces */
150 /* Cage geom needs an offset applied to avoid Z-fighting. */
151 for (int j = 0; j < 2; j++) {
152 DRWPass **edit_face_ps = (j == 0) ? &psl->edit_mesh_faces_ps[i] :
154 DRWShadingGroup **shgrp = (j == 0) ? &pd->edit_mesh_faces_grp[i] :
156 state = state_common;
157 if (show_retopology) {
158 /* Cull back-faces for retopology face pass.
159 * This makes it so back-faces are not drawn.
160 * Doing so lets us distinguish back-faces from front-faces. */
162 }
163 DRW_PASS_CREATE(*edit_face_ps, state | pd->clipping_state);
164
165 grp = *shgrp = DRW_shgroup_create(face_sh, *edit_face_ps);
166 DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
167 DRW_shgroup_uniform_ivec4(grp, "dataMask", mask, 1);
168 DRW_shgroup_uniform_float_copy(grp, "alpha", face_alpha);
169 DRW_shgroup_uniform_bool_copy(grp, "selectFace", select_face);
170 DRW_shgroup_uniform_bool_copy(grp, "wireShading", is_wire_shmode);
171 DRW_shgroup_uniform_float_copy(grp, "retopologyOffset", retopology_offset);
172 }
173
174 if (do_zbufclip) {
175 state_common |= DRW_STATE_WRITE_DEPTH;
176 // state_common &= ~DRW_STATE_BLEND_ALPHA;
177 }
178
179 /* Edges */
180 /* Change first vertex convention to match blender loop structure. */
183
184 grp = pd->edit_mesh_edges_grp[i] = DRW_shgroup_create(edge_sh, psl->edit_mesh_edges_ps[i]);
185 DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
186 DRW_shgroup_uniform_ivec4(grp, "dataMask", mask, 1);
187 DRW_shgroup_uniform_float_copy(grp, "alpha", backwire_opacity);
188 DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tex);
189 DRW_shgroup_uniform_bool_copy(grp, "selectEdge", select_edge);
190 DRW_shgroup_uniform_bool_copy(grp, "do_smooth_wire", do_smooth_wire);
191 DRW_shgroup_uniform_float_copy(grp, "retopologyOffset", retopology_offset);
192
193 /* Verts */
196 int vert_mask[4] = {0xFF, 0xFF, 0xFF, 0xFF};
197
198 if (select_vert) {
201 DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
202 DRW_shgroup_uniform_float_copy(grp, "alpha", backwire_opacity);
203 DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tex);
204 DRW_shgroup_uniform_ivec4_copy(grp, "dataMask", vert_mask);
205 DRW_shgroup_uniform_float_copy(grp, "retopologyOffset", retopology_offset);
206
209 DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
210 DRW_shgroup_uniform_float_copy(grp, "retopologyOffset", retopology_offset);
211 }
212 /* Face-dots */
213 if (select_face && show_face_dots) {
216 DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
217 DRW_shgroup_uniform_float_copy(grp, "alpha", backwire_opacity);
218 DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tex);
219 DRW_shgroup_uniform_ivec4_copy(grp, "dataMask", vert_mask);
220 DRW_shgroup_uniform_float_copy(grp, "retopologyOffset", retopology_offset);
222 }
223 else {
224 pd->edit_mesh_facedots_grp[i] = nullptr;
225 }
226 }
227}
228
230{
231 using namespace blender::draw;
232 blender::gpu::Batch *geom_tris, *geom_verts, *geom_edges, *geom_fcenter, *skin_roots, *circle;
233 DRWShadingGroup *vert_shgrp, *edge_shgrp, *fdot_shgrp, *face_shgrp, *skin_roots_shgrp;
234
235 bool has_edit_mesh_cage = false;
236 bool has_skin_roots = false;
237 /* TODO: Should be its own function. */
238 Mesh &mesh = *(Mesh *)ob->data;
239 if (BMEditMesh *em = mesh.runtime->edit_mesh.get()) {
240 const Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob);
241 const Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob);
242
243 has_edit_mesh_cage = editmesh_eval_cage && (editmesh_eval_cage != editmesh_eval_final);
244 has_skin_roots = CustomData_get_offset(&em->bm->vdata, CD_MVERT_SKIN) != -1;
245 }
246
247 vert_shgrp = pd->edit_mesh_verts_grp[in_front];
248 edge_shgrp = pd->edit_mesh_edges_grp[in_front];
249 fdot_shgrp = pd->edit_mesh_facedots_grp[in_front];
250 face_shgrp = (has_edit_mesh_cage) ? pd->edit_mesh_faces_cage_grp[in_front] :
251 pd->edit_mesh_faces_grp[in_front];
252 skin_roots_shgrp = pd->edit_mesh_skin_roots_grp[in_front];
253
254 geom_edges = DRW_mesh_batch_cache_get_edit_edges(mesh);
255 geom_tris = DRW_mesh_batch_cache_get_edit_triangles(mesh);
256 DRW_shgroup_call_no_cull(edge_shgrp, geom_edges, ob);
257 DRW_shgroup_call_no_cull(face_shgrp, geom_tris, ob);
258
259 if (pd->edit_mesh.select_vert) {
260 geom_verts = DRW_mesh_batch_cache_get_edit_vertices(mesh);
261 DRW_shgroup_call_no_cull(vert_shgrp, geom_verts, ob);
262
263 if (has_skin_roots) {
264 circle = DRW_cache_circle_get();
265 skin_roots = DRW_mesh_batch_cache_get_edit_skin_roots(mesh);
266 DRW_shgroup_call_instances_with_attrs(skin_roots_shgrp, ob, circle, skin_roots);
267 }
268 }
269
270 if (fdot_shgrp) {
271 geom_fcenter = DRW_mesh_batch_cache_get_edit_facedots(mesh);
272 DRW_shgroup_call_no_cull(fdot_shgrp, geom_fcenter, ob);
273 }
274}
275
277{
278 using namespace blender::draw;
279 OVERLAY_PrivateData *pd = vedata->stl->pd;
280 blender::gpu::Batch *geom = nullptr;
281
282 bool draw_as_solid = (ob->dt > OB_WIRE);
283 bool do_in_front = (ob->dtx & OB_DRAW_IN_FRONT) != 0;
284 bool show_retopology = (pd->edit_mesh.flag & V3D_OVERLAY_EDIT_RETOPOLOGY) != 0;
285 bool do_show_mesh_analysis = (pd->edit_mesh.flag & V3D_OVERLAY_EDIT_STATVIS) != 0;
286 bool fnormals_do = (pd->edit_mesh.flag & V3D_OVERLAY_EDIT_FACE_NORMALS) != 0;
287 bool vnormals_do = (pd->edit_mesh.flag & V3D_OVERLAY_EDIT_VERT_NORMALS) != 0;
288 bool lnormals_do = (pd->edit_mesh.flag & V3D_OVERLAY_EDIT_LOOP_NORMALS) != 0;
289
290 if (do_show_mesh_analysis && !pd->xray_enabled) {
292 if (geom) {
294 }
295 }
296
297 if (show_retopology) {
298 Mesh &mesh = *(Mesh *)ob->data;
299 geom = DRW_mesh_batch_cache_get_edit_triangles(mesh);
300 DRW_shgroup_call_no_cull(pd->edit_mesh_depth_grp[do_in_front], geom, ob);
301 }
302 else if (do_in_front && draw_as_solid) {
304 DRW_shgroup_call_no_cull(pd->edit_mesh_depth_grp[do_in_front], geom, ob);
305 }
306
307 if (vnormals_do || lnormals_do || fnormals_do) {
308 blender::gpu::Batch *normal_geom = DRW_cache_normal_arrow_get();
309 Mesh &mesh = *static_cast<Mesh *>(ob->data);
310 if (vnormals_do) {
311 geom = DRW_mesh_batch_cache_get_edit_vert_normals(mesh);
313 }
314 if (lnormals_do) {
315 geom = DRW_mesh_batch_cache_get_edit_loop_normals(mesh);
317 }
318 if (fnormals_do) {
319 geom = DRW_mesh_batch_cache_get_edit_facedots(mesh);
321 }
322 }
323
324 if (pd->edit_mesh.do_zbufclip) {
326 }
327 else {
328 overlay_edit_mesh_add_ob_to_pass(pd, ob, do_in_front);
329 }
330
332 const DRWContextState *draw_ctx = DRW_context_state_get();
333 DRW_text_edit_mesh_measure_stats(draw_ctx->region, draw_ctx->v3d, ob, &draw_ctx->scene->unit);
334 }
335}
336
353
355{
356 OVERLAY_PassList *psl = vedata->psl;
357 OVERLAY_PrivateData *pd = vedata->stl->pd;
358 OVERLAY_FramebufferList *fbl = vedata->fbl;
359
360 if (DRW_state_is_fbo()) {
362 }
363
365
367
368 if (pd->edit_mesh.do_zbufclip) {
370
371 /* Render face-fill. */
374
377
378 DRW_view_set_active(nullptr);
379
383
386
389 }
390 else {
392 overlay_edit_mesh_draw_components(psl, pd, false);
393
394 if (DRW_state_is_fbo()) {
396 }
397
399 DRW_view_set_active(nullptr);
401 }
402
404 }
405}
CustomData interface, see also DNA_customdata_types.h.
int CustomData_get_offset(const CustomData *data, eCustomDataType type)
General operations, lookup, etc. for blender objects.
const Mesh * BKE_object_get_editmesh_eval_cage(const Object *object)
const Mesh * BKE_object_get_editmesh_eval_final(const Object *object)
#define SET_FLAG_FROM_TEST(value, test, flag)
@ CD_MVERT_SKIN
@ OB_WIRE
@ OB_DRAW_IN_FRONT
@ SCE_SELECT_FACE
@ SCE_SELECT_VERTEX
@ SCE_SELECT_EDGE
@ USER_GPU_FLAG_NO_EDIT_MODE_SMOOTH_WIRE
@ V3D_OVERLAY_EDIT_VERT_NORMALS
@ V3D_OVERLAY_EDIT_FREESTYLE_FACE
@ V3D_OVERLAY_EDIT_RETOPOLOGY
@ V3D_OVERLAY_EDIT_LOOP_NORMALS
@ V3D_OVERLAY_EDIT_FACE_NORMALS
@ V3D_OVERLAY_EDIT_CREASES
@ V3D_OVERLAY_EDIT_FREESTYLE_EDGE
@ V3D_OVERLAY_EDIT_CONSTANT_SCREEN_SIZE_NORMALS
@ V3D_OVERLAY_EDIT_FACES
@ V3D_OVERLAY_EDIT_FACE_DOT
@ V3D_OVERLAY_EDIT_SEAMS
@ V3D_OVERLAY_EDIT_STATVIS
@ V3D_OVERLAY_EDIT_BWEIGHTS
@ V3D_OVERLAY_EDIT_SHARP
#define DRW_shgroup_call_no_cull(shgroup, geom, ob)
#define DRW_PASS_CREATE(pass, state)
#define DRW_shgroup_uniform_block(shgroup, name, ubo)
#define RETOPOLOGY_ENABLED(v3d)
#define RETOPOLOGY_OFFSET(v3d)
#define XRAY_FLAG_ENABLED(v3d)
void GPU_framebuffer_bind(GPUFrameBuffer *framebuffer)
void GPU_framebuffer_clear_depth(GPUFrameBuffer *fb, float clear_depth)
struct GPUShader GPUShader
unsigned int U
Definition btGjkEpa3.h:78
blender::gpu::Batch * DRW_cache_normal_arrow_get()
blender::gpu::Batch * DRW_cache_mesh_surface_get(Object *ob)
blender::gpu::Batch * DRW_cache_circle_get()
blender::gpu::Batch * DRW_cache_mesh_surface_mesh_analysis_get(Object *ob)
DRWView * DRW_view_create_with_zoffset(const DRWView *parent_view, const RegionView3D *rv3d, float offset)
DRW_Global G_draw
bool DRW_state_show_text()
DefaultTextureList * DRW_viewport_texture_list_get()
const DRWContextState * DRW_context_state_get()
bool DRW_state_is_fbo()
const DRWView * DRW_view_default_get()
DRWShadingGroup * DRW_shgroup_create(GPUShader *shader, DRWPass *pass)
void DRW_shgroup_uniform_float_copy(DRWShadingGroup *shgroup, const char *name, const float value)
void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex)
void DRW_shgroup_call_instances_with_attrs(DRWShadingGroup *shgroup, const Object *ob, blender::gpu::Batch *geom, blender::gpu::Batch *inst_attributes)
void DRW_shgroup_state_enable(DRWShadingGroup *shgroup, DRWState state)
bool DRW_pass_is_empty(DRWPass *pass)
void DRW_shgroup_uniform_ivec4(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize)
void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex)
void DRW_shgroup_uniform_bool_copy(DRWShadingGroup *shgroup, const char *name, const bool value)
void DRW_shgroup_uniform_ivec4_copy(DRWShadingGroup *shgroup, const char *name, const int *value)
void DRW_draw_pass(DRWPass *pass)
void DRW_view_set_active(const DRWView *view)
void DRW_text_edit_mesh_measure_stats(const ARegion *region, const View3D *v3d, const Object *ob, const UnitSettings *unit, DRWTextStore *dt)
DRWState
Definition draw_state.hh:25
@ DRW_STATE_BLEND_ALPHA
Definition draw_state.hh:55
@ DRW_STATE_WRITE_DEPTH
Definition draw_state.hh:29
@ DRW_STATE_WRITE_COLOR
Definition draw_state.hh:30
@ DRW_STATE_DEPTH_LESS_EQUAL
Definition draw_state.hh:38
@ DRW_STATE_CULL_BACK
Definition draw_state.hh:43
@ DRW_STATE_FIRST_VERTEX_CONVENTION
Definition draw_state.hh:70
static ulong state[N]
static void overlay_edit_mesh_draw_components(OVERLAY_PassList *psl, OVERLAY_PrivateData *pd, bool in_front)
void OVERLAY_edit_mesh_cache_init(OVERLAY_Data *vedata)
void OVERLAY_edit_mesh_cache_populate(OVERLAY_Data *vedata, Object *ob)
void OVERLAY_edit_mesh_init(OVERLAY_Data *vedata)
static void overlay_edit_mesh_add_ob_to_pass(OVERLAY_PrivateData *pd, Object *ob, bool in_front)
#define OVERLAY_EDIT_TEXT
void OVERLAY_edit_mesh_draw(OVERLAY_Data *vedata)
GPUShader * OVERLAY_shader_edit_mesh_facedot()
GPUShader * OVERLAY_shader_edit_mesh_normal()
GPUShader * OVERLAY_shader_edit_mesh_depth()
GPUShader * OVERLAY_shader_edit_mesh_edge(bool use_flat_interp)
#define IN_FRONT
GPUShader * OVERLAY_shader_edit_mesh_skin_root()
GPUShader * OVERLAY_shader_edit_mesh_analysis()
#define NOT_IN_FRONT
GPUShader * OVERLAY_shader_edit_mesh_vert()
GPUShader * OVERLAY_shader_edit_mesh_face()
ARegion * region
RegionView3D * rv3d
GPUTexture * weight_ramp
GPUUniformBuf * block_ubo
OVERLAY_PassList * psl
OVERLAY_StorageList * stl
OVERLAY_FramebufferList * fbl
OVERLAY_TextureList * txl
GPUFrameBuffer * overlay_default_fb
GPUFrameBuffer * overlay_in_front_fb
DRWPass * edit_mesh_depth_ps[2]
DRWPass * edit_mesh_edges_ps[2]
DRWPass * edit_mesh_faces_ps[2]
DRWPass * edit_mesh_analysis_ps
DRWPass * edit_mesh_verts_ps[2]
DRWPass * edit_mesh_faces_cage_ps[2]
DRWPass * edit_mesh_normals_ps
OVERLAY_ShadingData shdata
DRWShadingGroup * edit_mesh_normals_grp
DRWShadingGroup * edit_mesh_faces_cage_grp[2]
DRWShadingGroup * edit_mesh_depth_grp[2]
DRWShadingGroup * edit_mesh_edges_grp[2]
DRWShadingGroup * edit_mesh_analysis_grp
DRWShadingGroup * edit_mesh_verts_grp[2]
DRWShadingGroup * edit_mesh_faces_grp[2]
DRWShadingGroup * edit_mesh_skin_roots_grp[2]
struct OVERLAY_PrivateData::@230 edit_mesh
DRWShadingGroup * edit_mesh_facedots_grp[2]
OVERLAY_PrivateData * pd
GPUTexture * dummy_depth_tx
struct ToolSettings * toolsettings
struct UnitSettings unit
float normals_constant_screen_size
View3DOverlay overlay
View3DShading shading
uint8_t flag
Definition wm_window.cc:138