Blender V5.0
extract_mesh_ibo_edituv.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 "BKE_editmesh.hh"
10
11#include "BLI_math_geom.h"
12
13#include "extract_mesh.hh"
14
15#include "GPU_index_buffer.hh"
16
17#include "draw_subdivision.hh"
18
19namespace blender::draw {
20
21/* ---------------------------------------------------------------------- */
24
25inline bool skip_bm_face(const BMFace &face, const bool sync_selection)
26{
28 return true;
29 }
30 if (!sync_selection) {
32 return true;
33 }
34 }
35 return false;
36}
37
39{
40 r_offset_data.reinitialize(bm.totface + 1);
41 threading::parallel_for(IndexRange(bm.totface), 4096, [&](const IndexRange range) {
42 for (const int face : range) {
43 r_offset_data[face] = BM_face_at_index(&const_cast<BMesh &>(bm), face)->len;
44 }
45 });
47}
48
49static gpu::IndexBufPtr extract_edituv_tris_bm(const MeshRenderData &mr, const bool sync_selection)
50{
52 const BMesh &bm = *mr.bm;
53
54 IndexMaskMemory memory;
55 const IndexMask selection = IndexMask::from_predicate(
56 IndexRange(bm.totface), GrainSize(4096), memory, [&](const int face) {
57 return !skip_bm_face(*BM_face_at_index(&const_cast<BMesh &>(bm), face), sync_selection);
58 });
59
60 if (selection.size() == bm.totface) {
61 GPUIndexBufBuilder builder;
62 GPU_indexbuf_init(&builder, GPU_PRIM_TRIS, looptris.size(), mr.corners_num);
64 threading::parallel_for(looptris.index_range(), 4096, [&](const IndexRange range) {
65 for (const int i : range) {
66 data[i] = uint3(BM_elem_index_get(looptris[i][0]),
67 BM_elem_index_get(looptris[i][1]),
68 BM_elem_index_get(looptris[i][2]));
69 }
70 });
71 return gpu::IndexBufPtr(GPU_indexbuf_build_ex(&builder, 0, mr.corners_num, false));
72 }
73
74 Array<int> face_offset_data;
75 const OffsetIndices faces = build_bmesh_face_offsets(bm, face_offset_data);
76
77 Array<int> selected_face_offset_data(selection.size() + 1);
79 faces, selection, selected_face_offset_data);
80
81 const int tris_num = poly_to_tri_count(selected_faces.size(), selected_faces.total_size());
82
83 GPUIndexBufBuilder builder;
84 GPU_indexbuf_init(&builder, GPU_PRIM_TRIS, tris_num, mr.corners_num);
86
87 selection.foreach_index(GrainSize(4096), [&](const int face, const int mask) {
89 const IndexRange ibo_tris = bke::mesh::face_triangles_range(selected_faces, mask);
90 for (const int i : tris.index_range()) {
91 data[ibo_tris[i]] = uint3(BM_elem_index_get(looptris[tris[i]][0]),
92 BM_elem_index_get(looptris[tris[i]][1]),
93 BM_elem_index_get(looptris[tris[i]][2]));
94 }
95 });
96
97 return gpu::IndexBufPtr(GPU_indexbuf_build_ex(&builder, 0, mr.corners_num, false));
98}
99
101 const bool sync_selection)
102{
103 const OffsetIndices faces = mr.faces;
104 const Span<int3> corner_tris = mr.mesh->corner_tris();
105
106 IndexMaskMemory memory;
107 IndexMask selection;
108 if (mr.bm) {
109 selection = IndexMask::from_predicate(
110 faces.index_range(), GrainSize(4096), memory, [&](const int face) {
111 const BMFace *face_orig = bm_original_face_get(mr, face);
112 if (!face_orig) {
113 return false;
114 }
115 if (skip_bm_face(*face_orig, sync_selection)) {
116 return false;
117 }
118 return true;
119 });
120 }
121 else {
122 if (mr.hide_poly.is_empty()) {
123 selection = faces.index_range();
124 }
125 else {
126 selection = IndexMask::from_bools_inverse(faces.index_range(), mr.hide_poly, memory);
127 }
128
129 if (!sync_selection && !mr.select_poly.is_empty()) {
130 selection = IndexMask::from_bools(selection, mr.select_poly, memory);
131 }
132 }
133
134 if (selection.size() == faces.size()) {
136 corner_tris.cast<uint32_t>().data(),
137 corner_tris.size(),
138 0,
139 mr.corners_num,
140 false));
141 }
142
143 Array<int> selected_face_offset_data(selection.size() + 1);
145 faces, selection, selected_face_offset_data);
146
147 const int tris_num = poly_to_tri_count(selected_faces.size(), selected_faces.total_size());
148
149 GPUIndexBufBuilder builder;
150 GPU_indexbuf_init(&builder, GPU_PRIM_TRIS, tris_num, mr.corners_num);
152
153 selection.foreach_index(GrainSize(4096), [&](const int face, const int mask) {
155 const IndexRange ibo_tris = bke::mesh::face_triangles_range(selected_faces, mask);
156 for (const int i : tris.index_range()) {
157 data[ibo_tris[i]] = uint3(
158 corner_tris[tris[i]][0], corner_tris[tris[i]][1], corner_tris[tris[i]][2]);
159 }
160 });
161
162 return gpu::IndexBufPtr(GPU_indexbuf_build_ex(&builder, 0, mr.corners_num, false));
163}
164
166{
167 const bool sync_selection = edit_uvs ? (mr.toolsettings->uv_flag & UV_FLAG_SELECT_SYNC) : false;
169 return extract_edituv_tris_bm(mr, sync_selection);
170 }
171 return extract_edituv_tris_mesh(mr, sync_selection);
172}
173
175 const IndexMask &selection)
176{
177 const int tris_num = selection.size() * 2;
178
179 GPUIndexBufBuilder builder;
180 GPU_indexbuf_init(&builder, GPU_PRIM_TRIS, tris_num, subdiv_cache.num_subdiv_loops);
182
183 selection.foreach_index(GrainSize(4096), [&](const int subdiv_quad_index, const int mask) {
184 const uint corner_start = subdiv_quad_index * 4;
185 data[mask * 2 + 0] = uint3(corner_start, corner_start + 1, corner_start + 2);
186 data[mask * 2 + 1] = uint3(corner_start, corner_start + 2, corner_start + 3);
187 });
188
189 return gpu::IndexBufPtr(
190 GPU_indexbuf_build_ex(&builder, 0, subdiv_cache.num_subdiv_loops, false));
191}
192
194 const DRWSubdivCache &subdiv_cache,
195 const bool sync_selection)
196{
197 const BMesh &bm = *mr.bm;
198 const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index,
199 subdiv_cache.num_subdiv_loops);
200
201 IndexMaskMemory memory;
202 const IndexMask selection = IndexMask::from_predicate(
203 IndexRange(subdiv_cache.num_subdiv_quads),
204 GrainSize(4096),
205 memory,
206 [&](const int subdiv_quad_index) {
207 const uint corner_start = subdiv_quad_index * 4;
208 const int coarse_face = subdiv_loop_face_index[corner_start];
209 const BMFace &bm_face = *BM_face_at_index(&const_cast<BMesh &>(bm), coarse_face);
210 return !skip_bm_face(bm_face, sync_selection);
211 });
212
213 return build_tris_from_subdiv_quad_selection(subdiv_cache, selection);
214}
215
217 const DRWSubdivCache &subdiv_cache,
218 const bool sync_selection)
219{
220 const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index,
221 subdiv_cache.num_subdiv_loops);
222
223 IndexMaskMemory memory;
224 const IndexMask selection = IndexMask::from_predicate(
225 IndexRange(subdiv_cache.num_subdiv_quads),
226 GrainSize(4096),
227 memory,
228 [&](const int subdiv_quad_index) {
229 const uint corner_start = subdiv_quad_index * 4;
230 const int coarse_face = subdiv_loop_face_index[corner_start];
231 const BMFace *face_orig = bm_original_face_get(mr, coarse_face);
232 if (!face_orig) {
233 return false;
234 }
235 if (skip_bm_face(*face_orig, sync_selection)) {
236 return false;
237 }
238 return true;
239 });
240
241 return build_tris_from_subdiv_quad_selection(subdiv_cache, selection);
242}
243
245 const DRWSubdivCache &subdiv_cache)
246{
247 const bool sync_selection = (mr.toolsettings->uv_flag & UV_FLAG_SELECT_SYNC) != 0;
249 return extract_edituv_tris_subdiv_bm(mr, subdiv_cache, sync_selection);
250 }
251 return extract_edituv_tris_subdiv_mesh(mr, subdiv_cache, sync_selection);
252}
253
255
256/* ---------------------------------------------------------------------- */
259
261 const bool sync_selection)
262{
263 GPUIndexBufBuilder builder;
266 int line_index = 0;
267
268 const BMFace *face;
269 BMIter f_iter;
270 BM_ITER_MESH (face, &f_iter, mr.bm, BM_FACES_OF_MESH) {
271 if (skip_bm_face(*face, sync_selection)) {
272 continue;
273 }
274 const BMLoop *loop = BM_FACE_FIRST_LOOP(face);
275 for ([[maybe_unused]] const int i : IndexRange(face->len)) {
276 data[line_index++] = uint2(BM_elem_index_get(loop), BM_elem_index_get(loop->next));
277 loop = loop->next;
278 }
279 }
280
281 /* Only upload the part of the index buffer that is used. Alternatively it might be beneficial to
282 * count the number of visible edges first, especially if that allows parallelizing filling the
283 * data array. */
284 builder.index_len = line_index * 2;
285 builder.index_min = 0;
286 builder.index_max = mr.corners_num;
287 builder.uses_restart_indices = false;
289 GPU_indexbuf_build_in_place(&builder, result.get());
290 return result;
291}
292
294 const bool sync_selection)
295{
296 const OffsetIndices faces = mr.faces;
297 const Span<int> corner_edges = mr.corner_edges;
298 const Span<int> orig_index_edge = mr.orig_index_edge ?
300 Span<int>();
301
302 GPUIndexBufBuilder builder;
305 int line_index = 0;
306
307 if (mr.bm) {
308 for (const int face_index : faces.index_range()) {
309 const IndexRange face = faces[face_index];
310 const BMFace *face_orig = bm_original_face_get(mr, face_index);
311 if (!face_orig) {
312 continue;
313 }
314 if (skip_bm_face(*face_orig, sync_selection)) {
315 continue;
316 }
317 for (const int corner : face) {
318 const int edge = corner_edges[corner];
319 if (!orig_index_edge.is_empty() && orig_index_edge[edge] == ORIGINDEX_NONE) {
320 continue;
321 }
322 data[line_index++] = edge_from_corners(face, corner);
323 }
324 }
325 }
326 else {
327 IndexMaskMemory memory;
328 IndexMask visible = faces.index_range();
329 if (!mr.hide_poly.is_empty()) {
330 visible = IndexMask::from_bools_inverse(visible, mr.hide_poly, memory);
331 }
332 if (!sync_selection) {
333 if (mr.select_poly.is_empty()) {
334 visible = {};
335 }
336 else {
337 visible = IndexMask::from_bools(visible, mr.select_poly, memory);
338 }
339 }
340 visible.foreach_index([&](const int face_index) {
341 const IndexRange face = faces[face_index];
342 for (const int corner : face) {
343 const int edge = corner_edges[corner];
344 if (!orig_index_edge.is_empty() && orig_index_edge[edge] == ORIGINDEX_NONE) {
345 continue;
346 }
347 data[line_index++] = edge_from_corners(face, corner);
348 }
349 });
350 }
351
352 /* Only upload the part of the index buffer that is used. Alternatively it might be beneficial to
353 * count the number of visible edges first, especially if that allows parallelizing filling the
354 * data array. */
355 builder.index_len = line_index * 2;
356 builder.index_min = 0;
357 builder.index_max = mr.corners_num;
358 builder.uses_restart_indices = false;
360 GPU_indexbuf_build_in_place(&builder, result.get());
361 return result;
362}
363
365{
366 bool sync_selection = false;
367 switch (mode) {
369 sync_selection = true;
370 break;
372 sync_selection = ((mr.toolsettings->uv_flag & UV_FLAG_SELECT_SYNC) != 0);
373 break;
375 sync_selection = false;
376 break;
377 }
378
380 return extract_edituv_lines_bm(mr, sync_selection);
381 }
382 return extract_edituv_lines_mesh(mr, sync_selection);
383}
384
386 const DRWSubdivCache &subdiv_cache,
387 const bool sync_selection)
388{
389 const BMesh &bm = *mr.bm;
390 const Span<int> subdiv_loop_edge_index = subdiv_cache.edges_orig_index->data<int>();
391 const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index,
392 subdiv_cache.num_subdiv_loops);
393
394 GPUIndexBufBuilder builder;
396 &builder, GPU_PRIM_LINES, subdiv_cache.num_subdiv_loops, subdiv_cache.num_subdiv_loops);
398 int line_index = 0;
399
400 for (const int subdiv_quad : IndexRange(subdiv_cache.num_subdiv_quads)) {
401 const int coarse_face = subdiv_loop_face_index[subdiv_quad * 4];
402 const BMFace &face_orig = *BM_face_at_index(&const_cast<BMesh &>(bm), coarse_face);
403 if (skip_bm_face(face_orig, sync_selection)) {
404 continue;
405 }
406 const IndexRange subdiv_face(subdiv_quad * 4, 4);
407 for (const int subdiv_corner : subdiv_face) {
408 const int coarse_edge = subdiv_loop_edge_index[subdiv_corner];
409 if (coarse_edge == -1) {
410 continue;
411 }
412 data[line_index++] = edge_from_corners(subdiv_face, subdiv_corner);
413 }
414 }
415
416 return gpu::IndexBufPtr(
417 GPU_indexbuf_build_ex(&builder, 0, subdiv_cache.num_subdiv_loops, false));
418}
419
421 const DRWSubdivCache &subdiv_cache,
422 const bool sync_selection)
423{
424 GPUIndexBufBuilder builder;
426 &builder, GPU_PRIM_LINES, subdiv_cache.num_subdiv_loops, subdiv_cache.num_subdiv_loops);
428 int line_index = 0;
429
430 /* NOTE: #subdiv_loop_edge_index already has the #CD_ORIGINDEX layer baked in. */
431 const Span<int> subdiv_loop_edge_index = subdiv_cache.edges_orig_index->data<int>();
432 const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index,
433 subdiv_cache.num_subdiv_loops);
434 /* TODO: Replace subdiv quad iteration with coarse face iteration. */
435 for (const int subdiv_quad : IndexRange(subdiv_cache.num_subdiv_quads)) {
436 const int coarse_face = subdiv_loop_face_index[subdiv_quad * 4];
437 if (const BMesh *bm = mr.bm) {
438 const int orig_coarse_face = mr.orig_index_face ? mr.orig_index_face[coarse_face] :
439 coarse_face;
440 const BMFace &face_orig = *BM_face_at_index(const_cast<BMesh *>(bm), orig_coarse_face);
441 if (skip_bm_face(face_orig, sync_selection)) {
442 continue;
443 }
444 }
445 else {
446 if (!mr.hide_poly.is_empty() && mr.hide_poly[coarse_face]) {
447 continue;
448 }
449 if (!sync_selection) {
450 if (mr.select_poly.is_empty() || !mr.select_poly[coarse_face]) {
451 continue;
452 }
453 }
454 }
455 const IndexRange subdiv_face(subdiv_quad * 4, 4);
456 for (const int subdiv_corner : subdiv_face) {
457 const int coarse_edge = subdiv_loop_edge_index[subdiv_corner];
458 if (coarse_edge == -1) {
459 continue;
460 }
461 data[line_index++] = edge_from_corners(subdiv_face, subdiv_corner);
462 }
463 }
464
465 /* Only upload the part of the index buffer that is used. Alternatively it might be beneficial to
466 * count the number of visible edges first, especially if that allows parallelizing filling the
467 * data array. */
468 builder.index_len = line_index * 2;
469 builder.index_min = 0;
470 builder.index_max = subdiv_cache.num_subdiv_loops;
471 builder.uses_restart_indices = false;
473 GPU_indexbuf_build_in_place(&builder, result.get());
474 return result;
475}
476
478 const DRWSubdivCache &subdiv_cache,
479 const UvExtractionMode mode)
480{
481 bool sync_selection = false;
482 switch (mode) {
484 sync_selection = true;
485 break;
487 sync_selection = ((mr.toolsettings->uv_flag & UV_FLAG_SELECT_SYNC) != 0);
488 break;
490 sync_selection = false;
491 break;
492 }
493
495 return extract_edituv_lines_subdiv_bm(mr, subdiv_cache, sync_selection);
496 }
497 return extract_edituv_lines_subdiv_mesh(mr, subdiv_cache, sync_selection);
498}
499
501
502/* ---------------------------------------------------------------------- */
505
507 const bool sync_selection,
508 GPUIndexBufBuilder &builder)
509{
510 const BMesh &bm = *mr.bm;
511 const BMFace *face;
512 BMIter f_iter;
513 BM_ITER_MESH (face, &f_iter, &const_cast<BMesh &>(bm), BM_FACES_OF_MESH) {
514 if (skip_bm_face(*face, sync_selection)) {
515 continue;
516 }
517 const BMLoop *loop = BM_FACE_FIRST_LOOP(face);
518 for ([[maybe_unused]] const int i : IndexRange(face->len)) {
520 loop = loop->next;
521 }
522 }
523}
524
526 const bool sync_selection,
527 GPUIndexBufBuilder &builder)
528{
529 const OffsetIndices faces = mr.faces;
530 const Span<int> corner_verts = mr.corner_verts;
531 const Span<int> orig_index_vert = mr.orig_index_vert ?
533 Span<int>();
534 for (const int face_index : faces.index_range()) {
535 const BMFace *face_orig = bm_original_face_get(mr, face_index);
536 if (!face_orig) {
537 continue;
538 }
539 if (skip_bm_face(*face_orig, sync_selection)) {
540 continue;
541 }
542 for (const int corner : faces[face_index]) {
543 const int vert = corner_verts[corner];
544 if (!orig_index_vert.is_empty() && orig_index_vert[vert] == ORIGINDEX_NONE) {
545 continue;
546 }
547 GPU_indexbuf_add_point_vert(&builder, corner);
548 }
549 }
550}
551
553{
554 const bool sync_selection = (mr.toolsettings->uv_flag & UV_FLAG_SELECT_SYNC) != 0;
555
556 GPUIndexBufBuilder builder;
559 extract_edituv_points_bm(mr, sync_selection, builder);
560 }
561 else {
562 extract_edituv_points_mesh(mr, sync_selection, builder);
563 }
564 return gpu::IndexBufPtr(GPU_indexbuf_build(&builder));
565}
566
568 const DRWSubdivCache &subdiv_cache,
569 const bool sync_selection,
570 GPUIndexBufBuilder &builder)
571{
572 const BMesh &bm = *mr.bm;
573 const Span<int> subdiv_loop_vert_index = subdiv_cache.verts_orig_index->data<int>();
574 const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index,
575 subdiv_cache.num_subdiv_loops);
576
577 for (const int subdiv_quad : IndexRange(subdiv_cache.num_subdiv_quads)) {
578 const int coarse_face = subdiv_loop_face_index[subdiv_quad * 4];
579 const BMFace &face_orig = *BM_face_at_index(&const_cast<BMesh &>(bm), coarse_face);
580 if (skip_bm_face(face_orig, sync_selection)) {
581 continue;
582 }
583 for (const int subdiv_corner : IndexRange(subdiv_quad * 4, 4)) {
584 const int coarse_vert = subdiv_loop_vert_index[subdiv_corner];
585 if (coarse_vert == -1) {
586 continue;
587 }
588 GPU_indexbuf_add_point_vert(&builder, subdiv_corner);
589 }
590 }
591}
592
594 const DRWSubdivCache &subdiv_cache,
595 const bool sync_selection,
596 GPUIndexBufBuilder &builder)
597{
598 const Span<int> subdiv_loop_vert_index = subdiv_cache.verts_orig_index->data<int>();
599 const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index,
600 subdiv_cache.num_subdiv_loops);
601
602 for (const int subdiv_quad : IndexRange(subdiv_cache.num_subdiv_quads)) {
603 const int coarse_face = subdiv_loop_face_index[subdiv_quad * 4];
604 const BMFace *face_orig = bm_original_face_get(mr, coarse_face);
605 if (!face_orig) {
606 continue;
607 }
608 if (skip_bm_face(*face_orig, sync_selection)) {
609 continue;
610 }
611 for (const int subdiv_corner : IndexRange(subdiv_quad * 4, 4)) {
612 const int coarse_vert = subdiv_loop_vert_index[subdiv_corner];
613 if (coarse_vert == -1) {
614 continue;
615 }
616 GPU_indexbuf_add_point_vert(&builder, subdiv_corner);
617 }
618 }
619}
620
622 const DRWSubdivCache &subdiv_cache)
623{
624 const bool sync_selection = (mr.toolsettings->uv_flag & UV_FLAG_SELECT_SYNC) != 0;
625
626 GPUIndexBufBuilder builder;
628 &builder, GPU_PRIM_POINTS, subdiv_cache.num_subdiv_loops, subdiv_cache.num_subdiv_loops);
630 extract_edituv_points_subdiv_bm(mr, subdiv_cache, sync_selection, builder);
631 }
632 else {
633 extract_edituv_points_subdiv_mesh(mr, subdiv_cache, sync_selection, builder);
634 }
635 return gpu::IndexBufPtr(GPU_indexbuf_build(&builder));
636}
637
639
640/* ---------------------------------------------------------------------- */
643
645 const bool sync_selection)
646{
647 const BMesh &bm = *mr.bm;
648 IndexMaskMemory memory;
649 const IndexMask visible = IndexMask::from_predicate(
650 IndexMask(bm.totface), GrainSize(4096), memory, [&](const int i) {
651 return !skip_bm_face(*BM_face_at_index(&const_cast<BMesh &>(bm), i), sync_selection);
652 });
653
654 GPUIndexBufBuilder builder;
655 GPU_indexbuf_init(&builder, GPU_PRIM_POINTS, visible.size(), bm.totface);
656 visible.to_indices(GPU_indexbuf_get_data(&builder).cast<int>());
657 return gpu::IndexBufPtr(GPU_indexbuf_build_ex(&builder, 0, bm.totface, false));
658}
659
661 const bool sync_selection)
662{
663 const OffsetIndices faces = mr.faces;
664 IndexMaskMemory memory;
666 faces.index_range(), GrainSize(4096), memory, [&](const int i) {
667 const BMFace *face_orig = bm_original_face_get(mr, i);
668 if (!face_orig) {
669 return false;
670 }
671 if (skip_bm_face(*face_orig, sync_selection)) {
672 return false;
673 }
674 return true;
675 });
676 if (mr.use_subsurf_fdots) {
677 const BitSpan facedot_tags = mr.mesh->runtime->subsurf_face_dot_tags;
678 const Span<int> corner_verts = mr.corner_verts;
679 visible = IndexMask::from_predicate(visible, GrainSize(4096), memory, [&](const int i) {
680 const Span<int> face_verts = corner_verts.slice(faces[i]);
681 return std::any_of(face_verts.begin(), face_verts.end(), [&](const int vert) {
682 return facedot_tags[vert];
683 });
684 });
685 }
686
687 GPUIndexBufBuilder builder;
688 GPU_indexbuf_init(&builder, GPU_PRIM_POINTS, visible.size(), faces.size());
689 visible.to_indices(GPU_indexbuf_get_data(&builder).cast<int>());
690 return gpu::IndexBufPtr(GPU_indexbuf_build_ex(&builder, 0, faces.size(), false));
691}
692
694{
695 const bool sync_selection = (mr.toolsettings->uv_flag & UV_FLAG_SELECT_SYNC) != 0;
697 return extract_edituv_face_dots_bm(mr, sync_selection);
698 }
699 return extract_edituv_face_dots_mesh(mr, sync_selection);
700}
701
703
704} // namespace blender::draw
#define ORIGINDEX_NONE
MINLINE int poly_to_tri_count(int poly_count, int corner_count)
unsigned int uint
@ UV_FLAG_SELECT_SYNC
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)
blender::gpu::IndexBuf * GPU_indexbuf_calloc()
void GPU_indexbuf_add_point_vert(GPUIndexBufBuilder *, uint v)
blender::gpu::IndexBuf * GPU_indexbuf_build(GPUIndexBufBuilder *)
void GPU_indexbuf_build_in_place(GPUIndexBufBuilder *, blender::gpu::IndexBuf *)
blender::gpu::IndexBuf * GPU_indexbuf_build_from_memory(GPUPrimType prim_type, const uint32_t *data, int32_t data_len, int32_t index_min, int32_t index_max, bool uses_restart_indices)
@ GPU_PRIM_LINES
@ GPU_PRIM_POINTS
@ GPU_PRIM_TRIS
#define BM_FACE_FIRST_LOOP(p)
@ BM_ELEM_HIDDEN
@ BM_ELEM_SELECT
#define BM_elem_index_get(ele)
#define BM_elem_flag_test(ele, hflag)
#define BM_elem_flag_test_bool(ele, hflag)
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_FACES_OF_MESH
BMesh const char void * data
BMesh * bm
BLI_INLINE BMFace * BM_face_at_index(BMesh *bm, const int index)
static IndexMask from_predicate(const IndexMask &universe, GrainSize grain_size, IndexMaskMemory &memory, Fn &&predicate)
static IndexMask from_bools(Span< bool > bools, IndexMaskMemory &memory)
static IndexMask from_bools_inverse(const VArray< bool > &bools, IndexMaskMemory &memory)
constexpr bool is_empty() const
Definition BLI_span.hh:260
void reinitialize(const int64_t new_size)
Definition BLI_array.hh:419
constexpr IndexRange index_range() const
Span< NewT > constexpr cast() const
Definition BLI_span.hh:418
constexpr Span slice(int64_t start, int64_t size) const
Definition BLI_span.hh:137
constexpr int64_t size() const
Definition BLI_span.hh:252
constexpr const T * end() const
Definition BLI_span.hh:224
constexpr IndexRange index_range() const
Definition BLI_span.hh:401
constexpr const T * begin() const
Definition BLI_span.hh:220
constexpr bool is_empty() const
Definition BLI_span.hh:260
MutableSpan< T > data()
void to_indices(MutableSpan< T > r_indices) const
void foreach_index(Fn &&fn) const
Extraction of Mesh data into VBO to feed to GPU.
#define cast
VecBase< uint, 2 > uint2
VecBase< uint, 3 > uint3
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
static char faces[256]
IndexRange face_triangles_range(OffsetIndices< int > faces, int face_i)
Definition BKE_mesh.hh:359
BLI_INLINE BMFace * bm_original_face_get(const MeshRenderData &mr, int idx)
gpu::IndexBufPtr extract_edituv_lines_subdiv(const MeshRenderData &mr, const DRWSubdivCache &subdiv_cache, UvExtractionMode mode)
gpu::IndexBufPtr extract_edituv_face_dots(const MeshRenderData &mr)
static gpu::IndexBufPtr extract_edituv_face_dots_bm(const MeshRenderData &mr, const bool sync_selection)
static gpu::IndexBufPtr extract_edituv_lines_subdiv_mesh(const MeshRenderData &mr, const DRWSubdivCache &subdiv_cache, const bool sync_selection)
static OffsetIndices< int > build_bmesh_face_offsets(const BMesh &bm, Array< int > &r_offset_data)
gpu::IndexBufPtr extract_edituv_tris(const MeshRenderData &mr, bool edit_uvs)
static gpu::IndexBufPtr build_tris_from_subdiv_quad_selection(const DRWSubdivCache &subdiv_cache, const IndexMask &selection)
gpu::IndexBufPtr extract_edituv_points(const MeshRenderData &mr)
gpu::IndexBufPtr extract_edituv_tris_subdiv(const MeshRenderData &mr, const DRWSubdivCache &subdiv_cache)
static gpu::IndexBufPtr extract_edituv_tris_subdiv_mesh(const MeshRenderData &mr, const DRWSubdivCache &subdiv_cache, const bool sync_selection)
uint2 edge_from_corners(const IndexRange face, const int corner)
static gpu::IndexBufPtr extract_edituv_tris_subdiv_bm(const MeshRenderData &mr, const DRWSubdivCache &subdiv_cache, const bool sync_selection)
static void extract_edituv_points_subdiv_bm(const MeshRenderData &mr, const DRWSubdivCache &subdiv_cache, const bool sync_selection, GPUIndexBufBuilder &builder)
gpu::IndexBufPtr extract_edituv_points_subdiv(const MeshRenderData &mr, const DRWSubdivCache &subdiv_cache)
static gpu::IndexBufPtr extract_edituv_tris_mesh(const MeshRenderData &mr, const bool sync_selection)
static void extract_edituv_points_subdiv_mesh(const MeshRenderData &mr, const DRWSubdivCache &subdiv_cache, const bool sync_selection, GPUIndexBufBuilder &builder)
static gpu::IndexBufPtr extract_edituv_face_dots_mesh(const MeshRenderData &mr, const bool sync_selection)
static void extract_edituv_points_mesh(const MeshRenderData &mr, const bool sync_selection, GPUIndexBufBuilder &builder)
gpu::IndexBufPtr extract_edituv_lines(const MeshRenderData &mr, UvExtractionMode mode)
static gpu::IndexBufPtr extract_edituv_lines_bm(const MeshRenderData &mr, const bool sync_selection)
static void extract_edituv_points_bm(const MeshRenderData &mr, const bool sync_selection, GPUIndexBufBuilder &builder)
static gpu::IndexBufPtr extract_edituv_tris_bm(const MeshRenderData &mr, const bool sync_selection)
static gpu::IndexBufPtr extract_edituv_lines_subdiv_bm(const MeshRenderData &mr, const DRWSubdivCache &subdiv_cache, const bool sync_selection)
bool skip_bm_face(const BMFace &face, const bool sync_selection)
static gpu::IndexBufPtr extract_edituv_lines_mesh(const MeshRenderData &mr, const bool sync_selection)
std::unique_ptr< IndexBuf, IndexBufDeleter > IndexBufPtr
OffsetIndices< int > accumulate_counts_to_offsets(MutableSpan< int > counts_to_offsets, int start_offset=0)
OffsetIndices< int > gather_selected_offsets(OffsetIndices< int > src_offsets, const IndexMask &selection, int start_offset, MutableSpan< int > dst_offsets)
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
VecBase< uint32_t, 3 > uint3
blender::Array< std::array< BMLoop *, 3 > > looptris
struct BMLoop * next
MeshRuntimeHandle * runtime
const ToolSettings * toolsettings
VArraySpan< bool > select_poly
OffsetIndices< int > faces
i
Definition text_draw.cc:230