Blender V4.5
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
24
25/* TODO: Use #glVertexID to get loop index and use the data structure on the CPU to retrieve the
26 * select element associated with this loop ID. This would remove the need for this separate
27 * index VBO's. We could upload the p/e/orig_index_vert as a buffer texture and sample it inside
28 * the shader to output original index. */
29
31{
32 MutableSpan corners_data = vbo_data.take_front(mr.corners_num);
33 MutableSpan loose_edge_data = vbo_data.slice(mr.corners_num, mr.loose_edges.size() * 2);
34 MutableSpan loose_vert_data = vbo_data.take_back(mr.loose_verts.size());
35
36 if (mr.orig_index_vert) {
37 const Span<int> orig_index_vert(mr.orig_index_vert, mr.verts_num);
38 array_utils::gather(orig_index_vert, mr.corner_verts, corners_data);
39 extract_mesh_loose_edge_data(orig_index_vert, mr.edges, mr.loose_edges, loose_edge_data);
40 array_utils::gather(orig_index_vert, mr.loose_verts, loose_vert_data);
41 }
42 else {
43 array_utils::copy(mr.corner_verts, corners_data);
44 const Span<int2> edges = mr.edges;
45 const Span<int> loose_edges = mr.loose_edges;
46 threading::parallel_for(loose_edges.index_range(), 4096, [&](const IndexRange range) {
47 for (const int i : range) {
48 loose_edge_data[i * 2 + 0] = edges[loose_edges[i]][0];
49 loose_edge_data[i * 2 + 1] = edges[loose_edges[i]][1];
50 }
51 });
52 array_utils::copy(mr.loose_verts, loose_vert_data);
53 }
54}
55
57{
58 MutableSpan corners_data = vbo_data.take_front(mr.corners_num);
59 MutableSpan loose_edge_data = vbo_data.slice(mr.corners_num, mr.loose_edges.size() * 2);
60 MutableSpan loose_vert_data = vbo_data.take_back(mr.loose_verts.size());
61
62 const BMesh &bm = *mr.bm;
63 threading::parallel_for(IndexRange(bm.totface), 2048, [&](const IndexRange range) {
64 for (const int face_index : range) {
65 const BMFace &face = *BM_face_at_index(&const_cast<BMesh &>(bm), face_index);
66 const BMLoop *loop = BM_FACE_FIRST_LOOP(&face);
67 for ([[maybe_unused]] const int i : IndexRange(face.len)) {
68 const int index = BM_elem_index_get(loop);
69 corners_data[index] = BM_elem_index_get(loop->v);
70 loop = loop->next;
71 }
72 }
73 });
74
75 const Span<int> loose_edges = mr.loose_edges;
76 threading::parallel_for(loose_edges.index_range(), 4096, [&](const IndexRange range) {
77 for (const int i : range) {
78 const BMEdge &edge = *BM_edge_at_index(&const_cast<BMesh &>(bm), loose_edges[i]);
79 loose_edge_data[i * 2 + 0] = BM_elem_index_get(edge.v1);
80 loose_edge_data[i * 2 + 1] = BM_elem_index_get(edge.v2);
81 }
82 });
83
84 array_utils::copy(mr.loose_verts, loose_vert_data);
85}
86
88{
91 extract_vert_index_mesh(mr, vbo->data<int>());
92 }
93 else {
94 extract_vert_index_bm(mr, vbo->data<int>());
95 }
96 return vbo;
97}
98
100{
101 MutableSpan corners_data = vbo_data.take_front(mr.corners_num);
102 MutableSpan loose_edge_data = vbo_data.slice(mr.corners_num, mr.loose_edges.size() * 2);
103
104 const Span<int> loose_edges = mr.loose_edges;
105 if (mr.orig_index_edge) {
106 const Span<int> orig_index_edge(mr.orig_index_edge, mr.edges_num);
107 array_utils::gather(orig_index_edge, mr.corner_edges, corners_data);
108 threading::parallel_for(loose_edges.index_range(), 4096, [&](const IndexRange range) {
109 for (const int i : range) {
110 loose_edge_data[i * 2 + 0] = orig_index_edge[loose_edges[i]];
111 loose_edge_data[i * 2 + 1] = orig_index_edge[loose_edges[i]];
112 }
113 });
114 }
115 else {
116 array_utils::copy(mr.corner_edges, corners_data);
117 threading::parallel_for(loose_edges.index_range(), 4096, [&](const IndexRange range) {
118 for (const int i : range) {
119 loose_edge_data[i * 2 + 0] = loose_edges[i];
120 loose_edge_data[i * 2 + 1] = loose_edges[i];
121 }
122 });
123 }
124}
125
127{
128 MutableSpan corners_data = vbo_data.take_front(mr.corners_num);
129 MutableSpan loose_edge_data = vbo_data.slice(mr.corners_num, mr.loose_edges.size() * 2);
130
131 const BMesh &bm = *mr.bm;
132 threading::parallel_for(IndexRange(bm.totface), 2048, [&](const IndexRange range) {
133 for (const int face_index : range) {
134 const BMFace &face = *BM_face_at_index(&const_cast<BMesh &>(bm), face_index);
135 const BMLoop *loop = BM_FACE_FIRST_LOOP(&face);
136 for ([[maybe_unused]] const int i : IndexRange(face.len)) {
137 const int index = BM_elem_index_get(loop);
138 corners_data[index] = BM_elem_index_get(loop->e);
139 loop = loop->next;
140 }
141 }
142 });
143
144 const Span<int> loose_edges = mr.loose_edges;
145 threading::parallel_for(loose_edges.index_range(), 4096, [&](const IndexRange range) {
146 for (const int i : range) {
147 loose_edge_data[i * 2 + 0] = loose_edges[i];
148 loose_edge_data[i * 2 + 1] = loose_edges[i];
149 }
150 });
151}
152
154{
157 extract_edge_index_mesh(mr, vbo->data<int>());
158 }
159 else {
160 extract_edge_index_bm(mr, vbo->data<int>());
161 }
162 return vbo;
163}
164
166{
167 const OffsetIndices faces = mr.faces;
168 if (mr.orig_index_face) {
169 const Span<int> orig_index_face(mr.orig_index_face, mr.edges_num);
170 threading::parallel_for(faces.index_range(), 2048, [&](const IndexRange range) {
171 for (const int face : range) {
172 vbo_data.slice(faces[face]).fill(orig_index_face[face]);
173 }
174 });
175 }
176 else {
178 }
179}
180
182{
183 const BMesh &bm = *mr.bm;
184 threading::parallel_for(IndexRange(bm.totface), 2048, [&](const IndexRange range) {
185 for (const int face_index : range) {
186 const BMFace &face = *BM_face_at_index(&const_cast<BMesh &>(bm), face_index);
187 const IndexRange face_range(BM_elem_index_get(BM_FACE_FIRST_LOOP(&face)), face.len);
188 vbo_data.slice(face_range).fill(face_index);
189 }
190 });
191}
192
194{
197 extract_face_index_mesh(mr, vbo->data<int>());
198 }
199 else {
200 extract_face_index_bm(mr, vbo->data<int>());
201 }
202 return vbo;
203}
204
206 const MeshRenderData &mr,
207 MutableSpan<int32_t> vbo_data)
208{
209 const Span<int> loose_verts = mr.loose_verts;
210 const Span<int> loose_edges = mr.loose_edges;
211 if (loose_edges.is_empty() && loose_verts.is_empty()) {
212 return;
213 }
214
215 const Span<int2> coarse_edges = mr.edges;
216 const int verts_per_edge = subdiv_verts_per_coarse_edge(subdiv_cache);
217 MutableSpan<int32_t> edge_data = vbo_data.slice(subdiv_cache.num_subdiv_loops,
218 loose_edges.size() * verts_per_edge);
219 for (const int i : loose_edges.index_range()) {
220 const int2 edge = coarse_edges[loose_edges[i]];
221 MutableSpan data = edge_data.slice(i * verts_per_edge, verts_per_edge);
222 data.first() = mr.orig_index_vert ? mr.orig_index_vert[edge[0]] : edge[0];
223 data.last() = mr.orig_index_vert ? mr.orig_index_vert[edge[1]] : edge[1];
224 }
225
226 MutableSpan<int32_t> loose_vert_data = vbo_data.take_back(loose_verts.size());
227 if (mr.orig_index_vert) {
228 array_utils::gather(Span(mr.orig_index_vert, mr.verts_num), loose_verts, loose_vert_data);
229 }
230 else {
231 array_utils::copy(loose_verts, loose_vert_data);
232 }
233}
234
236 const MeshRenderData &mr)
237{
238 /* Each element points to an element in the `ibo.points`. */
240 subdiv_cache.verts_orig_index->data<int32_t>().data(),
241 subdiv_cache.num_subdiv_loops,
242 subdiv_full_vbo_size(mr, subdiv_cache));
243 if (!mr.orig_index_vert) {
244 return vbo;
245 }
246
247 /* Remap the vertex indices to those pointed by the origin indices layer. At this point, the
248 * VBO data is a copy of #verts_orig_index which contains the coarse vertices indices, so
249 * the memory can both be accessed for lookup and immediately overwritten. */
250 MutableSpan vbo_data = vbo->data<int32_t>();
251 for (int i = 0; i < subdiv_cache.num_subdiv_loops; i++) {
252 if (vbo_data[i] == -1) {
253 continue;
254 }
255 vbo_data[i] = mr.orig_index_vert[vbo_data[i]];
256 }
257 extract_vert_idx_loose_geom_subdiv(subdiv_cache, mr, vbo_data);
258 return vbo;
259}
260
262 const MeshRenderData &mr,
263 MutableSpan<int32_t> vbo_data)
264{
265 const Span<int> loose_edges = mr.loose_edges;
266 if (loose_edges.is_empty()) {
267 return;
268 }
269
270 const int verts_per_edge = subdiv_verts_per_coarse_edge(subdiv_cache);
271 MutableSpan data = vbo_data.slice(subdiv_cache.num_subdiv_loops,
272 loose_edges.size() * verts_per_edge);
273 for (const int i : loose_edges.index_range()) {
274 const int edge = loose_edges[i];
275 const int index = mr.orig_index_edge ? mr.orig_index_edge[edge] : edge;
276 data.slice(i * verts_per_edge, verts_per_edge).fill(index);
277 }
278}
279
281 const MeshRenderData &mr)
282{
284 subdiv_cache.edges_orig_index->data<int32_t>().data(),
285 subdiv_cache.num_subdiv_loops,
286 subdiv_loose_edges_num(mr, subdiv_cache) * 2);
287 extract_edge_idx_loose_geom_subdiv(subdiv_cache, mr, vbo->data<int32_t>());
288 return vbo;
289}
290
292 const MeshRenderData &mr)
293{
295 subdiv_cache.subdiv_loop_face_index, subdiv_cache.num_subdiv_loops, 0);
296
297 if (!mr.orig_index_face) {
298 return vbo;
299 }
300
301 /* Remap the face indices to those pointed by the origin indices layer. At this point, the
302 * VBO data is a copy of #subdiv_loop_face_index which contains the coarse face indices, so
303 * the memory can both be accessed for lookup and immediately overwritten. */
304 MutableSpan vbo_data = vbo->data<int32_t>();
305 for (int i = 0; i < subdiv_cache.num_subdiv_loops; i++) {
306 vbo_data[i] = mr.orig_index_face[vbo_data[i]];
307 }
308 return vbo;
309}
310
312{
315 if (mr.orig_index_face) {
316 const Span<int> orig_index_face(mr.orig_index_face, mr.faces_num);
317 array_utils::copy(orig_index_face, vbo->data<int>());
318 }
319 else {
320 array_utils::fill_index_range(vbo->data<int>());
321 }
322 }
323 else {
324 array_utils::fill_index_range(vbo->data<int>());
325 }
326 return vbo;
327}
328
329} // namespace blender::draw
#define GPU_vertbuf_create_with_format(format)
void GPU_vertbuf_data_alloc(blender::gpu::VertBuf &verts, uint v_len)
@ GPU_FETCH_INT
GPUVertFormat GPU_vertformat_from_attribute(blender::StringRef name, const GPUVertCompType comp_type, const uint comp_len, const GPUVertFetchMode fetch_mode)
@ GPU_COMP_I32
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