Blender V4.3
overlay_next_mesh.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#pragma once
10
11#include <string>
12
13#include "DNA_mesh_types.h"
14
15#include "BKE_customdata.hh"
16#include "BKE_editmesh.hh"
17#include "BKE_global.hh"
18#include "BKE_mask.h"
19#include "BKE_mesh_types.hh"
21
22#include "ED_image.hh"
23
24#include "GPU_capabilities.hh"
25
26#include "draw_cache_impl.hh"
27
29
30namespace blender::draw::overlay {
31
35
36class Meshes {
37 private:
38 PassSimple edit_mesh_normals_ps_ = {"Normals"};
39 PassSimple::Sub *face_normals_ = nullptr;
40 PassSimple::Sub *face_normals_subdiv_ = nullptr;
41 PassSimple::Sub *loop_normals_ = nullptr;
42 PassSimple::Sub *loop_normals_subdiv_ = nullptr;
43 PassSimple::Sub *vert_normals_ = nullptr;
44
45 PassSimple edit_mesh_analysis_ps_ = {"Mesh Analysis"};
46 PassSimple edit_mesh_weight_ps_ = {"Edit Weight"};
47
48 PassSimple edit_mesh_edges_ps_ = {"Edges"};
49 PassSimple edit_mesh_faces_ps_ = {"Faces"};
50 PassSimple edit_mesh_cages_ps_ = {"Cages"}; /* Same as faces but with a different offset. */
51 PassSimple edit_mesh_verts_ps_ = {"Verts"};
52 PassSimple edit_mesh_facedots_ps_ = {"FaceDots"};
53 PassSimple edit_mesh_skin_roots_ps_ = {"SkinRoots"};
54
55 /* Depth pre-pass to cull edit cage in case the object is not opaque. */
56 PassSimple edit_mesh_prepass_ps_ = {"Prepass"};
57
58 bool xray_enabled = false;
59
60 bool show_retopology = false;
61 bool show_mesh_analysis = false;
62 bool show_face = false;
63 bool show_face_dots = false;
64 bool show_weight = false;
65
66 bool select_edge = false;
67 bool select_face = false;
68 bool select_vert = false;
69
70 /* TODO(fclem): This is quite wasteful and expensive, prefer in shader Z modification like the
71 * retopology offset. */
72 View view_edit_cage = {"view_edit_cage"};
73 View view_edit_edge = {"view_edit_edge"};
74 View view_edit_vert = {"view_edit_vert"};
75 float view_dist = 0.0f;
76
77 bool enabled_ = false;
78
79 public:
80 void begin_sync(Resources &res, const State &state, const View &view)
81 {
82 enabled_ = state.space_type == SPACE_VIEW3D;
83
84 if (!enabled_) {
85 return;
86 }
87
88 view_dist = state.view_dist_get(view.winmat());
89 xray_enabled = state.xray_enabled;
90
91 ToolSettings *tsettings = state.scene->toolsettings;
92 select_edge = (tsettings->selectmode & SCE_SELECT_EDGE);
93 select_face = (tsettings->selectmode & SCE_SELECT_FACE);
94 select_vert = (tsettings->selectmode & SCE_SELECT_VERTEX);
95
96 int edit_flag = state.v3d->overlay.edit_flag;
97 show_retopology = (edit_flag & V3D_OVERLAY_EDIT_RETOPOLOGY) && !state.xray_enabled;
98 show_mesh_analysis = (edit_flag & V3D_OVERLAY_EDIT_STATVIS);
99 show_face = (edit_flag & V3D_OVERLAY_EDIT_FACES);
100 show_face_dots = ((edit_flag & V3D_OVERLAY_EDIT_FACE_DOT) || state.xray_enabled) & select_face;
101 show_weight = (edit_flag & V3D_OVERLAY_EDIT_WEIGHT);
102
103 const bool show_face_nor = (edit_flag & V3D_OVERLAY_EDIT_FACE_NORMALS);
104 const bool show_loop_nor = (edit_flag & V3D_OVERLAY_EDIT_LOOP_NORMALS);
105 const bool show_vert_nor = (edit_flag & V3D_OVERLAY_EDIT_VERT_NORMALS);
106
107 const bool do_smooth_wire = (U.gpu_flag & USER_GPU_FLAG_NO_EDIT_MODE_SMOOTH_WIRE) == 0;
108 const bool is_wire_shading_mode = (state.v3d->shading.type == OB_WIRE);
109
110 uint4 data_mask = data_mask_get(edit_flag);
111
112 float backwire_opacity = (state.xray_enabled) ? 0.5f : 1.0f;
113 float face_alpha = (show_face) ? 1.0f : 0.0f;
114 float retopology_offset = RETOPOLOGY_OFFSET(state.v3d);
115 /* Cull back-faces for retopology face pass. This makes it so back-faces are not drawn.
116 * Doing so lets us distinguish back-faces from front-faces. */
117 DRWState face_culling = (show_retopology) ? DRW_STATE_CULL_BACK : DRWState(0);
118
119 GPUTexture **depth_tex = (state.xray_enabled) ? &res.depth_tx : &res.dummy_depth_tx;
120
121 {
122 auto &pass = edit_mesh_prepass_ps_;
123 pass.init();
124 pass.state_set(DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | face_culling,
125 state.clipping_plane_count);
126 pass.shader_set(res.shaders.mesh_edit_depth.get());
127 pass.push_constant("retopologyOffset", retopology_offset);
128 }
129 {
130 /* Normals */
131 const bool use_screen_size = (edit_flag & V3D_OVERLAY_EDIT_CONSTANT_SCREEN_SIZE_NORMALS);
132 const bool use_hq_normals = (state.scene->r.perf_flag & SCE_PERF_HQ_NORMALS) ||
134
137 if (state.xray_enabled) {
138 pass_state |= DRW_STATE_BLEND_ALPHA;
139 }
140
141 auto &pass = edit_mesh_normals_ps_;
142 pass.init();
143 pass.state_set(pass_state, state.clipping_plane_count);
144
145 auto shader_pass = [&](GPUShader *shader, const char *name) {
146 auto &sub = pass.sub(name);
147 sub.shader_set(shader);
148 sub.bind_ubo("globalsBlock", &res.globals_buf);
149 sub.bind_texture("depthTex", depth_tex);
150 sub.push_constant("alpha", backwire_opacity);
151 sub.push_constant("isConstantScreenSizeNormals", use_screen_size);
152 sub.push_constant("normalSize", state.overlay.normals_length);
153 sub.push_constant("normalScreenSize", state.overlay.normals_constant_screen_size);
154 sub.push_constant("retopologyOffset", retopology_offset);
155 sub.push_constant("hq_normals", use_hq_normals);
156 return &sub;
157 };
158
159 face_normals_ = loop_normals_ = vert_normals_ = nullptr;
160
161 if (show_face_nor) {
162 face_normals_subdiv_ = shader_pass(res.shaders.mesh_face_normal_subdiv.get(), "SubdFNor");
163 face_normals_ = shader_pass(res.shaders.mesh_face_normal.get(), "FaceNor");
164 }
165 if (show_loop_nor) {
166 loop_normals_subdiv_ = shader_pass(res.shaders.mesh_loop_normal_subdiv.get(), "SubdLNor");
167 loop_normals_ = shader_pass(res.shaders.mesh_loop_normal.get(), "LoopNor");
168 }
169 if (show_vert_nor) {
170 vert_normals_ = shader_pass(res.shaders.mesh_vert_normal.get(), "VertexNor");
171 }
172 }
173 {
174 /* Support masked transparency in Workbench.
175 * EEVEE can't be supported since depth won't match. */
176 const bool shadeless = eDrawType(state.v3d->shading.type) == OB_WIRE;
177
178 auto &pass = edit_mesh_weight_ps_;
179 pass.init();
181 state.clipping_plane_count);
182 pass.shader_set(shadeless ? res.shaders.paint_weight.get() :
184 pass.bind_ubo("globalsBlock", &res.globals_buf);
185 pass.bind_texture("colorramp", &res.weight_ramp_tx);
186 pass.push_constant("drawContours", false);
187 pass.push_constant("opacity", state.overlay.weight_paint_mode_opacity);
188 if (!shadeless) {
189 /* Arbitrary light to give a hint of the geometry behind the weights. */
190 pass.push_constant("light_dir", math::normalize(float3(0.0f, 0.5f, 0.86602f)));
191 }
192 }
193 {
194 auto &pass = edit_mesh_analysis_ps_;
195 pass.init();
197 state.clipping_plane_count);
198 pass.shader_set(res.shaders.mesh_analysis.get());
199 pass.bind_texture("weightTex", res.weight_ramp_tx);
200 }
201
202 auto mesh_edit_common_resource_bind = [&](PassSimple &pass, float alpha) {
203 pass.bind_texture("depthTex", depth_tex);
204 /* TODO(fclem): UBO. */
205 pass.push_constant("wireShading", is_wire_shading_mode);
206 pass.push_constant("selectFace", select_face);
207 pass.push_constant("selectEdge", select_edge);
208 pass.push_constant("alpha", alpha);
209 pass.push_constant("retopologyOffset", retopology_offset);
210 pass.push_constant("dataMask", int4(data_mask));
211 pass.bind_ubo("globalsBlock", &res.globals_buf);
212 };
213
214 {
215 auto &pass = edit_mesh_edges_ps_;
216 pass.init();
217 /* Change first vertex convention to match blender loop structure. */
220 state.clipping_plane_count);
221 pass.shader_set(res.shaders.mesh_edit_edge.get());
222 pass.push_constant("do_smooth_wire", do_smooth_wire);
223 pass.push_constant("use_vertex_selection", select_vert);
224 mesh_edit_common_resource_bind(pass, backwire_opacity);
225 }
226 {
227 auto &pass = edit_mesh_faces_ps_;
228 pass.init();
230 face_culling,
231 state.clipping_plane_count);
232 pass.shader_set(res.shaders.mesh_edit_face.get());
233 mesh_edit_common_resource_bind(pass, face_alpha);
234 }
235 {
236 auto &pass = edit_mesh_cages_ps_;
237 pass.init();
239 state.clipping_plane_count);
240 pass.shader_set(res.shaders.mesh_edit_face.get());
241 mesh_edit_common_resource_bind(pass, face_alpha);
242 }
243 {
244 auto &pass = edit_mesh_verts_ps_;
245 pass.init();
248 state.clipping_plane_count);
249 pass.shader_set(res.shaders.mesh_edit_vert.get());
250 mesh_edit_common_resource_bind(pass, backwire_opacity);
251 }
252 {
253 auto &pass = edit_mesh_facedots_ps_;
254 pass.init();
257 state.clipping_plane_count);
258 pass.shader_set(res.shaders.mesh_edit_facedot.get());
259 mesh_edit_common_resource_bind(pass, backwire_opacity);
260 }
261 {
262 auto &pass = edit_mesh_skin_roots_ps_;
263 pass.init();
266 state.clipping_plane_count);
267 pass.shader_set(res.shaders.mesh_edit_skin_root.get());
268 pass.push_constant("retopologyOffset", retopology_offset);
269 pass.bind_ubo("globalsBlock", &res.globals_buf);
270 }
271 }
272
274 const ObjectRef &ob_ref,
275 const State &state,
276 Resources & /*res*/)
277 {
278 if (!enabled_) {
279 return;
280 }
281
282 ResourceHandle res_handle = manager.unique_handle(ob_ref);
283
284 Object *ob = ob_ref.object;
285 Mesh &mesh = *static_cast<Mesh *>(ob->data);
286 /* WORKAROUND: GPU subdiv uses a different normal format. Remove this once GPU subdiv is
287 * refactored. */
288 const bool use_gpu_subdiv = BKE_subsurf_modifier_has_gpu_subdiv(static_cast<Mesh *>(ob->data));
289 const bool draw_as_solid = (ob->dt > OB_WIRE);
290
291 if (show_retopology) {
292 gpu::Batch *geom = DRW_mesh_batch_cache_get_edit_triangles(mesh);
293 edit_mesh_prepass_ps_.draw(geom, res_handle);
294 }
295 if (draw_as_solid) {
296 gpu::Batch *geom = DRW_cache_mesh_surface_get(ob);
297 edit_mesh_prepass_ps_.draw(geom, res_handle);
298 }
299
300 if (show_mesh_analysis) {
301 gpu::Batch *geom = DRW_cache_mesh_surface_mesh_analysis_get(ob);
302 edit_mesh_analysis_ps_.draw(geom, res_handle);
303 }
304
305 if (show_weight) {
306 gpu::Batch *geom = DRW_cache_mesh_surface_weights_get(ob);
307 edit_mesh_weight_ps_.draw(geom, res_handle);
308 }
309
310 if (face_normals_) {
311 gpu::Batch *geom = DRW_mesh_batch_cache_get_edit_facedots(mesh);
312 (use_gpu_subdiv ? face_normals_subdiv_ : face_normals_)
313 ->draw_expand(geom, GPU_PRIM_LINES, 1, 1, res_handle);
314 }
315 if (loop_normals_) {
316 gpu::Batch *geom = DRW_mesh_batch_cache_get_edit_loop_normals(mesh);
317 (use_gpu_subdiv ? loop_normals_subdiv_ : loop_normals_)
318 ->draw_expand(geom, GPU_PRIM_LINES, 1, 1, res_handle);
319 }
320 if (vert_normals_) {
321 gpu::Batch *geom = DRW_mesh_batch_cache_get_edit_vert_normals(mesh);
322 vert_normals_->draw_expand(geom, GPU_PRIM_LINES, 1, 1, res_handle);
323 }
324
325 {
326 gpu::Batch *geom = DRW_mesh_batch_cache_get_edit_edges(mesh);
327 edit_mesh_edges_ps_.draw_expand(geom, GPU_PRIM_TRIS, 2, 1, res_handle);
328 }
329 {
330 gpu::Batch *geom = DRW_mesh_batch_cache_get_edit_triangles(mesh);
331 (mesh_has_edit_cage(ob) ? &edit_mesh_cages_ps_ : &edit_mesh_faces_ps_)
332 ->draw(geom, res_handle);
333 }
334 if (select_vert) {
335 gpu::Batch *geom = DRW_mesh_batch_cache_get_edit_vertices(mesh);
336 edit_mesh_verts_ps_.draw(geom, res_handle);
337 }
338 if (show_face_dots) {
339 gpu::Batch *geom = DRW_mesh_batch_cache_get_edit_facedots(mesh);
340 edit_mesh_facedots_ps_.draw(geom, res_handle);
341 }
342
343 if (mesh_has_skin_roots(ob)) {
344 gpu::Batch *geom = DRW_mesh_batch_cache_get_edit_skin_roots(mesh);
345 edit_mesh_skin_roots_ps_.draw_expand(geom, GPU_PRIM_LINES, 32, 1, res_handle);
346 }
347 if (DRW_state_show_text() && (state.overlay.edit_flag & overlay_edit_text)) {
348 DRW_text_edit_mesh_measure_stats(state.region, state.v3d, ob, &state.scene->unit, state.dt);
349 }
350 }
351
352 void draw(Framebuffer &framebuffer, Manager &manager, View &view)
353 {
354 if (!enabled_) {
355 return;
356 }
357
358 GPU_debug_group_begin("Mesh Edit");
359
360 GPU_framebuffer_bind(framebuffer);
361 manager.submit(edit_mesh_prepass_ps_, view);
362 manager.submit(edit_mesh_analysis_ps_, view);
363 manager.submit(edit_mesh_weight_ps_, view);
364
365 if (xray_enabled) {
367 return;
368 }
369
370 view_edit_cage.sync(view.viewmat(), winmat_polygon_offset(view.winmat(), view_dist, 0.5f));
371 view_edit_edge.sync(view.viewmat(), winmat_polygon_offset(view.winmat(), view_dist, 1.0f));
372 view_edit_vert.sync(view.viewmat(), winmat_polygon_offset(view.winmat(), view_dist, 1.5f));
373
374 manager.submit(edit_mesh_normals_ps_, view);
375 manager.submit(edit_mesh_faces_ps_, view);
376 manager.submit(edit_mesh_cages_ps_, view_edit_cage);
377 manager.submit(edit_mesh_edges_ps_, view_edit_edge);
378 manager.submit(edit_mesh_verts_ps_, view_edit_vert);
379 manager.submit(edit_mesh_skin_roots_ps_, view_edit_vert);
380 manager.submit(edit_mesh_facedots_ps_, view_edit_vert);
381
383 }
384
385 void draw_color_only(Framebuffer &framebuffer, Manager &manager, View &view)
386 {
387 if (!enabled_) {
388 return;
389 }
390
391 if (!xray_enabled) {
392 return;
393 }
394
395 GPU_debug_group_begin("Mesh Edit Color Only");
396
397 view_edit_cage.sync(view.viewmat(), winmat_polygon_offset(view.winmat(), view_dist, 0.5f));
398 view_edit_edge.sync(view.viewmat(), winmat_polygon_offset(view.winmat(), view_dist, 1.0f));
399 view_edit_vert.sync(view.viewmat(), winmat_polygon_offset(view.winmat(), view_dist, 1.5f));
400
401 GPU_framebuffer_bind(framebuffer);
402 manager.submit(edit_mesh_normals_ps_, view);
403 manager.submit(edit_mesh_faces_ps_, view);
404 manager.submit(edit_mesh_cages_ps_, view_edit_cage);
405 manager.submit(edit_mesh_edges_ps_, view_edit_edge);
406 manager.submit(edit_mesh_verts_ps_, view_edit_vert);
407 manager.submit(edit_mesh_skin_roots_ps_, view_edit_vert);
408 manager.submit(edit_mesh_facedots_ps_, view_edit_vert);
409
411 }
412
413 static bool mesh_has_edit_cage(const Object *ob)
414 {
415 const Mesh &mesh = *static_cast<const Mesh *>(ob->data);
416 if (mesh.runtime->edit_mesh.get() != nullptr) {
417 const Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob);
418 const Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob);
419
420 return (editmesh_eval_cage != nullptr) && (editmesh_eval_cage != editmesh_eval_final);
421 }
422 return false;
423 }
424
425 private:
426 uint4 data_mask_get(const int flag)
427 {
428 uint4 mask = {0xFF, 0xFF, 0x00, 0x00};
436 return mask;
437 }
438
439 static bool mesh_has_skin_roots(const Object *ob)
440 {
441 const Mesh &mesh = *static_cast<const Mesh *>(ob->data);
442 if (BMEditMesh *em = mesh.runtime->edit_mesh.get()) {
443 return CustomData_get_offset(&em->bm->vdata, CD_MVERT_SKIN) != -1;
444 }
445 return false;
446 }
447};
448
449class MeshUVs {
450 private:
451 PassSimple analysis_ps_ = {"Mesh Analysis"};
452
453 /* TODO(fclem): Should be its own Overlay?. */
454 PassSimple wireframe_ps_ = {"Wireframe"};
455
456 PassSimple edges_ps_ = {"Edges"};
457 PassSimple faces_ps_ = {"Faces"};
458 PassSimple verts_ps_ = {"Verts"};
459 PassSimple facedots_ps_ = {"FaceDots"};
460
461 /* TODO(fclem): Should be its own Overlay?. */
462 PassSimple image_border_ps_ = {"ImageBorder"};
463
464 /* TODO(fclem): Should be its own Overlay?. */
465 PassSimple brush_stencil_ps_ = {"BrushStencil"};
466
467 /* TODO(fclem): Should be its own Overlay?. */
468 PassSimple paint_mask_ps_ = {"PaintMask"};
469
470 bool show_vert = false;
471 bool show_face = false;
472 bool show_face_dots = false;
473 bool show_uv_edit = false;
474
476 /* Draw final evaluated UVs (modifier stack applied) as grayed out wire-frame. */
477 /* TODO(fclem): Maybe should be its own Overlay?. */
478 bool show_wireframe = false;
479
481 /* TODO(fclem): Maybe should be its own Overlay?. */
482 bool show_stencil = false;
483
485 /* TODO(fclem): Maybe should be its own Overlay?. */
486 bool show_mask = false;
488 Mask *mask_id = nullptr;
489 Texture mask_texture_ = {"mask_texture_"};
490
492 bool show_mesh_analysis = false;
493 eSpaceImage_UVDT_Stretch mesh_analysis_type;
499 Vector<float *> per_mesh_area_3d;
500 Vector<float *> per_mesh_area_2d;
501 float total_area_ratio_;
502
504 bool show_tiled_image_active = false;
505 bool show_tiled_image_border = false;
506 bool show_tiled_image_label = false;
507
508 /* Set of original objects that have been drawn. */
509 Set<const Object *> drawn_object_set_;
510
511 bool enabled_ = false;
512
513 public:
514 void begin_sync(Resources &res, const State &state)
515 {
516 enabled_ = state.space_type == SPACE_IMAGE;
517
518 if (!enabled_) {
519 return;
520 }
521
522 const ToolSettings *tool_setting = state.scene->toolsettings;
523 const SpaceImage *space_image = reinterpret_cast<const SpaceImage *>(state.space_data);
524 ::Image *image = space_image->image;
525 const bool is_tiled_image = image && (image->source == IMA_SRC_TILED);
526 const bool is_viewer = image && ELEM(image->type, IMA_TYPE_R_RESULT, IMA_TYPE_COMPOSITE);
527 /* Only disable UV drawing on top of render results.
528 * Otherwise, show UVs even in the absence of active image. */
529 enabled_ = !is_viewer;
530
531 if (!enabled_) {
532 return;
533 }
534
535 const bool space_mode_is_paint = space_image->mode == SI_MODE_PAINT;
536 const bool space_mode_is_view = space_image->mode == SI_MODE_VIEW;
537 const bool space_mode_is_mask = space_image->mode == SI_MODE_MASK;
538 const bool space_mode_is_uv = space_image->mode == SI_MODE_UV;
539
540 const bool object_mode_is_edit = state.object_mode & OB_MODE_EDIT;
541 const bool object_mode_is_paint = state.object_mode & OB_MODE_TEXTURE_PAINT;
542
543 {
544 /* Edit UV Overlay. */
545 show_uv_edit = space_mode_is_uv && object_mode_is_edit;
546 show_mesh_analysis = show_uv_edit && (space_image->flag & SI_DRAW_STRETCH);
547
548 if (!show_uv_edit) {
549 show_vert = false;
550 show_face = false;
551 show_face_dots = false;
552 }
553 else {
554 const bool hide_faces = space_image->flag & SI_NO_DRAWFACES;
555
556 int sel_mode_2d = tool_setting->uv_selectmode;
557 show_vert = (sel_mode_2d != UV_SELECT_EDGE);
558 show_face = !show_mesh_analysis && !hide_faces;
559 show_face_dots = (sel_mode_2d & UV_SELECT_FACE) && !hide_faces;
560
561 if (tool_setting->uv_flag & UV_SYNC_SELECTION) {
562 int sel_mode_3d = tool_setting->selectmode;
563 /* NOTE: Ignore #SCE_SELECT_VERTEX because a single selected edge
564 * on the mesh may cause single UV vertices to be selected. */
565 show_vert = true /* (sel_mode_3d & SCE_SELECT_VERTEX) */;
566 show_face_dots = (sel_mode_3d & SCE_SELECT_FACE) && !hide_faces;
567 }
568 }
569
570 if (show_mesh_analysis) {
571 mesh_analysis_type = eSpaceImage_UVDT_Stretch(space_image->dt_uvstretch);
572 }
573 }
574 {
575 /* Wireframe UV Overlay. */
576 const bool show_wireframe_uv_edit = space_image->flag & SI_DRAWSHADOW;
577 const bool show_wireframe_tex_paint = !(space_image->flag & SI_NO_DRAW_TEXPAINT);
578
579 if (space_mode_is_uv && object_mode_is_edit) {
580 show_wireframe = show_wireframe_uv_edit;
581 }
582 else if (space_mode_is_uv && object_mode_is_paint) {
583 show_wireframe = show_wireframe_tex_paint;
584 }
585 else if (space_mode_is_paint && (object_mode_is_paint || object_mode_is_edit)) {
586 show_wireframe = show_wireframe_tex_paint;
587 }
588 else if (space_mode_is_view && object_mode_is_paint) {
589 show_wireframe = show_wireframe_tex_paint;
590 }
591 else {
592 show_wireframe = false;
593 }
594 }
595 {
596 /* Brush Stencil Overlay. */
597 const Brush *brush = BKE_paint_brush_for_read(&tool_setting->imapaint.paint);
598 show_stencil = space_mode_is_paint && brush &&
600 brush->clone.image;
601 }
602 {
603 /* Mask Overlay. */
604 show_mask = space_mode_is_mask && space_image->mask_info.mask &&
606 if (show_mask) {
607 mask_mode = eMaskOverlayMode(space_image->mask_info.overlay_mode);
608 mask_id = (Mask *)DEG_get_evaluated_id(state.depsgraph, &space_image->mask_info.mask->id);
609 }
610 else {
611 mask_id = nullptr;
612 }
613 }
614 {
615 /* UDIM Overlay. */
616 /* TODO: Always enable this overlay even if overlays are disabled. */
617 show_tiled_image_border = is_tiled_image;
618 show_tiled_image_active = is_tiled_image; /* TODO: Only disable this if overlays are off. */
619 show_tiled_image_label = is_tiled_image; /* TODO: Only disable this if overlays are off. */
620 }
621
622 const bool do_smooth_wire = (U.gpu_flag & USER_GPU_FLAG_OVERLAY_SMOOTH_WIRE) != 0;
623 const float dash_length = 4.0f * UI_SCALE_FAC;
624
625 if (show_wireframe) {
626 auto &pass = wireframe_ps_;
627 pass.init();
630 pass.shader_set(res.shaders.uv_wireframe.get());
631 pass.bind_ubo("globalsBlock", &res.globals_buf);
632 pass.push_constant("alpha", space_image->uv_opacity);
633 pass.push_constant("doSmoothWire", do_smooth_wire);
634 }
635
636 if (show_uv_edit) {
637 auto &pass = edges_ps_;
638 pass.init();
641
642 GPUShader *sh = res.shaders.uv_edit_edge.get();
643 pass.specialize_constant(sh, "use_edge_select", !show_vert);
644 pass.shader_set(sh);
645 pass.bind_ubo("globalsBlock", &res.globals_buf);
646 pass.push_constant("lineStyle", int(edit_uv_line_style_from_space_image(space_image)));
647 pass.push_constant("alpha", space_image->uv_opacity);
648 pass.push_constant("dashLength", dash_length);
649 pass.push_constant("doSmoothWire", do_smooth_wire);
650 }
651
652 if (show_vert) {
653 const float point_size = UI_GetThemeValuef(TH_VERTEX_SIZE) * UI_SCALE_FAC;
654 float4 theme_color;
655 UI_GetThemeColor4fv(TH_VERTEX, theme_color);
656 srgb_to_linearrgb_v4(theme_color, theme_color);
657
658 auto &pass = verts_ps_;
659 pass.init();
662 pass.shader_set(res.shaders.uv_edit_vert.get());
663 pass.bind_ubo("globalsBlock", &res.globals_buf);
664 pass.push_constant("pointSize", (point_size + 1.5f) * float(M_SQRT2));
665 pass.push_constant("outlineWidth", 0.75f);
666 pass.push_constant("color", theme_color);
667 }
668
669 if (show_face_dots) {
670 const float point_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) * UI_SCALE_FAC;
671
672 auto &pass = facedots_ps_;
673 pass.init();
676 pass.shader_set(res.shaders.uv_edit_facedot.get());
677 pass.bind_ubo("globalsBlock", &res.globals_buf);
678 pass.push_constant("pointSize", (point_size + 1.5f) * float(M_SQRT2));
679 }
680
681 if (show_face) {
682 auto &pass = faces_ps_;
683 pass.init();
685 pass.shader_set(res.shaders.uv_edit_face.get());
686 pass.bind_ubo("globalsBlock", &res.globals_buf);
687 pass.push_constant("uvOpacity", space_image->uv_opacity);
688 }
689
690 if (show_mesh_analysis) {
691 auto &pass = analysis_ps_;
692 pass.init();
694 pass.shader_set(mesh_analysis_type == SI_UVDT_STRETCH_ANGLE ?
697 pass.bind_ubo("globalsBlock", &res.globals_buf);
698 pass.push_constant("aspect", state.image_uv_aspect);
699 pass.push_constant("stretch_opacity", space_image->stretch_opacity);
700 pass.push_constant("totalAreaRatio", &total_area_ratio_);
701 }
702
703 per_mesh_area_3d.clear();
704 per_mesh_area_2d.clear();
705
706 drawn_object_set_.clear();
707 }
708
709 void edit_object_sync(Manager &manager, const ObjectRef &ob_ref, const State &state)
710 {
711 if (!enabled_ || ob_ref.object->type != OB_MESH) {
712 return;
713 }
714
715 /* When editing objects that share the same mesh we should only draw the
716 * first object to avoid overlapping UVs. Moreover, only the first evaluated object has the
717 * correct batches with the correct selection state.
718 * To this end, we skip duplicates and use the evaluated object returned by the depsgraph.
719 * See #83187. */
720 Object *object_orig = DEG_get_original_object(ob_ref.object);
721 Object *object_eval = DEG_get_evaluated_object(state.depsgraph, object_orig);
722
723 if (drawn_object_set_.contains(object_orig)) {
724 return;
725 }
726 drawn_object_set_.add(object_orig);
727
728 ResourceHandle res_handle = manager.unique_handle(ob_ref);
729
730 Object &ob = *object_eval;
731 Mesh &mesh = *static_cast<Mesh *>(ob.data);
732
733 if (object_eval != ob_ref.object) {
734 /* We are requesting batches on an evaluated ID that is potentially not iterated over.
735 * So we have to manually call these cache validation and extraction method. */
737 }
738
739 if (show_uv_edit) {
740 gpu::Batch *geom = DRW_mesh_batch_cache_get_edituv_edges(ob, mesh);
741 edges_ps_.draw_expand(geom, GPU_PRIM_TRIS, 2, 1, res_handle);
742 }
743 if (show_vert) {
744 gpu::Batch *geom = DRW_mesh_batch_cache_get_edituv_verts(ob, mesh);
745 verts_ps_.draw(geom, res_handle);
746 }
747 if (show_face_dots) {
748 gpu::Batch *geom = DRW_mesh_batch_cache_get_edituv_facedots(ob, mesh);
749 facedots_ps_.draw(geom, res_handle);
750 }
751 if (show_face) {
752 gpu::Batch *geom = DRW_mesh_batch_cache_get_edituv_faces(ob, mesh);
753 faces_ps_.draw(geom, res_handle);
754 }
755
756 if (show_mesh_analysis) {
757 int index_3d, index_2d;
758 if (mesh_analysis_type == SI_UVDT_STRETCH_AREA) {
759 index_3d = per_mesh_area_3d.append_and_get_index(nullptr);
760 index_2d = per_mesh_area_2d.append_and_get_index(nullptr);
761 }
762
763 gpu::Batch *geom =
764 mesh_analysis_type == SI_UVDT_STRETCH_ANGLE ?
767 ob, mesh, &per_mesh_area_3d[index_3d], &per_mesh_area_2d[index_2d]);
768
769 analysis_ps_.draw(geom, res_handle);
770 }
771
772 if (show_wireframe) {
773 gpu::Batch *geom = DRW_mesh_batch_cache_get_uv_edges(ob, mesh);
774 wireframe_ps_.draw_expand(geom, GPU_PRIM_TRIS, 2, 1, res_handle);
775 }
776
777 if (object_eval != ob_ref.object) {
778 /* TODO(fclem): Refactor. Global access. But as explained above it is a bit complicated. */
780 }
781 }
782
783 void end_sync(Resources &res, ShapeCache &shapes, const State &state)
784 {
785 if (!enabled_) {
786 return;
787 }
788
789 {
790 float total_3d = 0.0f;
791 float total_2d = 0.0f;
792 for (const float *mesh_area_2d : per_mesh_area_2d) {
793 total_2d += *mesh_area_2d;
794 }
795 for (const float *mesh_area_3d : per_mesh_area_3d) {
796 total_3d += *mesh_area_3d;
797 }
798 total_area_ratio_ = total_3d * math::safe_rcp(total_2d);
799 }
800
801 const ToolSettings *tool_setting = state.scene->toolsettings;
802 const SpaceImage *space_image = reinterpret_cast<const SpaceImage *>(state.space_data);
803 ::Image *image = space_image->image;
804
805 if (show_tiled_image_border) {
806 float4 theme_color;
807 float4 selected_color;
808 uchar4 text_color;
809 /* Color Management: Exception here as texts are drawn in sRGB space directly. No conversion
810 * required. */
811 UI_GetThemeColorShade4ubv(TH_BACK, 60, text_color);
812 UI_GetThemeColorShade4fv(TH_BACK, 60, theme_color);
813 UI_GetThemeColor4fv(TH_FACE_SELECT, selected_color);
814 srgb_to_linearrgb_v4(theme_color, theme_color);
815 srgb_to_linearrgb_v4(selected_color, selected_color);
816
817 auto &pass = image_border_ps_;
818 pass.init();
820 pass.shader_set(res.shaders.uv_image_borders.get());
821
822 auto draw_tile = [&](const ImageTile *tile, const bool is_active) {
823 const int tile_x = ((tile->tile_number - 1001) % 10);
824 const int tile_y = ((tile->tile_number - 1001) / 10);
825 const float3 tile_location(tile_x, tile_y, 0.0f);
826 pass.push_constant("tile_pos", tile_location);
827 pass.push_constant("ucolor", is_active ? selected_color : theme_color);
828 pass.draw(shapes.quad_wire.get());
829
830 /* Note: don't draw label twice for active tile. */
831 if (show_tiled_image_label && !is_active) {
832 std::string text = std::to_string(tile->tile_number);
834 tile_location,
835 text.c_str(),
836 text.size(),
837 10,
838 10,
840 text_color);
841 }
842 };
843
844 ListBaseWrapper<ImageTile> tiles(image->tiles);
845
846 for (const ImageTile *tile : tiles) {
847 draw_tile(tile, false);
848 }
849 /* Draw active tile on top. */
850 if (show_tiled_image_active) {
851 draw_tile(tiles.get(image->active_tile_index), true);
852 }
853 }
854
855 if (show_stencil) {
856 auto &pass = brush_stencil_ps_;
857 pass.init();
860
861 const Brush *brush = BKE_paint_brush_for_read(&tool_setting->imapaint.paint);
862 ::Image *stencil_image = brush->clone.image;
863 TextureRef stencil_texture;
864 stencil_texture.wrap(BKE_image_get_gpu_texture(stencil_image, nullptr));
865
866 if (stencil_texture.is_valid()) {
867 float2 size_image;
868 BKE_image_get_size_fl(image, nullptr, &size_image[0]);
869
870 pass.shader_set(res.shaders.uv_brush_stencil.get());
871 pass.bind_texture("imgTexture", stencil_texture);
872 pass.push_constant("imgPremultiplied", true);
873 pass.push_constant("imgAlphaBlend", true);
874 pass.push_constant("ucolor", float4(1.0f, 1.0f, 1.0f, brush->clone.alpha));
875 pass.push_constant("brush_offset", float2(brush->clone.offset));
876 pass.push_constant("brush_scale", float2(stencil_texture.size().xy()) / size_image);
877 pass.draw(shapes.quad_solid.get());
878 }
879 }
880
881 if (show_mask) {
882 paint_mask_texture_ensure(mask_id, state.image_size, state.image_aspect);
883
884 const bool is_combined = mask_mode == MASK_OVERLAY_COMBINED;
885 const float opacity = is_combined ? space_image->mask_info.blend_factor : 1.0f;
886
887 auto &pass = paint_mask_ps_;
888 pass.init();
891 pass.shader_set(res.shaders.uv_paint_mask.get());
892 pass.bind_texture("imgTexture", mask_texture_);
893 pass.push_constant("color", float4(1.0f, 1.0f, 1.0f, 1.0f));
894 pass.push_constant("opacity", opacity);
895 pass.push_constant("brush_offset", float2(0.0f));
896 pass.push_constant("brush_scale", float2(1.0f));
897 pass.draw(shapes.quad_solid.get());
898 }
899 }
900
901 void draw(Framebuffer &framebuffer, Manager &manager, View &view)
902 {
903 if (!enabled_) {
904 return;
905 }
906
907 GPU_debug_group_begin("Mesh Edit UVs");
908
909 GPU_framebuffer_bind(framebuffer);
910 if (show_mask && (mask_mode != MASK_OVERLAY_COMBINED)) {
911 manager.submit(paint_mask_ps_, view);
912 }
913 if (show_tiled_image_border) {
914 manager.submit(image_border_ps_, view);
915 }
916 if (show_wireframe) {
917 manager.submit(wireframe_ps_, view);
918 }
919 if (show_mesh_analysis) {
920 manager.submit(analysis_ps_, view);
921 }
922 if (show_face) {
923 manager.submit(faces_ps_, view);
924 }
925 if (show_uv_edit) {
926 manager.submit(edges_ps_, view);
927 }
928 if (show_face_dots) {
929 manager.submit(facedots_ps_, view);
930 }
931 if (show_vert) {
932 manager.submit(verts_ps_, view);
933 }
934 if (show_stencil) {
935 manager.submit(brush_stencil_ps_, view);
936 }
937
939 }
940
941 void draw_on_render(GPUFrameBuffer *framebuffer, Manager &manager, View &view)
942 {
943 if (!enabled_) {
944 return;
945 }
946
947 GPU_framebuffer_bind(framebuffer);
948 /* Mask in #MASK_OVERLAY_COMBINED mode renders onto the render framebuffer and modifies the
949 * image in scene referred color space. The #MASK_OVERLAY_ALPHACHANNEL renders onto the overlay
950 * framebuffer. */
951 if (show_mask && (mask_mode == MASK_OVERLAY_COMBINED)) {
952 manager.submit(paint_mask_ps_, view);
953 }
954 }
955
956 private:
957 static OVERLAY_UVLineStyle edit_uv_line_style_from_space_image(const SpaceImage *sima)
958 {
959 const bool is_uv_editor = sima->mode == SI_MODE_UV;
960 if (is_uv_editor) {
961 switch (sima->dt_uv) {
962 case SI_UVDT_OUTLINE:
964 case SI_UVDT_BLACK:
966 case SI_UVDT_WHITE:
968 case SI_UVDT_DASH:
970 default:
972 }
973 }
974 else {
976 }
977 }
978
979 /* TODO(jbakker): the GPU texture should be cached with the mask. */
980 void paint_mask_texture_ensure(Mask *mask, const int2 &resolution, const float2 &aspect)
981 {
982 const int width = resolution.x;
983 const int height = floor(float(resolution.y) * (aspect.y / aspect.x));
984 float *buffer = static_cast<float *>(MEM_mallocN(sizeof(float) * height * width, __func__));
985
987 BKE_maskrasterize_handle_init(handle, mask, width, height, true, true, true);
988 BKE_maskrasterize_buffer(handle, width, height, buffer);
990
991 mask_texture_.free();
992 mask_texture_.ensure_2d(GPU_R16F, int2(width, height), GPU_TEXTURE_USAGE_SHADER_READ, buffer);
993
994 MEM_freeN(buffer);
995 }
996};
997
998} // namespace blender::draw::overlay
CustomData interface, see also DNA_customdata_types.h.
int CustomData_get_offset(const CustomData *data, eCustomDataType type)
void BKE_image_get_size_fl(Image *image, ImageUser *iuser, float r_size[2])
GPUTexture * BKE_image_get_gpu_texture(Image *image, ImageUser *iuser)
Definition image_gpu.cc:476
void BKE_maskrasterize_handle_free(MaskRasterHandle *mr_handle)
MaskRasterHandle * BKE_maskrasterize_handle_new(void)
void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mask, int width, int height, bool do_aspect_correct, bool do_mask_aa, bool do_feather)
void BKE_maskrasterize_buffer(MaskRasterHandle *mr_handle, unsigned int width, unsigned int height, float *buffer)
Rasterize a buffer from a single mask (threaded execution).
const Mesh * BKE_object_get_editmesh_eval_cage(const Object *object)
const Mesh * BKE_object_get_editmesh_eval_final(const Object *object)
const Brush * BKE_paint_brush_for_read(const Paint *paint)
Definition paint.cc:654
bool BKE_subsurf_modifier_has_gpu_subdiv(const Mesh *mesh)
#define M_SQRT2
MINLINE void srgb_to_linearrgb_v4(float linear[4], const float srgb[4])
#define SET_FLAG_FROM_TEST(value, test, flag)
#define ELEM(...)
Object * DEG_get_original_object(Object *object)
ID * DEG_get_evaluated_id(const Depsgraph *depsgraph, ID *id)
Object * DEG_get_evaluated_object(const Depsgraph *depsgraph, Object *object)
@ IMAGE_PAINT_BRUSH_TYPE_CLONE
@ CD_MVERT_SKIN
@ IMA_SRC_TILED
@ IMA_TYPE_R_RESULT
@ IMA_TYPE_COMPOSITE
eMaskOverlayMode
@ MASK_OVERLAY_COMBINED
@ MASK_OVERLAY_ALPHACHANNEL
@ MASK_DRAWFLAG_OVERLAY
eDrawType
@ OB_WIRE
@ OB_MODE_EDIT
@ OB_MODE_TEXTURE_PAINT
@ OB_MESH
@ SCE_PERF_HQ_NORMALS
@ UV_SELECT_FACE
@ UV_SELECT_EDGE
@ SCE_SELECT_FACE
@ SCE_SELECT_VERTEX
@ SCE_SELECT_EDGE
@ UV_SYNC_SELECTION
@ SI_NO_DRAW_TEXPAINT
@ SI_DRAW_STRETCH
@ SI_NO_DRAWFACES
@ SI_DRAWSHADOW
@ SPACE_IMAGE
@ SPACE_VIEW3D
@ SI_UVDT_BLACK
@ SI_UVDT_DASH
@ SI_UVDT_WHITE
@ SI_UVDT_OUTLINE
eSpaceImage_UVDT_Stretch
@ SI_UVDT_STRETCH_AREA
@ SI_UVDT_STRETCH_ANGLE
@ SI_MODE_PAINT
@ SI_MODE_VIEW
@ SI_MODE_MASK
@ SI_MODE_UV
@ USER_GPU_FLAG_OVERLAY_SMOOTH_WIRE
@ USER_GPU_FLAG_NO_EDIT_MODE_SMOOTH_WIRE
#define UI_SCALE_FAC
@ V3D_OVERLAY_EDIT_VERT_NORMALS
@ V3D_OVERLAY_EDIT_INDICES
@ 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_AREA
@ V3D_OVERLAY_EDIT_EDGE_ANG
@ V3D_OVERLAY_EDIT_FACE_DOT
@ V3D_OVERLAY_EDIT_FACE_ANG
@ V3D_OVERLAY_EDIT_SEAMS
@ V3D_OVERLAY_EDIT_STATVIS
@ V3D_OVERLAY_EDIT_BWEIGHTS
@ V3D_OVERLAY_EDIT_WEIGHT
@ V3D_OVERLAY_EDIT_SHARP
@ V3D_OVERLAY_EDIT_EDGE_LEN
#define RETOPOLOGY_OFFSET(v3d)
bool GPU_use_hq_normals_workaround()
void GPU_debug_group_end()
Definition gpu_debug.cc:33
void GPU_debug_group_begin(const char *name)
Definition gpu_debug.cc:22
void GPU_framebuffer_bind(GPUFrameBuffer *framebuffer)
@ GPU_PRIM_LINES
@ GPU_PRIM_TRIS
@ GPU_TEXTURE_USAGE_SHADER_READ
@ TH_BACK
@ TH_FACEDOT_SIZE
@ TH_VERTEX
@ TH_VERTEX_SIZE
@ TH_FACE_SELECT
void UI_GetThemeColor4fv(int colorid, float col[4])
void UI_GetThemeColorShade4fv(int colorid, int offset, float col[4])
void UI_GetThemeColorShade4ubv(int colorid, int offset, unsigned char col[4])
float UI_GetThemeValuef(int colorid)
static void draw_tile(const float2 &zoom, const int texcoord_attribute, const int position_attribute, const DrawTile &draw_tile)
struct GPUShader GPUShader
unsigned int U
Definition btGjkEpa3.h:78
bool contains(const Key &key) const
Definition BLI_set.hh:291
bool add(const Key &key)
Definition BLI_set.hh:248
void clear()
Definition BLI_set.hh:532
int64_t append_and_get_index(const T &value)
ResourceHandle unique_handle(const ObjectRef &ref)
void submit(PassSimple &pass, View &view)
void wrap(GPUTexture *tex)
bool ensure_2d(eGPUTextureFormat format, int2 extent, eGPUTextureUsage usage=GPU_TEXTURE_USAGE_GENERAL, const float *data=nullptr, int mip_len=1)
int3 size(int miplvl=0) const
void sync(const float4x4 &view_mat, const float4x4 &win_mat, int view_id=0)
Definition draw_view.cc:20
void draw(gpu::Batch *batch, uint instance_len=-1, uint vertex_len=-1, uint vertex_first=-1, ResourceHandle handle={0}, uint custom_id=0)
Definition draw_pass.hh:760
void draw_expand(gpu::Batch *batch, GPUPrimType primitive_type, uint primitive_len, uint instance_len, uint vertex_len=-1, uint vertex_first=-1, ResourceHandle handle={0}, uint custom_id=0)
Definition draw_pass.hh:793
void draw(Framebuffer &framebuffer, Manager &manager, View &view)
void edit_object_sync(Manager &manager, const ObjectRef &ob_ref, const State &state)
void begin_sync(Resources &res, const State &state)
void draw_on_render(GPUFrameBuffer *framebuffer, Manager &manager, View &view)
void end_sync(Resources &res, ShapeCache &shapes, const State &state)
void draw_color_only(Framebuffer &framebuffer, Manager &manager, View &view)
void draw(Framebuffer &framebuffer, Manager &manager, View &view)
static bool mesh_has_edit_cage(const Object *ob)
void begin_sync(Resources &res, const State &state, const View &view)
void edit_object_sync(Manager &manager, const ObjectRef &ob_ref, const State &state, Resources &)
blender::gpu::Batch * DRW_cache_mesh_surface_weights_get(Object *ob)
blender::gpu::Batch * DRW_cache_mesh_surface_get(Object *ob)
void drw_batch_cache_generate_requested_delayed(Object *ob)
blender::gpu::Batch * DRW_cache_mesh_surface_mesh_analysis_get(Object *ob)
bool DRW_state_show_text()
void DRW_text_cache_add(DRWTextStore *dt, const float co[3], const char *str, const int str_len, short xoffs, short yoffs, short flag, const uchar col[4], const bool shadow, const bool align_center)
void DRW_text_edit_mesh_measure_stats(const ARegion *region, const View3D *v3d, const Object *ob, const UnitSettings *unit, DRWTextStore *dt)
@ DRW_TEXT_CACHE_GLOBALSPACE
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
@ DRW_STATE_DEPTH_ALWAYS
Definition draw_state.hh:36
@ DRW_STATE_BLEND_ALPHA_PREMUL
Definition draw_state.hh:57
@ DRW_STATE_BLEND_MUL
Definition draw_state.hh:60
ccl_gpu_kernel_postfix ccl_global KernelWorkTile * tiles
ccl_global const KernelWorkTile * tile
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
ccl_device_inline float4 mask(const int4 mask, const float4 a)
static ulong state[N]
static float4x4 winmat_polygon_offset(float4x4 winmat, float view_dist, float offset)
blender::gpu::Batch * DRW_mesh_batch_cache_get_edituv_faces_stretch_angle(Object &object, Mesh &mesh)
blender::gpu::Batch * DRW_mesh_batch_cache_get_edituv_edges(Object &object, Mesh &mesh)
blender::gpu::Batch * DRW_mesh_batch_cache_get_edit_edges(Mesh &mesh)
blender::gpu::Batch * DRW_mesh_batch_cache_get_edituv_facedots(Object &object, Mesh &mesh)
blender::gpu::Batch * DRW_mesh_batch_cache_get_edit_facedots(Mesh &mesh)
blender::gpu::Batch * DRW_mesh_batch_cache_get_edituv_verts(Object &object, Mesh &mesh)
blender::gpu::Batch * DRW_mesh_batch_cache_get_edituv_faces(Object &object, Mesh &mesh)
blender::gpu::Batch * DRW_mesh_batch_cache_get_edit_loop_normals(Mesh &mesh)
blender::gpu::Batch * DRW_mesh_batch_cache_get_edit_triangles(Mesh &mesh)
blender::gpu::Batch * DRW_mesh_batch_cache_get_edit_vertices(Mesh &mesh)
blender::gpu::Batch * DRW_mesh_batch_cache_get_uv_edges(Object &object, Mesh &mesh)
void DRW_mesh_batch_cache_validate(Object &object, Mesh &mesh)
blender::gpu::Batch * DRW_mesh_batch_cache_get_edit_vert_normals(Mesh &mesh)
blender::gpu::Batch * DRW_mesh_batch_cache_get_edituv_faces_stretch_area(Object &object, Mesh &mesh, float **tot_area, float **tot_uv_area)
blender::gpu::Batch * DRW_mesh_batch_cache_get_edit_skin_roots(Mesh &mesh)
T safe_rcp(const T &a)
T floor(const T &a)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
VecBase< int32_t, 4 > int4
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
VecBase< float, 3 > float3
OVERLAY_UVLineStyle
@ OVERLAY_UV_LINE_STYLE_DASH
@ OVERLAY_UV_LINE_STYLE_SHADOW
@ OVERLAY_UV_LINE_STYLE_WHITE
@ OVERLAY_UV_LINE_STYLE_OUTLINE
@ OVERLAY_UV_LINE_STYLE_BLACK
struct Image * image
float offset[2]
struct BrushClone clone
char image_brush_type
struct Mask * mask
MaskSpaceInfo mask_info
struct Image * image
struct ImagePaintSettings imapaint
VecBase< T, 2 > xy() const
float x
float y
int x
Definition types_int2.h:15
int y
Definition types_int2.h:15
uint8_t flag
Definition wm_window.cc:138