Blender V4.3
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
11#include "MEM_guardedalloc.h"
12
13#include "BLI_array.hh"
14#include "BLI_array_utils.hh"
16#include "BLI_index_mask.hh"
17#include "BLI_math_matrix.h"
18#include "BLI_task.hh"
19#include "BLI_virtual_array.hh"
20
21#include "BKE_attribute.hh"
22#include "BKE_editmesh.hh"
23#include "BKE_editmesh_cache.hh"
24#include "BKE_mesh.hh"
25#include "BKE_mesh_runtime.hh"
26#include "BKE_object.hh"
27
28#include "GPU_batch.hh"
29
30#include "ED_mesh.hh"
31
33
34/* ---------------------------------------------------------------------- */
38namespace blender::draw {
39
40static void extract_set_bits(const BitSpan bits, MutableSpan<int> indices)
41{
42 int count = 0;
43 for (const int64_t i : bits.index_range()) {
44 if (bits[i]) {
45 indices[count] = int(i);
46 count++;
47 }
48 }
49 BLI_assert(count == indices.size());
50}
51
53{
54 const Mesh &mesh = *mr.mesh;
55 const bool no_loose_vert_hint = mesh.runtime->loose_verts_cache.is_cached() &&
56 mesh.runtime->loose_verts_cache.data().count == 0;
57 const bool no_loose_edge_hint = mesh.runtime->loose_edges_cache.is_cached() &&
58 mesh.runtime->loose_edges_cache.data().count == 0;
60 mesh.edges_num > 4096 && !no_loose_vert_hint && !no_loose_edge_hint,
61 [&]() {
62 const bke::LooseEdgeCache &loose_edges = mesh.loose_edges();
63 if (loose_edges.count > 0) {
64 cache.loose_geom.edges.reinitialize(loose_edges.count);
65 extract_set_bits(loose_edges.is_loose_bits, cache.loose_geom.edges);
66 }
67 },
68 [&]() {
69 const bke::LooseVertCache &loose_verts = mesh.loose_verts();
70 if (loose_verts.count > 0) {
71 cache.loose_geom.verts.reinitialize(loose_verts.count);
72 extract_set_bits(loose_verts.is_loose_bits, cache.loose_geom.verts);
73 }
74 });
75}
76
78 MeshBufferCache &cache,
79 BMesh &bm)
80{
81 int i;
82 BMIter iter;
83 BMVert *vert;
84 int count = 0;
85 Array<int> loose_verts(mr.verts_num);
86 BM_ITER_MESH_INDEX (vert, &iter, &bm, BM_VERTS_OF_MESH, i) {
87 if (vert->e == nullptr) {
88 loose_verts[count] = i;
89 count++;
90 }
91 }
92 if (count < mr.verts_num) {
93 cache.loose_geom.verts = loose_verts.as_span().take_front(count);
94 }
95 else {
96 cache.loose_geom.verts = std::move(loose_verts);
97 }
98}
99
101 MeshBufferCache &cache,
102 BMesh &bm)
103{
104 int i;
105 BMIter iter;
106 BMEdge *edge;
107 int count = 0;
108 Array<int> loose_edges(mr.edges_num);
109 BM_ITER_MESH_INDEX (edge, &iter, &bm, BM_EDGES_OF_MESH, i) {
110 if (edge->l == nullptr) {
111 loose_edges[count] = i;
112 count++;
113 }
114 }
115 if (count < mr.edges_num) {
116 cache.loose_geom.edges = loose_edges.as_span().take_front(count);
117 }
118 else {
119 cache.loose_geom.edges = std::move(loose_edges);
120 }
121}
122
124{
125 if (mr.extract_type != MR_EXTRACT_BMESH) {
126 /* Mesh */
128 }
129 else {
130 /* #BMesh */
131 BMesh &bm = *mr.bm;
134 }
135}
136
138{
139 /* Early exit: Are loose geometry already available.
140 * Only checking for loose verts as loose edges and verts are calculated at the same time. */
141 if (!cache.loose_geom.verts.is_empty()) {
142 return;
143 }
145}
146
157
160/* ---------------------------------------------------------------------- */
168{
169 threading::parallel_for(IndexRange(bm.totface), 1024, [&](const IndexRange range) {
170 Array<int> &tri_counts = all_tri_counts.local();
171 const short last_index = tri_counts.size() - 1;
172 for (const int i : range) {
173 const BMFace &face = *BM_face_at_index(&const_cast<BMesh &>(bm), i);
174 if (!BM_elem_flag_test(&face, BM_ELEM_HIDDEN)) {
175 const short mat = std::clamp<short>(face.mat_nr, 0, last_index);
176 tri_counts[mat] += face.len - 2;
177 }
178 }
179 });
180}
181
184{
185 const OffsetIndices faces = mr.faces;
186 const Span<bool> hide_poly = mr.hide_poly;
187 const Span material_indices = mr.material_indices;
188 if (material_indices.is_empty()) {
189 if (!hide_poly.is_empty()) {
190 all_tri_counts.local().first() = threading::parallel_reduce(
191 faces.index_range(),
192 4096,
193 0,
194 [&](const IndexRange range, int count) {
195 for (const int face : range) {
196 if (!hide_poly[face]) {
197 count += bke::mesh::face_triangles_num(faces[face].size());
198 }
199 }
200 return count;
201 },
202 std::plus<int>());
203 }
204 else {
205 all_tri_counts.local().first() = poly_to_tri_count(mr.faces_num, mr.corners_num);
206 }
207 return;
208 }
209
210 threading::parallel_for(material_indices.index_range(), 1024, [&](const IndexRange range) {
211 Array<int> &tri_counts = all_tri_counts.local();
212 const int last_index = tri_counts.size() - 1;
213 if (!hide_poly.is_empty()) {
214 for (const int i : range) {
215 if (!hide_poly[i]) {
216 const int mat = std::clamp(material_indices[i], 0, last_index);
217 tri_counts[mat] += bke::mesh::face_triangles_num(faces[i].size());
218 }
219 }
220 }
221 else {
222 for (const int i : range) {
223 const int mat = std::clamp(material_indices[i], 0, last_index);
224 tri_counts[mat] += bke::mesh::face_triangles_num(faces[i].size());
225 }
226 }
227 });
228}
229
230/* Count how many triangles for each material. */
232{
234 [&]() { return Array<int>(mr.materials_num, 0); });
235
236 if (mr.extract_type == MR_EXTRACT_BMESH) {
237 accumululate_material_counts_bm(*mr.bm, all_tri_counts);
238 }
239 else {
240 accumululate_material_counts_mesh(mr, all_tri_counts);
241 }
242
243 Array<int> &tris_num_by_material = all_tri_counts.local();
244 for (const Array<int> &counts : all_tri_counts) {
245 if (&counts != &tris_num_by_material) {
246 for (const int i : tris_num_by_material.index_range()) {
247 tris_num_by_material[i] += counts[i];
248 }
249 }
250 }
251 return std::move(tris_num_by_material);
252}
253
255 MutableSpan<int> material_tri_starts)
256{
257 BMesh &bm = *mr.bm;
258 Array<int> face_tri_offsets(bm.totface);
259#ifndef NDEBUG
260 face_tri_offsets.fill(-1);
261#endif
262
263 const int mat_last = mr.materials_num - 1;
264 BMIter iter;
265 BMFace *face;
266 int i;
267 BM_ITER_MESH_INDEX (face, &iter, &bm, BM_FACES_OF_MESH, i) {
269 continue;
270 }
271 const int mat = std::clamp(int(face->mat_nr), 0, mat_last);
272 face_tri_offsets[i] = material_tri_starts[mat];
273 material_tri_starts[mat] += face->len - 2;
274 }
275
276 return face_tri_offsets;
277}
278
279static bool mesh_is_single_material(const OffsetIndices<int> material_tri_starts)
280{
281 const int used_materials = std::count_if(
282 material_tri_starts.index_range().begin(),
283 material_tri_starts.index_range().end(),
284 [&](const int i) { return material_tri_starts[i].size() > 0; });
285 return used_materials == 1;
286}
287
288static std::optional<Array<int>> calc_face_tri_starts_mesh(const MeshRenderData &mr,
289 MutableSpan<int> material_tri_starts)
290{
291 const bool single_material = mesh_is_single_material(material_tri_starts.as_span());
292 if (single_material && mr.hide_poly.is_empty()) {
293 return std::nullopt;
294 }
295
296 const OffsetIndices faces = mr.faces;
297 const Span<bool> hide_poly = mr.hide_poly;
298
299 Array<int> face_tri_offsets(faces.size());
300#ifndef NDEBUG
301 face_tri_offsets.fill(-1);
302#endif
303
304 if (single_material) {
305 int offset = 0;
306 for (const int face : faces.index_range()) {
307 if (hide_poly[face]) {
308 continue;
309 }
310 face_tri_offsets[face] = offset;
311 offset += bke::mesh::face_triangles_num(faces[face].size());
312 }
313 return face_tri_offsets;
314 }
315
316 const Span<int> material_indices = mr.material_indices;
317 const int mat_last = mr.materials_num - 1;
318 for (const int face : faces.index_range()) {
319 if (!hide_poly.is_empty() && hide_poly[face]) {
320 continue;
321 }
322 const int mat = std::clamp(material_indices[face], 0, mat_last);
323 face_tri_offsets[face] = material_tri_starts[mat];
324 material_tri_starts[mat] += bke::mesh::face_triangles_num(faces[face].size());
325 }
326
327 return face_tri_offsets;
328}
329
331{
332 SortedFaceData cache;
334 const Span<int> tris_num_by_material = cache.tris_num_by_material;
335
336 Array<int, 32> material_tri_starts(mr.materials_num + 1);
337 material_tri_starts.as_mutable_span().drop_back(1).copy_from(tris_num_by_material);
338 offset_indices::accumulate_counts_to_offsets(material_tri_starts);
339 cache.visible_tris_num = material_tri_starts.last();
340
341 /* Sort per material. */
342 if (mr.extract_type == MR_EXTRACT_BMESH) {
343 cache.face_tri_offsets = calc_face_tri_starts_bmesh(mr, material_tri_starts);
344 }
345 else {
346 cache.face_tri_offsets = calc_face_tri_starts_mesh(mr, material_tri_starts);
347 }
348 return cache;
349}
350
352 MeshBufferCache &cache)
353{
354 if (cache.face_sorted.visible_tris_num == 0) {
356 }
357 return cache.face_sorted;
358}
359
362/* ---------------------------------------------------------------------- */
366const Mesh &editmesh_final_or_this(const Object &object, const Mesh &mesh)
367{
368 if (mesh.runtime->edit_mesh != nullptr) {
369 if (const Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(&object)) {
370 return *editmesh_eval_final;
371 }
372 }
373
374 return mesh;
375}
376
378{
379 switch (mesh.runtime->wrapper_type) {
382 return mesh.corner_data;
383 break;
385 return mesh.runtime->edit_mesh->bm->ldata;
386 break;
387 }
388
389 BLI_assert(0);
390 return mesh.corner_data;
391}
392
394{
395 switch (mesh.runtime->wrapper_type) {
398 return mesh.face_data;
399 break;
401 return mesh.runtime->edit_mesh->bm->pdata;
402 break;
403 }
404
405 BLI_assert(0);
406 return mesh.face_data;
407}
408
410{
411 switch (mesh.runtime->wrapper_type) {
414 return mesh.edge_data;
415 break;
417 return mesh.runtime->edit_mesh->bm->edata;
418 break;
419 }
420
421 BLI_assert(0);
422 return mesh.edge_data;
423}
424
426{
427 switch (mesh.runtime->wrapper_type) {
430 return mesh.vert_data;
431 break;
433 return mesh.runtime->edit_mesh->bm->vdata;
434 break;
435 }
436
437 BLI_assert(0);
438 return mesh.vert_data;
439}
440
441static bool bm_edge_is_sharp(const BMEdge *const &edge)
442{
443 return !BM_elem_flag_test(edge, BM_ELEM_SMOOTH);
444}
445
446static bool bm_face_is_sharp(const BMFace *const &face)
447{
448 return !BM_elem_flag_test(face, BM_ELEM_SMOOTH);
449}
450
456{
457 if (bm->totface == 0) {
458 return bke::MeshNormalDomain::Point;
459 }
460
462 return bke::MeshNormalDomain::Corner;
463 }
464
467 Span(bm->ftable, bm->totface));
468 const array_utils::BooleanMix face_mix = array_utils::booleans_mix_calc(sharp_faces);
469 if (face_mix == array_utils::BooleanMix::AllTrue) {
470 return bke::MeshNormalDomain::Face;
471 }
472
475 Span(bm->etable, bm->totedge));
476 const array_utils::BooleanMix edge_mix = array_utils::booleans_mix_calc(sharp_edges);
477 if (edge_mix == array_utils::BooleanMix::AllTrue) {
478 return bke::MeshNormalDomain::Face;
479 }
480
481 if (edge_mix == array_utils::BooleanMix::AllFalse &&
482 face_mix == array_utils::BooleanMix::AllFalse)
483 {
484 return bke::MeshNormalDomain::Point;
485 }
486
487 return bke::MeshNormalDomain::Corner;
488}
489
491{
492 if (mr.extract_type != MR_EXTRACT_BMESH) {
493 mr.corner_normals = mr.mesh->corner_normals();
494 }
495 else {
497 const int clnors_offset = CustomData_get_offset(&mr.bm->ldata, CD_CUSTOMLOOPNORMAL);
502 true,
504 nullptr,
505 nullptr,
506 clnors_offset,
507 false);
508 }
509}
510
512{
513 if (mr.extract_type != MR_EXTRACT_BMESH) {
514 /* Eager calculation of face normals can reduce waiting on the lazy cache's lock. */
515 mr.face_normals = mr.mesh->face_normals();
516 }
517 else {
518 /* Use #BMFace.no instead. */
519 }
520}
521
523 const Object &object,
524 const Mesh &mesh)
525{
526 const Mesh &mesh_final = editmesh_final_or_this(object, mesh);
529}
530
531std::unique_ptr<MeshRenderData> mesh_render_data_create(Object &object,
532 Mesh &mesh,
533 const bool is_editmode,
534 const bool is_paint_mode,
535 const bool edit_mode_active,
536 const float4x4 &object_to_world,
537 const bool do_final,
538 const bool do_uvedit,
539 const bool use_hide,
540 const ToolSettings *ts)
541{
542 std::unique_ptr<MeshRenderData> mr = std::make_unique<MeshRenderData>();
543 mr->toolsettings = ts;
544 mr->materials_num = mesh_render_mat_len_get(object, mesh);
545
546 mr->object_to_world = object_to_world;
547
548 mr->use_hide = use_hide;
549
550 if (is_editmode) {
551 const Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(&object);
552 const Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(&object);
553
554 BLI_assert(editmesh_eval_cage && editmesh_eval_final);
555 mr->bm = mesh.runtime->edit_mesh->bm;
556 mr->edit_bmesh = mesh.runtime->edit_mesh.get();
557 mr->mesh = (do_final) ? editmesh_eval_final : editmesh_eval_cage;
558 mr->edit_data = edit_mode_active ? mr->mesh->runtime->edit_data.get() : nullptr;
559
560 /* If there is no distinct cage, hide unmapped edges that can't be selected. */
561 mr->hide_unmapped_edges = !do_final || editmesh_eval_final == editmesh_eval_cage;
562
563 if (bke::EditMeshData *emd = mr->edit_data) {
564 if (!emd->vert_positions.is_empty()) {
565 mr->bm_vert_coords = mr->edit_data->vert_positions;
566 mr->bm_vert_normals = BKE_editmesh_cache_ensure_vert_normals(*mr->edit_bmesh, *emd);
567 mr->bm_face_normals = BKE_editmesh_cache_ensure_face_normals(*mr->edit_bmesh, *emd);
568 }
569 }
570
571 int bm_ensure_types = BM_VERT | BM_EDGE | BM_LOOP | BM_FACE;
572
573 BM_mesh_elem_index_ensure(mr->bm, bm_ensure_types);
574 BM_mesh_elem_table_ensure(mr->bm, bm_ensure_types & ~BM_LOOP);
575
576 mr->efa_act_uv = EDBM_uv_active_face_get(mr->edit_bmesh, false, false);
577 mr->efa_act = BM_mesh_active_face_get(mr->bm, false, true);
578 mr->eed_act = BM_mesh_active_edge_get(mr->bm);
579 mr->eve_act = BM_mesh_active_vert_get(mr->bm);
580
581 mr->vert_crease_ofs = CustomData_get_offset_named(
582 &mr->bm->vdata, CD_PROP_FLOAT, "crease_vert");
583 mr->edge_crease_ofs = CustomData_get_offset_named(
584 &mr->bm->edata, CD_PROP_FLOAT, "crease_edge");
585 mr->bweight_ofs = CustomData_get_offset_named(
586 &mr->bm->edata, CD_PROP_FLOAT, "bevel_weight_edge");
587#ifdef WITH_FREESTYLE
588 mr->freestyle_edge_ofs = CustomData_get_offset(&mr->bm->edata, CD_FREESTYLE_EDGE);
589 mr->freestyle_face_ofs = CustomData_get_offset(&mr->bm->pdata, CD_FREESTYLE_FACE);
590#endif
591
592 /* Use bmesh directly when the object is in edit mode unchanged by any modifiers.
593 * For non-final UVs, always use original bmesh since the UV editor does not support
594 * using the cage mesh with deformed coordinates. */
595 if ((edit_mode_active && mr->mesh->runtime->is_original_bmesh &&
596 mr->mesh->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH) ||
597 (do_uvedit && !do_final))
598 {
599 mr->extract_type = MR_EXTRACT_BMESH;
600 }
601 else {
602 mr->extract_type = MR_EXTRACT_MESH;
603
604 /* Use mapping from final to original mesh when the object is in edit mode. */
605 if (edit_mode_active && do_final) {
606 mr->orig_index_vert = static_cast<const int *>(
607 CustomData_get_layer(&mr->mesh->vert_data, CD_ORIGINDEX));
608 mr->orig_index_edge = static_cast<const int *>(
609 CustomData_get_layer(&mr->mesh->edge_data, CD_ORIGINDEX));
610 mr->orig_index_face = static_cast<const int *>(
611 CustomData_get_layer(&mr->mesh->face_data, CD_ORIGINDEX));
612 }
613 else {
614 mr->orig_index_vert = nullptr;
615 mr->orig_index_edge = nullptr;
616 mr->orig_index_face = nullptr;
617 }
618 }
619 }
620 else {
621 mr->mesh = &mesh;
622 mr->edit_bmesh = nullptr;
623 mr->extract_type = MR_EXTRACT_MESH;
624 mr->hide_unmapped_edges = false;
625
626 if (is_paint_mode && mr->mesh) {
627 mr->orig_index_vert = static_cast<const int *>(
628 CustomData_get_layer(&mr->mesh->vert_data, CD_ORIGINDEX));
629 mr->orig_index_edge = static_cast<const int *>(
630 CustomData_get_layer(&mr->mesh->edge_data, CD_ORIGINDEX));
631 mr->orig_index_face = static_cast<const int *>(
632 CustomData_get_layer(&mr->mesh->face_data, CD_ORIGINDEX));
633 }
634 else {
635 mr->orig_index_vert = nullptr;
636 mr->orig_index_edge = nullptr;
637 mr->orig_index_face = nullptr;
638 }
639 }
640
641 if (mr->extract_type != MR_EXTRACT_BMESH) {
642 /* Mesh */
643 mr->verts_num = mr->mesh->verts_num;
644 mr->edges_num = mr->mesh->edges_num;
645 mr->faces_num = mr->mesh->faces_num;
646 mr->corners_num = mr->mesh->corners_num;
647 mr->corner_tris_num = poly_to_tri_count(mr->faces_num, mr->corners_num);
648
649 mr->vert_positions = mr->mesh->vert_positions();
650 mr->edges = mr->mesh->edges();
651 mr->faces = mr->mesh->faces();
652 mr->corner_verts = mr->mesh->corner_verts();
653 mr->corner_edges = mr->mesh->corner_edges();
654
655 mr->orig_index_vert = static_cast<const int *>(
656 CustomData_get_layer(&mr->mesh->vert_data, CD_ORIGINDEX));
657 mr->orig_index_edge = static_cast<const int *>(
658 CustomData_get_layer(&mr->mesh->edge_data, CD_ORIGINDEX));
659 mr->orig_index_face = static_cast<const int *>(
660 CustomData_get_layer(&mr->mesh->face_data, CD_ORIGINDEX));
661
662 mr->normals_domain = mr->mesh->normals_domain();
663
664 const bke::AttributeAccessor attributes = mr->mesh->attributes();
665
666 mr->material_indices = *attributes.lookup<int>("material_index", bke::AttrDomain::Face);
667
668 if (edit_mode_active || is_paint_mode) {
669 if (use_hide) {
670 mr->hide_vert = *attributes.lookup<bool>(".hide_vert", bke::AttrDomain::Point);
671 mr->hide_edge = *attributes.lookup<bool>(".hide_edge", bke::AttrDomain::Edge);
672 mr->hide_poly = *attributes.lookup<bool>(".hide_poly", bke::AttrDomain::Face);
673 }
674
675 mr->select_vert = *attributes.lookup<bool>(".select_vert", bke::AttrDomain::Point);
676 mr->select_edge = *attributes.lookup<bool>(".select_edge", bke::AttrDomain::Edge);
677 mr->select_poly = *attributes.lookup<bool>(".select_poly", bke::AttrDomain::Face);
678 }
679
680 mr->sharp_faces = *attributes.lookup<bool>("sharp_face", bke::AttrDomain::Face);
681 }
682 else {
683 /* #BMesh */
684 BMesh *bm = mr->bm;
685
686 mr->verts_num = bm->totvert;
687 mr->edges_num = bm->totedge;
688 mr->faces_num = bm->totface;
689 mr->corners_num = bm->totloop;
690 mr->corner_tris_num = poly_to_tri_count(mr->faces_num, mr->corners_num);
691
692 mr->normals_domain = bmesh_normals_domain(bm);
693 }
694
695 retrieve_active_attribute_names(*mr, object, *mr->mesh);
696
697 return mr;
698}
699
702} // namespace blender::draw
int CustomData_get_offset(const CustomData *data, eCustomDataType type)
const void * CustomData_get_layer(const CustomData *data, eCustomDataType type)
int CustomData_get_offset_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
bool CustomData_has_layer(const CustomData *data, eCustomDataType type)
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)
@ ME_WRAPPER_TYPE_MDATA
@ ME_WRAPPER_TYPE_SUBD
@ ME_WRAPPER_TYPE_BMESH
General operations, lookup, etc. for blender objects.
const Mesh * BKE_object_get_editmesh_eval_cage(const Object *object)
const Mesh * BKE_object_get_editmesh_eval_final(const Object *object)
#define BLI_assert(a)
Definition BLI_assert.h:50
MINLINE int poly_to_tri_count(int poly_count, int corner_count)
@ CD_PROP_FLOAT
@ CD_CUSTOMLOOPNORMAL
@ CD_FREESTYLE_EDGE
@ CD_FREESTYLE_FACE
BMFace * EDBM_uv_active_face_get(BMEditMesh *em, bool sloppy, bool selected)
Read Guarded memory(de)allocation.
@ BM_LOOP
@ BM_ELEM_HIDDEN
@ BM_ELEM_SMOOTH
#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
ATTR_WARN_UNUSED_RESULT 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
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
int64_t size() const
Definition BLI_array.hh:245
Span< T > as_span() const
Definition BLI_array.hh:232
MutableSpan< T > as_mutable_span()
Definition BLI_array.hh:237
const T & last(const int64_t n=0) const
Definition BLI_array.hh:285
IndexRange index_range() const
Definition BLI_array.hh:349
void fill(const T &value) const
Definition BLI_array.hh:261
void reinitialize(const int64_t new_size)
Definition BLI_array.hh:388
bool is_empty() const
Definition BLI_array.hh:253
constexpr Iterator end() const
constexpr Iterator begin() const
constexpr Span< T > as_span() const
Definition BLI_span.hh:662
constexpr const T & first() const
Definition BLI_span.hh:316
constexpr bool is_empty() const
Definition BLI_span.hh:261
IndexRange index_range() const
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
Extraction of Mesh data into VBO to feed to GPU.
int count
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)
int mesh_render_mat_len_get(const Object &object, const Mesh &mesh)
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)
std::unique_ptr< MeshRenderData > mesh_render_data_create(Object &object, Mesh &mesh, const bool is_editmode, const bool is_paint_mode, const bool edit_mode_active, const float4x4 &object_to_world, const bool do_final, const bool do_uvedit, const bool use_hide, const ToolSettings *ts)
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)
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)
void parallel_invoke(Functions &&...functions)
Definition BLI_task.hh:199
__int64 int64_t
Definition stdint.h:89
struct BMEdge * e
int totvert
BMEdge ** etable
int totedge
int totloop
CustomData ldata
BMFace ** ftable
int totface
MeshRuntimeHandle * runtime
char * default_color_attribute
char * active_color_attribute
blender::BitVector is_loose_bits
VArraySpan< int > material_indices
OffsetIndices< int > faces
std::optional< Array< int > > face_tri_offsets