Blender V4.5
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
50 const IndexMask &selection,
51 Array<int> &r_offset_data)
52{
53 if (selection.size() == faces.size()) {
54 return faces;
55 }
56 r_offset_data.reinitialize(selection.size() + 1);
57 return offset_indices::gather_selected_offsets(faces, selection, r_offset_data);
58}
59
60static gpu::IndexBufPtr extract_edituv_tris_bm(const MeshRenderData &mr, const bool sync_selection)
61{
63 const BMesh &bm = *mr.bm;
64
65 IndexMaskMemory memory;
66 const IndexMask selection = IndexMask::from_predicate(
67 IndexRange(bm.totface), GrainSize(4096), memory, [&](const int face) {
68 return !skip_bm_face(*BM_face_at_index(&const_cast<BMesh &>(bm), face), sync_selection);
69 });
70
71 Array<int> face_offset_data;
72 const OffsetIndices faces = build_bmesh_face_offsets(bm, face_offset_data);
73
74 Array<int> selected_face_offset_data;
75 const OffsetIndices selected_faces = gather_or_reference_offsets(
76 faces, selection, selected_face_offset_data);
77
78 const int tris_num = poly_to_tri_count(selected_faces.size(), selected_faces.total_size());
79
80 GPUIndexBufBuilder builder;
81 GPU_indexbuf_init(&builder, GPU_PRIM_TRIS, tris_num, mr.corners_num);
83
84 selection.foreach_index(GrainSize(4096), [&](const int face, const int mask) {
86 const IndexRange ibo_tris = bke::mesh::face_triangles_range(selected_faces, mask);
87 for (const int i : tris.index_range()) {
88 data[ibo_tris[i]] = uint3(BM_elem_index_get(looptris[tris[i]][0]),
89 BM_elem_index_get(looptris[tris[i]][1]),
90 BM_elem_index_get(looptris[tris[i]][2]));
91 }
92 });
93
94 return gpu::IndexBufPtr(GPU_indexbuf_build_ex(&builder, 0, mr.corners_num, false));
95}
96
98 const bool sync_selection)
99{
100 const OffsetIndices faces = mr.faces;
101 const Span<int3> corner_tris = mr.mesh->corner_tris();
102
103 IndexMaskMemory memory;
104 IndexMask selection;
105 if (mr.bm) {
106 selection = IndexMask::from_predicate(
107 faces.index_range(), GrainSize(4096), memory, [&](const int face) {
108 const BMFace *face_orig = bm_original_face_get(mr, face);
109 if (!face_orig) {
110 return false;
111 }
112 if (skip_bm_face(*face_orig, sync_selection)) {
113 return false;
114 }
115 return true;
116 });
117 }
118 else {
119 if (mr.hide_poly.is_empty()) {
120 selection = faces.index_range();
121 }
122 else {
123 selection = IndexMask::from_bools_inverse(faces.index_range(), mr.hide_poly, memory);
124 }
125
126 if (!sync_selection && !mr.select_poly.is_empty()) {
127 selection = IndexMask::from_bools(selection, mr.select_poly, memory);
128 }
129 }
130
131 Array<int> selected_face_offset_data;
132 const OffsetIndices selected_faces = gather_or_reference_offsets(
133 faces, selection, selected_face_offset_data);
134
135 const int tris_num = poly_to_tri_count(selected_faces.size(), selected_faces.total_size());
136
137 GPUIndexBufBuilder builder;
138 GPU_indexbuf_init(&builder, GPU_PRIM_TRIS, tris_num, mr.corners_num);
140
141 selection.foreach_index(GrainSize(4096), [&](const int face, const int mask) {
143 const IndexRange ibo_tris = bke::mesh::face_triangles_range(selected_faces, mask);
144 for (const int i : tris.index_range()) {
145 data[ibo_tris[i]] = uint3(
146 corner_tris[tris[i]][0], corner_tris[tris[i]][1], corner_tris[tris[i]][2]);
147 }
148 });
149
150 return gpu::IndexBufPtr(GPU_indexbuf_build_ex(&builder, 0, mr.corners_num, false));
151}
152
154{
155 const bool sync_selection = edit_uvs ? (mr.toolsettings->uv_flag & UV_SYNC_SELECTION) : false;
157 return extract_edituv_tris_bm(mr, sync_selection);
158 }
159 return extract_edituv_tris_mesh(mr, sync_selection);
160}
161
163 const IndexMask &selection)
164{
165 const int tris_num = selection.size() * 2;
166
167 GPUIndexBufBuilder builder;
168 GPU_indexbuf_init(&builder, GPU_PRIM_TRIS, tris_num, subdiv_cache.num_subdiv_loops);
170
171 selection.foreach_index(GrainSize(4096), [&](const int subdiv_quad_index, const int mask) {
172 const uint corner_start = subdiv_quad_index * 4;
173 data[mask * 2 + 0] = uint3(corner_start, corner_start + 1, corner_start + 2);
174 data[mask * 2 + 1] = uint3(corner_start, corner_start + 2, corner_start + 3);
175 });
176
177 return gpu::IndexBufPtr(
178 GPU_indexbuf_build_ex(&builder, 0, subdiv_cache.num_subdiv_loops, false));
179}
180
182 const DRWSubdivCache &subdiv_cache,
183 const bool sync_selection)
184{
185 const BMesh &bm = *mr.bm;
186 const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index,
187 subdiv_cache.num_subdiv_loops);
188
189 IndexMaskMemory memory;
190 const IndexMask selection = IndexMask::from_predicate(
191 IndexRange(subdiv_cache.num_subdiv_quads),
192 GrainSize(4096),
193 memory,
194 [&](const int subdiv_quad_index) {
195 const uint corner_start = subdiv_quad_index * 4;
196 const int coarse_face = subdiv_loop_face_index[corner_start];
197 const BMFace &bm_face = *BM_face_at_index(&const_cast<BMesh &>(bm), coarse_face);
198 return !skip_bm_face(bm_face, sync_selection);
199 });
200
201 return build_tris_from_subdiv_quad_selection(subdiv_cache, selection);
202}
203
205 const DRWSubdivCache &subdiv_cache,
206 const bool sync_selection)
207{
208 const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index,
209 subdiv_cache.num_subdiv_loops);
210
211 IndexMaskMemory memory;
212 const IndexMask selection = IndexMask::from_predicate(
213 IndexRange(subdiv_cache.num_subdiv_quads),
214 GrainSize(4096),
215 memory,
216 [&](const int subdiv_quad_index) {
217 const uint corner_start = subdiv_quad_index * 4;
218 const int coarse_face = subdiv_loop_face_index[corner_start];
219 const BMFace *face_orig = bm_original_face_get(mr, coarse_face);
220 if (!face_orig) {
221 return false;
222 }
223 if (skip_bm_face(*face_orig, sync_selection)) {
224 return false;
225 }
226 return true;
227 });
228
229 return build_tris_from_subdiv_quad_selection(subdiv_cache, selection);
230}
231
233 const DRWSubdivCache &subdiv_cache)
234{
235 const bool sync_selection = (mr.toolsettings->uv_flag & UV_SYNC_SELECTION) != 0;
237 return extract_edituv_tris_subdiv_bm(mr, subdiv_cache, sync_selection);
238 }
239 return extract_edituv_tris_subdiv_mesh(mr, subdiv_cache, sync_selection);
240}
241
243
244/* ---------------------------------------------------------------------- */
247
249 const bool sync_selection)
250{
251 GPUIndexBufBuilder builder;
252 /* The entire data array might not be used. It might be beneficial to count the number of visible
253 * edges first, especially if that allows parallelizing filling the data array. */
256 int line_index = 0;
257
258 const BMFace *face;
259 BMIter f_iter;
260 BM_ITER_MESH (face, &f_iter, mr.bm, BM_FACES_OF_MESH) {
261 if (skip_bm_face(*face, sync_selection)) {
262 continue;
263 }
264 const BMLoop *loop = BM_FACE_FIRST_LOOP(face);
265 for ([[maybe_unused]] const int i : IndexRange(face->len)) {
266 data[line_index++] = uint2(BM_elem_index_get(loop), BM_elem_index_get(loop->next));
267 loop = loop->next;
268 }
269 }
270
271 return gpu::IndexBufPtr(GPU_indexbuf_build_ex(&builder, 0, mr.corners_num, false));
272}
273
275 const bool sync_selection)
276{
277 const OffsetIndices faces = mr.faces;
278 const Span<int> corner_edges = mr.corner_edges;
279 const Span<int> orig_index_edge = mr.orig_index_edge ?
281 Span<int>();
282
283 GPUIndexBufBuilder builder;
286 int line_index = 0;
287
288 if (mr.bm) {
289 for (const int face_index : faces.index_range()) {
290 const IndexRange face = faces[face_index];
291 const BMFace *face_orig = bm_original_face_get(mr, face_index);
292 if (!face_orig) {
293 continue;
294 }
295 if (skip_bm_face(*face_orig, sync_selection)) {
296 continue;
297 }
298 for (const int corner : face) {
299 const int edge = corner_edges[corner];
300 if (!orig_index_edge.is_empty() && orig_index_edge[edge] == ORIGINDEX_NONE) {
301 continue;
302 }
303 data[line_index++] = edge_from_corners(face, corner);
304 }
305 }
306 }
307 else {
308 IndexMaskMemory memory;
309 IndexMask visible = faces.index_range();
310 if (!mr.hide_poly.is_empty()) {
311 visible = IndexMask::from_bools_inverse(visible, mr.hide_poly, memory);
312 }
313 if (!sync_selection) {
314 if (mr.select_poly.is_empty()) {
315 visible = {};
316 }
317 else {
318 visible = IndexMask::from_bools(visible, mr.select_poly, memory);
319 }
320 }
321 visible.foreach_index([&](const int face_index) {
322 const IndexRange face = faces[face_index];
323 for (const int corner : face) {
324 const int edge = corner_edges[corner];
325 if (!orig_index_edge.is_empty() && orig_index_edge[edge] == ORIGINDEX_NONE) {
326 continue;
327 }
328 data[line_index++] = edge_from_corners(face, corner);
329 }
330 });
331 }
332
333 return gpu::IndexBufPtr(GPU_indexbuf_build_ex(&builder, 0, mr.corners_num, false));
334}
335
337{
338 bool sync_selection = false;
339 switch (mode) {
341 sync_selection = true;
342 break;
344 sync_selection = ((mr.toolsettings->uv_flag & UV_SYNC_SELECTION) != 0);
345 break;
347 sync_selection = false;
348 break;
349 }
350
352 return extract_edituv_lines_bm(mr, sync_selection);
353 }
354 return extract_edituv_lines_mesh(mr, sync_selection);
355}
356
358 const DRWSubdivCache &subdiv_cache,
359 const bool sync_selection)
360{
361 const BMesh &bm = *mr.bm;
362 const Span<int> subdiv_loop_edge_index = subdiv_cache.edges_orig_index->data<int>();
363 const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index,
364 subdiv_cache.num_subdiv_loops);
365
366 GPUIndexBufBuilder builder;
368 &builder, GPU_PRIM_LINES, subdiv_cache.num_subdiv_loops, subdiv_cache.num_subdiv_loops);
370 int line_index = 0;
371
372 for (const int subdiv_quad : IndexRange(subdiv_cache.num_subdiv_quads)) {
373 const int coarse_face = subdiv_loop_face_index[subdiv_quad * 4];
374 const BMFace &face_orig = *BM_face_at_index(&const_cast<BMesh &>(bm), coarse_face);
375 if (skip_bm_face(face_orig, sync_selection)) {
376 continue;
377 }
378 const IndexRange subdiv_face(subdiv_quad * 4, 4);
379 for (const int subdiv_corner : subdiv_face) {
380 const int coarse_edge = subdiv_loop_edge_index[subdiv_corner];
381 if (coarse_edge == -1) {
382 continue;
383 }
384 data[line_index++] = edge_from_corners(subdiv_face, subdiv_corner);
385 }
386 }
387
388 return gpu::IndexBufPtr(
389 GPU_indexbuf_build_ex(&builder, 0, subdiv_cache.num_subdiv_loops, false));
390}
391
393 const DRWSubdivCache &subdiv_cache,
394 const bool sync_selection)
395{
396 GPUIndexBufBuilder builder;
398 &builder, GPU_PRIM_LINES, subdiv_cache.num_subdiv_loops, subdiv_cache.num_subdiv_loops);
400 int line_index = 0;
401
402 /* NOTE: #subdiv_loop_edge_index already has the #CD_ORIGINDEX layer baked in. */
403 const Span<int> subdiv_loop_edge_index = subdiv_cache.edges_orig_index->data<int>();
404 const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index,
405 subdiv_cache.num_subdiv_loops);
406 /* TODO: Replace subdiv quad iteration with coarse face iteration. */
407 for (const int subdiv_quad : IndexRange(subdiv_cache.num_subdiv_quads)) {
408 const int coarse_face = subdiv_loop_face_index[subdiv_quad * 4];
409 if (const BMesh *bm = mr.bm) {
410 const int orig_coarse_face = mr.orig_index_face ? mr.orig_index_face[coarse_face] :
411 coarse_face;
412 const BMFace &face_orig = *BM_face_at_index(const_cast<BMesh *>(bm), orig_coarse_face);
413 if (skip_bm_face(face_orig, sync_selection)) {
414 continue;
415 }
416 }
417 else {
418 if (!mr.hide_poly.is_empty() && mr.hide_poly[coarse_face]) {
419 continue;
420 }
421 if (!sync_selection) {
422 if (mr.select_poly.is_empty() || !mr.select_poly[coarse_face]) {
423 continue;
424 }
425 }
426 }
427 const IndexRange subdiv_face(subdiv_quad * 4, 4);
428 for (const int subdiv_corner : subdiv_face) {
429 const int coarse_edge = subdiv_loop_edge_index[subdiv_corner];
430 if (coarse_edge == -1) {
431 continue;
432 }
433 data[line_index++] = edge_from_corners(subdiv_face, subdiv_corner);
434 }
435 }
436
437 return gpu::IndexBufPtr(
438 GPU_indexbuf_build_ex(&builder, 0, subdiv_cache.num_subdiv_loops, false));
439}
440
442 const DRWSubdivCache &subdiv_cache,
443 const UvExtractionMode mode)
444{
445 bool sync_selection = false;
446 switch (mode) {
448 sync_selection = true;
449 break;
451 sync_selection = ((mr.toolsettings->uv_flag & UV_SYNC_SELECTION) != 0);
452 break;
454 sync_selection = false;
455 break;
456 }
457
459 return extract_edituv_lines_subdiv_bm(mr, subdiv_cache, sync_selection);
460 }
461 return extract_edituv_lines_subdiv_mesh(mr, subdiv_cache, sync_selection);
462}
463
465
466/* ---------------------------------------------------------------------- */
469
471 const bool sync_selection,
472 GPUIndexBufBuilder &builder)
473{
474 const BMesh &bm = *mr.bm;
475 const BMFace *face;
476 BMIter f_iter;
477 BM_ITER_MESH (face, &f_iter, &const_cast<BMesh &>(bm), BM_FACES_OF_MESH) {
478 if (skip_bm_face(*face, sync_selection)) {
479 continue;
480 }
481 const BMLoop *loop = BM_FACE_FIRST_LOOP(face);
482 for ([[maybe_unused]] const int i : IndexRange(face->len)) {
484 loop = loop->next;
485 }
486 }
487}
488
490 const bool sync_selection,
491 GPUIndexBufBuilder &builder)
492{
493 const OffsetIndices faces = mr.faces;
494 const Span<int> corner_verts = mr.corner_verts;
495 const Span<int> orig_index_vert = mr.orig_index_vert ?
497 Span<int>();
498 for (const int face_index : faces.index_range()) {
499 const BMFace *face_orig = bm_original_face_get(mr, face_index);
500 if (!face_orig) {
501 continue;
502 }
503 if (skip_bm_face(*face_orig, sync_selection)) {
504 continue;
505 }
506 for (const int corner : faces[face_index]) {
507 const int vert = corner_verts[corner];
508 if (!orig_index_vert.is_empty() && orig_index_vert[vert] == ORIGINDEX_NONE) {
509 continue;
510 }
511 GPU_indexbuf_add_point_vert(&builder, corner);
512 }
513 }
514}
515
517{
518 const bool sync_selection = (mr.toolsettings->uv_flag & UV_SYNC_SELECTION) != 0;
519
520 GPUIndexBufBuilder builder;
523 extract_edituv_points_bm(mr, sync_selection, builder);
524 }
525 else {
526 extract_edituv_points_mesh(mr, sync_selection, builder);
527 }
528 return gpu::IndexBufPtr(GPU_indexbuf_build(&builder));
529}
530
532 const DRWSubdivCache &subdiv_cache,
533 const bool sync_selection,
534 GPUIndexBufBuilder &builder)
535{
536 const BMesh &bm = *mr.bm;
537 const Span<int> subdiv_loop_vert_index = subdiv_cache.verts_orig_index->data<int>();
538 const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index,
539 subdiv_cache.num_subdiv_loops);
540
541 for (const int subdiv_quad : IndexRange(subdiv_cache.num_subdiv_quads)) {
542 const int coarse_face = subdiv_loop_face_index[subdiv_quad * 4];
543 const BMFace &face_orig = *BM_face_at_index(&const_cast<BMesh &>(bm), coarse_face);
544 if (skip_bm_face(face_orig, sync_selection)) {
545 continue;
546 }
547 for (const int subdiv_corner : IndexRange(subdiv_quad * 4, 4)) {
548 const int coarse_vert = subdiv_loop_vert_index[subdiv_corner];
549 if (coarse_vert == -1) {
550 continue;
551 }
552 GPU_indexbuf_add_point_vert(&builder, subdiv_corner);
553 }
554 }
555}
556
558 const DRWSubdivCache &subdiv_cache,
559 const bool sync_selection,
560 GPUIndexBufBuilder &builder)
561{
562 const Span<int> subdiv_loop_vert_index = subdiv_cache.verts_orig_index->data<int>();
563 const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index,
564 subdiv_cache.num_subdiv_loops);
565
566 for (const int subdiv_quad : IndexRange(subdiv_cache.num_subdiv_quads)) {
567 const int coarse_face = subdiv_loop_face_index[subdiv_quad * 4];
568 const BMFace *face_orig = bm_original_face_get(mr, coarse_face);
569 if (!face_orig) {
570 continue;
571 }
572 if (skip_bm_face(*face_orig, sync_selection)) {
573 continue;
574 }
575 for (const int subdiv_corner : IndexRange(subdiv_quad * 4, 4)) {
576 const int coarse_vert = subdiv_loop_vert_index[subdiv_corner];
577 if (coarse_vert == -1) {
578 continue;
579 }
580 GPU_indexbuf_add_point_vert(&builder, subdiv_corner);
581 }
582 }
583}
584
586 const DRWSubdivCache &subdiv_cache)
587{
588 const bool sync_selection = (mr.toolsettings->uv_flag & UV_SYNC_SELECTION) != 0;
589
590 GPUIndexBufBuilder builder;
592 &builder, GPU_PRIM_POINTS, subdiv_cache.num_subdiv_loops, subdiv_cache.num_subdiv_loops);
594 extract_edituv_points_subdiv_bm(mr, subdiv_cache, sync_selection, builder);
595 }
596 else {
597 extract_edituv_points_subdiv_mesh(mr, subdiv_cache, sync_selection, builder);
598 }
599 return gpu::IndexBufPtr(GPU_indexbuf_build(&builder));
600}
601
603
604/* ---------------------------------------------------------------------- */
607
609 const bool sync_selection)
610{
611 const BMesh &bm = *mr.bm;
612 IndexMaskMemory memory;
613 const IndexMask visible = IndexMask::from_predicate(
614 IndexMask(bm.totface), GrainSize(4096), memory, [&](const int i) {
615 return !skip_bm_face(*BM_face_at_index(&const_cast<BMesh &>(bm), i), sync_selection);
616 });
617
618 GPUIndexBufBuilder builder;
619 GPU_indexbuf_init(&builder, GPU_PRIM_POINTS, visible.size(), bm.totface);
620 visible.to_indices(GPU_indexbuf_get_data(&builder).cast<int>());
621 return gpu::IndexBufPtr(GPU_indexbuf_build_ex(&builder, 0, bm.totface, false));
622}
623
625 const bool sync_selection)
626{
627 const OffsetIndices faces = mr.faces;
628 IndexMaskMemory memory;
630 faces.index_range(), GrainSize(4096), memory, [&](const int i) {
631 const BMFace *face_orig = bm_original_face_get(mr, i);
632 if (!face_orig) {
633 return false;
634 }
635 if (skip_bm_face(*face_orig, sync_selection)) {
636 return false;
637 }
638 return true;
639 });
640 if (mr.use_subsurf_fdots) {
641 const BitSpan facedot_tags = mr.mesh->runtime->subsurf_face_dot_tags;
642 const Span<int> corner_verts = mr.corner_verts;
643 visible = IndexMask::from_predicate(visible, GrainSize(4096), memory, [&](const int i) {
644 const Span<int> face_verts = corner_verts.slice(faces[i]);
645 return std::any_of(face_verts.begin(), face_verts.end(), [&](const int vert) {
646 return facedot_tags[vert];
647 });
648 });
649 }
650
651 GPUIndexBufBuilder builder;
652 GPU_indexbuf_init(&builder, GPU_PRIM_POINTS, visible.size(), faces.size());
653 visible.to_indices(GPU_indexbuf_get_data(&builder).cast<int>());
654 return gpu::IndexBufPtr(GPU_indexbuf_build_ex(&builder, 0, faces.size(), false));
655}
656
658{
659 const bool sync_selection = (mr.toolsettings->uv_flag & UV_SYNC_SELECTION) != 0;
661 return extract_edituv_face_dots_bm(mr, sync_selection);
662 }
663 return extract_edituv_face_dots_mesh(mr, sync_selection);
664}
665
667
668} // namespace blender::draw
#define ORIGINDEX_NONE
MINLINE int poly_to_tri_count(int poly_count, int corner_count)
unsigned int uint
@ UV_SYNC_SELECTION
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)
void GPU_indexbuf_add_point_vert(GPUIndexBufBuilder *, uint v)
blender::gpu::IndexBuf * GPU_indexbuf_build(GPUIndexBufBuilder *)
@ GPU_PRIM_LINES
@ GPU_PRIM_POINTS
@ GPU_PRIM_TRIS
@ BM_ELEM_HIDDEN
@ BM_ELEM_SELECT
#define BM_FACE_FIRST_LOOP(p)
#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:398
constexpr IndexRange index_range() const
constexpr Span slice(int64_t start, int64_t size) const
Definition BLI_span.hh:137
constexpr const T * end() const
Definition BLI_span.hh:224
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:343
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)
static OffsetIndices< int > gather_or_reference_offsets(const OffsetIndices< int > faces, const IndexMask &selection, Array< int > &r_offset_data)
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