Blender V5.0
extract_mesh_vbo_select_idx.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_array_utils.hh"
10
11#include "draw_subdivision.hh"
12#include "extract_mesh.hh"
13
14namespace blender::draw {
15
17{
18 static GPUVertFormat format = GPU_vertformat_from_attribute("index", gpu::VertAttrType::SINT_32);
21 return vbo;
22}
23
24/* TODO: Use #glVertexID to get loop index and use the data structure on the CPU to retrieve the
25 * select element associated with this loop ID. This would remove the need for this separate
26 * index VBO's. We could upload the p/e/orig_index_vert as a buffer texture and sample it inside
27 * the shader to output original index. */
28
30{
31 MutableSpan corners_data = vbo_data.take_front(mr.corners_num);
32 MutableSpan loose_edge_data = vbo_data.slice(mr.corners_num, mr.loose_edges.size() * 2);
33 MutableSpan loose_vert_data = vbo_data.take_back(mr.loose_verts.size());
34
35 if (mr.orig_index_vert) {
36 const Span<int> orig_index_vert(mr.orig_index_vert, mr.verts_num);
37 array_utils::gather(orig_index_vert, mr.corner_verts, corners_data);
38 extract_mesh_loose_edge_data(orig_index_vert, mr.edges, mr.loose_edges, loose_edge_data);
39 array_utils::gather(orig_index_vert, mr.loose_verts, loose_vert_data);
40 }
41 else {
42 array_utils::copy(mr.corner_verts, corners_data);
43 const Span<int2> edges = mr.edges;
44 const Span<int> loose_edges = mr.loose_edges;
45 threading::parallel_for(loose_edges.index_range(), 4096, [&](const IndexRange range) {
46 for (const int i : range) {
47 loose_edge_data[i * 2 + 0] = edges[loose_edges[i]][0];
48 loose_edge_data[i * 2 + 1] = edges[loose_edges[i]][1];
49 }
50 });
51 array_utils::copy(mr.loose_verts, loose_vert_data);
52 }
53}
54
56{
57 MutableSpan corners_data = vbo_data.take_front(mr.corners_num);
58 MutableSpan loose_edge_data = vbo_data.slice(mr.corners_num, mr.loose_edges.size() * 2);
59 MutableSpan loose_vert_data = vbo_data.take_back(mr.loose_verts.size());
60
61 const BMesh &bm = *mr.bm;
62 threading::parallel_for(IndexRange(bm.totface), 2048, [&](const IndexRange range) {
63 for (const int face_index : range) {
64 const BMFace &face = *BM_face_at_index(&const_cast<BMesh &>(bm), face_index);
65 const BMLoop *loop = BM_FACE_FIRST_LOOP(&face);
66 for ([[maybe_unused]] const int i : IndexRange(face.len)) {
67 const int index = BM_elem_index_get(loop);
68 corners_data[index] = BM_elem_index_get(loop->v);
69 loop = loop->next;
70 }
71 }
72 });
73
74 const Span<int> loose_edges = mr.loose_edges;
75 threading::parallel_for(loose_edges.index_range(), 4096, [&](const IndexRange range) {
76 for (const int i : range) {
77 const BMEdge &edge = *BM_edge_at_index(&const_cast<BMesh &>(bm), loose_edges[i]);
78 loose_edge_data[i * 2 + 0] = BM_elem_index_get(edge.v1);
79 loose_edge_data[i * 2 + 1] = BM_elem_index_get(edge.v2);
80 }
81 });
82
83 array_utils::copy(mr.loose_verts, loose_vert_data);
84}
85
87{
90 extract_vert_index_mesh(mr, vbo->data<int>());
91 }
92 else {
93 extract_vert_index_bm(mr, vbo->data<int>());
94 }
95 return vbo;
96}
97
99{
100 MutableSpan corners_data = vbo_data.take_front(mr.corners_num);
101 MutableSpan loose_edge_data = vbo_data.slice(mr.corners_num, mr.loose_edges.size() * 2);
102
103 const Span<int> loose_edges = mr.loose_edges;
104 if (mr.orig_index_edge) {
105 const Span<int> orig_index_edge(mr.orig_index_edge, mr.edges_num);
106 array_utils::gather(orig_index_edge, mr.corner_edges, corners_data);
107 threading::parallel_for(loose_edges.index_range(), 4096, [&](const IndexRange range) {
108 for (const int i : range) {
109 loose_edge_data[i * 2 + 0] = orig_index_edge[loose_edges[i]];
110 loose_edge_data[i * 2 + 1] = orig_index_edge[loose_edges[i]];
111 }
112 });
113 }
114 else {
115 array_utils::copy(mr.corner_edges, corners_data);
116 threading::parallel_for(loose_edges.index_range(), 4096, [&](const IndexRange range) {
117 for (const int i : range) {
118 loose_edge_data[i * 2 + 0] = loose_edges[i];
119 loose_edge_data[i * 2 + 1] = loose_edges[i];
120 }
121 });
122 }
123}
124
126{
127 MutableSpan corners_data = vbo_data.take_front(mr.corners_num);
128 MutableSpan loose_edge_data = vbo_data.slice(mr.corners_num, mr.loose_edges.size() * 2);
129
130 const BMesh &bm = *mr.bm;
131 threading::parallel_for(IndexRange(bm.totface), 2048, [&](const IndexRange range) {
132 for (const int face_index : range) {
133 const BMFace &face = *BM_face_at_index(&const_cast<BMesh &>(bm), face_index);
134 const BMLoop *loop = BM_FACE_FIRST_LOOP(&face);
135 for ([[maybe_unused]] const int i : IndexRange(face.len)) {
136 const int index = BM_elem_index_get(loop);
137 corners_data[index] = BM_elem_index_get(loop->e);
138 loop = loop->next;
139 }
140 }
141 });
142
143 const Span<int> loose_edges = mr.loose_edges;
144 threading::parallel_for(loose_edges.index_range(), 4096, [&](const IndexRange range) {
145 for (const int i : range) {
146 loose_edge_data[i * 2 + 0] = loose_edges[i];
147 loose_edge_data[i * 2 + 1] = loose_edges[i];
148 }
149 });
150}
151
153{
156 extract_edge_index_mesh(mr, vbo->data<int>());
157 }
158 else {
159 extract_edge_index_bm(mr, vbo->data<int>());
160 }
161 return vbo;
162}
163
165{
166 const OffsetIndices faces = mr.faces;
167 if (mr.orig_index_face) {
168 const Span<int> orig_index_face(mr.orig_index_face, mr.edges_num);
169 threading::parallel_for(faces.index_range(), 2048, [&](const IndexRange range) {
170 for (const int face : range) {
171 vbo_data.slice(faces[face]).fill(orig_index_face[face]);
172 }
173 });
174 }
175 else {
177 }
178}
179
181{
182 const BMesh &bm = *mr.bm;
183 threading::parallel_for(IndexRange(bm.totface), 2048, [&](const IndexRange range) {
184 for (const int face_index : range) {
185 const BMFace &face = *BM_face_at_index(&const_cast<BMesh &>(bm), face_index);
186 const IndexRange face_range(BM_elem_index_get(BM_FACE_FIRST_LOOP(&face)), face.len);
187 vbo_data.slice(face_range).fill(face_index);
188 }
189 });
190}
191
193{
196 extract_face_index_mesh(mr, vbo->data<int>());
197 }
198 else {
199 extract_face_index_bm(mr, vbo->data<int>());
200 }
201 return vbo;
202}
203
205 const MeshRenderData &mr,
206 MutableSpan<int32_t> vbo_data)
207{
208 const Span<int> loose_verts = mr.loose_verts;
209 const Span<int> loose_edges = mr.loose_edges;
210 if (loose_edges.is_empty() && loose_verts.is_empty()) {
211 return;
212 }
213
214 const Span<int2> coarse_edges = mr.edges;
215 const int verts_per_edge = subdiv_verts_per_coarse_edge(subdiv_cache);
216 MutableSpan<int32_t> edge_data = vbo_data.slice(subdiv_cache.num_subdiv_loops,
217 loose_edges.size() * verts_per_edge);
218 for (const int i : loose_edges.index_range()) {
219 const int2 edge = coarse_edges[loose_edges[i]];
220 MutableSpan data = edge_data.slice(i * verts_per_edge, verts_per_edge);
221 data.first() = mr.orig_index_vert ? mr.orig_index_vert[edge[0]] : edge[0];
222 data.last() = mr.orig_index_vert ? mr.orig_index_vert[edge[1]] : edge[1];
223 }
224
225 MutableSpan<int32_t> loose_vert_data = vbo_data.take_back(loose_verts.size());
226 if (mr.orig_index_vert) {
227 array_utils::gather(Span(mr.orig_index_vert, mr.verts_num), loose_verts, loose_vert_data);
228 }
229 else {
230 array_utils::copy(loose_verts, loose_vert_data);
231 }
232}
233
235 const MeshRenderData &mr)
236{
237 /* Each element points to an element in the `ibo.points`. */
239 subdiv_cache.verts_orig_index->data<int32_t>().data(),
240 subdiv_cache.num_subdiv_loops,
241 subdiv_full_vbo_size(mr, subdiv_cache));
242 if (!mr.orig_index_vert) {
243 return vbo;
244 }
245
246 /* Remap the vertex indices to those pointed by the origin indices layer. At this point, the
247 * VBO data is a copy of #verts_orig_index which contains the coarse vertices indices, so
248 * the memory can both be accessed for lookup and immediately overwritten. */
249 MutableSpan vbo_data = vbo->data<int32_t>();
250 for (int i = 0; i < subdiv_cache.num_subdiv_loops; i++) {
251 if (vbo_data[i] == -1) {
252 continue;
253 }
254 vbo_data[i] = mr.orig_index_vert[vbo_data[i]];
255 }
256 extract_vert_idx_loose_geom_subdiv(subdiv_cache, mr, vbo_data);
257 return vbo;
258}
259
261 const MeshRenderData &mr,
262 MutableSpan<int32_t> vbo_data)
263{
264 const Span<int> loose_edges = mr.loose_edges;
265 if (loose_edges.is_empty()) {
266 return;
267 }
268
269 const int verts_per_edge = subdiv_verts_per_coarse_edge(subdiv_cache);
270 MutableSpan data = vbo_data.slice(subdiv_cache.num_subdiv_loops,
271 loose_edges.size() * verts_per_edge);
272 for (const int i : loose_edges.index_range()) {
273 const int edge = loose_edges[i];
274 const int index = mr.orig_index_edge ? mr.orig_index_edge[edge] : edge;
275 data.slice(i * verts_per_edge, verts_per_edge).fill(index);
276 }
277}
278
280 const MeshRenderData &mr)
281{
283 subdiv_cache.edges_orig_index->data<int32_t>().data(),
284 subdiv_cache.num_subdiv_loops,
285 subdiv_loose_edges_num(mr, subdiv_cache) * 2);
286 extract_edge_idx_loose_geom_subdiv(subdiv_cache, mr, vbo->data<int32_t>());
287 return vbo;
288}
289
291 const MeshRenderData &mr)
292{
294 subdiv_cache.subdiv_loop_face_index, subdiv_cache.num_subdiv_loops, 0);
295
296 if (!mr.orig_index_face) {
297 return vbo;
298 }
299
300 /* Remap the face indices to those pointed by the origin indices layer. At this point, the
301 * VBO data is a copy of #subdiv_loop_face_index which contains the coarse face indices, so
302 * the memory can both be accessed for lookup and immediately overwritten. */
303 MutableSpan vbo_data = vbo->data<int32_t>();
304 for (int i = 0; i < subdiv_cache.num_subdiv_loops; i++) {
305 vbo_data[i] = mr.orig_index_face[vbo_data[i]];
306 }
307 return vbo;
308}
309
311{
314 if (mr.orig_index_face) {
315 const Span<int> orig_index_face(mr.orig_index_face, mr.faces_num);
316 array_utils::copy(orig_index_face, vbo->data<int>());
317 }
318 else {
319 array_utils::fill_index_range(vbo->data<int>());
320 }
321 }
322 else {
323 array_utils::fill_index_range(vbo->data<int>());
324 }
325 return vbo;
326}
327
328} // namespace blender::draw
static blender::gpu::VertBuf * GPU_vertbuf_create_with_format(const GPUVertFormat &format)
void GPU_vertbuf_data_alloc(blender::gpu::VertBuf &verts, uint v_len)
GPUVertFormat GPU_vertformat_from_attribute(blender::StringRef name, blender::gpu::VertAttrType type)
BMesh const char void * data
BMesh * bm
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
constexpr int64_t size() const
Definition BLI_span.hh:252
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
Definition BLI_span.hh:573
constexpr MutableSpan take_back(const int64_t n) const
Definition BLI_span.hh:640
constexpr T * data() const
Definition BLI_span.hh:539
constexpr MutableSpan take_front(const int64_t n) const
Definition BLI_span.hh:629
constexpr const T * data() const
Definition BLI_span.hh:215
constexpr int64_t size() const
Definition BLI_span.hh:252
constexpr IndexRange index_range() const
Definition BLI_span.hh:401
constexpr bool is_empty() const
Definition BLI_span.hh:260
MutableSpan< T > data()
Extraction of Mesh data into VBO to feed to GPU.
format
static char faces[256]
void copy(const GVArray &src, GMutableSpan dst, int64_t grain_size=4096)
void gather(const GVArray &src, const IndexMask &indices, GMutableSpan dst, int64_t grain_size=4096)
void fill_index_range(MutableSpan< T > span, const T start=0)
int subdiv_loose_edges_num(const MeshRenderData &mr, const DRWSubdivCache &cache)
static void extract_vert_index_bm(const MeshRenderData &mr, MutableSpan< int > vbo_data)
static void extract_face_index_bm(const MeshRenderData &mr, MutableSpan< int > vbo_data)
int subdiv_verts_per_coarse_edge(const DRWSubdivCache &cache)
gpu::VertBufPtr extract_edge_index(const MeshRenderData &mr)
gpu::VertBufPtr draw_subdiv_init_origindex_buffer(int32_t *vert_origindex, uint num_loops, uint loose_len)
gpu::VertBufPtr extract_vert_index_subdiv(const DRWSubdivCache &subdiv_cache, const MeshRenderData &mr)
gpu::VertBufPtr extract_face_dot_index(const MeshRenderData &mr)
static gpu::VertBufPtr create_vbo(const int size)
static void extract_edge_index_bm(const MeshRenderData &mr, MutableSpan< int > vbo_data)
int subdiv_full_vbo_size(const MeshRenderData &mr, const DRWSubdivCache &cache)
gpu::VertBufPtr extract_face_index_subdiv(const DRWSubdivCache &subdiv_cache, const MeshRenderData &mr)
static void extract_vert_index_mesh(const MeshRenderData &mr, MutableSpan< int > vbo_data)
gpu::VertBufPtr extract_edge_index_subdiv(const DRWSubdivCache &subdiv_cache, const MeshRenderData &mr)
static void extract_edge_idx_loose_geom_subdiv(const DRWSubdivCache &subdiv_cache, const MeshRenderData &mr, MutableSpan< int32_t > vbo_data)
static void extract_edge_index_mesh(const MeshRenderData &mr, MutableSpan< int > vbo_data)
static void extract_vert_idx_loose_geom_subdiv(const DRWSubdivCache &subdiv_cache, const MeshRenderData &mr, MutableSpan< int32_t > vbo_data)
gpu::VertBufPtr extract_vert_index(const MeshRenderData &mr)
void extract_mesh_loose_edge_data(const Span< T > vert_data, const Span< int2 > edges, const Span< int > loose_edges, MutableSpan< T > gpu_data)
gpu::VertBufPtr extract_face_index(const MeshRenderData &mr)
static void extract_face_index_mesh(const MeshRenderData &mr, MutableSpan< int > vbo_data)
std::unique_ptr< gpu::VertBuf, gpu::VertBufDeleter > VertBufPtr
void build_reverse_map(OffsetIndices< int > offsets, MutableSpan< int > r_map)
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< int32_t, 2 > int2
OffsetIndices< int > faces
i
Definition text_draw.cc:230