Blender V4.3
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
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 GPU_indexbuf_build_in_place_ex(&builder, 0, max_index, true, &lines);
71
72 MEM_freeN(select_map);
73}
74
76 const DRWSubdivCache &subdiv_cache,
77 gpu::IndexBuf &lines)
78{
79 const Span<bool> hide_edge = mr.hide_edge;
80 const Span<bool> select_poly = mr.select_poly;
81 const Span<int> orig_index_edge = mr.orig_index_edge ?
83 Span<int>();
84 const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index,
85 subdiv_cache.num_subdiv_loops);
86 const Span<int> subdiv_loop_subdiv_edge_index(subdiv_cache.subdiv_loop_subdiv_edge_index,
87 subdiv_cache.num_subdiv_loops);
88 const Span<int> subdiv_loop_edge_index = subdiv_cache.edges_orig_index->data<int>();
89
90 GPUIndexBufBuilder builder;
91 const int max_index = subdiv_cache.num_subdiv_loops;
92 GPU_indexbuf_init(&builder, GPU_PRIM_LINES, subdiv_cache.num_subdiv_edges, max_index);
94
95 BLI_bitmap *select_map = BLI_BITMAP_NEW(mr.edges_num, __func__);
96 const int quads_num = subdiv_cache.num_subdiv_quads;
97 threading::parallel_for(IndexRange(quads_num), 4096, [&](const IndexRange range) {
98 for (const int subdiv_quad_index : range) {
99 const int coarse_quad_index = subdiv_loop_face_index[subdiv_quad_index * 4];
100 const IndexRange subdiv_face(subdiv_quad_index * 4, 4);
101 for (const int corner : subdiv_face) {
102 const uint coarse_edge_index = uint(subdiv_loop_edge_index[corner]);
103 const uint subdiv_edge_index = uint(subdiv_loop_subdiv_edge_index[corner]);
104 if (coarse_edge_index == -1u) {
105 data[subdiv_edge_index] = uint2(gpu::RESTART_INDEX);
106 continue;
107 }
108 if ((!hide_edge.is_empty() && hide_edge[coarse_edge_index]) ||
109 (!orig_index_edge.is_empty() &&
110 (orig_index_edge[coarse_edge_index] == ORIGINDEX_NONE)))
111 {
112 data[subdiv_edge_index] = uint2(gpu::RESTART_INDEX);
113 continue;
114 }
115
116 const int corner_next = bke::mesh::face_corner_next(subdiv_face, corner);
117 if (!select_poly.is_empty() && select_poly[coarse_quad_index]) {
118 if (BLI_BITMAP_TEST_AND_SET_ATOMIC(select_map, coarse_edge_index)) {
119 /* Hide edge as it has more than 2 selected loop. */
120 data[subdiv_edge_index] = uint2(gpu::RESTART_INDEX);
121 }
122 else {
123 /* First selected loop. Set edge visible, overwriting any unselected loop. */
124 data[subdiv_edge_index] = uint2(corner, corner_next);
125 }
126 }
127 else {
128 /* Set these unselected loop only if this edge has no other selected loop. */
129 if (!BLI_BITMAP_TEST(select_map, coarse_edge_index)) {
130 data[subdiv_edge_index] = uint2(corner, corner_next);
131 }
132 }
133 }
134 }
135 });
136
137 GPU_indexbuf_build_in_place_ex(&builder, 0, max_index, true, &lines);
138
139 MEM_freeN(select_map);
140}
141
142} // namespace blender::draw
#define ORIGINDEX_NONE
#define BLI_BITMAP_NEW(_num, _alloc_string)
Definition BLI_bitmap.h:41
#define BLI_BITMAP_TEST(_bitmap, _index)
Definition BLI_bitmap.h:65
#define BLI_BITMAP_TEST_AND_SET_ATOMIC(_bitmap, _index)
Definition BLI_bitmap.h:69
unsigned int BLI_bitmap
Definition BLI_bitmap.h:17
unsigned int uint
void GPU_indexbuf_build_in_place_ex(GPUIndexBufBuilder *builder, uint index_min, uint index_max, bool uses_restart_indices, blender::gpu::IndexBuf *elem)
blender::MutableSpan< uint32_t > GPU_indexbuf_get_data(GPUIndexBufBuilder *)
void GPU_indexbuf_init(GPUIndexBufBuilder *, GPUPrimType, uint prim_len, uint vertex_len)
@ GPU_PRIM_LINES
Read Guarded memory(de)allocation.
Provides wrapper around system-specific atomic primitives, and some extensions (faked-atomic operatio...
constexpr MutableSpan< NewT > cast() const
Definition BLI_span.hh:736
constexpr bool is_empty() const
Definition BLI_span.hh:261
MutableSpan< T > data()
Extraction of Mesh data into VBO to feed to GPU.
IndexRange range
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void extract_lines_paint_mask(const MeshRenderData &mr, gpu::IndexBuf &lines)
void extract_lines_paint_mask_subdiv(const MeshRenderData &mr, const DRWSubdivCache &subdiv_cache, gpu::IndexBuf &lines)
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:95
VArraySpan< bool > select_poly
OffsetIndices< int > faces