52 const bool no_loose_vert_hint =
mesh.
runtime->loose_verts_cache.is_cached() &&
54 const bool no_loose_edge_hint =
mesh.
runtime->loose_edges_cache.is_cached() &&
57 mesh.
edges_num > 4096 && !no_loose_vert_hint && !no_loose_edge_hint,
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);
67 if (loose_verts.
count > 0) {
68 cache.loose_geom.verts.reinitialize(loose_verts.
count);
84 if (vert->
e ==
nullptr) {
85 loose_verts[
count] = i;
107 if (edge->
l ==
nullptr) {
108 loose_edges[
count] = i;
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;
185 all_tri_counts.local().
first() = threading::parallel_reduce(
190 for (const int face : range) {
191 if (!hide_poly[face]) {
192 count += bke::mesh::face_triangles_num(faces[face].size());
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) {
211 const int mat = std::clamp(material_indices[i], 0, last_index);
212 tri_counts[mat] += bke::mesh::face_triangles_num(faces[i].size());
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());
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];
246 return std::move(tris_num_by_material);
255 face_tri_offsets.
fill(-1);
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;
271 return face_tri_offsets;
276 const int used_materials = std::count_if(
279 [&](
const int i) { return material_tri_starts[i].size() > 0; });
280 return used_materials == 1;
296 face_tri_offsets.
fill(-1);
299 if (single_material) {
301 for (
const int face :
faces.index_range()) {
302 if (hide_poly[face]) {
305 face_tri_offsets[face] = offset;
306 offset += bke::mesh::face_triangles_num(
faces[face].
size());
308 return face_tri_offsets;
313 for (
const int face :
faces.index_range()) {
314 if (!hide_poly.
is_empty() && hide_poly[face]) {
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());
322 return face_tri_offsets;
332 material_tri_starts.
as_mutable_span().drop_back(1).copy_from(tris_num_by_material);
333 offset_indices::accumulate_counts_to_offsets(material_tri_starts);
365 return *editmesh_eval_final;
453 return bke::MeshNormalDomain::Point;
457 return bke::MeshNormalDomain::Point;
460 return bke::MeshNormalDomain::Face;
463 return bke::MeshNormalDomain::Corner;
466 return bke::MeshNormalDomain::Corner;
473 if (face_mix == array_utils::BooleanMix::AllTrue) {
474 return bke::MeshNormalDomain::Face;
481 if (edge_mix == array_utils::BooleanMix::AllTrue) {
482 return bke::MeshNormalDomain::Face;
485 if (edge_mix == array_utils::BooleanMix::AllFalse &&
486 face_mix == array_utils::BooleanMix::AllFalse)
488 return bke::MeshNormalDomain::Point;
491 return bke::MeshNormalDomain::Corner;
545 const bool is_editmode,
546 const bool is_paint_mode,
548 const bool do_uvedit,
556 mr.use_hide = use_hide;
559 if (editmesh_orig && editmesh_orig->
runtime->edit_mesh) {
562 mr.bm = editmesh_orig->
runtime->edit_mesh->bm;
563 mr.edit_bmesh = editmesh_orig->
runtime->edit_mesh.get();
564 mr.mesh = (do_final) ? &
mesh : eval_cage;
565 mr.edit_data = is_editmode ? mr.mesh->
runtime->edit_data.get() :
nullptr;
568 mr.hide_unmapped_edges = !do_final || &
mesh == eval_cage;
578 if (!emd->vert_positions.is_empty()) {
579 mr.bm_vert_coords = mr.edit_data->vert_positions;
580 if (mr.bm_free_normal_offset_vert == -1) {
583 if (mr.bm_free_normal_offset_face == -1) {
611 if ((mr.mesh->runtime->is_original_bmesh &&
613 (do_uvedit && !do_final))
615 mr.extract_type = MeshExtractType::BMesh;
618 mr.extract_type = MeshExtractType::Mesh;
621 if (is_editmode && do_final) {
622 mr.orig_index_vert =
static_cast<const int *
>(
624 mr.orig_index_edge =
static_cast<const int *
>(
626 mr.orig_index_face =
static_cast<const int *
>(
630 mr.orig_index_vert =
nullptr;
631 mr.orig_index_edge =
nullptr;
632 mr.orig_index_face =
nullptr;
638 mr.edit_bmesh =
nullptr;
639 mr.extract_type = MeshExtractType::Mesh;
640 mr.hide_unmapped_edges =
false;
642 if (is_paint_mode && mr.mesh) {
643 mr.orig_index_vert =
static_cast<const int *
>(
645 mr.orig_index_edge =
static_cast<const int *
>(
647 mr.orig_index_face =
static_cast<const int *
>(
651 mr.orig_index_vert =
nullptr;
652 mr.orig_index_edge =
nullptr;
653 mr.orig_index_face =
nullptr;
657 if (mr.extract_type == MeshExtractType::Mesh) {
659 mr.edges_num = mr.mesh->edges_num;
660 mr.faces_num = mr.mesh->faces_num;
661 mr.corners_num = mr.mesh->corners_num;
664 mr.vert_positions = mr.mesh->vert_positions();
665 mr.edges = mr.mesh->edges();
666 mr.faces = mr.mesh->faces();
667 mr.corner_verts = mr.mesh->corner_verts();
668 mr.corner_edges = mr.mesh->corner_edges();
670 mr.orig_index_vert =
static_cast<const int *
>(
672 mr.orig_index_edge =
static_cast<const int *
>(
674 mr.orig_index_face =
static_cast<const int *
>(
677 mr.normals_domain = mr.mesh->normals_domain();
681 mr.material_indices = *attributes.
lookup<
int>(
"material_index", bke::AttrDomain::Face);
683 if (is_editmode || is_paint_mode) {
685 mr.hide_vert = *attributes.
lookup<
bool>(
".hide_vert", bke::AttrDomain::Point);
686 mr.hide_edge = *attributes.
lookup<
bool>(
".hide_edge", bke::AttrDomain::Edge);
687 mr.hide_poly = *attributes.
lookup<
bool>(
".hide_poly", bke::AttrDomain::Face);
690 mr.select_vert = *attributes.
lookup<
bool>(
".select_vert", bke::AttrDomain::Point);
691 mr.select_edge = *attributes.
lookup<
bool>(
".select_edge", bke::AttrDomain::Edge);
692 mr.select_poly = *attributes.
lookup<
bool>(
".select_poly", bke::AttrDomain::Face);
695 mr.sharp_faces = *attributes.
lookup<
bool>(
"sharp_face", bke::AttrDomain::Face);
int CustomData_get_offset(const CustomData *data, eCustomDataType type)
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)
General operations, lookup, etc. for blender objects.
const Mesh * BKE_object_get_pre_modified_mesh(const Object *object)
const Mesh * BKE_object_get_editmesh_eval_final(const Object *object)
MINLINE int poly_to_tri_count(int poly_count, int corner_count)
BMFace * EDBM_uv_active_face_get(BMEditMesh *em, bool sloppy, bool selected)
#define BM_elem_flag_test(ele, hflag)
#define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar)
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)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Span< T > as_span() const
MutableSpan< T > as_mutable_span()
const T & last(const int64_t n=0) const
IndexRange index_range() const
void fill(const T &value) const
void reinitialize(const int64_t new_size)
constexpr Iterator end() const
constexpr Iterator begin() const
constexpr Span< T > as_span() const
constexpr const T & first() const
constexpr bool is_empty() const
IndexRange index_range() const
GAttributeReader lookup(const StringRef attribute_id) const
IndexRange index_range() const
const Mesh * DRW_object_get_editmesh_cage_for_drawing(const Object &object)
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)
void parallel_invoke(Functions &&...functions)
MeshRuntimeHandle * runtime
char * default_color_attribute
char * active_color_attribute
blender::BitVector is_loose_bits
MeshExtractLooseGeom loose_geom
SortedFaceData face_sorted
const char * default_color_name
Span< float3 > bm_vert_coords
Span< float3 > bm_vert_normals
const ToolSettings * toolsettings
MeshExtractType extract_type
const char * active_color_name
int bm_free_normal_offset_face
Span< float3 > bm_face_normals
Span< float3 > face_normals
int bm_free_normal_offset_corner
Span< float3 > corner_normals
VArraySpan< int > material_indices
VArraySpan< bool > hide_poly
OffsetIndices< int > faces
int bm_free_normal_offset_vert
Array< float3 > bm_loop_normals
std::optional< Array< int > > face_tri_offsets
Array< int > tris_num_by_material