Blender  V3.3
overlay_edit_mesh.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2019 Blender Foundation. */
3 
8 #include "DRW_render.h"
9 
10 #include "ED_view3d.h"
11 
12 #include "DNA_mesh_types.h"
13 
14 #include "BKE_customdata.h"
15 #include "BKE_editmesh.h"
16 #include "BKE_object.h"
17 
18 #include "draw_cache_impl.h"
19 #include "draw_manager_text.h"
20 
21 #include "overlay_private.h"
22 
23 #define OVERLAY_EDIT_TEXT \
24  (V3D_OVERLAY_EDIT_EDGE_LEN | V3D_OVERLAY_EDIT_FACE_AREA | V3D_OVERLAY_EDIT_FACE_ANG | \
25  V3D_OVERLAY_EDIT_EDGE_ANG | V3D_OVERLAY_EDIT_INDICES)
26 
28 {
29  OVERLAY_PrivateData *pd = vedata->stl->pd;
30  const DRWContextState *draw_ctx = DRW_context_state_get();
31 
32  pd->edit_mesh.do_zbufclip = XRAY_FLAG_ENABLED(draw_ctx->v3d);
33 
34  /* Create view with depth offset */
35  DRWView *default_view = (DRWView *)DRW_view_default_get();
36  pd->view_edit_faces = default_view;
37  pd->view_edit_faces_cage = DRW_view_create_with_zoffset(default_view, draw_ctx->rv3d, 0.5f);
38  pd->view_edit_edges = DRW_view_create_with_zoffset(default_view, draw_ctx->rv3d, 1.0f);
39  pd->view_edit_verts = DRW_view_create_with_zoffset(default_view, draw_ctx->rv3d, 1.5f);
40 }
41 
43 {
44  OVERLAY_TextureList *txl = vedata->txl;
45  OVERLAY_PassList *psl = vedata->psl;
46  OVERLAY_PrivateData *pd = vedata->stl->pd;
47  OVERLAY_ShadingData *shdata = &pd->shdata;
48  DRWShadingGroup *grp = NULL;
49  GPUShader *sh = NULL;
50  DRWState state = 0;
51 
53 
54  const DRWContextState *draw_ctx = DRW_context_state_get();
55  ToolSettings *tsettings = draw_ctx->scene->toolsettings;
56  View3D *v3d = draw_ctx->v3d;
57  bool select_vert = pd->edit_mesh.select_vert = (tsettings->selectmode & SCE_SELECT_VERTEX) != 0;
58  bool select_face = pd->edit_mesh.select_face = (tsettings->selectmode & SCE_SELECT_FACE) != 0;
59  bool select_edge = pd->edit_mesh.select_edge = (tsettings->selectmode & SCE_SELECT_EDGE) != 0;
60 
61  bool do_occlude_wire = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_OCCLUDE_WIRE) != 0;
62  bool show_face_dots = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT) != 0 ||
64 
65  pd->edit_mesh.do_faces = true;
66  pd->edit_mesh.do_edges = true;
67 
68  int *mask = shdata->data_mask;
69  mask[0] = 0xFF; /* Face Flag */
70  mask[1] = 0xFF; /* Edge Flag */
71 
72  const int flag = pd->edit_mesh.flag = v3d->overlay.edit_flag;
73 
81 
82  if ((flag & V3D_OVERLAY_EDIT_FACES) == 0) {
83  pd->edit_mesh.do_faces = false;
84  }
85  if ((flag & V3D_OVERLAY_EDIT_EDGES) == 0) {
86  if ((tsettings->selectmode & SCE_SELECT_EDGE) == 0) {
87  if ((v3d->shading.type < OB_SOLID) || (v3d->shading.flag & V3D_SHADING_XRAY)) {
88  /* Special case, when drawing wire, draw edges, see: T67637. */
89  }
90  else {
91  pd->edit_mesh.do_edges = false;
92  }
93  }
94  }
95 
96  float backwire_opacity = (pd->edit_mesh.do_zbufclip) ? v3d->overlay.backwire_opacity : 1.0f;
97  float face_alpha = (do_occlude_wire || !pd->edit_mesh.do_faces) ? 0.0f : 1.0f;
98  GPUTexture **depth_tex = (pd->edit_mesh.do_zbufclip) ? &dtxl->depth : &txl->dummy_depth_tx;
99 
100  /* Run Twice for in-front passes. */
101  for (int i = 0; i < 2; i++) {
102  /* Complementary Depth Pass */
105 
108  }
109  {
110  /* Normals */
114 
117  DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
118  DRW_shgroup_uniform_float_copy(grp, "normalSize", v3d->overlay.normals_length);
119  DRW_shgroup_uniform_float_copy(grp, "alpha", backwire_opacity);
120  DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tex);
122  "isConstantScreenSizeNormals",
125  grp, "normalScreenSize", v3d->overlay.normals_constant_screen_size);
126  }
127  {
128  /* Mesh Analysis Pass */
131 
135  }
136  /* Run Twice for in-front passes. */
137  for (int i = 0; i < 2; i++) {
138  GPUShader *edge_sh = OVERLAY_shader_edit_mesh_edge(!select_vert);
140  const bool do_zbufclip = (i == 0 && pd->edit_mesh.do_zbufclip);
141  const bool do_smooth_wire = (U.gpu_flag & USER_GPU_FLAG_NO_EDIT_MODE_SMOOTH_WIRE) == 0;
144  /* Faces */
145  /* Cage geom needs an offset applied to avoid Z-fighting. */
146  for (int j = 0; j < 2; j++) {
147  DRWPass **edit_face_ps = (j == 0) ? &psl->edit_mesh_faces_ps[i] :
148  &psl->edit_mesh_faces_cage_ps[i];
149  DRWShadingGroup **shgrp = (j == 0) ? &pd->edit_mesh_faces_grp[i] :
150  &pd->edit_mesh_faces_cage_grp[i];
151  state = state_common;
152  DRW_PASS_CREATE(*edit_face_ps, state | pd->clipping_state);
153 
154  grp = *shgrp = DRW_shgroup_create(face_sh, *edit_face_ps);
155  DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
156  DRW_shgroup_uniform_ivec4(grp, "dataMask", mask, 1);
157  DRW_shgroup_uniform_float_copy(grp, "alpha", face_alpha);
158  DRW_shgroup_uniform_bool_copy(grp, "selectFaces", select_face);
159  }
160 
161  if (do_zbufclip) {
162  state_common |= DRW_STATE_WRITE_DEPTH;
163  // state_common &= ~DRW_STATE_BLEND_ALPHA;
164  }
165 
166  /* Edges */
167  /* Change first vertex convention to match blender loop structure. */
168  state = state_common | DRW_STATE_FIRST_VERTEX_CONVENTION;
170 
171  grp = pd->edit_mesh_edges_grp[i] = DRW_shgroup_create(edge_sh, psl->edit_mesh_edges_ps[i]);
172  DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
173  DRW_shgroup_uniform_ivec4(grp, "dataMask", mask, 1);
174  DRW_shgroup_uniform_float_copy(grp, "alpha", backwire_opacity);
175  DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tex);
176  DRW_shgroup_uniform_bool_copy(grp, "selectEdges", pd->edit_mesh.do_edges || select_edge);
177  DRW_shgroup_uniform_bool_copy(grp, "do_smooth_wire", do_smooth_wire);
178 
179  /* Verts */
182  int vert_mask[4] = {0xFF, 0xFF, 0xFF, 0xFF};
183 
184  if (select_vert) {
187  DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
188  DRW_shgroup_uniform_float_copy(grp, "alpha", backwire_opacity);
189  DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tex);
190  DRW_shgroup_uniform_ivec4_copy(grp, "dataMask", vert_mask);
191 
194  DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
195  }
196  /* Face-dots */
197  if (select_face && show_face_dots) {
200  DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
201  DRW_shgroup_uniform_float_copy(grp, "alpha", backwire_opacity);
202  DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tex);
203  DRW_shgroup_uniform_ivec4_copy(grp, "dataMask", vert_mask);
205  }
206  else {
207  pd->edit_mesh_facedots_grp[i] = NULL;
208  }
209  }
210 }
211 
212 static void overlay_edit_mesh_add_ob_to_pass(OVERLAY_PrivateData *pd, Object *ob, bool in_front)
213 {
214  struct GPUBatch *geom_tris, *geom_verts, *geom_edges, *geom_fcenter, *skin_roots, *circle;
215  DRWShadingGroup *vert_shgrp, *edge_shgrp, *fdot_shgrp, *face_shgrp, *skin_roots_shgrp;
216 
217  bool has_edit_mesh_cage = false;
218  bool has_skin_roots = false;
219  /* TODO: Should be its own function. */
220  Mesh *me = (Mesh *)ob->data;
221  BMEditMesh *embm = me->edit_mesh;
222  if (embm) {
223  Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob);
224  Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob);
225 
226  has_edit_mesh_cage = editmesh_eval_cage && (editmesh_eval_cage != editmesh_eval_final);
227  has_skin_roots = CustomData_get_offset(&embm->bm->vdata, CD_MVERT_SKIN) != -1;
228  }
229 
230  vert_shgrp = pd->edit_mesh_verts_grp[in_front];
231  edge_shgrp = pd->edit_mesh_edges_grp[in_front];
232  fdot_shgrp = pd->edit_mesh_facedots_grp[in_front];
233  face_shgrp = (has_edit_mesh_cage) ? pd->edit_mesh_faces_cage_grp[in_front] :
234  pd->edit_mesh_faces_grp[in_front];
235  skin_roots_shgrp = pd->edit_mesh_skin_roots_grp[in_front];
236 
237  geom_edges = DRW_mesh_batch_cache_get_edit_edges(ob->data);
239  DRW_shgroup_call_no_cull(edge_shgrp, geom_edges, ob);
240  DRW_shgroup_call_no_cull(face_shgrp, geom_tris, ob);
241 
242  if (pd->edit_mesh.select_vert) {
244  DRW_shgroup_call_no_cull(vert_shgrp, geom_verts, ob);
245 
246  if (has_skin_roots) {
247  circle = DRW_cache_circle_get();
249  DRW_shgroup_call_instances_with_attrs(skin_roots_shgrp, ob, circle, skin_roots);
250  }
251  }
252 
253  if (fdot_shgrp) {
254  geom_fcenter = DRW_mesh_batch_cache_get_edit_facedots(ob->data);
255  DRW_shgroup_call_no_cull(fdot_shgrp, geom_fcenter, ob);
256  }
257 }
258 
260 {
261  OVERLAY_PrivateData *pd = vedata->stl->pd;
262  struct GPUBatch *geom = NULL;
263 
264  bool draw_as_solid = (ob->dt > OB_WIRE);
265  bool do_in_front = (ob->dtx & OB_DRAW_IN_FRONT) != 0;
266  bool do_occlude_wire = (pd->edit_mesh.flag & V3D_OVERLAY_EDIT_OCCLUDE_WIRE) != 0;
267  bool do_show_mesh_analysis = (pd->edit_mesh.flag & V3D_OVERLAY_EDIT_STATVIS) != 0;
268  bool fnormals_do = (pd->edit_mesh.flag & V3D_OVERLAY_EDIT_FACE_NORMALS) != 0;
269  bool vnormals_do = (pd->edit_mesh.flag & V3D_OVERLAY_EDIT_VERT_NORMALS) != 0;
270  bool lnormals_do = (pd->edit_mesh.flag & V3D_OVERLAY_EDIT_LOOP_NORMALS) != 0;
271 
272  if (do_show_mesh_analysis && !pd->xray_enabled) {
274  if (geom) {
276  }
277  }
278 
279  if (do_occlude_wire || (do_in_front && draw_as_solid)) {
280  geom = DRW_cache_mesh_surface_get(ob);
281  DRW_shgroup_call_no_cull(pd->edit_mesh_depth_grp[do_in_front], geom, ob);
282  }
283 
284  if (vnormals_do || lnormals_do || fnormals_do) {
285  struct GPUBatch *normal_geom = DRW_cache_normal_arrow_get();
286  if (vnormals_do) {
289  }
290  if (lnormals_do) {
293  }
294  if (fnormals_do) {
297  }
298  }
299 
300  if (pd->edit_mesh.do_zbufclip) {
301  overlay_edit_mesh_add_ob_to_pass(pd, ob, false);
302  }
303  else {
304  overlay_edit_mesh_add_ob_to_pass(pd, ob, do_in_front);
305  }
306 
308  const DRWContextState *draw_ctx = DRW_context_state_get();
309  DRW_text_edit_mesh_measure_stats(draw_ctx->region, draw_ctx->v3d, ob, &draw_ctx->scene->unit);
310  }
311 }
312 
315  bool in_front)
316 {
318  DRW_draw_pass(psl->edit_mesh_faces_ps[in_front]);
319 
321  DRW_draw_pass(psl->edit_mesh_faces_cage_ps[in_front]);
322 
324  DRW_draw_pass(psl->edit_mesh_edges_ps[in_front]);
325 
327  DRW_draw_pass(psl->edit_mesh_verts_ps[in_front]);
328 }
329 
331 {
332  OVERLAY_PassList *psl = vedata->psl;
333  OVERLAY_PrivateData *pd = vedata->stl->pd;
334  OVERLAY_FramebufferList *fbl = vedata->fbl;
335 
336  if (DRW_state_is_fbo()) {
338  }
339 
341 
343 
344  if (pd->edit_mesh.do_zbufclip) {
346 
347  /* Render face-fill. */
350 
353 
355 
357  GPU_framebuffer_clear_depth(fbl->overlay_in_front_fb, 1.0f);
359 
362 
365  }
366  else {
368  overlay_edit_mesh_draw_components(psl, pd, false);
369 
370  if (DRW_state_is_fbo()) {
372  }
373 
377  }
378 
379  overlay_edit_mesh_draw_components(psl, pd, true);
380  }
381 }
CustomData interface, see also DNA_customdata_types.h.
int CustomData_get_offset(const struct CustomData *data, int type)
General operations, lookup, etc. for blender objects.
struct Mesh * BKE_object_get_editmesh_eval_final(const struct Object *object)
struct Mesh * BKE_object_get_editmesh_eval_cage(const struct Object *object)
#define SET_FLAG_FROM_TEST(value, test, flag)
@ CD_MVERT_SKIN
@ OB_WIRE
@ OB_SOLID
@ OB_DRAW_IN_FRONT
#define SCE_SELECT_FACE
#define SCE_SELECT_VERTEX
#define SCE_SELECT_EDGE
@ USER_GPU_FLAG_NO_EDIT_MODE_SMOOTH_WIRE
@ V3D_SHADING_XRAY
@ V3D_OVERLAY_EDIT_VERT_NORMALS
@ V3D_OVERLAY_EDIT_FREESTYLE_FACE
@ 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_OCCLUDE_WIRE
@ V3D_OVERLAY_EDIT_SEAMS
@ V3D_OVERLAY_EDIT_STATVIS
@ V3D_OVERLAY_EDIT_BWEIGHTS
@ V3D_OVERLAY_EDIT_SHARP
@ V3D_OVERLAY_EDIT_EDGES
#define DRW_shgroup_call_no_cull(shgroup, geom, ob)
Definition: DRW_render.h:431
DRWState
Definition: DRW_render.h:298
@ DRW_STATE_BLEND_ALPHA
Definition: DRW_render.h:328
@ DRW_STATE_WRITE_DEPTH
Definition: DRW_render.h:302
@ DRW_STATE_WRITE_COLOR
Definition: DRW_render.h:303
@ DRW_STATE_DEPTH_LESS_EQUAL
Definition: DRW_render.h:311
@ DRW_STATE_CULL_BACK
Definition: DRW_render.h:316
@ DRW_STATE_FIRST_VERTEX_CONVENTION
Definition: DRW_render.h:343
#define DRW_PASS_CREATE(pass, state)
Definition: DRW_render.h:690
#define DRW_shgroup_uniform_block(shgroup, name, ubo)
Definition: DRW_render.h:651
#define XRAY_FLAG_ENABLED(v3d)
Definition: ED_view3d.h:1298
GPUBatch
Definition: GPU_batch.h:78
void GPU_framebuffer_bind(GPUFrameBuffer *fb)
struct GPUShader GPUShader
Definition: GPU_shader.h:20
struct GPUTexture GPUTexture
Definition: GPU_texture.h:17
unsigned int U
Definition: btGjkEpa3.h:78
GPUBatch * DRW_cache_circle_get(void)
Definition: draw_cache.c:728
GPUBatch * DRW_cache_normal_arrow_get(void)
Definition: draw_cache.c:751
GPUBatch * DRW_cache_mesh_surface_get(Object *ob)
Definition: draw_cache.c:2858
GPUBatch * DRW_cache_mesh_surface_mesh_analysis_get(Object *ob)
Definition: draw_cache.c:2914
struct GPUBatch * DRW_mesh_batch_cache_get_edit_vertices(struct Mesh *me)
@ VFLAG_EDGE_SEAM
@ VFLAG_EDGE_FREESTYLE
@ VFLAG_EDGE_SHARP
struct GPUBatch * DRW_mesh_batch_cache_get_edit_vnors(struct Mesh *me)
struct GPUBatch * DRW_mesh_batch_cache_get_edit_edges(struct Mesh *me)
struct GPUBatch * DRW_mesh_batch_cache_get_edit_skin_roots(struct Mesh *me)
struct GPUBatch * DRW_mesh_batch_cache_get_edit_triangles(struct Mesh *me)
struct GPUBatch * DRW_mesh_batch_cache_get_edit_facedots(struct Mesh *me)
struct GPUBatch * DRW_mesh_batch_cache_get_edit_lnors(struct Mesh *me)
@ VFLAG_FACE_SELECTED
@ VFLAG_FACE_FREESTYLE
struct DRW_Global G_draw
Definition: draw_common.c:32
DRWView * DRW_view_create_with_zoffset(const DRWView *parent_view, const RegionView3D *rv3d, float offset)
Definition: draw_common.c:255
bool DRW_state_show_text(void)
bool DRW_state_is_fbo(void)
const DRWContextState * DRW_context_state_get(void)
DefaultTextureList * DRW_viewport_texture_list_get(void)
Definition: draw_manager.c:638
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)
const DRWView * DRW_view_default_get(void)
void DRW_shgroup_state_enable(DRWShadingGroup *shgroup, DRWState state)
void DRW_shgroup_call_instances_with_attrs(DRWShadingGroup *shgroup, Object *ob, struct GPUBatch *geom, struct GPUBatch *inst_attributes)
bool DRW_pass_is_empty(DRWPass *pass)
DRWShadingGroup * DRW_shgroup_create(struct GPUShader *shader, 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(ARegion *region, View3D *v3d, Object *ob, const UnitSettings *unit)
const int state
ccl_gpu_kernel_postfix ccl_global float int int int int sh
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
Definition: math_float4.h:513
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_edge(bool use_flat_interp)
GPUShader * OVERLAY_shader_edit_mesh_facedot(void)
GPUShader * OVERLAY_shader_edit_mesh_skin_root(void)
GPUShader * OVERLAY_shader_edit_mesh_vert(void)
#define IN_FRONT
GPUShader * OVERLAY_shader_edit_mesh_face(void)
GPUShader * OVERLAY_shader_edit_mesh_normal(void)
GPUShader * OVERLAY_shader_depth_only(void)
#define NOT_IN_FRONT
GPUShader * OVERLAY_shader_edit_mesh_analysis(void)
struct Scene * scene
Definition: DRW_render.h:979
struct View3D * v3d
Definition: DRW_render.h:976
struct ARegion * region
Definition: DRW_render.h:974
struct RegionView3D * rv3d
Definition: DRW_render.h:975
struct GPUUniformBuf * block_ubo
Definition: draw_common.h:129
struct GPUTexture * weight_ramp
Definition: draw_common.h:132
struct GPUTexture * depth
struct BMEditMesh * edit_mesh
OVERLAY_PassList * psl
OVERLAY_StorageList * stl
OVERLAY_FramebufferList * fbl
OVERLAY_TextureList * txl
struct GPUFrameBuffer * overlay_in_front_fb
struct GPUFrameBuffer * overlay_default_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
DRWView * view_edit_faces_cage
DRWShadingGroup * edit_mesh_normals_grp
DRWShadingGroup * edit_mesh_faces_cage_grp[2]
DRWShadingGroup * edit_mesh_depth_grp[2]
DRWShadingGroup * edit_mesh_edges_grp[2]
struct OVERLAY_PrivateData::@252 edit_mesh
DRWShadingGroup * edit_mesh_analysis_grp
DRWShadingGroup * edit_mesh_verts_grp[2]
DRWShadingGroup * edit_mesh_faces_grp[2]
DRWShadingGroup * edit_mesh_skin_roots_grp[2]
DRWShadingGroup * edit_mesh_facedots_grp[2]
struct OVERLAY_PrivateData * pd
struct GPUTexture * dummy_depth_tx
void * data
struct ToolSettings * toolsettings
struct UnitSettings unit
float normals_constant_screen_size
View3DOverlay overlay
View3DShading shading