Blender V5.0
extract_mesh_ibo_lines_paint_mask.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2021 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "BLI_bitmap.h"
10#include "atomic_ops.h"
11
12#include "MEM_guardedalloc.h"
13
14#include "GPU_index_buffer.hh"
15
16#include "draw_subdivision.hh"
17#include "extract_mesh.hh"
18
19namespace blender::draw {
20
22{
23 const OffsetIndices faces = mr.faces;
24 const Span<int> corner_edges = mr.corner_edges;
25 const Span<bool> hide_edge = mr.hide_edge;
26 const Span<bool> select_poly = mr.select_poly;
27 const Span<int> orig_index_edge = mr.orig_index_edge ?
29 Span<int>();
30
31 GPUIndexBufBuilder builder;
32 const int max_index = mr.corners_num;
33 GPU_indexbuf_init(&builder, GPU_PRIM_LINES, mr.edges_num, max_index);
35
36 BLI_bitmap *select_map = BLI_BITMAP_NEW(mr.edges_num, __func__);
37 threading::parallel_for(faces.index_range(), 1024, [&](const IndexRange range) {
38 for (const int face_index : range) {
39 const IndexRange face = faces[face_index];
40 for (const int corner : face) {
41 const int edge = corner_edges[corner];
42 if ((!hide_edge.is_empty() && hide_edge[edge]) ||
43 (!orig_index_edge.is_empty() && (orig_index_edge[edge] == ORIGINDEX_NONE)))
44 {
45 data[edge] = uint2(gpu::RESTART_INDEX);
46 continue;
47 }
48
49 const int corner_next = bke::mesh::face_corner_next(face, corner);
50 if (!select_poly.is_empty() && select_poly[face_index]) {
51 if (BLI_BITMAP_TEST_AND_SET_ATOMIC(select_map, edge)) {
52 /* Hide edge as it has more than 2 selected loop. */
53 data[edge] = uint2(gpu::RESTART_INDEX);
54 }
55 else {
56 /* First selected loop. Set edge visible, overwriting any unselected loop. */
57 data[edge] = uint2(corner, corner_next);
58 }
59 }
60 else {
61 /* Set these unselected loop only if this edge has no other selected loop. */
62 if (!BLI_BITMAP_TEST(select_map, edge)) {
63 data[edge] = uint2(corner, corner_next);
64 }
65 }
66 }
67 }
68 });
69
70 MEM_freeN(select_map);
71 return gpu::IndexBufPtr(GPU_indexbuf_build_ex(&builder, 0, max_index, true));
72}
73
75 const DRWSubdivCache &subdiv_cache)
76{
77 const Span<bool> hide_edge = mr.hide_edge;
78 const Span<bool> select_poly = mr.select_poly;
79 const Span<int> orig_index_edge = mr.orig_index_edge ?
81 Span<int>();
82 const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index,
83 subdiv_cache.num_subdiv_loops);
84 const Span<int> subdiv_loop_subdiv_edge_index(subdiv_cache.subdiv_loop_subdiv_edge_index,
85 subdiv_cache.num_subdiv_loops);
86 const Span<int> subdiv_loop_edge_index = subdiv_cache.edges_orig_index->data<int>();
87
88 GPUIndexBufBuilder builder;
89 const int max_index = subdiv_cache.num_subdiv_loops;
90 GPU_indexbuf_init(&builder, GPU_PRIM_LINES, subdiv_cache.num_subdiv_edges, max_index);
92
93 BLI_bitmap *select_map = BLI_BITMAP_NEW(mr.edges_num, __func__);
94 const int quads_num = subdiv_cache.num_subdiv_quads;
95 threading::parallel_for(IndexRange(quads_num), 4096, [&](const IndexRange range) {
96 for (const int subdiv_quad_index : range) {
97 const int coarse_quad_index = subdiv_loop_face_index[subdiv_quad_index * 4];
98 const IndexRange subdiv_face(subdiv_quad_index * 4, 4);
99 for (const int corner : subdiv_face) {
100 const uint coarse_edge_index = uint(subdiv_loop_edge_index[corner]);
101 const uint subdiv_edge_index = uint(subdiv_loop_subdiv_edge_index[corner]);
102 if (coarse_edge_index == -1u) {
103 data[subdiv_edge_index] = uint2(gpu::RESTART_INDEX);
104 continue;
105 }
106 if ((!hide_edge.is_empty() && hide_edge[coarse_edge_index]) ||
107 (!orig_index_edge.is_empty() &&
108 (orig_index_edge[coarse_edge_index] == ORIGINDEX_NONE)))
109 {
110 data[subdiv_edge_index] = uint2(gpu::RESTART_INDEX);
111 continue;
112 }
113
114 const int corner_next = bke::mesh::face_corner_next(subdiv_face, corner);
115 if (!select_poly.is_empty() && select_poly[coarse_quad_index]) {
116 if (BLI_BITMAP_TEST_AND_SET_ATOMIC(select_map, coarse_edge_index)) {
117 /* Hide edge as it has more than 2 selected loop. */
118 data[subdiv_edge_index] = uint2(gpu::RESTART_INDEX);
119 }
120 else {
121 /* First selected loop. Set edge visible, overwriting any unselected loop. */
122 data[subdiv_edge_index] = uint2(corner, corner_next);
123 }
124 }
125 else {
126 /* Set these unselected loop only if this edge has no other selected loop. */
127 if (!BLI_BITMAP_TEST(select_map, coarse_edge_index)) {
128 data[subdiv_edge_index] = uint2(corner, corner_next);
129 }
130 }
131 }
132 }
133 });
134
135 MEM_freeN(select_map);
136 return gpu::IndexBufPtr(GPU_indexbuf_build_ex(&builder, 0, max_index, true));
137}
138
139} // namespace blender::draw
#define ORIGINDEX_NONE
#define BLI_BITMAP_NEW(_num, _alloc_string)
Definition BLI_bitmap.h:37
#define BLI_BITMAP_TEST(_bitmap, _index)
Definition BLI_bitmap.h:61
#define BLI_BITMAP_TEST_AND_SET_ATOMIC(_bitmap, _index)
Definition BLI_bitmap.h:65
unsigned int BLI_bitmap
Definition BLI_bitmap.h:13
unsigned int uint
blender::MutableSpan< uint32_t > GPU_indexbuf_get_data(GPUIndexBufBuilder *)
void GPU_indexbuf_init(GPUIndexBufBuilder *, GPUPrimType, uint prim_len, uint vertex_len)
blender::gpu::IndexBuf * GPU_indexbuf_build_ex(GPUIndexBufBuilder *builder, uint index_min, uint index_max, bool uses_restart_indices)
@ GPU_PRIM_LINES
Read Guarded memory(de)allocation.
Provides wrapper around system-specific atomic primitives, and some extensions (faked-atomic operatio...
BMesh const char void * data
constexpr bool is_empty() const
Definition BLI_span.hh:260
MutableSpan< T > data()
Extraction of Mesh data into VBO to feed to GPU.
VecBase< uint, 2 > uint2
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
static char faces[256]
int face_corner_next(const IndexRange face, const int corner)
Definition BKE_mesh.hh:315
gpu::IndexBufPtr extract_lines_paint_mask(const MeshRenderData &mr)
gpu::IndexBufPtr extract_lines_paint_mask_subdiv(const MeshRenderData &mr, const DRWSubdivCache &subdiv_cache)
std::unique_ptr< IndexBuf, IndexBufDeleter > IndexBufPtr
constexpr uint32_t RESTART_INDEX
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Definition BLI_task.hh:93
VecBase< uint32_t, 2 > uint2
VArraySpan< bool > select_poly
OffsetIndices< int > faces