Blender  V2.93
overlay_edit_mesh.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * Copyright 2019, Blender Foundation.
17  */
18 
23 #include "DRW_render.h"
24 
25 #include "ED_view3d.h"
26 
27 #include "DNA_mesh_types.h"
28 
29 #include "BKE_editmesh.h"
30 
31 #include "draw_cache_impl.h"
32 #include "draw_manager_text.h"
33 
34 #include "overlay_private.h"
35 
36 #define OVERLAY_EDIT_TEXT \
37  (V3D_OVERLAY_EDIT_EDGE_LEN | V3D_OVERLAY_EDIT_FACE_AREA | V3D_OVERLAY_EDIT_FACE_ANG | \
38  V3D_OVERLAY_EDIT_EDGE_ANG | V3D_OVERLAY_EDIT_INDICES)
39 
41 {
42  OVERLAY_PrivateData *pd = vedata->stl->pd;
43  const DRWContextState *draw_ctx = DRW_context_state_get();
44 
45  pd->edit_mesh.do_zbufclip = XRAY_FLAG_ENABLED(draw_ctx->v3d);
46 
47  /* Create view with depth offset */
48  DRWView *default_view = (DRWView *)DRW_view_default_get();
49  pd->view_edit_faces = default_view;
50  pd->view_edit_faces_cage = DRW_view_create_with_zoffset(default_view, draw_ctx->rv3d, 0.5f);
51  pd->view_edit_edges = DRW_view_create_with_zoffset(default_view, draw_ctx->rv3d, 1.0f);
52  pd->view_edit_verts = DRW_view_create_with_zoffset(default_view, draw_ctx->rv3d, 1.5f);
53 }
54 
56 {
57  OVERLAY_TextureList *txl = vedata->txl;
58  OVERLAY_PassList *psl = vedata->psl;
59  OVERLAY_PrivateData *pd = vedata->stl->pd;
60  OVERLAY_ShadingData *shdata = &pd->shdata;
61  DRWShadingGroup *grp = NULL;
62  GPUShader *sh = NULL;
63  DRWState state = 0;
64 
66 
67  const DRWContextState *draw_ctx = DRW_context_state_get();
68  ToolSettings *tsettings = draw_ctx->scene->toolsettings;
69  View3D *v3d = draw_ctx->v3d;
70  bool select_vert = pd->edit_mesh.select_vert = (tsettings->selectmode & SCE_SELECT_VERTEX) != 0;
71  bool select_face = pd->edit_mesh.select_face = (tsettings->selectmode & SCE_SELECT_FACE) != 0;
72  bool select_edge = pd->edit_mesh.select_edge = (tsettings->selectmode & SCE_SELECT_EDGE) != 0;
73 
74  bool do_occlude_wire = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_OCCLUDE_WIRE) != 0;
75  bool show_face_dots = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT) != 0 ||
77 
78  pd->edit_mesh.do_faces = true;
79  pd->edit_mesh.do_edges = true;
80 
81  int *mask = shdata->data_mask;
82  mask[0] = 0xFF; /* Face Flag */
83  mask[1] = 0xFF; /* Edge Flag */
84 
85  const int flag = pd->edit_mesh.flag = v3d->overlay.edit_flag;
86 
94 
95  if ((flag & V3D_OVERLAY_EDIT_FACES) == 0) {
96  pd->edit_mesh.do_faces = false;
97  }
98  if ((flag & V3D_OVERLAY_EDIT_EDGES) == 0) {
99  if ((tsettings->selectmode & SCE_SELECT_EDGE) == 0) {
100  if ((v3d->shading.type < OB_SOLID) || (v3d->shading.flag & V3D_SHADING_XRAY)) {
101  /* Special case, when drawing wire, draw edges, see: T67637. */
102  }
103  else {
104  pd->edit_mesh.do_edges = false;
105  }
106  }
107  }
108 
109  float backwire_opacity = (pd->edit_mesh.do_zbufclip) ? v3d->overlay.backwire_opacity : 1.0f;
110  float face_alpha = (do_occlude_wire || !pd->edit_mesh.do_faces) ? 0.0f : 1.0f;
111  GPUTexture **depth_tex = (pd->edit_mesh.do_zbufclip) ? &dtxl->depth : &txl->dummy_depth_tx;
112 
113  /* Run Twice for in-front passes. */
114  for (int i = 0; i < 2; i++) {
115  /* Complementary Depth Pass */
118 
121  }
122  {
123  /* Normals */
127 
130  DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
131  DRW_shgroup_uniform_float_copy(grp, "normalSize", v3d->overlay.normals_length);
132  DRW_shgroup_uniform_float_copy(grp, "alpha", backwire_opacity);
133  DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tex);
134  }
135  {
136  /* Mesh Analysis Pass */
139 
143  }
144  /* Run Twice for in-front passes. */
145  for (int i = 0; i < 2; i++) {
146  GPUShader *edge_sh = OVERLAY_shader_edit_mesh_edge(!select_vert);
148  const bool do_zbufclip = (i == 0 && pd->edit_mesh.do_zbufclip);
151  /* Faces */
152  /* Cage geom needs to be offsetted to avoid Z-fighting. */
153  for (int j = 0; j < 2; j++) {
154  DRWPass **edit_face_ps = (j == 0) ? &psl->edit_mesh_faces_ps[i] :
155  &psl->edit_mesh_faces_cage_ps[i];
156  DRWShadingGroup **shgrp = (j == 0) ? &pd->edit_mesh_faces_grp[i] :
157  &pd->edit_mesh_faces_cage_grp[i];
158  state = state_common;
159  DRW_PASS_CREATE(*edit_face_ps, state | pd->clipping_state);
160 
161  grp = *shgrp = DRW_shgroup_create(face_sh, *edit_face_ps);
162  DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
163  DRW_shgroup_uniform_ivec4(grp, "dataMask", mask, 1);
164  DRW_shgroup_uniform_float_copy(grp, "alpha", face_alpha);
165  DRW_shgroup_uniform_bool_copy(grp, "selectFaces", select_face);
166  }
167 
168  if (do_zbufclip) {
169  state_common |= DRW_STATE_WRITE_DEPTH;
170  // state_common &= ~DRW_STATE_BLEND_ALPHA;
171  }
172 
173  /* Edges */
174  /* Change first vertex convention to match blender loop structure. */
175  state = state_common | DRW_STATE_FIRST_VERTEX_CONVENTION;
177 
178  grp = pd->edit_mesh_edges_grp[i] = DRW_shgroup_create(edge_sh, psl->edit_mesh_edges_ps[i]);
179  DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
180  DRW_shgroup_uniform_ivec4(grp, "dataMask", mask, 1);
181  DRW_shgroup_uniform_float_copy(grp, "alpha", backwire_opacity);
182  DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tex);
183  DRW_shgroup_uniform_bool_copy(grp, "selectEdges", pd->edit_mesh.do_edges || select_edge);
184 
185  /* Verts */
188 
189  if (select_vert) {
191  grp = pd->edit_mesh_verts_grp[i] = DRW_shgroup_create(sh, psl->edit_mesh_verts_ps[i]);
192  DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
193  DRW_shgroup_uniform_float_copy(grp, "alpha", backwire_opacity);
194  DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tex);
195 
198  DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
199  }
200  /* Facedots */
201  if (select_face && show_face_dots) {
204  DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
205  DRW_shgroup_uniform_float_copy(grp, "alpha", backwire_opacity);
206  DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tex);
208  }
209  else {
210  pd->edit_mesh_facedots_grp[i] = NULL;
211  }
212  }
213 }
214 
215 static void overlay_edit_mesh_add_ob_to_pass(OVERLAY_PrivateData *pd, Object *ob, bool in_front)
216 {
217  struct GPUBatch *geom_tris, *geom_verts, *geom_edges, *geom_fcenter, *skin_roots, *circle;
218  DRWShadingGroup *vert_shgrp, *edge_shgrp, *fdot_shgrp, *face_shgrp, *skin_roots_shgrp;
219 
220  bool has_edit_mesh_cage = false;
221  bool has_skin_roots = false;
222  /* TODO: Should be its own function. */
223  Mesh *me = (Mesh *)ob->data;
224  BMEditMesh *embm = me->edit_mesh;
225  if (embm) {
226  has_edit_mesh_cage = embm->mesh_eval_cage && (embm->mesh_eval_cage != embm->mesh_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 }
int CustomData_get_offset(const struct CustomData *data, int type)
#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
@ 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_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
@ V3D_SHADING_XRAY
#define DRW_shgroup_call_no_cull(shgroup, geom, ob)
Definition: DRW_render.h:433
DRWState
Definition: DRW_render.h:312
@ DRW_STATE_BLEND_ALPHA
Definition: DRW_render.h:340
@ DRW_STATE_WRITE_DEPTH
Definition: DRW_render.h:314
@ DRW_STATE_WRITE_COLOR
Definition: DRW_render.h:315
@ DRW_STATE_DEPTH_LESS_EQUAL
Definition: DRW_render.h:323
@ DRW_STATE_CULL_BACK
Definition: DRW_render.h:328
@ DRW_STATE_FIRST_VERTEX_CONVENTION
Definition: DRW_render.h:355
#define DRW_PASS_CREATE(pass, state)
Definition: DRW_render.h:593
#define XRAY_FLAG_ENABLED(v3d)
Definition: ED_view3d.h:709
GPUBatch
Definition: GPU_batch.h:93
void GPU_framebuffer_bind(GPUFrameBuffer *fb)
struct GPUShader GPUShader
Definition: GPU_shader.h:33
struct GPUTexture GPUTexture
Definition: GPU_texture.h:33
GPUBatch * DRW_cache_circle_get(void)
Definition: draw_cache.c:733
GPUBatch * DRW_cache_normal_arrow_get(void)
Definition: draw_cache.c:756
GPUBatch * DRW_cache_mesh_surface_get(Object *ob)
Definition: draw_cache.c:2859
GPUBatch * DRW_cache_mesh_surface_mesh_analysis_get(Object *ob)
Definition: draw_cache.c:2917
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)
@ VFLAG_FACE_SELECTED
@ VFLAG_FACE_FREESTYLE
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)
struct DRW_Global G_draw
Definition: draw_common.c:45
DRWView * DRW_view_create_with_zoffset(const DRWView *parent_view, const RegionView3D *rv3d, float offset)
Definition: draw_common.c:271
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:702
void DRW_shgroup_uniform_float_copy(DRWShadingGroup *shgroup, const char *name, const float value)
void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup, const char *name, const GPUUniformBuf *ubo)
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_view_set_active(DRWView *view)
void DRW_draw_pass(DRWPass *pass)
void DRW_text_edit_mesh_measure_stats(ARegion *region, View3D *v3d, Object *ob, const UnitSettings *unit)
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_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:745
struct View3D * v3d
Definition: DRW_render.h:742
struct ARegion * region
Definition: DRW_render.h:740
struct RegionView3D * rv3d
Definition: DRW_render.h:741
struct GPUUniformBuf * block_ubo
Definition: draw_common.h:210
struct GPUTexture * weight_ramp
Definition: draw_common.h:213
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]
DRWShadingGroup * edit_mesh_analysis_grp
DRWShadingGroup * edit_mesh_verts_grp[2]
struct OVERLAY_PrivateData::@242 edit_mesh
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
View3DOverlay overlay
View3DShading shading
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)