Blender V5.0
draw_cache_extract_mesh_render_data.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
10
11#include "BLI_array.hh"
12#include "BLI_array_utils.hh"
14#include "BLI_math_geom.h"
15#include "BLI_task.hh"
16#include "BLI_virtual_array.hh"
17
18#include "BKE_attribute.hh"
19#include "BKE_editmesh.hh"
20#include "BKE_editmesh_cache.hh"
21#include "BKE_material.hh"
22#include "BKE_mesh.hh"
23#include "BKE_object.hh"
24
25#include "ED_mesh.hh"
26
27#include "DRW_render.hh"
28
30
31/* ---------------------------------------------------------------------- */
34
35namespace blender::draw {
36
38{
39 int count = 0;
40 for (const int64_t i : bits.index_range()) {
41 if (bits[i]) {
42 indices[count] = int(i);
43 count++;
44 }
45 }
46 BLI_assert(count == indices.size());
47}
48
50{
51 const Mesh &mesh = *mr.mesh;
52 const bool no_loose_vert_hint = mesh.runtime->loose_verts_cache.is_cached() &&
53 mesh.runtime->loose_verts_cache.data().count == 0;
54 const bool no_loose_edge_hint = mesh.runtime->loose_edges_cache.is_cached() &&
55 mesh.runtime->loose_edges_cache.data().count == 0;
57 mesh.edges_num > 4096 && !no_loose_vert_hint && !no_loose_edge_hint,
58 [&]() {
59 const bke::LooseEdgeCache &loose_edges = mesh.loose_edges();
60 if (loose_edges.count > 0) {
61 cache.loose_geom.edges.reinitialize(loose_edges.count);
62 extract_set_bits(loose_edges.is_loose_bits, cache.loose_geom.edges);
63 }
64 },
65 [&]() {
66 const bke::LooseVertCache &loose_verts = mesh.loose_verts();
67 if (loose_verts.count > 0) {
68 cache.loose_geom.verts.reinitialize(loose_verts.count);
69 extract_set_bits(loose_verts.is_loose_bits, cache.loose_geom.verts);
70 }
71 });
72}
73
75 MeshBufferCache &cache,
76 BMesh &bm)
77{
78 int i;
79 BMIter iter;
80 BMVert *vert;
81 int count = 0;
82 Array<int> loose_verts(mr.verts_num);
83 BM_ITER_MESH_INDEX (vert, &iter, &bm, BM_VERTS_OF_MESH, i) {
84 if (vert->e == nullptr) {
85 loose_verts[count] = i;
86 count++;
87 }
88 }
89 if (count < mr.verts_num) {
90 cache.loose_geom.verts = loose_verts.as_span().take_front(count);
91 }
92 else {
93 cache.loose_geom.verts = std::move(loose_verts);
94 }
95}
96
98 MeshBufferCache &cache,
99 BMesh &bm)
100{
101 int i;
102 BMIter iter;
103 BMEdge *edge;
104 int count = 0;
105 Array<int> loose_edges(mr.edges_num);
106 BM_ITER_MESH_INDEX (edge, &iter, &bm, BM_EDGES_OF_MESH, i) {
107 if (edge->l == nullptr) {
108 loose_edges[count] = i;
109 count++;
110 }
111 }
112 if (count < mr.edges_num) {
113 cache.loose_geom.edges = loose_edges.as_span().take_front(count);
114 }
115 else {
116 cache.loose_geom.edges = std::move(loose_edges);
117 }
118}
119
121{
124 }
125 else {
126 BMesh &bm = *mr.bm;
129 }
130}
131
133{
134 /* Early exit: Are loose geometry already available.
135 * Only checking for loose verts as loose edges and verts are calculated at the same time. */
136 if (!cache.loose_geom.verts.is_empty()) {
137 return;
138 }
140}
141
152
154
155/* ---------------------------------------------------------------------- */
160
163{
164 threading::parallel_for(IndexRange(bm.totface), 1024, [&](const IndexRange range) {
165 Array<int> &tri_counts = all_tri_counts.local();
166 const short last_index = tri_counts.size() - 1;
167 for (const int i : range) {
168 const BMFace &face = *BM_face_at_index(&const_cast<BMesh &>(bm), i);
169 if (!BM_elem_flag_test(&face, BM_ELEM_HIDDEN)) {
170 const short mat = std::clamp<short>(face.mat_nr, 0, last_index);
171 tri_counts[mat] += face.len - 2;
172 }
173 }
174 });
175}
176
179{
180 const OffsetIndices faces = mr.faces;
181 const Span<bool> hide_poly = mr.hide_poly;
182 const Span material_indices = mr.material_indices;
183 if (material_indices.is_empty()) {
184 if (!hide_poly.is_empty()) {
185 all_tri_counts.local().first() = threading::parallel_reduce(
186 faces.index_range(),
187 4096,
188 0,
189 [&](const IndexRange range, int count) {
190 for (const int face : range) {
191 if (!hide_poly[face]) {
192 count += bke::mesh::face_triangles_num(faces[face].size());
193 }
194 }
195 return count;
196 },
197 std::plus<>());
198 }
199 else {
200 all_tri_counts.local().first() = poly_to_tri_count(mr.faces_num, mr.corners_num);
201 }
202 return;
203 }
204
205 threading::parallel_for(material_indices.index_range(), 1024, [&](const IndexRange range) {
206 Array<int> &tri_counts = all_tri_counts.local();
207 const int last_index = tri_counts.size() - 1;
208 if (!hide_poly.is_empty()) {
209 for (const int i : range) {
210 if (!hide_poly[i]) {
211 const int mat = std::clamp(material_indices[i], 0, last_index);
212 tri_counts[mat] += bke::mesh::face_triangles_num(faces[i].size());
213 }
214 }
215 }
216 else {
217 for (const int i : range) {
218 const int mat = std::clamp(material_indices[i], 0, last_index);
219 tri_counts[mat] += bke::mesh::face_triangles_num(faces[i].size());
220 }
221 }
222 });
223}
224
225/* Count how many triangles for each material. */
227{
229 [&]() { return Array<int>(mr.materials_num, 0); });
230
232 accumululate_material_counts_bm(*mr.bm, all_tri_counts);
233 }
234 else {
235 accumululate_material_counts_mesh(mr, all_tri_counts);
236 }
237
238 Array<int> &tris_num_by_material = all_tri_counts.local();
239 for (const Array<int> &counts : all_tri_counts) {
240 if (&counts != &tris_num_by_material) {
241 for (const int i : tris_num_by_material.index_range()) {
242 tris_num_by_material[i] += counts[i];
243 }
244 }
245 }
246 return std::move(tris_num_by_material);
247}
248
250 MutableSpan<int> material_tri_starts)
251{
252 BMesh &bm = *mr.bm;
253 Array<int> face_tri_offsets(bm.totface);
254#ifndef NDEBUG
255 face_tri_offsets.fill(-1);
256#endif
257
258 const int mat_last = mr.materials_num - 1;
259 BMIter iter;
260 BMFace *face;
261 int i;
262 BM_ITER_MESH_INDEX (face, &iter, &bm, BM_FACES_OF_MESH, i) {
264 continue;
265 }
266 const int mat = std::clamp(int(face->mat_nr), 0, mat_last);
267 face_tri_offsets[i] = material_tri_starts[mat];
268 material_tri_starts[mat] += face->len - 2;
269 }
270
271 return face_tri_offsets;
272}
273
274static bool mesh_is_single_material(const OffsetIndices<int> material_tri_starts)
275{
276 const int used_materials = std::count_if(
277 material_tri_starts.index_range().begin(),
278 material_tri_starts.index_range().end(),
279 [&](const int i) { return material_tri_starts[i].size() > 0; });
280 return used_materials == 1;
281}
282
283static std::optional<Array<int>> calc_face_tri_starts_mesh(const MeshRenderData &mr,
284 MutableSpan<int> material_tri_starts)
285{
286 const bool single_material = mesh_is_single_material(material_tri_starts.as_span());
287 if (single_material && mr.hide_poly.is_empty()) {
288 return std::nullopt;
289 }
290
291 const OffsetIndices faces = mr.faces;
292 const Span<bool> hide_poly = mr.hide_poly;
293
294 Array<int> face_tri_offsets(faces.size());
295#ifndef NDEBUG
296 face_tri_offsets.fill(-1);
297#endif
298
299 if (single_material) {
300 int offset = 0;
301 for (const int face : faces.index_range()) {
302 if (hide_poly[face]) {
303 continue;
304 }
305 face_tri_offsets[face] = offset;
306 offset += bke::mesh::face_triangles_num(faces[face].size());
307 }
308 return face_tri_offsets;
309 }
310
311 const Span<int> material_indices = mr.material_indices;
312 const int mat_last = mr.materials_num - 1;
313 for (const int face : faces.index_range()) {
314 if (!hide_poly.is_empty() && hide_poly[face]) {
315 continue;
316 }
317 const int mat = std::clamp(material_indices[face], 0, mat_last);
318 face_tri_offsets[face] = material_tri_starts[mat];
319 material_tri_starts[mat] += bke::mesh::face_triangles_num(faces[face].size());
320 }
321
322 return face_tri_offsets;
323}
324
326{
327 SortedFaceData cache;
329 const Span<int> tris_num_by_material = cache.tris_num_by_material;
330
331 Array<int, 32> material_tri_starts(mr.materials_num + 1);
332 material_tri_starts.as_mutable_span().drop_back(1).copy_from(tris_num_by_material);
334 cache.visible_tris_num = material_tri_starts.last();
335
336 /* Sort per material. */
338 cache.face_tri_offsets = calc_face_tri_starts_bmesh(mr, material_tri_starts);
339 }
340 else {
341 cache.face_tri_offsets = calc_face_tri_starts_mesh(mr, material_tri_starts);
342 }
343 return cache;
344}
345
347 MeshBufferCache &cache)
348{
349 if (cache.face_sorted.visible_tris_num == 0) {
351 }
352 return cache.face_sorted;
353}
354
356
357/* ---------------------------------------------------------------------- */
360
362{
363 switch (mesh.runtime->wrapper_type) {
366 return mesh.corner_data;
367 break;
369 return mesh.runtime->edit_mesh->bm->ldata;
370 break;
371 }
372
373 BLI_assert(0);
374 return mesh.corner_data;
375}
376
378{
379 switch (mesh.runtime->wrapper_type) {
382 return mesh.face_data;
383 break;
385 return mesh.runtime->edit_mesh->bm->pdata;
386 break;
387 }
388
389 BLI_assert(0);
390 return mesh.face_data;
391}
392
394{
395 switch (mesh.runtime->wrapper_type) {
398 return mesh.edge_data;
399 break;
401 return mesh.runtime->edit_mesh->bm->edata;
402 break;
403 }
404
405 BLI_assert(0);
406 return mesh.edge_data;
407}
408
410{
411 switch (mesh.runtime->wrapper_type) {
414 return mesh.vert_data;
415 break;
417 return mesh.runtime->edit_mesh->bm->vdata;
418 break;
419 }
420
421 BLI_assert(0);
422 return mesh.vert_data;
423}
424
425static bool bm_edge_is_sharp(const BMEdge *const &edge)
426{
427 return !BM_elem_flag_test(edge, BM_ELEM_SMOOTH);
428}
429
430static bool bm_face_is_sharp(const BMFace *const &face)
431{
432 return !BM_elem_flag_test(face, BM_ELEM_SMOOTH);
433}
434
440{
441 if (bm->totface == 0) {
443 }
444
445 if (CustomData_has_layer_named(&bm->vdata, CD_PROP_FLOAT3, "custom_normal")) {
447 }
448 if (CustomData_has_layer_named(&bm->pdata, CD_PROP_FLOAT3, "custom_normal")) {
450 }
451 if (CustomData_has_layer_named(&bm->ldata, CD_PROP_FLOAT3, "custom_normal")) {
453 }
454 if (CustomData_has_layer_named(&bm->ldata, CD_PROP_INT16_2D, "custom_normal")) {
456 }
457
459 const VArray<bool> sharp_faces =
461 Span(bm->ftable, bm->totface));
462 const array_utils::BooleanMix face_mix = array_utils::booleans_mix_calc(sharp_faces);
463 if (face_mix == array_utils::BooleanMix::AllTrue) {
465 }
466
468 const VArray<bool> sharp_edges =
470 Span(bm->etable, bm->totedge));
471 const array_utils::BooleanMix edge_mix = array_utils::booleans_mix_calc(sharp_edges);
472 if (edge_mix == array_utils::BooleanMix::AllTrue) {
474 }
475
476 if (edge_mix == array_utils::BooleanMix::AllFalse &&
478 {
480 }
481
483}
484
486{
488 mr.corner_normals = mr.mesh->corner_normals();
489 }
490 else {
493 {
494 /* If there are free custom normals they should be used directly. */
495 mr.bm_loop_normals = {};
496 return;
497 }
498 mr.bm_loop_normals.reinitialize(mr.corners_num);
499 const int clnors_offset = CustomData_get_offset_named(
500 &mr.bm->ldata, CD_PROP_INT16_2D, "custom_normal");
505 true,
507 nullptr,
508 nullptr,
509 clnors_offset,
510 false);
511 }
512}
513
515{
517 /* Eager calculation of face normals can reduce waiting on the lazy cache's lock. */
518 mr.face_normals = mr.mesh->face_normals();
519 }
520 else {
521 /* Use #BMFace.no. */
522 }
523}
524
526 const Object &object,
527 const Mesh &mesh)
528{
529 const Mesh &mesh_final = editmesh_final_or_this(object, mesh);
532}
533
535 Mesh &mesh,
536 const bool is_editmode,
537 const bool is_paint_mode,
538 const bool do_final,
539 const bool do_uvedit,
540 const bool use_hide,
541 const ToolSettings *ts)
542{
543 MeshRenderData mr{};
544 mr.toolsettings = ts;
546
547 mr.use_hide = use_hide;
548
549 const Mesh *editmesh_orig = BKE_object_get_pre_modified_mesh(&object);
550 if (editmesh_orig && editmesh_orig->runtime->edit_mesh) {
551 const Mesh *eval_cage = DRW_object_get_editmesh_cage_for_drawing(object);
552
553 mr.bm = editmesh_orig->runtime->edit_mesh->bm;
554 mr.edit_bmesh = editmesh_orig->runtime->edit_mesh.get();
555 mr.mesh = (do_final) ? &mesh : eval_cage;
556 mr.edit_data = is_editmode ? mr.mesh->runtime->edit_data.get() : nullptr;
557
558 /* If there is no distinct cage, hide unmapped edges that can't be selected. */
559 mr.hide_unmapped_edges = !do_final || &mesh == eval_cage;
560
562 &mr.bm->vdata, CD_PROP_FLOAT3, "custom_normal");
564 &mr.bm->pdata, CD_PROP_FLOAT3, "custom_normal");
566 &mr.bm->ldata, CD_PROP_FLOAT3, "custom_normal");
567
568 if (bke::EditMeshData *emd = mr.edit_data) {
569 if (!emd->vert_positions.is_empty()) {
571 if (mr.bm_free_normal_offset_vert == -1) {
573 }
574 if (mr.bm_free_normal_offset_face == -1) {
576 }
577 }
578 }
579
580 int bm_ensure_types = BM_VERT | BM_EDGE | BM_LOOP | BM_FACE;
581
582 BM_mesh_elem_index_ensure(mr.bm, bm_ensure_types);
583 BM_mesh_elem_table_ensure(mr.bm, bm_ensure_types & ~BM_LOOP);
584
585 mr.efa_act_uv = EDBM_uv_active_face_get(mr.edit_bmesh, false, false);
586 mr.efa_act = BM_mesh_active_face_get(mr.bm, false, true);
589
593 &mr.bm->edata, CD_PROP_FLOAT, "bevel_weight_edge");
594#ifdef WITH_FREESTYLE
596 &mr.bm->edata, CD_PROP_BOOL, "freestyle_edge");
598 &mr.bm->pdata, CD_PROP_BOOL, "freestyle_face");
599#endif
600
601 /* Use bmesh directly when the object is unchanged by any modifiers. For non-final UVs, always
602 * use original bmesh since the UV editor does not support using the cage mesh with deformed
603 * coordinates. */
604 if ((mr.mesh->runtime->is_original_bmesh &&
605 mr.mesh->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH) ||
606 (do_uvedit && !do_final))
607 {
609 }
610 else {
612
613 /* Use mapping from final to original mesh when the object is in edit mode. */
614 if (is_editmode && do_final) {
615 mr.orig_index_vert = static_cast<const int *>(
617 mr.orig_index_edge = static_cast<const int *>(
619 mr.orig_index_face = static_cast<const int *>(
621 }
622 else {
623 mr.orig_index_vert = nullptr;
624 mr.orig_index_edge = nullptr;
625 mr.orig_index_face = nullptr;
626 }
627 }
628 }
629 else {
630 mr.mesh = &mesh;
631 mr.edit_bmesh = nullptr;
633 mr.hide_unmapped_edges = false;
634
635 if (is_paint_mode && mr.mesh) {
636 mr.orig_index_vert = static_cast<const int *>(
638 mr.orig_index_edge = static_cast<const int *>(
640 mr.orig_index_face = static_cast<const int *>(
642 }
643 else {
644 mr.orig_index_vert = nullptr;
645 mr.orig_index_edge = nullptr;
646 mr.orig_index_face = nullptr;
647 }
648 }
649
651 mr.verts_num = mr.mesh->verts_num;
652 mr.edges_num = mr.mesh->edges_num;
653 mr.faces_num = mr.mesh->faces_num;
656
657 mr.vert_positions = mr.mesh->vert_positions();
658 mr.edges = mr.mesh->edges();
659 mr.faces = mr.mesh->faces();
660 mr.corner_verts = mr.mesh->corner_verts();
661 mr.corner_edges = mr.mesh->corner_edges();
662
663 mr.orig_index_vert = static_cast<const int *>(
665 mr.orig_index_edge = static_cast<const int *>(
667 mr.orig_index_face = static_cast<const int *>(
669
670 mr.normals_domain = mr.mesh->normals_domain();
671
672 const bke::AttributeAccessor attributes = mr.mesh->attributes();
673
674 mr.material_indices = *attributes.lookup<int>("material_index", bke::AttrDomain::Face);
675
676 if (is_editmode || is_paint_mode) {
677 if (use_hide) {
678 mr.hide_vert = *attributes.lookup<bool>(".hide_vert", bke::AttrDomain::Point);
679 mr.hide_edge = *attributes.lookup<bool>(".hide_edge", bke::AttrDomain::Edge);
680 mr.hide_poly = *attributes.lookup<bool>(".hide_poly", bke::AttrDomain::Face);
681 }
682
683 mr.select_vert = *attributes.lookup<bool>(".select_vert", bke::AttrDomain::Point);
684 mr.select_edge = *attributes.lookup<bool>(".select_edge", bke::AttrDomain::Edge);
685 mr.select_poly = *attributes.lookup<bool>(".select_poly", bke::AttrDomain::Face);
686 }
687
688 mr.sharp_faces = *attributes.lookup<bool>("sharp_face", bke::AttrDomain::Face);
689 }
690 else {
691 BMesh *bm = mr.bm;
692
693 mr.verts_num = bm->totvert;
694 mr.edges_num = bm->totedge;
695 mr.faces_num = bm->totface;
696 mr.corners_num = bm->totloop;
698
700 }
701
702 retrieve_active_attribute_names(mr, object, *mr.mesh);
703
704 return mr;
705}
706
708
709} // namespace blender::draw
const void * CustomData_get_layer(const CustomData *data, eCustomDataType type)
bool CustomData_has_layer_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
int CustomData_get_offset_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
blender::Span< blender::float3 > BKE_editmesh_cache_ensure_vert_normals(BMEditMesh &em, blender::bke::EditMeshData &emd)
blender::Span< blender::float3 > BKE_editmesh_cache_ensure_face_normals(BMEditMesh &em, blender::bke::EditMeshData &emd)
General operations, lookup, etc. for materials.
int BKE_object_material_used_with_fallback_eval(const Object &ob)
@ ME_WRAPPER_TYPE_MDATA
@ ME_WRAPPER_TYPE_SUBD
@ ME_WRAPPER_TYPE_BMESH
General operations, lookup, etc. for blender objects.
const Mesh * BKE_object_get_pre_modified_mesh(const Object *object)
#define BLI_assert(a)
Definition BLI_assert.h:46
MINLINE int poly_to_tri_count(int poly_count, int corner_count)
@ CD_PROP_FLOAT
@ CD_PROP_FLOAT3
@ CD_PROP_INT16_2D
BMFace * EDBM_uv_active_face_get(BMEditMesh *em, bool sloppy, bool selected)
@ BM_ELEM_HIDDEN
@ BM_ELEM_SMOOTH
@ BM_LOOP
#define BM_elem_flag_test(ele, hflag)
#define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar)
@ BM_EDGES_OF_MESH
@ BM_VERTS_OF_MESH
@ BM_FACES_OF_MESH
BMesh * bm
BMVert * BM_mesh_active_vert_get(BMesh *bm)
BMEdge * BM_mesh_active_edge_get(BMesh *bm)
BMFace * BM_mesh_active_face_get(BMesh *bm, const bool is_sloppy, const bool is_selected)
void BM_mesh_elem_table_ensure(BMesh *bm, const char htype)
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
void BM_loops_calc_normal_vcos(BMesh *bm, const Span< float3 > vcos, const Span< float3 > vnos, const Span< float3 > fnos, const bool use_split_normals, MutableSpan< float3 > r_lnos, MLoopNorSpaceArray *r_lnors_spacearr, short(*clnors_data)[2], const int cd_loop_clnors_offset, const bool do_rebuild)
#define BM_FACE
#define BM_EDGE
#define BM_VERT
long long int int64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
int64_t size() const
Definition BLI_array.hh:256
bool is_empty() const
Definition BLI_array.hh:264
AttributeSet attributes
constexpr bool is_empty() const
Definition BLI_span.hh:260
static VArray from_derived_span(Span< StructT > values)
Span< T > as_span() const
Definition BLI_array.hh:243
MutableSpan< T > as_mutable_span()
Definition BLI_array.hh:248
const T & last(const int64_t n=0) const
Definition BLI_array.hh:296
IndexRange index_range() const
Definition BLI_array.hh:360
void fill(const T &value) const
Definition BLI_array.hh:272
constexpr Iterator end() const
constexpr Iterator begin() const
constexpr Span< T > as_span() const
Definition BLI_span.hh:661
constexpr bool is_empty() const
Definition BLI_span.hh:260
GAttributeReader lookup(const StringRef attribute_id) const
const Mesh * DRW_object_get_editmesh_cage_for_drawing(const Object &object)
Extraction of Mesh data into VBO to feed to GPU.
static ushort indices[]
int count
static char faces[256]
BooleanMix booleans_mix_calc(const VArray< bool > &varray, IndexRange range_to_check)
int face_triangles_num(const int face_size)
Definition BKE_mesh.hh:350
const CustomData & mesh_cd_ldata_get_from_mesh(const Mesh &mesh)
static Array< int > calc_face_tri_starts_bmesh(const MeshRenderData &mr, MutableSpan< int > material_tri_starts)
void mesh_render_data_update_face_normals(MeshRenderData &mr)
static Array< int > mesh_render_data_mat_tri_len_build(const MeshRenderData &mr)
static bool mesh_is_single_material(const OffsetIndices< int > material_tri_starts)
static void mesh_render_data_loose_verts_bm(const MeshRenderData &mr, MeshBufferCache &cache, BMesh &bm)
const CustomData & mesh_cd_edata_get_from_mesh(const Mesh &mesh)
static void mesh_render_data_loose_geom_ensure(const MeshRenderData &mr, MeshBufferCache &cache)
static bke::MeshNormalDomain bmesh_normals_domain(BMesh *bm)
static void accumululate_material_counts_mesh(const MeshRenderData &mr, threading::EnumerableThreadSpecific< Array< int > > &all_tri_counts)
static void accumululate_material_counts_bm(const BMesh &bm, threading::EnumerableThreadSpecific< Array< int > > &all_tri_counts)
static void retrieve_active_attribute_names(MeshRenderData &mr, const Object &object, const Mesh &mesh)
static std::optional< Array< int > > calc_face_tri_starts_mesh(const MeshRenderData &mr, MutableSpan< int > material_tri_starts)
const Mesh & editmesh_final_or_this(const Object &object, const Mesh &mesh)
static void mesh_render_data_loose_geom_mesh(const MeshRenderData &mr, MeshBufferCache &cache)
void mesh_render_data_update_corner_normals(MeshRenderData &mr)
const SortedFaceData & mesh_render_data_faces_sorted_ensure(const MeshRenderData &mr, MeshBufferCache &cache)
const CustomData & mesh_cd_vdata_get_from_mesh(const Mesh &mesh)
MeshRenderData mesh_render_data_create(Object &object, Mesh &mesh, const bool is_editmode, const bool is_paint_mode, const bool do_final, const bool do_uvedit, const bool use_hide, const ToolSettings *ts)
void mesh_render_data_update_loose_geom(MeshRenderData &mr, MeshBufferCache &cache)
static void mesh_render_data_loose_geom_build(const MeshRenderData &mr, MeshBufferCache &cache)
static void extract_set_bits(const BitSpan bits, MutableSpan< int > indices)
static SortedFaceData mesh_render_data_faces_sorted_build(const MeshRenderData &mr)
static void mesh_render_data_loose_edges_bm(const MeshRenderData &mr, MeshBufferCache &cache, BMesh &bm)
static bool bm_face_is_sharp(const BMFace *const &face)
static bool bm_edge_is_sharp(const BMEdge *const &edge)
const CustomData & mesh_cd_pdata_get_from_mesh(const Mesh &mesh)
OffsetIndices< int > accumulate_counts_to_offsets(MutableSpan< int > counts_to_offsets, int start_offset=0)
void parallel_invoke(Functions &&...functions)
Definition BLI_task.hh:221
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
Value parallel_reduce(IndexRange range, int64_t grain_size, const Value &identity, const Function &function, const Reduction &reduction)
Definition BLI_task.hh:151
struct BMLoop * l
short mat_nr
struct BMEdge * e
CustomData vdata
CustomData edata
CustomData pdata
CustomData ldata
int corners_num
CustomData edge_data
int edges_num
MeshRuntimeHandle * runtime
CustomData corner_data
CustomData face_data
char * default_color_attribute
CustomData vert_data
int faces_num
int verts_num
char * active_color_attribute
blender::BitVector is_loose_bits
bke::EditMeshData * edit_data
const ToolSettings * toolsettings
VArraySpan< bool > select_vert
VArraySpan< bool > sharp_faces
VArraySpan< bool > select_poly
VArraySpan< bool > select_edge
VArraySpan< int > material_indices
OffsetIndices< int > faces
bke::MeshNormalDomain normals_domain
std::optional< Array< int > > face_tri_offsets
i
Definition text_draw.cc:230