diff --git a/intern/cycles/blender/mesh.cpp b/intern/cycles/blender/mesh.cpp index b0302cbfeca..e307c418bd2 100644 --- a/intern/cycles/blender/mesh.cpp +++ b/intern/cycles/blender/mesh.cpp @@ -319,10 +319,10 @@ static void fill_generic_attribute(BL::Mesh &b_mesh, } else { const int tris_num = b_mesh.loop_triangles.length(); - const MLoopTri *looptris = static_cast( - b_mesh.loop_triangles[0].ptr.data); + const int *looptri_polys = static_cast( + b_mesh.loop_triangle_polygons[0].ptr.data); for (int i = 0; i < tris_num; i++) { - data[i] = get_value_at_index(looptris[i].poly); + data[i] = get_value_at_index(looptri_polys[i]); } } break; @@ -1095,9 +1095,10 @@ static void create_mesh(Scene *scene, } if (material_indices) { + const int *looptri_polys = static_cast( + b_mesh.loop_triangle_polygons[0].ptr.data); for (int i = 0; i < numtris; i++) { - const int poly_index = looptris[i].poly; - shader[i] = clamp_material_index(material_indices[poly_index]); + shader[i] = clamp_material_index(material_indices[looptri_polys[i]]); } } else { @@ -1105,9 +1106,10 @@ static void create_mesh(Scene *scene, } if (sharp_faces && !(use_loop_normals && corner_normals)) { + const int *looptri_polys = static_cast( + b_mesh.loop_triangle_polygons[0].ptr.data); for (int i = 0; i < numtris; i++) { - const int poly_index = looptris[i].poly; - smooth[i] = !sharp_faces[poly_index]; + smooth[i] = !sharp_faces[looptri_polys[i]]; } } else { diff --git a/source/blender/blenkernel/BKE_mesh.hh b/source/blender/blenkernel/BKE_mesh.hh index 2fa1bbda6e8..95c67822020 100644 --- a/source/blender/blenkernel/BKE_mesh.hh +++ b/source/blender/blenkernel/BKE_mesh.hh @@ -37,6 +37,8 @@ void looptris_calc_with_normals(Span vert_positions, Span poly_normals, MutableSpan looptris); +void looptris_calc_poly_indices(OffsetIndices polys, MutableSpan looptri_polys); + /** Calculate the average position of the vertices in the polygon. */ float3 poly_center_calc(Span vert_positions, Span poly_verts); diff --git a/source/blender/blenkernel/BKE_mesh_mapping.h b/source/blender/blenkernel/BKE_mesh_mapping.h index a4a78b33da2..8b52ddcc3c3 100644 --- a/source/blender/blenkernel/BKE_mesh_mapping.h +++ b/source/blender/blenkernel/BKE_mesh_mapping.h @@ -211,7 +211,7 @@ void BKE_mesh_origindex_map_create( void BKE_mesh_origindex_map_create_looptri(MeshElemMap **r_map, int **r_mem, blender::OffsetIndices polys, - const struct MLoopTri *looptri, + const int *looptri_polys, int looptri_num); /* islands */ diff --git a/source/blender/blenkernel/BKE_mesh_runtime.h b/source/blender/blenkernel/BKE_mesh_runtime.h index 48907c21bc8..aed7b883197 100644 --- a/source/blender/blenkernel/BKE_mesh_runtime.h +++ b/source/blender/blenkernel/BKE_mesh_runtime.h @@ -33,6 +33,7 @@ int BKE_mesh_runtime_looptri_len(const struct Mesh *mesh); * \note Prefer #Mesh::looptris() in C++ code. */ const struct MLoopTri *BKE_mesh_runtime_looptri_ensure(const struct Mesh *mesh); +const int *BKE_mesh_runtime_looptri_polys_ensure(const struct Mesh *mesh); bool BKE_mesh_runtime_ensure_edit_data(struct Mesh *mesh); void BKE_mesh_runtime_reset_edit_data(struct Mesh *mesh); diff --git a/source/blender/blenkernel/BKE_mesh_sample.hh b/source/blender/blenkernel/BKE_mesh_sample.hh index e40c6456c79..6e94d4ccec4 100644 --- a/source/blender/blenkernel/BKE_mesh_sample.hh +++ b/source/blender/blenkernel/BKE_mesh_sample.hh @@ -49,7 +49,7 @@ void sample_corner_normals(Span looptris, IndexMask mask, MutableSpan dst); -void sample_face_attribute(Span looptris, +void sample_face_attribute(Span looptri_polys, Span looptri_indices, const GVArray &src, IndexMask mask, diff --git a/source/blender/blenkernel/BKE_mesh_tangent.h b/source/blender/blenkernel/BKE_mesh_tangent.h index 88c150ed261..2d1101bf7dc 100644 --- a/source/blender/blenkernel/BKE_mesh_tangent.h +++ b/source/blender/blenkernel/BKE_mesh_tangent.h @@ -60,6 +60,7 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3], blender::OffsetIndices polys, const int *corner_verts, const struct MLoopTri *looptri, + const int *looptri_polys, uint looptri_len, const bool *sharp_faces, diff --git a/source/blender/blenkernel/BKE_mesh_types.h b/source/blender/blenkernel/BKE_mesh_types.h index 3a1f64fdbeb..7f84a8a8830 100644 --- a/source/blender/blenkernel/BKE_mesh_types.h +++ b/source/blender/blenkernel/BKE_mesh_types.h @@ -119,6 +119,7 @@ struct MeshRuntime { /** Cache for derived triangulation of the mesh, accessed with #Mesh::looptris(). */ SharedCache> looptris_cache; + SharedCache> looptri_polys_cache; /** Cache for BVH trees generated for the mesh. Defined in 'BKE_bvhutil.c' */ BVHCache *bvh_cache = nullptr; diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index ac4f0532315..cb674d3f744 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -218,7 +218,7 @@ bool BKE_paint_always_hide_test(struct Object *ob); /** * Returns non-zero if any of the face's vertices are hidden, zero otherwise. */ -bool paint_is_face_hidden(const struct MLoopTri *lt, const bool *hide_poly); +bool paint_is_face_hidden(const int *looptri_polys, const bool *hide_poly, int tri_index); /** * Returns non-zero if any of the corners of the grid * face whose inner corner is at (x, y) are hidden, zero otherwise. diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 877f11d3069..0a9b7b629e9 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -713,7 +713,7 @@ typedef struct PBVHFaceIter { bool *hide_poly_; int *face_sets_; const int *poly_offsets_; - const struct MLoopTri *looptri_; + const int *looptri_polys_; const int *corner_verts_; int prim_index_; const struct SubdivCCG *subdiv_ccg_; diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index b4866067015..cc146cc3079 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -134,6 +134,7 @@ static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int mesh_dst->runtime->verts_no_face_cache = mesh_src->runtime->verts_no_face_cache; mesh_dst->runtime->loose_edges_cache = mesh_src->runtime->loose_edges_cache; mesh_dst->runtime->looptris_cache = mesh_src->runtime->looptris_cache; + mesh_dst->runtime->looptri_polys_cache = mesh_src->runtime->looptri_polys_cache; /* Only do tessface if we have no polys. */ const bool do_tessface = ((mesh_src->totface != 0) && (mesh_src->totpoly == 0)); diff --git a/source/blender/blenkernel/intern/mesh_mapping.cc b/source/blender/blenkernel/intern/mesh_mapping.cc index ad3cfbc482d..29655e7266c 100644 --- a/source/blender/blenkernel/intern/mesh_mapping.cc +++ b/source/blender/blenkernel/intern/mesh_mapping.cc @@ -498,7 +498,7 @@ void BKE_mesh_origindex_map_create(MeshElemMap **r_map, void BKE_mesh_origindex_map_create_looptri(MeshElemMap **r_map, int **r_mem, const blender::OffsetIndices polys, - const MLoopTri *looptri, + const int *looptri_polys, const int looptri_num) { MeshElemMap *map = MEM_cnew_array(size_t(polys.size()), __func__); @@ -514,7 +514,7 @@ void BKE_mesh_origindex_map_create_looptri(MeshElemMap **r_map, /* assign poly-tessface users */ for (int i = 0; i < looptri_num; i++) { - MeshElemMap *map_ele = &map[looptri[i].poly]; + MeshElemMap *map_ele = &map[looptri_polys[i]]; map_ele->indices[map_ele->count++] = i; } diff --git a/source/blender/blenkernel/intern/mesh_remap.cc b/source/blender/blenkernel/intern/mesh_remap.cc index a8805705e82..207ea5bb327 100644 --- a/source/blender/blenkernel/intern/mesh_remap.cc +++ b/source/blender/blenkernel/intern/mesh_remap.cc @@ -567,6 +567,7 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode, const blender::Span corner_verts_src = me_src->corner_verts(); const blender::Span positions_src = me_src->vert_positions(); const blender::Span vert_normals_dst = me_dst->vert_normals(); + const blender::Span looptri_polys = me_src->looptri_polys(); size_t tmp_buff_size = MREMAP_DEFAULT_BUFSIZE; float(*vcos)[3] = static_cast( @@ -591,8 +592,8 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode, if (mesh_remap_bvhtree_query_raycast( &treedata, &rayhit, tmp_co, tmp_no, ray_radius, max_dist, &hit_dist)) { - const MLoopTri *lt = &treedata.looptri[rayhit.index]; - const int sources_num = mesh_remap_interp_poly_data_get(polys_src[lt->poly], + const int poly_index = looptri_polys[rayhit.index]; + const int sources_num = mesh_remap_interp_poly_data_get(polys_src[poly_index], corner_verts_src, positions_src, rayhit.co, @@ -625,11 +626,11 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode, if (mesh_remap_bvhtree_query_nearest( &treedata, &nearest, tmp_co, max_dist_sq, &hit_dist)) { - const MLoopTri *lt = &treedata.looptri[nearest.index]; + const int poly_index = looptri_polys[rayhit.index]; if (mode == MREMAP_MODE_VERT_POLY_NEAREST) { int index; - mesh_remap_interp_poly_data_get(polys_src[lt->poly], + mesh_remap_interp_poly_data_get(polys_src[poly_index], corner_verts_src, positions_src, nearest.co, @@ -644,7 +645,7 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode, mesh_remap_item_define(r_map, i, hit_dist, 0, 1, &index, &full_weight); } else if (mode == MREMAP_MODE_VERT_POLYINTERP_NEAREST) { - const int sources_num = mesh_remap_interp_poly_data_get(polys_src[lt->poly], + const int sources_num = mesh_remap_interp_poly_data_get(polys_src[poly_index], corner_verts_src, positions_src, nearest.co, @@ -870,6 +871,7 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode, const blender::OffsetIndices polys_src = me_src->polys(); const blender::Span corner_edges_src = me_src->corner_edges(); const float(*positions_src)[3] = BKE_mesh_vert_positions(me_src); + const blender::Span looptri_polys = me_src->looptri_polys(); BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_LOOPTRI, 2); @@ -886,8 +888,8 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode, if (mesh_remap_bvhtree_query_nearest(&treedata, &nearest, tmp_co, max_dist_sq, &hit_dist)) { - const MLoopTri *lt = &treedata.looptri[nearest.index]; - const blender::IndexRange poly_src = polys_src[lt->poly]; + const int poly_index = looptri_polys[rayhit.index]; + const blender::IndexRange poly_src = polys_src[poly_index]; const int *corner_edge_src = &corner_edges_src[poly_src.start()]; int nloops = int(poly_src.size()); float best_dist_sq = FLT_MAX; @@ -1302,6 +1304,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, const blender::Span corner_verts_src = me_src->corner_verts(); const blender::Span corner_edges_src = me_src->corner_edges(); blender::Span looptris_src; + blender::Span looptri_polys_src; size_t buff_size_interp = MREMAP_DEFAULT_BUFSIZE; float(*vcos_interp)[3] = nullptr; @@ -1510,13 +1513,14 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, else { /* We use polygons. */ if (use_islands) { looptris_src = me_src->looptris(); + looptri_polys_src = me_src->looptri_polys(); blender::BitVector<> looptri_active(looptris_src.size()); for (tindex = 0; tindex < num_trees; tindex++) { int num_looptri_active = 0; looptri_active.fill(false); for (const int64_t i : looptris_src.index_range()) { - const blender::IndexRange poly = polys_src[looptris_src[i].poly]; + const blender::IndexRange poly = polys_src[looptri_polys_src[i]]; if (island_store.items_to_islands[poly.start()] == tindex) { looptri_active[i].set(); num_looptri_active++; @@ -1547,6 +1551,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, islands_res[tindex] = static_cast( MEM_mallocN(sizeof(**islands_res) * islands_res_buff_size, __func__)); } + const blender::Span looptri_polys = me_src->looptri_polys(); for (pidx_dst = 0; pidx_dst < polys_dst.size(); pidx_dst++) { const blender::IndexRange poly_dst = polys_dst[pidx_dst]; @@ -1703,7 +1708,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, { islands_res[tindex][plidx_dst].factor = (hit_dist ? (1.0f / hit_dist) : 1e18f) * w; islands_res[tindex][plidx_dst].hit_dist = hit_dist; - islands_res[tindex][plidx_dst].index_src = int(tdata->looptri[rayhit.index].poly); + islands_res[tindex][plidx_dst].index_src = looptri_polys[rayhit.index]; copy_v3_v3(islands_res[tindex][plidx_dst].hit_point, rayhit.co); break; } @@ -1732,7 +1737,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, if (mesh_remap_bvhtree_query_nearest( tdata, &nearest, tmp_co, max_dist_sq, &hit_dist)) { islands_res[tindex][plidx_dst].hit_dist = hit_dist; - islands_res[tindex][plidx_dst].index_src = int(tdata->looptri[nearest.index].poly); + islands_res[tindex][plidx_dst].index_src = looptri_polys[nearest.index]; copy_v3_v3(islands_res[tindex][plidx_dst].hit_point, nearest.co); } else { @@ -1755,7 +1760,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, { islands_res[tindex][plidx_dst].factor = hit_dist ? (1.0f / hit_dist) : 1e18f; islands_res[tindex][plidx_dst].hit_dist = hit_dist; - islands_res[tindex][plidx_dst].index_src = int(tdata->looptri[nearest.index].poly); + islands_res[tindex][plidx_dst].index_src = looptri_polys[nearest.index]; copy_v3_v3(islands_res[tindex][plidx_dst].hit_point, nearest.co); } else { @@ -1980,8 +1985,8 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, BKE_mesh_origindex_map_create_looptri(&poly_to_looptri_map_src, &poly_to_looptri_map_src_buff, polys_src, - looptris_src.data(), - int(looptris_src.size())); + looptri_polys_src.data(), + int(looptri_polys_src.size())); } for (j = poly_to_looptri_map_src[pidx_src].count; j--;) { @@ -2152,6 +2157,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode, BVHTreeNearest nearest = {0}; BVHTreeRayHit rayhit = {0}; float hit_dist; + const blender::Span looptri_polys = me_src->looptri_polys(); BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_LOOPTRI, 2); @@ -2171,8 +2177,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode, if (mesh_remap_bvhtree_query_nearest(&treedata, &nearest, tmp_co, max_dist_sq, &hit_dist)) { - const MLoopTri *lt = &treedata.looptri[nearest.index]; - const int poly_index = int(lt->poly); + const int poly_index = looptri_polys[nearest.index]; mesh_remap_item_define(r_map, int(i), hit_dist, 0, 1, &poly_index, &full_weight); } else { @@ -2199,9 +2204,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode, if (mesh_remap_bvhtree_query_raycast( &treedata, &rayhit, tmp_co, tmp_no, ray_radius, max_dist, &hit_dist)) { - const MLoopTri *lt = &treedata.looptri[rayhit.index]; - const int poly_index = int(lt->poly); - + const int poly_index = looptri_polys[rayhit.index]; mesh_remap_item_define(r_map, int(i), hit_dist, 0, 1, &poly_index, &full_weight); } else { @@ -2355,9 +2358,8 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode, if (mesh_remap_bvhtree_query_raycast( &treedata, &rayhit, tmp_co, tmp_no, ray_radius / w, max_dist, &hit_dist)) { - const MLoopTri *lt = &treedata.looptri[rayhit.index]; - - weights[lt->poly] += w; + const int poly_index = looptri_polys[rayhit.index]; + weights[poly_index] += w; totweights += w; hit_dist_accum += hit_dist; break; diff --git a/source/blender/blenkernel/intern/mesh_remesh_voxel.cc b/source/blender/blenkernel/intern/mesh_remesh_voxel.cc index 8b3808b5034..30d7bd3a461 100644 --- a/source/blender/blenkernel/intern/mesh_remesh_voxel.cc +++ b/source/blender/blenkernel/intern/mesh_remesh_voxel.cc @@ -330,7 +330,7 @@ void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, const Mesh *source) const VArraySpan src(src_face_sets); MutableSpan dst = dst_face_sets.span; - const blender::Span looptris = source->looptris(); + const blender::Span looptri_polys = source->looptri_polys(); BVHTreeFromMesh bvhtree = {nullptr}; BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_LOOPTRI, 2); @@ -344,7 +344,7 @@ void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, const Mesh *source) BLI_bvhtree_find_nearest( bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree); if (nearest.index != -1) { - dst[i] = src[looptris[nearest.index].poly]; + dst[i] = src[looptri_polys[nearest.index]]; } else { dst[i] = 1; diff --git a/source/blender/blenkernel/intern/mesh_runtime.cc b/source/blender/blenkernel/intern/mesh_runtime.cc index 4a294aa5a7b..a6c6b523e84 100644 --- a/source/blender/blenkernel/intern/mesh_runtime.cc +++ b/source/blender/blenkernel/intern/mesh_runtime.cc @@ -221,6 +221,17 @@ blender::Span Mesh::looptris() const return this->runtime->looptris_cache.data(); } +blender::Span Mesh::looptri_polys() const +{ + using namespace blender; + this->runtime->looptri_polys_cache.ensure([&](blender::Array &r_data) { + const OffsetIndices polys = this->polys(); + r_data.reinitialize(poly_to_tri_count(polys.size(), this->totloop)); + bke::mesh::looptris_calc_poly_indices(polys, r_data); + }); + return this->runtime->looptri_polys_cache.data(); +} + int BKE_mesh_runtime_looptri_len(const Mesh *mesh) { /* Allow returning the size without calculating the cache. */ @@ -232,6 +243,11 @@ const MLoopTri *BKE_mesh_runtime_looptri_ensure(const Mesh *mesh) return mesh->looptris().data(); } +const int *BKE_mesh_runtime_looptri_polys_ensure(const Mesh *mesh) +{ + return mesh->looptri_polys().data(); +} + void BKE_mesh_runtime_verttri_from_looptri(MVertTri *r_verttri, const int *corner_verts, const MLoopTri *looptri, @@ -281,6 +297,7 @@ void BKE_mesh_runtime_clear_geometry(Mesh *mesh) mesh->runtime->loose_verts_cache.tag_dirty(); mesh->runtime->verts_no_face_cache.tag_dirty(); mesh->runtime->looptris_cache.tag_dirty(); + mesh->runtime->looptri_polys_cache.tag_dirty(); mesh->runtime->subsurf_face_dot_tags.clear_and_shrink(); mesh->runtime->subsurf_optimal_display_edges.clear_and_shrink(); if (mesh->runtime->shrinkwrap_data) { diff --git a/source/blender/blenkernel/intern/mesh_sample.cc b/source/blender/blenkernel/intern/mesh_sample.cc index f5549b47e2e..2883751ebc1 100644 --- a/source/blender/blenkernel/intern/mesh_sample.cc +++ b/source/blender/blenkernel/intern/mesh_sample.cc @@ -107,7 +107,7 @@ void sample_corner_attribute(const Span looptris, } template -void sample_face_attribute(const Span looptris, +void sample_face_attribute(const Span looptri_polys, const Span looptri_indices, const VArray &src, const IndexMask mask, @@ -115,13 +115,12 @@ void sample_face_attribute(const Span looptris, { for (const int i : mask) { const int looptri_index = looptri_indices[i]; - const MLoopTri &looptri = looptris[looptri_index]; - const int poly_index = looptri.poly; + const int poly_index = looptri_polys[looptri_index]; dst[i] = src[poly_index]; } } -void sample_face_attribute(const Span looptris, +void sample_face_attribute(const Span looptri_polys, const Span looptri_indices, const GVArray &src, const IndexMask mask, @@ -132,7 +131,7 @@ void sample_face_attribute(const Span looptris, const CPPType &type = src.type(); attribute_math::convert_to_static_type(type, [&](auto dummy) { using T = decltype(dummy); - sample_face_attribute(looptris, looptri_indices, src.typed(), mask, dst.typed()); + sample_face_attribute(looptri_polys, looptri_indices, src.typed(), mask, dst.typed()); }); } @@ -414,8 +413,8 @@ CornerBaryWeightFromPositionFn::CornerBaryWeightFromPositionFn(GeometrySet geome } void CornerBaryWeightFromPositionFn::call(IndexMask mask, - mf::Params params, - mf::Context /*context*/) const + mf::Params params, + mf::Context /*context*/) const { const VArraySpan sample_positions = params.readonly_single_input(0, "Position"); const VArraySpan triangle_indices = params.readonly_single_input(1, "Triangle Index"); diff --git a/source/blender/blenkernel/intern/mesh_tangent.cc b/source/blender/blenkernel/intern/mesh_tangent.cc index b60eadf4e09..025ab04ac15 100644 --- a/source/blender/blenkernel/intern/mesh_tangent.cc +++ b/source/blender/blenkernel/intern/mesh_tangent.cc @@ -177,8 +177,8 @@ struct SGLSLMeshToTangent { { #ifdef USE_LOOPTRI_DETECT_QUADS if (face_as_quad_map) { - const MLoopTri *lt = &looptri[face_as_quad_map[face_num]]; - if (polys[lt->poly].size() == 4) { + const int poly_index = looptri_polys[face_as_quad_map[face_num]]; + if (polys[poly_index].size() == 4) { return 4; } } @@ -189,36 +189,40 @@ struct SGLSLMeshToTangent { #endif } - uint GetLoop(const uint face_num, const uint vert_num, const MLoopTri *<) + uint GetLoop(const uint face_num, const uint vert_num, MLoopTri <, int &poly_index) { #ifdef USE_LOOPTRI_DETECT_QUADS if (face_as_quad_map) { - lt = &looptri[face_as_quad_map[face_num]]; - if (polys[lt->poly].size() == 4) { - return uint(polys[lt->poly][vert_num]); + lt = looptri[face_as_quad_map[face_num]]; + poly_index = looptri_polys[face_as_quad_map[face_num]]; + if (polys[poly_index].size() == 4) { + return uint(polys[poly_index][vert_num]); } /* fall through to regular triangle */ } else { - lt = &looptri[face_num]; + lt = looptri[face_num]; + poly_index = looptri_polys[face_num]; } #else lt = &looptri[face_num]; #endif - return lt->tri[vert_num]; + return lt.tri[vert_num]; } mikk::float3 GetPosition(const uint face_num, const uint vert_num) { - const MLoopTri *lt; - uint loop_index = GetLoop(face_num, vert_num, lt); + MLoopTri lt; + int poly_index; + uint loop_index = GetLoop(face_num, vert_num, lt, poly_index); return mikk::float3(positions[corner_verts[loop_index]]); } mikk::float3 GetTexCoord(const uint face_num, const uint vert_num) { - const MLoopTri *lt; - uint loop_index = GetLoop(face_num, vert_num, lt); + MLoopTri lt; + int poly_index; + uint loop_index = GetLoop(face_num, vert_num, lt, poly_index); if (mloopuv != nullptr) { const float2 &uv = mloopuv[loop_index]; return mikk::float3(uv[0], uv[1], 1.0f); @@ -231,17 +235,18 @@ struct SGLSLMeshToTangent { mikk::float3 GetNormal(const uint face_num, const uint vert_num) { - const MLoopTri *lt; - uint loop_index = GetLoop(face_num, vert_num, lt); + MLoopTri lt; + int poly_index; + uint loop_index = GetLoop(face_num, vert_num, lt, poly_index); if (precomputedLoopNormals) { return mikk::float3(precomputedLoopNormals[loop_index]); } - if (sharp_faces && sharp_faces[lt->poly]) { /* flat */ + if (sharp_faces && sharp_faces[poly_index]) { /* flat */ if (precomputedFaceNormals) { - return mikk::float3(precomputedFaceNormals[lt->poly]); + return mikk::float3(precomputedFaceNormals[poly_index]); } #ifdef USE_LOOPTRI_DETECT_QUADS - const blender::IndexRange poly = polys[lt->poly]; + const blender::IndexRange poly = polys[poly_index]; float normal[3]; if (poly.size() == 4) { normal_quad_v3(normal, @@ -254,9 +259,9 @@ struct SGLSLMeshToTangent { #endif { normal_tri_v3(normal, - positions[corner_verts[lt->tri[0]]], - positions[corner_verts[lt->tri[1]]], - positions[corner_verts[lt->tri[2]]]); + positions[corner_verts[lt.tri[0]]], + positions[corner_verts[lt.tri[1]]], + positions[corner_verts[lt.tri[2]]]); } return mikk::float3(normal); } @@ -265,8 +270,9 @@ struct SGLSLMeshToTangent { void SetTangentSpace(const uint face_num, const uint vert_num, mikk::float3 T, bool orientation) { - const MLoopTri *lt; - uint loop_index = GetLoop(face_num, vert_num, lt); + MLoopTri lt; + int poly_index; + uint loop_index = GetLoop(face_num, vert_num, lt, poly_index); copy_v4_fl4(tangent[loop_index], T.x, T.y, T.z, orientation ? 1.0f : -1.0f); } @@ -274,6 +280,7 @@ struct SGLSLMeshToTangent { const float (*precomputedFaceNormals)[3]; const float (*precomputedLoopNormals)[3]; const MLoopTri *looptri; + const int *looptri_polys; const float2 *mloopuv; /* texture coordinates */ blender::OffsetIndices polys; const int *corner_verts; /* indices */ @@ -390,6 +397,7 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3], const blender::OffsetIndices polys, const int *corner_verts, const MLoopTri *looptri, + const int *looptri_polys, const uint looptri_len, const bool *sharp_faces, @@ -464,7 +472,7 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3], for (k = 0, j = 0; j < int(looptri_len); k++, j++) { face_as_quad_map[k] = j; /* step over all quads */ - if (polys[looptri[j].poly].size() == 4) { + if (polys[looptri_polys[j]].size() == 4) { j++; /* skips the nest looptri */ } } @@ -497,6 +505,7 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3], mesh2tangent->polys = polys; mesh2tangent->corner_verts = corner_verts; mesh2tangent->looptri = looptri; + mesh2tangent->looptri_polys = looptri_polys; mesh2tangent->sharp_faces = sharp_faces; /* NOTE: we assume we do have tessellated loop normals at this point * (in case it is object-enabled), have to check this is valid. */ @@ -581,6 +590,7 @@ void BKE_mesh_calc_loop_tangents(Mesh *me_eval, me_eval->polys(), me_eval->corner_verts().data(), looptris.data(), + me_eval->looptri_polys().data(), uint(looptris.size()), static_cast( CustomData_get_layer_named(&me_eval->pdata, CD_PROP_BOOL, "sharp_face")), diff --git a/source/blender/blenkernel/intern/mesh_tessellate.cc b/source/blender/blenkernel/intern/mesh_tessellate.cc index 2f82196d149..32d5050424d 100644 --- a/source/blender/blenkernel/intern/mesh_tessellate.cc +++ b/source/blender/blenkernel/intern/mesh_tessellate.cc @@ -15,6 +15,7 @@ #include "BLI_memarena.h" #include "BLI_polyfill_2d.h" #include "BLI_task.h" +#include "BLI_task.hh" #include "BKE_mesh.hh" @@ -50,7 +51,6 @@ BLI_INLINE void mesh_calc_tessellation_for_face_impl(const Span corner_vert mlt->tri[0] = mp_loopstart + i1; mlt->tri[1] = mp_loopstart + i2; mlt->tri[2] = mp_loopstart + i3; - mlt->poly = poly_index; }; switch (mp_totloop) { @@ -298,6 +298,18 @@ void looptris_calc(const Span vert_positions, looptris_calc_all(vert_positions, polys, corner_verts, {}, looptris); } +void looptris_calc_poly_indices(const OffsetIndices polys, MutableSpan looptri_polys) +{ + threading::parallel_for(polys.index_range(), 1024, [&](const IndexRange range) { + for (const int64_t i : range) { + const IndexRange poly = polys[i]; + const int start = poly_to_tri_count(int(i), int(poly.start())); + const int num = ME_POLY_TRI_TOT(int(poly.size())); + looptri_polys.slice(start, num).fill(int(i)); + } + }); +} + void looptris_calc_with_normals(const Span vert_positions, const OffsetIndices polys, const Span corner_verts, diff --git a/source/blender/blenkernel/intern/paint.cc b/source/blender/blenkernel/intern/paint.cc index 4b448cfe778..3c03d679771 100644 --- a/source/blender/blenkernel/intern/paint.cc +++ b/source/blender/blenkernel/intern/paint.cc @@ -1259,12 +1259,12 @@ void BKE_paint_blend_read_lib(BlendLibReader *reader, Scene *sce, Paint *p) } } -bool paint_is_face_hidden(const MLoopTri *lt, const bool *hide_poly) +bool paint_is_face_hidden(const int *looptri_polys, const bool *hide_poly, const int tri_index) { if (!hide_poly) { return false; } - return hide_poly[lt->poly]; + return hide_poly[looptri_polys[tri_index]]; } bool paint_is_grid_face_hidden(const uint *grid_hidden, int gridsize, int x, int y) diff --git a/source/blender/blenkernel/intern/pbvh.cc b/source/blender/blenkernel/intern/pbvh.cc index cd9a96601a3..259508456ab 100644 --- a/source/blender/blenkernel/intern/pbvh.cc +++ b/source/blender/blenkernel/intern/pbvh.cc @@ -189,7 +189,7 @@ static int partition_indices_faces(int *prim_indices, int axis, float mid, BBC *prim_bbc, - const MLoopTri *looptri) + const int *looptri_polys) { for (int i = lo; i < hi; i++) { prim_scratch[i - lo] = prim_indices[i]; @@ -199,10 +199,10 @@ static int partition_indices_faces(int *prim_indices, int i1 = lo, i2 = 0; while (i1 < hi) { - int poly = looptri[prim_scratch[i2]].poly; + int poly = looptri_polys[prim_scratch[i2]]; bool side = prim_bbc[prim_scratch[i2]].bcentroid[axis] >= mid; - while (i1 < hi && looptri[prim_scratch[i2]].poly == poly) { + while (i1 < hi && looptri_polys[prim_scratch[i2]] == poly) { prim_indices[side ? hi2-- : lo2++] = prim_scratch[i2]; i1++; i2++; @@ -246,19 +246,20 @@ static int partition_indices_grids(int *prim_indices, static int partition_indices_material( PBVH *pbvh, const int *material_indices, const bool *sharp_faces, int lo, int hi) { - const MLoopTri *looptri = pbvh->looptri; + const int *looptri_polys = pbvh->looptri_polys; const DMFlagMat *flagmats = pbvh->grid_flag_mats; const int *indices = pbvh->prim_indices; int i = lo, j = hi; for (;;) { - if (pbvh->looptri) { - const int first = looptri[pbvh->prim_indices[lo]].poly; - for (; face_materials_match(material_indices, sharp_faces, first, looptri[indices[i]].poly); + if (pbvh->looptri_polys) { + const int first = looptri_polys[pbvh->prim_indices[lo]]; + for (; face_materials_match(material_indices, sharp_faces, first, looptri_polys[indices[i]]); i++) { /* pass */ } - for (; !face_materials_match(material_indices, sharp_faces, first, looptri[indices[j]].poly); + for (; + !face_materials_match(material_indices, sharp_faces, first, looptri_polys[indices[j]]); j--) { /* pass */ } @@ -345,7 +346,7 @@ static void build_mesh_leaf_node(PBVH *pbvh, PBVHNode *node) } if (has_visible == false) { - if (!paint_is_face_hidden(lt, pbvh->hide_poly)) { + if (!paint_is_face_hidden(pbvh->looptri_polys, pbvh->hide_poly, node->prim_indices[i])) { has_visible = true; } } @@ -471,11 +472,10 @@ static bool leaf_needs_material_split( } if (pbvh->looptri) { - const MLoopTri *first = &pbvh->looptri[pbvh->prim_indices[offset]]; + const int first = pbvh->looptri_polys[pbvh->prim_indices[offset]]; for (int i = offset + count - 1; i > offset; i--) { int prim = pbvh->prim_indices[i]; - if (!face_materials_match( - material_indices, sharp_faces, first->poly, pbvh->looptri[prim].poly)) { + if (!face_materials_match(material_indices, sharp_faces, first, pbvh->looptri_polys[prim])) { return true; } } @@ -513,7 +513,7 @@ static void test_face_boundaries(PBVH *pbvh) switch (BKE_pbvh_type(pbvh)) { case PBVH_FACES: { for (int j = 0; j < node->totprim; j++) { - int poly = pbvh->looptri[node->prim_indices[j]].poly; + int poly = pbvh->looptri_polys[node->prim_indices[j]]; if (node_map[poly] >= 0 && node_map[poly] != i) { int old_i = node_map[poly]; @@ -612,7 +612,7 @@ static void build_sub(PBVH *pbvh, axis, (cb->bmax[axis] + cb->bmin[axis]) * 0.5f, prim_bbc, - pbvh->looptri); + pbvh->looptri_polys); } else { end = partition_indices_grids(pbvh->prim_indices, @@ -792,7 +792,7 @@ static void pbvh_validate_node_prims(PBVH *pbvh) int poly; if (pbvh->header.type == PBVH_FACES) { - poly = pbvh->looptri[node->prim_indices[j]].poly; + poly = pbvh->looptri_polys[node->prim_indices[j]]; } else { poly = BKE_subdiv_ccg_grid_to_face_index(pbvh->subdiv_ccg, node->prim_indices[j]); @@ -819,7 +819,7 @@ static void pbvh_validate_node_prims(PBVH *pbvh) int poly; if (pbvh->header.type == PBVH_FACES) { - poly = pbvh->looptri[node->prim_indices[j]].poly; + poly = pbvh->looptri_polys[node->prim_indices[j]]; } else { poly = BKE_subdiv_ccg_grid_to_face_index(pbvh->subdiv_ccg, node->prim_indices[j]); @@ -845,6 +845,7 @@ void BKE_pbvh_update_mesh_pointers(PBVH *pbvh, Mesh *mesh) pbvh->polys = mesh->polys(); pbvh->corner_verts = mesh->corner_verts().data(); + pbvh->looptri_polys = mesh->looptri_polys().data(); if (!pbvh->deformed) { /* Deformed positions not matching the original mesh are owned directly by the PBVH, and are * set separately by #BKE_pbvh_vert_coords_apply. */ @@ -888,7 +889,6 @@ void BKE_pbvh_build_mesh(PBVH *pbvh, Mesh *mesh) /* Those are not set in #BKE_pbvh_update_mesh_pointers because they are owned by the #PBVH. */ pbvh->looptri = looptri; - pbvh->vert_bitmap = static_cast( MEM_calloc_arrayN(totvert, sizeof(bool), "bvh->vert_bitmap")); pbvh->totvert = totvert; @@ -1412,6 +1412,8 @@ static void pbvh_update_normals_accum_task_cb(void *__restrict userdata, const int totface = node->totprim; for (int i = 0; i < totface; i++) { + const int tri_index = faces[i]; + const int poly_index = pbvh->looptri_polys[tri_index]; const MLoopTri *lt = &pbvh->looptri[faces[i]]; const int vtri[3] = { pbvh->corner_verts[lt->tri[0]], @@ -1421,12 +1423,12 @@ static void pbvh_update_normals_accum_task_cb(void *__restrict userdata, const int sides = 3; /* Face normal and mask */ - if (lt->poly != mpoly_prev) { - const blender::IndexRange poly = pbvh->polys[lt->poly]; + if (poly_index != mpoly_prev) { + const blender::IndexRange poly = pbvh->polys[poly_index]; fn = blender::bke::mesh::poly_normal_calc( {reinterpret_cast(pbvh->vert_positions), pbvh->totvert}, {&pbvh->corner_verts[poly.start()], poly.size()}); - mpoly_prev = lt->poly; + mpoly_prev = poly_index; } for (int j = sides; j--;) { @@ -2533,10 +2535,11 @@ static bool pbvh_faces_node_raycast(PBVH *pbvh, float nearest_vertex_co[3] = {0.0f}; for (int i = 0; i < totface; i++) { - const MLoopTri *lt = &pbvh->looptri[faces[i]]; + const int tri_index = faces[i]; + const MLoopTri *lt = &pbvh->looptri[tri_index]; const int *face_verts = node->face_vert_indices[i]; - if (paint_is_face_hidden(lt, pbvh->hide_poly)) { + if (paint_is_face_hidden(pbvh->looptri_polys, pbvh->hide_poly, tri_index)) { continue; } @@ -2572,7 +2575,7 @@ static bool pbvh_faces_node_raycast(PBVH *pbvh, len_squared_v3v3(location, co[j]) < len_squared_v3v3(location, nearest_vertex_co)) { copy_v3_v3(nearest_vertex_co, co[j]); r_active_vertex->i = corner_verts[lt->tri[j]]; - *r_active_face_index = lt->poly; + *r_active_face_index = pbvh->looptri_polys[tri_index]; } } } @@ -2842,10 +2845,11 @@ static bool pbvh_faces_node_nearest_to_ray(PBVH *pbvh, bool hit = false; for (i = 0; i < totface; i++) { - const MLoopTri *lt = &pbvh->looptri[faces[i]]; + const int tri_index = faces[i]; + const MLoopTri *lt = &pbvh->looptri[tri_index]; const int *face_verts = node->face_vert_indices[i]; - if (paint_is_face_hidden(lt, pbvh->hide_poly)) { + if (paint_is_face_hidden(pbvh->looptri_polys, pbvh->hide_poly, tri_index)) { continue; } @@ -3586,7 +3590,7 @@ BLI_INLINE int face_iter_prim_to_face(PBVHFaceIter *fd, int prim_index) return BKE_subdiv_ccg_grid_to_face_index(fd->subdiv_ccg_, prim_index); } - return fd->looptri_[prim_index].poly; + return fd->looptri_polys_[prim_index]; } static void pbvh_face_iter_step(PBVHFaceIter *fd, bool do_step) @@ -3705,7 +3709,7 @@ void BKE_pbvh_face_iter_init(PBVH *pbvh, PBVHNode *node, PBVHFaceIter *fd) case PBVH_FACES: fd->poly_offsets_ = pbvh->polys.data(); fd->corner_verts_ = pbvh->corner_verts; - fd->looptri_ = pbvh->looptri; + fd->looptri_polys_ = pbvh->looptri_polys; fd->hide_poly_ = pbvh->hide_poly; fd->face_sets_ = pbvh->face_sets; fd->last_face_index_ = -1; diff --git a/source/blender/blenkernel/intern/pbvh_intern.hh b/source/blender/blenkernel/intern/pbvh_intern.hh index f714f03a580..3b810d6f6de 100644 --- a/source/blender/blenkernel/intern/pbvh_intern.hh +++ b/source/blender/blenkernel/intern/pbvh_intern.hh @@ -163,6 +163,7 @@ struct PBVH { const int *corner_verts; /* Owned by the #PBVH, because after deformations they have to be recomputed. */ const MLoopTri *looptri; + const int *looptri_polys; CustomData *vdata; CustomData *ldata; CustomData *pdata; diff --git a/source/blender/blenkernel/intern/pbvh_uv_islands.cc b/source/blender/blenkernel/intern/pbvh_uv_islands.cc index d3f0b35f1ed..c59cadb0b46 100644 --- a/source/blender/blenkernel/intern/pbvh_uv_islands.cc +++ b/source/blender/blenkernel/intern/pbvh_uv_islands.cc @@ -542,7 +542,6 @@ struct FanSegment { void print_debug(const MeshData &mesh_data) const { std::stringstream ss; - ss << "# p:" << primitive->poly; ss << " v1:" << mesh_data.corner_verts[primitive->tri[vert_order[0]]]; ss << " v2:" << mesh_data.corner_verts[primitive->tri[vert_order[1]]]; ss << " v3:" << mesh_data.corner_verts[primitive->tri[vert_order[2]]]; diff --git a/source/blender/blenkernel/intern/shrinkwrap.cc b/source/blender/blenkernel/intern/shrinkwrap.cc index 74d6f44d052..101c2fd3f18 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.cc +++ b/source/blender/blenkernel/intern/shrinkwrap.cc @@ -1188,9 +1188,10 @@ void BKE_shrinkwrap_compute_smooth_normal(const ShrinkwrapTreeData *tree, const BVHTreeFromMesh *treeData = &tree->treeData; const MLoopTri *tri = &treeData->looptri[looptri_idx]; const float(*vert_normals)[3] = tree->vert_normals; + const int poly_i = tree->mesh->looptri_polys()[looptri_idx]; /* Interpolate smooth normals if enabled. */ - if (!(tree->sharp_faces && tree->sharp_faces[tri->poly])) { + if (!(tree->sharp_faces && tree->sharp_faces[poly_i])) { const int vert_indices[3] = {treeData->corner_verts[tri->tri[0]], treeData->corner_verts[tri->tri[1]], treeData->corner_verts[tri->tri[2]]}; @@ -1234,7 +1235,7 @@ void BKE_shrinkwrap_compute_smooth_normal(const ShrinkwrapTreeData *tree, } /* Use the polygon normal if flat. */ else if (tree->poly_normals != nullptr) { - copy_v3_v3(r_no, tree->poly_normals[tri->poly]); + copy_v3_v3(r_no, tree->poly_normals[poly_i]); } /* Finally fallback to the looptri normal. */ else { diff --git a/source/blender/draw/DRW_pbvh.hh b/source/blender/draw/DRW_pbvh.hh index 3c393526284..55893091f4b 100644 --- a/source/blender/draw/DRW_pbvh.hh +++ b/source/blender/draw/DRW_pbvh.hh @@ -63,6 +63,7 @@ struct PBVH_GPU_Args { int node_verts_num; const MLoopTri *mlooptri; + const int *looptri_polys; PBVHNode *node; /* BMesh. */ diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc index f32467a15de..06e20d2565e 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc @@ -310,6 +310,7 @@ void mesh_render_data_update_looptris(MeshRenderData *mr, /* Mesh */ if ((iter_type & MR_ITER_LOOPTRI) || (data_flag & MR_DATA_LOOPTRI)) { mr->looptris = mr->me->looptris(); + mr->looptri_polys = mr->me->looptri_polys(); } } else { diff --git a/source/blender/draw/intern/draw_pbvh.cc b/source/blender/draw/intern/draw_pbvh.cc index feb61ec8e75..591ae1fa4d7 100644 --- a/source/blender/draw/intern/draw_pbvh.cc +++ b/source/blender/draw/intern/draw_pbvh.cc @@ -191,7 +191,7 @@ struct PBVHBatches { switch (args->pbvh_type) { case PBVH_FACES: { for (int i = 0; i < args->totprim; i++) { - int face_index = args->mlooptri[args->prim_indices[i]].poly; + int face_index = args->looptri_polys[args->prim_indices[i]]; if (args->hide_poly && args->hide_poly[face_index]) { continue; @@ -337,14 +337,15 @@ struct PBVHBatches { int last_poly = -1; bool flat = false; - foreach_faces([&](int /*buffer_i*/, int /*tri_i*/, int vertex_i, const MLoopTri *tri) { - if (tri->poly != last_poly) { - last_poly = tri->poly; - flat = sharp_faces && sharp_faces[tri->poly]; + foreach_faces([&](int /*buffer_i*/, int tri_i, int vertex_i, const MLoopTri * /*tri*/) { + const int poly_i = args->looptri_polys[tri_i]; + if (args->looptri_polys[tri_i] != last_poly) { + last_poly = poly_i; + flat = sharp_faces && sharp_faces[poly_i]; if (flat) { const float3 fno = blender::bke::mesh::poly_normal_calc( {reinterpret_cast(args->vert_positions), args->mesh_verts_num}, - args->corner_verts.slice(args->polys[tri->poly])); + args->corner_verts.slice(args->polys[poly_i])); normal_float_to_short_v3(no, fno); } } @@ -549,7 +550,7 @@ struct PBVHBatches { int buffer_i = 0; for (int i : IndexRange(args->totprim)) { - int face_index = args->mlooptri[args->prim_indices[i]].poly; + int face_index = args->looptri_polys[args->prim_indices[i]]; if (args->hide_poly && args->hide_poly[face_index]) { continue; @@ -617,11 +618,12 @@ struct PBVHBatches { uchar fset_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX}; foreach_faces( - [&](int /*buffer_i*/, int /*tri_i*/, int /*vertex_i*/, const MLoopTri *tri) { - if (last_poly != tri->poly) { - last_poly = tri->poly; + [&](int /*buffer_i*/, int tri_i, int /*vertex_i*/, const MLoopTri * /*tri*/) { + const int poly_i = args->looptri_polys[tri_i]; + if (last_poly != poly_i) { + last_poly = poly_i; - const int fset = face_sets[tri->poly]; + const int fset = face_sets[poly_i]; if (fset != args->face_sets_color_default) { BKE_paint_face_set_overlay_color_get( @@ -973,7 +975,7 @@ struct PBVHBatches { CustomData_get_layer_named(args->pdata, CD_PROP_INT32, "material_index")); if (mat_index && args->totprim) { - int poly_index = args->mlooptri[args->prim_indices[0]].poly; + int poly_index = args->looptri_polys[args->prim_indices[0]]; material_index = mat_index[poly_index]; } @@ -982,12 +984,13 @@ struct PBVHBatches { /* Calculate number of edges. */ int edge_count = 0; for (int i = 0; i < args->totprim; i++) { - const MLoopTri *lt = args->mlooptri + args->prim_indices[i]; - - if (args->hide_poly && args->hide_poly[lt->poly]) { + const int tri_i = args->prim_indices[i]; + const int poly_i = args->looptri_polys[tri_i]; + if (args->hide_poly && args->hide_poly[poly_i]) { continue; } + const MLoopTri *lt = args->mlooptri + args->prim_indices[i]; int r_edges[3]; BKE_mesh_looptri_get_real_edges( edges.data(), args->corner_verts.data(), args->corner_edges.data(), lt, r_edges); @@ -1008,12 +1011,13 @@ struct PBVHBatches { int vertex_i = 0; for (int i = 0; i < args->totprim; i++) { - const MLoopTri *lt = args->mlooptri + args->prim_indices[i]; - - if (args->hide_poly && args->hide_poly[lt->poly]) { + const int tri_i = args->prim_indices[i]; + const int poly_i = args->looptri_polys[tri_i]; + if (args->hide_poly && args->hide_poly[poly_i]) { continue; } + const MLoopTri *lt = args->mlooptri + args->prim_indices[i]; int r_edges[3]; BKE_mesh_looptri_get_real_edges( edges.data(), args->corner_verts.data(), args->corner_edges.data(), lt, r_edges); diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh.hh b/source/blender/draw/intern/mesh_extractors/extract_mesh.hh index 8c8191a48cd..09c78a199cf 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh.hh +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh.hh @@ -86,6 +86,7 @@ struct MeshRenderData { BMFace *efa_act_uv; /* The triangulation of #Mesh polygons, owned by the mesh. */ blender::Span looptris; + blender::Span looptri_polys; const int *material_indices; blender::Span vert_normals; blender::Span poly_normals; diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc index dbb2d2a63ca..be6f6104636 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc @@ -55,11 +55,12 @@ static void extract_edituv_tris_iter_looptri_bm(const MeshRenderData * /*mr*/, static void extract_edituv_tris_iter_looptri_mesh(const MeshRenderData *mr, const MLoopTri *mlt, - const int /*elt_index*/, + const int elt_index, void *_data) { MeshExtract_EditUvElem_Data *data = static_cast(_data); - const BMFace *efa = bm_original_face_get(mr, mlt->poly); + const int poly_i = mr->looptri_polys[elt_index]; + const BMFace *efa = bm_original_face_get(mr, poly_i); const bool mp_hidden = (efa) ? BM_elem_flag_test_bool(efa, BM_ELEM_HIDDEN) : true; const bool mp_select = (efa) ? BM_elem_flag_test_bool(efa, BM_ELEM_SELECT) : false; diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc index c7cc4eeb0f5..d35a8289055 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc @@ -115,11 +115,12 @@ static void extract_lines_adjacency_iter_looptri_bm(const MeshRenderData * /*mr* static void extract_lines_adjacency_iter_looptri_mesh(const MeshRenderData *mr, const MLoopTri *mlt, - const int /*elt_index*/, + const int elt_index, void *_data) { MeshExtract_LineAdjacency_Data *data = static_cast(_data); - const bool hidden = mr->use_hide && mr->hide_poly && mr->hide_poly[mlt->poly]; + const int poly_i = mr->looptri_polys[elt_index]; + const bool hidden = mr->use_hide && mr->hide_poly && mr->hide_poly[poly_i]; if (hidden) { return; } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc index bb04552d3df..9ff55241f81 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc @@ -190,7 +190,8 @@ static void extract_tris_single_mat_iter_looptri_mesh(const MeshRenderData *mr, void *_data) { GPUIndexBufBuilder *elb = static_cast(_data); - const bool hidden = mr->use_hide && mr->hide_poly && mr->hide_poly[mlt->poly]; + const int poly_i = mr->looptri_polys[mlt_index]; + const bool hidden = mr->use_hide && mr->hide_poly && mr->hide_poly[poly_i]; if (hidden) { GPU_indexbuf_set_tri_restart(elb, mlt_index); } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc index 6050089fd25..4e7d02d5913 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc @@ -214,8 +214,9 @@ static void statvis_calc_thickness(const MeshRenderData *mr, float *r_thickness) BVHTree *tree = BKE_bvhtree_from_mesh_get(&treeData, mr->me, BVHTREE_FROM_LOOPTRI, 4); const Span looptris = mr->looptris; + const Span looptri_polys = mr->looptri_polys; for (const int i : looptris.index_range()) { - const int index = looptris[i].poly; + const int index = looptri_polys[i]; const float *cos[3] = {mr->vert_positions[mr->corner_verts[looptris[i].tri[0]]], mr->vert_positions[mr->corner_verts[looptris[i].tri[1]]], mr->vert_positions[mr->corner_verts[looptris[i].tri[2]]]}; @@ -261,6 +262,7 @@ struct BVHTree_OverlapData { Span positions; Span corner_verts; Span looptris; + Span looptri_polys; float epsilon; }; @@ -268,13 +270,13 @@ static bool bvh_overlap_cb(void *userdata, int index_a, int index_b, int /*threa { struct BVHTree_OverlapData *data = static_cast(userdata); - const MLoopTri *tri_a = &data->looptris[index_a]; - const MLoopTri *tri_b = &data->looptris[index_b]; - - if (UNLIKELY(tri_a->poly == tri_b->poly)) { + if (UNLIKELY(data->looptri_polys[index_a] == data->looptri_polys[index_b])) { return false; } + const MLoopTri *tri_a = &data->looptris[index_a]; + const MLoopTri *tri_b = &data->looptris[index_b]; + const float *tri_a_co[3] = {data->positions[data->corner_verts[tri_a->tri[0]]], data->positions[data->corner_verts[tri_a->tri[1]]], data->positions[data->corner_verts[tri_a->tri[2]]]}; @@ -344,14 +346,15 @@ static void statvis_calc_intersect(const MeshRenderData *mr, float *r_intersect) data.positions = mr->vert_positions; data.corner_verts = mr->corner_verts; data.looptris = mr->looptris; + data.looptri_polys = mr->looptri_polys; data.epsilon = BLI_bvhtree_get_epsilon(tree); BVHTreeOverlap *overlap = BLI_bvhtree_overlap_self(tree, &overlap_len, bvh_overlap_cb, &data); if (overlap) { for (int i = 0; i < overlap_len; i++) { - for (const IndexRange f_hit : {mr->polys[mr->looptris[overlap[i].indexA].poly], - mr->polys[mr->looptris[overlap[i].indexB].poly]}) + for (const IndexRange f_hit : {mr->polys[mr->looptri_polys[overlap[i].indexA]], + mr->polys[mr->looptri_polys[overlap[i].indexB]]}) { int l_index = f_hit.start(); for (int k = 0; k < f_hit.size(); k++, l_index++) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc index c6361345b10..ecbb1efb2aa 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc @@ -118,6 +118,7 @@ static void extract_tan_init_common(const MeshRenderData *mr, mr->polys, mr->corner_verts.data(), mr->looptris.data(), + mr->looptri_polys.data(), mr->tri_len, mr->sharp_faces, cd_ldata, diff --git a/source/blender/editors/armature/meshlaplacian.cc b/source/blender/editors/armature/meshlaplacian.cc index a990e434988..b5d0dee887c 100644 --- a/source/blender/editors/armature/meshlaplacian.cc +++ b/source/blender/editors/armature/meshlaplacian.cc @@ -921,6 +921,7 @@ typedef struct MeshDeformBind { blender::OffsetIndices polys; blender::Span corner_verts; blender::Span looptris; + blender::Span looptri_polys; blender::Span poly_normals; } cagemesh_cache; } MeshDeformBind; @@ -951,6 +952,7 @@ static void harmonic_ray_callback(void *userdata, MeshRayCallbackData *data = static_cast(userdata); MeshDeformBind *mdb = data->mdb; const blender::Span corner_verts = mdb->cagemesh_cache.corner_verts; + const blender::Span looptri_polys = mdb->cagemesh_cache.looptri_polys; const blender::Span poly_normals = mdb->cagemesh_cache.poly_normals; MeshDeformIsect *isec = data->isec; float no[3], co[3], dist; @@ -970,7 +972,7 @@ static void harmonic_ray_callback(void *userdata, } if (!poly_normals.is_empty()) { - copy_v3_v3(no, poly_normals[lt->poly]); + copy_v3_v3(no, poly_normals[looptri_polys[index]]); } else { normal_tri_v3(no, UNPACK3(face)); @@ -1026,8 +1028,8 @@ static MDefBoundIsect *meshdeform_ray_tree_intersect(MeshDeformBind *mdb, BVH_RAYCAST_WATERTIGHT) != -1) { const blender::Span corner_verts = mdb->cagemesh_cache.corner_verts; - const MLoopTri *lt = &mdb->cagemesh_cache.looptris[hit.index]; - const blender::IndexRange poly = mdb->cagemesh_cache.polys[lt->poly]; + const int poly_i = mdb->cagemesh_cache.looptri_polys[hit.index]; + const blender::IndexRange poly = mdb->cagemesh_cache.polys[poly_i]; const float(*cagecos)[3] = mdb->cagecos; const float len = isect_mdef.lambda; MDefBoundIsect *isect; @@ -1043,7 +1045,7 @@ static MDefBoundIsect *meshdeform_ray_tree_intersect(MeshDeformBind *mdb, isect->facing = isect_mdef.isect; - isect->poly_index = lt->poly; + isect->poly_index = poly_i; isect->len = max_ff(len_v3v3(co1, isect->co), MESHDEFORM_LEN_THRESHOLD); @@ -1626,6 +1628,7 @@ static void harmonic_coordinates_bind(MeshDeformModifierData *mmd, MeshDeformBin mdb->cagemesh_cache.polys = me->polys(); mdb->cagemesh_cache.corner_verts = me->corner_verts(); mdb->cagemesh_cache.looptris = me->looptris(); + mdb->cagemesh_cache.looptri_polys = me->looptri_polys(); mdb->cagemesh_cache.poly_normals = me->poly_normals(); } diff --git a/source/blender/editors/curves/intern/curves_ops.cc b/source/blender/editors/curves/intern/curves_ops.cc index 34bfdddd928..13b9e76c934 100644 --- a/source/blender/editors/curves/intern/curves_ops.cc +++ b/source/blender/editors/curves/intern/curves_ops.cc @@ -268,9 +268,9 @@ static void try_convert_single_object(Object &curves_ob, BLI_SCOPED_DEFER([&]() { free_bvhtree_from_mesh(&surface_bvh); }); const Span positions_cu = curves.positions(); - const Span looptris = surface_me.looptris(); + const Span looptri_polys = surface_me.looptri_polys(); - if (looptris.is_empty()) { + if (looptri_polys.is_empty()) { *r_could_not_convert_some_curves = true; } @@ -338,8 +338,7 @@ static void try_convert_single_object(Object &curves_ob, BLI_assert(nearest.index >= 0); const int looptri_i = nearest.index; - const MLoopTri &looptri = looptris[looptri_i]; - const int poly_i = looptri.poly; + const int poly_i = looptri_polys[looptri_i]; const int mface_i = find_mface_for_root_position( positions, mfaces, poly_to_mface_map[poly_i], root_pos_su); diff --git a/source/blender/editors/object/object_bake_api.cc b/source/blender/editors/object/object_bake_api.cc index 1c2f182ae20..3e6ab1794af 100644 --- a/source/blender/editors/object/object_bake_api.cc +++ b/source/blender/editors/object/object_bake_api.cc @@ -1039,6 +1039,7 @@ static void bake_targets_populate_pixels_color_attributes(BakeTargets *targets, const blender::Span corner_verts = me_eval->corner_verts(); blender::bke::mesh::looptris_calc( me_eval->vert_positions(), me_eval->polys(), corner_verts, {looptri, tottri}); + const blender::Span looptri_polys = me_eval->looptri_polys(); /* For mapping back to original mesh in case there are modifiers. */ const int *vert_origindex = static_cast( @@ -1050,6 +1051,7 @@ static void bake_targets_populate_pixels_color_attributes(BakeTargets *targets, for (int i = 0; i < tottri; i++) { const MLoopTri *lt = &looptri[i]; + const int poly_i = looptri_polys[i]; for (int j = 0; j < 3; j++) { uint l = lt->tri[j]; @@ -1058,7 +1060,7 @@ static void bake_targets_populate_pixels_color_attributes(BakeTargets *targets, /* Map back to original loop if there are modifiers. */ if (vert_origindex != nullptr && poly_origindex != nullptr) { l = find_original_loop( - orig_polys, orig_corner_verts, vert_origindex, poly_origindex, lt->poly, v); + orig_polys, orig_corner_verts, vert_origindex, poly_origindex, poly_i, v); if (l == ORIGINDEX_NONE || l >= me->totloop) { continue; } diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.cc b/source/blender/editors/sculpt_paint/paint_image_proj.cc index 292fd03aa6c..232748061ef 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.cc +++ b/source/blender/editors/sculpt_paint/paint_image_proj.cc @@ -420,6 +420,7 @@ struct ProjPaintState { const int *material_indices; const bool *sharp_faces_eval; blender::Span looptris_eval; + blender::Span looptri_polys_eval; const float (*mloopuv_stencil_eval)[2]; @@ -512,14 +513,14 @@ struct VertSeam { ps->corner_verts_eval[lt->tri[0]], ps->corner_verts_eval[lt->tri[1]], \ ps->corner_verts_eval[lt->tri[2]], -#define PS_LOOPTRI_AS_UV_3(uvlayer, lt) \ - uvlayer[lt->poly][lt->tri[0]], uvlayer[lt->poly][lt->tri[1]], uvlayer[lt->poly][lt->tri[2]], +#define PS_LOOPTRI_AS_UV_3(uvlayer, poly_i, lt) \ + uvlayer[poly_i][lt->tri[0]], uvlayer[poly_i][lt->tri[1]], uvlayer[poly_i][lt->tri[2]], -#define PS_LOOPTRI_ASSIGN_UV_3(uv_tri, uvlayer, lt) \ +#define PS_LOOPTRI_ASSIGN_UV_3(uv_tri, uvlayer, poly_i, lt) \ { \ - (uv_tri)[0] = uvlayer[lt->poly][lt->tri[0]]; \ - (uv_tri)[1] = uvlayer[lt->poly][lt->tri[1]]; \ - (uv_tri)[2] = uvlayer[lt->poly][lt->tri[2]]; \ + (uv_tri)[0] = uvlayer[poly_i][lt->tri[0]]; \ + (uv_tri)[1] = uvlayer[poly_i][lt->tri[1]]; \ + (uv_tri)[2] = uvlayer[poly_i][lt->tri[2]]; \ } \ ((void)0) @@ -551,7 +552,7 @@ static Material *tex_get_material(const ProjPaintState *ps, int poly_i) static TexPaintSlot *project_paint_face_paint_slot(const ProjPaintState *ps, int tri_index) { - const int poly_i = ps->looptris_eval[tri_index].poly; + const int poly_i = ps->looptri_polys_eval[tri_index]; Material *ma = tex_get_material(ps, poly_i); return ma ? ma->texpaintslot + ma->paint_active_slot : nullptr; } @@ -562,7 +563,7 @@ static Image *project_paint_face_paint_image(const ProjPaintState *ps, int tri_i return ps->stencil_ima; } - const int poly_i = ps->looptris_eval[tri_index].poly; + const int poly_i = ps->looptri_polys_eval[tri_index]; Material *ma = tex_get_material(ps, poly_i); TexPaintSlot *slot = ma ? ma->texpaintslot + ma->paint_active_slot : nullptr; return slot ? slot->ima : ps->canvas_ima; @@ -570,14 +571,14 @@ static Image *project_paint_face_paint_image(const ProjPaintState *ps, int tri_i static TexPaintSlot *project_paint_face_clone_slot(const ProjPaintState *ps, int tri_index) { - const int poly_i = ps->looptris_eval[tri_index].poly; + const int poly_i = ps->looptri_polys_eval[tri_index]; Material *ma = tex_get_material(ps, poly_i); return ma ? ma->texpaintslot + ma->paint_clone_slot : nullptr; } static Image *project_paint_face_clone_image(const ProjPaintState *ps, int tri_index) { - const int poly_i = ps->looptris_eval[tri_index].poly; + const int poly_i = ps->looptri_polys_eval[tri_index]; Material *ma = tex_get_material(ps, poly_i); TexPaintSlot *slot = ma ? ma->texpaintslot + ma->paint_clone_slot : nullptr; return slot ? slot->ima : ps->clone_ima; @@ -738,7 +739,7 @@ static bool project_paint_PickColor( } lt = &ps->looptris_eval[tri_index]; - PS_LOOPTRI_ASSIGN_UV_3(lt_tri_uv, ps->poly_to_loop_uv, lt); + PS_LOOPTRI_ASSIGN_UV_3(lt_tri_uv, ps->poly_to_loop_uv, ps->looptri_polys_eval[tri_index], lt); interp_v2_v2v2v2(uv, UNPACK3(lt_tri_uv), w); @@ -1122,7 +1123,8 @@ static void project_face_winding_init(const ProjPaintState *ps, const int tri_in { /* detect the winding of faces in uv space */ const MLoopTri *lt = &ps->looptris_eval[tri_index]; - const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)}; + const int poly_i = ps->looptri_polys_eval[tri_index]; + const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, poly_i, lt)}; float winding = cross_tri_v2(lt_tri_uv[0], lt_tri_uv[1], lt_tri_uv[2]); if (winding > 0) { @@ -1142,7 +1144,8 @@ static bool check_seam(const ProjPaintState *ps, int *orig_fidx) { const MLoopTri *orig_lt = &ps->looptris_eval[orig_face]; - const float *orig_lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, orig_lt)}; + const int orig_poly_i = ps->looptri_polys_eval[orig_face]; + const float *orig_lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, orig_poly_i, orig_lt)}; /* vert indices from face vert order indices */ const uint i1 = ps->corner_verts_eval[orig_lt->tri[orig_i1_fidx]]; const uint i2 = ps->corner_verts_eval[orig_lt->tri[orig_i2_fidx]]; @@ -1155,6 +1158,7 @@ static bool check_seam(const ProjPaintState *ps, if (tri_index != orig_face) { const MLoopTri *lt = &ps->looptris_eval[tri_index]; + const int poly_i = ps->looptri_polys_eval[tri_index]; const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)}; /* could check if the 2 faces images match here, * but then there wouldn't be a way to return the opposite face's info */ @@ -1167,7 +1171,7 @@ static bool check_seam(const ProjPaintState *ps, /* Only need to check if 'i2_fidx' is valid because * we know i1_fidx is the same vert on both faces. */ if (i2_fidx != -1) { - const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)}; + const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, poly_i, lt)}; Image *tpage = project_paint_face_paint_image(ps, tri_index); Image *orig_tpage = project_paint_face_paint_image(ps, orig_face); int tile = project_paint_face_paint_tile(tpage, lt_tri_uv[0]); @@ -1389,7 +1393,8 @@ static void insert_seam_vert_array(const ProjPaintState *ps, const int ibuf_y) { const MLoopTri *lt = &ps->looptris_eval[tri_index]; - const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)}; + const int poly_i = ps->looptri_polys_eval[tri_index]; + const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, poly_i, lt)}; const int fidx[2] = {fidx1, ((fidx1 + 1) % 3)}; float vec[2]; @@ -1724,10 +1729,11 @@ static float project_paint_uvpixel_mask(const ProjPaintState *ps, /* calculate mask */ if (ps->do_mask_normal) { const MLoopTri *lt = &ps->looptris_eval[tri_index]; + const int poly_i = ps->looptri_polys_eval[tri_index]; const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)}; float no[3], angle_cos; - if (!(ps->sharp_faces_eval && ps->sharp_faces_eval[lt->poly])) { + if (!(ps->sharp_faces_eval && ps->sharp_faces_eval[poly_i])) { const float *no1, *no2, *no3; no1 = ps->vert_normals[lt_vtri[0]]; no2 = ps->vert_normals[lt_vtri[1]]; @@ -1963,8 +1969,9 @@ static ProjPixel *project_paint_uvpixel_init(const ProjPaintState *ps, if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, nullptr, nullptr))) { const MLoopTri *lt_other = &ps->looptris_eval[tri_index]; + const int poly_other_i = ps->looptri_polys_eval[tri_index]; const float *lt_other_tri_uv[3] = { - PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv_clone, lt_other)}; + PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv_clone, poly_other_i, lt_other)}; /* #BKE_image_acquire_ibuf - TODO: this may be slow. */ @@ -3007,8 +3014,9 @@ static void project_paint_face_init(const ProjPaintState *ps, }; const MLoopTri *lt = &ps->looptris_eval[tri_index]; + const int poly_i = ps->looptri_polys_eval[tri_index]; const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)}; - const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)}; + const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, poly_i, lt)}; /* UV/pixel seeking data */ /* Image X/Y-Pixel */ @@ -3544,7 +3552,8 @@ static void project_bucket_init(const ProjPaintState *ps, tri_index = POINTER_AS_INT(node->link); const MLoopTri *lt = &ps->looptris_eval[tri_index]; - const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)}; + const int poly_i = ps->looptri_polys_eval[tri_index]; + const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, poly_i, lt)}; /* Image context switching */ tpage = project_paint_face_paint_image(ps, tri_index); @@ -4027,7 +4036,8 @@ static void project_paint_bleed_add_face_user(const ProjPaintState *ps, /* add face user if we have bleed enabled, set the UV seam flags later */ /* annoying but we need to add all faces even ones we never use elsewhere */ if (ps->seam_bleed_px > 0.0f) { - const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)}; + const int poly_i = ps->looptri_polys_eval[tri_index]; + const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, poly_i, lt)}; /* Check for degenerate triangles. Degenerate faces cause trouble with bleed computations. * Ideally this would be checked later, not to add to the cost of computing non-degenerate @@ -4112,6 +4122,7 @@ static bool proj_paint_state_mesh_eval_init(const bContext *C, ProjPaintState *p ps->totloop_eval = ps->me_eval->totloop; ps->looptris_eval = ps->me_eval->looptris(); + ps->looptri_polys_eval = ps->me_eval->looptri_polys(); ps->poly_to_loop_uv = static_cast( MEM_mallocN(ps->totpoly_eval * sizeof(float(*)[2]), "proj_paint_mtfaces")); @@ -4185,7 +4196,7 @@ static bool project_paint_clone_face_skip(ProjPaintState *ps, } /* will set multiple times for 4+ sided poly */ - ps->poly_to_loop_uv_clone[ps->looptris_eval[tri_index].poly] = lc->mloopuv_clone_base; + ps->poly_to_loop_uv_clone[ps->looptri_polys_eval[tri_index]] = lc->mloopuv_clone_base; } return false; } @@ -4213,27 +4224,27 @@ static void proj_paint_face_lookup_init(const ProjPaintState *ps, ProjPaintFaceL /* Return true if face should be considered paintable, false otherwise */ static bool project_paint_check_face_paintable(const ProjPaintState *ps, const ProjPaintFaceLookup *face_lookup, - const MLoopTri *lt) + const int tri_i) { if (ps->do_face_sel) { int orig_index; - + const int poly_i = ps->looptri_polys_eval[tri_i]; if ((face_lookup->index_mp_to_orig != nullptr) && - ((orig_index = (face_lookup->index_mp_to_orig[lt->poly])) != ORIGINDEX_NONE)) + ((orig_index = (face_lookup->index_mp_to_orig[poly_i])) != ORIGINDEX_NONE)) { return face_lookup->select_poly_orig && face_lookup->select_poly_orig[orig_index]; } - return ps->select_poly_eval && ps->select_poly_eval[lt->poly]; + return ps->select_poly_eval && ps->select_poly_eval[poly_i]; } else { int orig_index; - + const int poly_i = ps->looptri_polys_eval[tri_i]; if ((face_lookup->index_mp_to_orig != nullptr) && - ((orig_index = (face_lookup->index_mp_to_orig[lt->poly])) != ORIGINDEX_NONE)) + ((orig_index = (face_lookup->index_mp_to_orig[poly_i])) != ORIGINDEX_NONE)) { return !(face_lookup->hide_poly_orig && face_lookup->hide_poly_orig[orig_index]); } - return !(ps->hide_poly_eval && ps->hide_poly_eval[lt->poly]); + return !(ps->hide_poly_eval && ps->hide_poly_eval[poly_i]); } } @@ -4346,6 +4357,7 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps, int image_index = -1, tri_index; int prev_poly = -1; const blender::Span looptris = ps->looptris_eval; + const blender::Span looptri_polys = ps->looptri_polys_eval; BLI_assert(ps->image_tot == 0); @@ -4353,7 +4365,7 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps, bool is_face_paintable; bool skip_tri = false; - is_face_paintable = project_paint_check_face_paintable(ps, face_lookup, &looptris[tri_index]); + is_face_paintable = project_paint_check_face_paintable(ps, face_lookup, tri_index); if (!ps->do_stencil_brush) { slot = project_paint_face_paint_slot(ps, tri_index); @@ -4393,7 +4405,7 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps, tpage = ps->stencil_ima; } - ps->poly_to_loop_uv[looptris[tri_index].poly] = mloopuv_base; + ps->poly_to_loop_uv[looptri_polys[tri_index]] = mloopuv_base; tile = project_paint_face_paint_tile(tpage, mloopuv_base[looptris[tri_index].tri[0]]); @@ -4426,10 +4438,10 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps, /* Back-face culls individual triangles but mask normal will use polygon. */ if (ps->do_backfacecull) { if (ps->do_mask_normal) { - if (prev_poly != looptris[tri_index].poly) { + if (prev_poly != looptri_polys[tri_index]) { bool culled = true; - const blender::IndexRange poly = ps->polys_eval[looptris[tri_index].poly]; - prev_poly = looptris[tri_index].poly; + const blender::IndexRange poly = ps->polys_eval[looptri_polys[tri_index]]; + prev_poly = looptri_polys[tri_index]; for (const int corner : poly) { if (!(ps->vertFlags[ps->corner_verts_eval[corner]] & PROJ_VERT_CULL)) { culled = false; diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index e8f81c736aa..94fa0268cb7 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -272,6 +272,7 @@ static void imapaint_pick_uv( const MLoopTri *lt = BKE_mesh_runtime_looptri_ensure(me_eval); const int tottri = BKE_mesh_runtime_looptri_len(me_eval); + const int *looptri_polys = BKE_mesh_runtime_looptri_polys_ensure(me_eval); const float(*positions)[3] = BKE_mesh_vert_positions(me_eval); const int *corner_verts = BKE_mesh_corner_verts(me_eval); @@ -294,7 +295,8 @@ static void imapaint_pick_uv( /* test all faces in the derivedmesh with the original index of the picked face */ /* face means poly here, not triangle, indeed */ for (i = 0; i < tottri; i++, lt++) { - findex = index_mp_to_orig ? index_mp_to_orig[lt->poly] : lt->poly; + const int poly_i = looptri_polys[i]; + findex = index_mp_to_orig ? index_mp_to_orig[poly_i] : poly_i; if (findex == faceindex) { const float(*mloopuv)[2]; @@ -309,8 +311,8 @@ static void imapaint_pick_uv( const Material *ma; const TexPaintSlot *slot; - ma = BKE_object_material_get( - ob_eval, material_indices == NULL ? 1 : material_indices[lt->poly] + 1); + ma = BKE_object_material_get(ob_eval, + material_indices == NULL ? 1 : material_indices[poly_i] + 1); slot = &ma->texpaintslot[ma->paint_active_slot]; if (!(slot && slot->uvname && diff --git a/source/blender/editors/transform/transform_snap_object.cc b/source/blender/editors/transform/transform_snap_object.cc index 87872227936..5df0dbdc7b9 100644 --- a/source/blender/editors/transform/transform_snap_object.cc +++ b/source/blender/editors/transform/transform_snap_object.cc @@ -749,6 +749,8 @@ static bool raycastMesh(SnapObjectContext *sctx, BVHTreeFromMesh treedata; snap_object_data_mesh_get(sctx, ob_eval, me_eval, use_hide, &treedata); + const blender::Span looptri_polys = me_eval->looptri_polys(); + if (treedata.tree == nullptr) { return retval; } @@ -809,7 +811,7 @@ static bool raycastMesh(SnapObjectContext *sctx, retval = true; if (r_index) { - *r_index = treedata.looptri[hit.index].poly; + *r_index = looptri_polys[hit.index]; } } } diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp index 9b24df6fc18..78fcb5fd595 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp @@ -414,6 +414,7 @@ void BlenderFileLoader::insertShapeNode(Object *ob, Mesh *me, int id) int tottri = poly_to_tri_count(me->totpoly, me->totloop); MLoopTri *mlooptri = (MLoopTri *)MEM_malloc_arrayN(tottri, sizeof(*mlooptri), __func__); blender::bke::mesh::looptris_calc(vert_positions, mesh_polys, corner_verts, {mlooptri, tottri}); + const blender::Span looptri_polys = me->looptri_polys(); // Compute loop normals BKE_mesh_calc_normals_split(me); @@ -523,7 +524,8 @@ void BlenderFileLoader::insertShapeNode(Object *ob, Mesh *me, int id) // by the near and far view planes. for (int a = 0; a < tottri; a++) { const MLoopTri *lt = &mlooptri[a]; - Material *mat = BKE_object_material_get(ob, material_indices[lt->poly] + 1); + const int poly_i = looptri_polys[a]; + Material *mat = BKE_object_material_get(ob, material_indices[poly_i] + 1); copy_v3_v3(v1, vert_positions[corner_verts[lt->tri[0]]]); copy_v3_v3(v2, vert_positions[corner_verts[lt->tri[1]]]); @@ -537,7 +539,7 @@ void BlenderFileLoader::insertShapeNode(Object *ob, Mesh *me, int id) v2[2] += _z_offset; v3[2] += _z_offset; - if (_smooth && (!sharp_faces[lt->poly]) && lnors) { + if (_smooth && (!sharp_faces[poly_i]) && lnors) { copy_v3_v3(n1, lnors[lt->tri[0]]); copy_v3_v3(n2, lnors[lt->tri[1]]); copy_v3_v3(n3, lnors[lt->tri[2]]); @@ -563,7 +565,7 @@ void BlenderFileLoader::insertShapeNode(Object *ob, Mesh *me, int id) continue; } - bool fm = (ffa) ? (ffa[lt->poly].flag & FREESTYLE_FACE_MARK) != 0 : false; + bool fm = (ffa) ? (ffa[poly_i].flag & FREESTYLE_FACE_MARK) != 0 : false; bool em1 = false, em2 = false, em3 = false; if (fed) { diff --git a/source/blender/gpencil_modifiers_legacy/intern/lineart/lineart_cpu.cc b/source/blender/gpencil_modifiers_legacy/intern/lineart/lineart_cpu.cc index a31008d39f0..8a045aeb98f 100644 --- a/source/blender/gpencil_modifiers_legacy/intern/lineart/lineart_cpu.cc +++ b/source/blender/gpencil_modifiers_legacy/intern/lineart/lineart_cpu.cc @@ -1466,6 +1466,7 @@ struct EdgeFeatData { blender::Span corner_verts; blender::Span corner_edges; blender::Span looptris; + blender::Span looptri_polys; LineartTriangle *tri_array; blender::VArray sharp_edges; blender::VArray sharp_faces; @@ -1503,6 +1504,7 @@ static void lineart_identify_mlooptri_feature_edges(void *__restrict userdata, Object *ob_eval = e_feat_data->ob_eval; LineartEdgeNeighbor *edge_nabr = e_feat_data->edge_nabr; const blender::Span looptris = e_feat_data->looptris; + const blender::Span looptri_polys = e_feat_data->looptri_polys; uint16_t edge_flag_result = 0; @@ -1520,10 +1522,10 @@ static void lineart_identify_mlooptri_feature_edges(void *__restrict userdata, FreestyleFace *ff1, *ff2; int index = e_feat_data->freestyle_face_index; if (index > -1) { - ff1 = &((FreestyleFace *)me->pdata.layers[index].data)[looptris[i / 3].poly]; + ff1 = &((FreestyleFace *)me->pdata.layers[index].data)[looptri_polys[i / 3]]; } if (edge_nabr[i].e > -1) { - ff2 = &((FreestyleFace *)me->pdata.layers[index].data)[looptris[edge_nabr[i].e / 3].poly]; + ff2 = &((FreestyleFace *)me->pdata.layers[index].data)[looptri_polys[edge_nabr[i].e / 3]]; } else { /* Handle mesh boundary cases: We want mesh boundaries to respect @@ -1637,8 +1639,8 @@ static void lineart_identify_mlooptri_feature_edges(void *__restrict userdata, if (ld->conf.use_crease) { bool do_crease = true; if (!ld->conf.force_crease && !e_feat_data->use_auto_smooth && - (!e_feat_data->sharp_faces[looptris[f1].poly]) && - (!e_feat_data->sharp_faces[looptris[f2].poly])) + (!e_feat_data->sharp_faces[looptri_polys[f1]]) && + (!e_feat_data->sharp_faces[looptri_polys[f2]])) { do_crease = false; } @@ -1647,8 +1649,8 @@ static void lineart_identify_mlooptri_feature_edges(void *__restrict userdata, } } - int mat1 = material_indices ? material_indices[looptris[f1].poly] : 0; - int mat2 = material_indices ? material_indices[looptris[f2].poly] : 0; + int mat1 = material_indices ? material_indices[looptri_polys[f1]] : 0; + int mat2 = material_indices ? material_indices[looptri_polys[f2]] : 0; if (mat1 != mat2) { Material *m1 = BKE_object_material_get_eval(ob_eval, mat1 + 1); @@ -1785,6 +1787,7 @@ struct TriData { blender::Span positions; blender::Span corner_verts; blender::Span looptris; + blender::Span looptri_polys; const int *material_indices; LineartVert *vert_arr; LineartTriangle *tri_arr; @@ -1801,6 +1804,7 @@ static void lineart_load_tri_task(void *__restrict userdata, const blender::Span positions = tri_task_data->positions; const blender::Span corner_verts = tri_task_data->corner_verts; const MLoopTri *looptri = &tri_task_data->looptris[i]; + const int poly_i = tri_task_data->looptri_polys[i]; const int *material_indices = tri_task_data->material_indices; LineartVert *vert_arr = tri_task_data->vert_arr; LineartTriangle *tri = tri_task_data->tri_arr; @@ -1816,8 +1820,8 @@ static void lineart_load_tri_task(void *__restrict userdata, tri->v[2] = &vert_arr[v3]; /* Material mask bits and occlusion effectiveness assignment. */ - Material *mat = BKE_object_material_get( - ob_info->original_ob_eval, material_indices ? material_indices[looptri->poly] + 1 : 1); + Material *mat = BKE_object_material_get(ob_info->original_ob_eval, + material_indices ? material_indices[poly_i] + 1 : 1); tri->material_mask_bits |= ((mat && (mat->lineart.flags & LRT_MATERIAL_MASK_ENABLED)) ? mat->lineart.material_mask_bits : 0); @@ -1859,6 +1863,7 @@ struct EdgeNeighborData { LineartAdjacentEdge *adj_e; blender::Span corner_verts; blender::Span looptris; + blender::Span looptri_polys; }; static void lineart_edge_neighbor_init_task(void *__restrict userdata, @@ -1921,6 +1926,7 @@ static LineartEdgeNeighbor *lineart_build_edge_neighbor(Mesh *me, int total_edge en_data.edge_nabr = edge_nabr; en_data.corner_verts = me->corner_verts(); en_data.looptris = me->looptris(); + en_data.looptri_polys = me->looptri_polys(); BLI_task_parallel_range(0, total_edges, &en_data, lineart_edge_neighbor_init_task, &en_settings); diff --git a/source/blender/gpu/intern/gpu_shader_builder_stubs.cc b/source/blender/gpu/intern/gpu_shader_builder_stubs.cc index f31b73bcd60..b0ccc8844d6 100644 --- a/source/blender/gpu/intern/gpu_shader_builder_stubs.cc +++ b/source/blender/gpu/intern/gpu_shader_builder_stubs.cc @@ -119,7 +119,9 @@ eAttrDomain BKE_id_attribute_domain(const struct ID * /*id*/, /* -------------------------------------------------------------------- */ /** \name Stubs of BKE_paint.h * \{ */ -bool paint_is_face_hidden(const struct MLoopTri * /*lt*/, const bool * /*hide_poly*/) +bool paint_is_face_hidden(const int * /*looptri_polys*/, + const bool * /*hide_poly*/, + int /*tri_index*/) { BLI_assert_unreachable(); return false; diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index 446aacae2b4..a99c3fffe4b 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -292,10 +292,15 @@ typedef struct Mesh { blender::MutableSpan deform_verts_for_write(); /** - * Cached triangulation of the mesh. + * Cached triangulation of mesh faces, depending on the face topology and the vertex positions. */ blender::Span looptris() const; + /** + * A map containing the face index that each cached triangle from #Mesh::looptris() came from. + */ + blender::Span looptri_polys() const; + /** Set cached mesh bounds to a known-correct value to avoid their lazy calculation later on. */ void bounds_set_eager(const blender::Bounds &bounds); diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index 61948b9a449..d788dfe8e3b 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -69,9 +69,6 @@ enum { * * Usage examples: * \code{.c} - * // access polygon attribute value. - * T value = polygon_attribute[lt->poly]; - * * // access vertex locations. * float *vtri_co[3] = { * positions[corner_verts[lt->tri[0]]], @@ -137,7 +134,6 @@ enum { */ typedef struct MLoopTri { unsigned int tri[3]; - unsigned int poly; } MLoopTri; # # diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 809ccb93bcd..4b04db0f58f 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -413,6 +413,14 @@ static int rna_MeshLoopTriangle_index_get(PointerRNA *ptr) return index; } +static int rna_MeshLoopTriangle_polygon_index_get(PointerRNA *ptr) +{ + const Mesh *mesh = rna_mesh(ptr); + const int index = rna_MeshLoopTriangle_index_get(ptr); + const int *looptri_polys = BKE_mesh_runtime_looptri_polys_ensure(mesh); + return looptri_polys[index]; +} + static void rna_Mesh_loop_triangles_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { const Mesh *mesh = rna_mesh(ptr); @@ -440,6 +448,30 @@ int rna_Mesh_loop_triangles_lookup_int(PointerRNA *ptr, int index, PointerRNA *r return true; } +static void rna_Mesh_loop_triangle_faces_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +{ + const Mesh *mesh = rna_mesh(ptr); + rna_iterator_array_begin(iter, + (void *)BKE_mesh_runtime_looptri_polys_ensure(mesh), + sizeof(int), + BKE_mesh_runtime_looptri_len(mesh), + false, + NULL); +} + +int rna_Mesh_loop_triangle_faces_lookup_int(PointerRNA *ptr, int index, PointerRNA *r_ptr) +{ + const Mesh *mesh = rna_mesh(ptr); + if (index < 0 || index >= BKE_mesh_runtime_looptri_len(mesh)) { + return false; + } + /* Casting away const is okay because this RNA type doesn't allow changing the value. */ + r_ptr->owner_id = (ID *)&mesh->id; + r_ptr->type = &RNA_ReadOnlyInteger; + r_ptr->data = (void *)&BKE_mesh_runtime_looptri_polys_ensure(mesh)[index]; + return true; +} + static void rna_MeshVertex_co_get(PointerRNA *ptr, float *value) { copy_v3_v3(value, (const float *)ptr->data); @@ -1832,18 +1864,18 @@ static bool rna_MeshEdge_is_loose_get(PointerRNA *ptr) static int rna_MeshLoopTriangle_material_index_get(PointerRNA *ptr) { const Mesh *me = rna_mesh(ptr); + const int poly_i = rna_MeshLoopTriangle_polygon_index_get(ptr); const int *material_indices = BKE_mesh_material_indices(me); - const MLoopTri *ltri = (MLoopTri *)ptr->data; - return material_indices == NULL ? 0 : material_indices[ltri->poly]; + return material_indices == NULL ? 0 : material_indices[poly_i]; } static bool rna_MeshLoopTriangle_use_smooth_get(PointerRNA *ptr) { const Mesh *me = rna_mesh(ptr); - const MLoopTri *ltri = (MLoopTri *)ptr->data; + const int poly_i = rna_MeshLoopTriangle_polygon_index_get(ptr); const bool *sharp_faces = (const bool *)CustomData_get_layer_named( &me->pdata, CD_PROP_BOOL, "sharp_face"); - return !(sharp_faces && sharp_faces[ltri->poly]); + return !(sharp_faces && sharp_faces[poly_i]); } /* path construction */ @@ -2883,7 +2915,7 @@ static void rna_def_mlooptri(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); prop = RNA_def_property(srna, "polygon_index", PROP_INT, PROP_UNSIGNED); - RNA_def_property_int_sdna(prop, NULL, "poly"); + RNA_def_property_int_funcs(prop, "rna_MeshLoopTriangle_polygon_index_get", NULL, NULL); RNA_def_property_ui_text( prop, "Polygon", "Index of mesh polygon that the triangle is a part of"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); @@ -4190,6 +4222,18 @@ static void rna_def_face_maps(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); } +static void rna_def_looptri_poly_value(BlenderRNA *brna) +{ + StructRNA *srna = RNA_def_struct(brna, "ReadOnlyInteger", NULL); + RNA_def_struct_sdna(srna, "MIntProperty"); + RNA_def_struct_ui_text(srna, "Read-only Integer", ""); + + PropertyRNA *prop = RNA_def_property(srna, "value", PROP_INT, PROP_NONE); + RNA_def_property_ui_text(prop, "Value", ""); + RNA_def_property_int_sdna(prop, NULL, "i"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); +} + static void rna_def_mesh(BlenderRNA *brna) { StructRNA *srna; @@ -4328,6 +4372,23 @@ static void rna_def_mesh(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Loop Triangles", "Tessellation of mesh polygons into triangles"); rna_def_mesh_looptris(brna, prop); + rna_def_looptri_poly_value(brna); + + prop = RNA_def_property(srna, "loop_triangle_polygons", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_funcs(prop, + "rna_Mesh_loop_triangle_faces_begin", + "rna_iterator_array_next", + "rna_iterator_array_end", + "rna_iterator_array_get", + "rna_Mesh_loop_triangles_length", + "rna_Mesh_loop_triangle_faces_lookup_int", + NULL, + NULL); + RNA_def_property_struct_type(prop, "ReadOnlyInteger"); + RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Triangle Faces", "The polygon index for each loop triangle"); + /* TODO: should this be allowed to be itself? */ prop = RNA_def_property(srna, "texture_mesh", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "texcomesh"); diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index ec86553ea7c..226d8c2bb81 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -59,6 +59,7 @@ static const EnumPropertyItem space_items[] = { # include "BKE_main.h" # include "BKE_mball.h" # include "BKE_mesh.h" +# include "BKE_mesh_runtime.h" # include "BKE_modifier.h" # include "BKE_object.h" # include "BKE_report.h" @@ -546,10 +547,12 @@ static void rna_Mesh_assign_verts_to_group( # endif /* don't call inside a loop */ -static int mesh_looptri_to_poly_index(Mesh *me_eval, const MLoopTri *lt) +static int mesh_looptri_to_poly_index(Mesh *me_eval, const int tri_index) { + const int *looptri_polys = BKE_mesh_runtime_looptri_polys_ensure(me_eval); + const int poly_i = looptri_polys[tri_index]; const int *index_mp_to_orig = CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX); - return index_mp_to_orig ? index_mp_to_orig[lt->poly] : lt->poly; + return index_mp_to_orig ? index_mp_to_orig[poly_i] : poly_i; } /* TODO(sergey): Make the Python API more clear that evaluation might happen, or require @@ -635,7 +638,7 @@ static void rna_Object_ray_cast(Object *ob, copy_v3_v3(r_location, hit.co); copy_v3_v3(r_normal, hit.no); - *r_index = mesh_looptri_to_poly_index(mesh_eval, &treeData.looptri[hit.index]); + *r_index = mesh_looptri_to_poly_index(mesh_eval, hit.index); } } @@ -693,7 +696,7 @@ static void rna_Object_closest_point_on_mesh(Object *ob, copy_v3_v3(r_location, nearest.co); copy_v3_v3(r_normal, nearest.no); - *r_index = mesh_looptri_to_poly_index(mesh_eval, &treeData.looptri[nearest.index]); + *r_index = mesh_looptri_to_poly_index(mesh_eval, nearest.index); goto finally; } diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.cc b/source/blender/modifiers/intern/MOD_surfacedeform.cc index 728cbeeb02b..7313904faf2 100644 --- a/source/blender/modifiers/intern/MOD_surfacedeform.cc +++ b/source/blender/modifiers/intern/MOD_surfacedeform.cc @@ -73,6 +73,7 @@ struct SDefBindCalcData { blender::Span corner_verts; blender::Span corner_edges; blender::Span looptris; + blender::Span looptri_polys; /** Coordinates to bind to, transformed into local space (compatible with `vertexCos`). */ float (*targetCos)[3]; @@ -390,7 +391,7 @@ BLI_INLINE uint nearestVert(SDefBindCalcData *const data, const float point_co[3 BLI_bvhtree_find_nearest( data->treeData->tree, t_point, &nearest, data->treeData->nearest_callback, data->treeData); - const blender::IndexRange poly = data->polys[data->looptris[nearest.index].poly]; + const blender::IndexRange poly = data->polys[data->looptri_polys[nearest.index]]; for (int i = 0; i < poly.size(); i++) { const int edge_i = data->corner_edges[poly.start() + i]; @@ -1258,6 +1259,7 @@ static bool surfacedeformBind(Object *ob, data.corner_verts = corner_verts; data.corner_edges = corner_edges; data.looptris = target->looptris(); + data.looptri_polys = target->looptri_polys(); data.targetCos = static_cast( MEM_malloc_arrayN(target_verts_num, sizeof(float[3]), "SDefTargetBindVertArray")); data.bind_verts = smd_orig->verts; diff --git a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc index 46adc21bfeb..16b84af3470 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc @@ -274,7 +274,7 @@ BLI_NOINLINE static void interpolate_attribute(const Mesh &mesh, break; } case ATTR_DOMAIN_FACE: { - bke::mesh_surface_sample::sample_face_attribute(mesh.looptris(), + bke::mesh_surface_sample::sample_face_attribute(mesh.looptri_polys(), looptri_indices, source_data, IndexMask(output_data.size()), diff --git a/source/blender/nodes/geometry/nodes/node_geo_sample_nearest.cc b/source/blender/nodes/geometry/nodes/node_geo_sample_nearest.cc index 35c8bbd5561..9453503e80b 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_sample_nearest.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_sample_nearest.cc @@ -1,5 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ +#include "BLI_array_utils.hh" + #include "DNA_pointcloud_types.h" #include "BKE_bvhutils.h" @@ -147,11 +149,10 @@ static void get_closest_mesh_polys(const Mesh &mesh, Array looptri_indices(positions.size()); get_closest_mesh_looptris(mesh, positions, mask, looptri_indices, r_distances_sq, r_positions); - const Span looptris = mesh.looptris(); + const Span looptri_polys = mesh.looptri_polys(); for (const int i : mask) { - const MLoopTri &looptri = looptris[looptri_indices[i]]; - r_poly_indices[i] = looptri.poly; + r_poly_indices[i] = looptri_polys[looptri_indices[i]]; } } diff --git a/source/blender/python/mathutils/mathutils_bvhtree.cc b/source/blender/python/mathutils/mathutils_bvhtree.cc index ee8cda2c931..de34c802ce7 100644 --- a/source/blender/python/mathutils/mathutils_bvhtree.cc +++ b/source/blender/python/mathutils/mathutils_bvhtree.cc @@ -1142,6 +1142,7 @@ static PyObject *C_BVHTree_FromObject(PyObject * /*cls*/, PyObject *args, PyObje const blender::Span corner_verts = mesh->corner_verts(); const blender::Span looptris = mesh->looptris(); + const blender::Span looptri_polys = mesh->looptri_polys(); /* Get data for tessellation */ @@ -1182,7 +1183,7 @@ static PyObject *C_BVHTree_FromObject(PyObject * /*cls*/, PyObject *args, PyObje copy_v3_v3(co[2], coords[tris[i][2]]); BLI_bvhtree_insert(tree, int(i), co[0], 3); - orig_index[i] = int(looptris[i].poly); + orig_index[i] = int(looptri_polys[i]); } BLI_bvhtree_balance(tree); diff --git a/source/blender/render/intern/bake.cc b/source/blender/render/intern/bake.cc index 8022d875e65..22efdcb60bc 100644 --- a/source/blender/render/intern/bake.cc +++ b/source/blender/render/intern/bake.cc @@ -501,8 +501,10 @@ static TriTessFace *mesh_calc_tri_tessface(Mesh *me, bool tangent, Mesh *me_eval } const blender::Span vert_normals = me->vert_normals(); + const blender::Span looptri_polys = me->looptri_polys(); for (i = 0; i < tottri; i++) { const MLoopTri *lt = &looptri[i]; + const int poly_i = looptri_polys[i]; triangles[i].positions[0] = positions[corner_verts[lt->tri[0]]]; triangles[i].positions[1] = positions[corner_verts[lt->tri[1]]]; @@ -510,7 +512,7 @@ static TriTessFace *mesh_calc_tri_tessface(Mesh *me, bool tangent, Mesh *me_eval triangles[i].vert_normals[0] = vert_normals[corner_verts[lt->tri[0]]]; triangles[i].vert_normals[1] = vert_normals[corner_verts[lt->tri[1]]]; triangles[i].vert_normals[2] = vert_normals[corner_verts[lt->tri[2]]]; - triangles[i].is_smooth = !sharp_faces[lt->poly]; + triangles[i].is_smooth = !sharp_faces[poly_i]; if (tangent) { triangles[i].tspace[0] = &tspace[lt->tri[0]]; @@ -525,14 +527,14 @@ static TriTessFace *mesh_calc_tri_tessface(Mesh *me, bool tangent, Mesh *me_eval } if (calculate_normal) { - if (lt->poly != mpoly_prev) { - no = blender::bke::mesh::poly_normal_calc(positions, corner_verts.slice(polys[lt->poly])); - mpoly_prev = lt->poly; + if (poly_i != mpoly_prev) { + no = blender::bke::mesh::poly_normal_calc(positions, corner_verts.slice(polys[poly_i])); + mpoly_prev = poly_i; } copy_v3_v3(triangles[i].normal, no); } else { - copy_v3_v3(triangles[i].normal, precomputed_normals[lt->poly]); + copy_v3_v3(triangles[i].normal, precomputed_normals[poly_i]); } } @@ -753,17 +755,20 @@ void RE_bake_pixels_populate(Mesh *me, blender::bke::mesh::looptris_calc( me->vert_positions(), me->polys(), me->corner_verts(), {looptri, tottri}); + const blender::Span looptri_polys = me->looptri_polys(); + const int *material_indices = BKE_mesh_material_indices(me); const int materials_num = targets->materials_num; for (int i = 0; i < tottri; i++) { const MLoopTri *lt = &looptri[i]; + const int poly_i = looptri_polys[i]; bd.primitive_id = i; /* Find images matching this material. */ const int material_index = (material_indices && materials_num) ? - clamp_i(material_indices[lt->poly], 0, materials_num - 1) : + clamp_i(material_indices[poly_i], 0, materials_num - 1) : 0; Image *image = targets->material_to_image[material_index]; for (int image_id = 0; image_id < targets->images_num; image_id++) { diff --git a/source/blender/render/intern/multires_bake.cc b/source/blender/render/intern/multires_bake.cc index 097fad22b45..06d82cdaf23 100644 --- a/source/blender/render/intern/multires_bake.cc +++ b/source/blender/render/intern/multires_bake.cc @@ -45,6 +45,7 @@ using MPassKnownData = void (*)(blender::Span vert_positions, blender::OffsetIndices polys, blender::Span corner_verts, blender::Span looptris, + blender::Span looptri_polys, blender::Span uv_map, DerivedMesh *hires_dm, void *thread_data, @@ -70,6 +71,7 @@ struct MResolvePixelData { blender::OffsetIndices polys; blender::Span corner_verts; blender::Span looptris; + blender::Span looptri_polys; blender::Span vert_normals; blender::Span poly_normals; @@ -125,7 +127,7 @@ static void multiresbake_get_normal(const MResolvePixelData *data, const int vert_index, float r_normal[3]) { - const int poly_index = data->looptris[tri_num].poly; + const int poly_index = data->looptri_polys[tri_num]; const bool smoothnormal = !(data->sharp_faces && data->sharp_faces[poly_index]); if (smoothnormal) { @@ -209,6 +211,7 @@ static void flush_pixel(const MResolvePixelData *data, const int x, const int y) data->polys, data->corner_verts, data->looptris, + data->looptri_polys, data->uv_map, data->hires_dm, data->thread_data, @@ -395,7 +398,8 @@ static void *do_multires_bake_thread(void *data_v) while ((tri_index = multires_bake_queue_next_tri(handle->queue)) >= 0) { const MLoopTri *lt = &data->looptris[tri_index]; - const short mat_nr = data->material_indices == nullptr ? 0 : data->material_indices[lt->poly]; + const int poly_i = data->looptri_polys[tri_index]; + const short mat_nr = data->material_indices == nullptr ? 0 : data->material_indices[poly_i]; if (multiresbake_test_break(bkr)) { break; @@ -507,6 +511,7 @@ static void do_multires_bake(MultiresBakeRender *bkr, const blender::Span vert_normals = temp_mesh->vert_normals(); const blender::Span poly_normals = temp_mesh->poly_normals(); const blender::Span looptris = temp_mesh->looptris(); + const blender::Span looptri_polys = temp_mesh->looptri_polys(); if (require_tangent) { if (CustomData_get_layer_index(&dm->loopData, CD_TANGENT) == -1) { @@ -515,6 +520,7 @@ static void do_multires_bake(MultiresBakeRender *bkr, polys, dm->getCornerVertArray(dm), looptris.data(), + looptri_polys.data(), looptris.size(), static_cast( CustomData_get_layer_named(&dm->polyData, CD_PROP_BOOL, "sharp_face")), @@ -565,6 +571,7 @@ static void do_multires_bake(MultiresBakeRender *bkr, handle->data.polys = polys; handle->data.corner_verts = corner_verts; handle->data.looptris = looptris; + handle->data.looptri_polys = looptri_polys; handle->data.vert_normals = vert_normals; handle->data.poly_normals = poly_normals; handle->data.material_indices = static_cast( @@ -658,7 +665,7 @@ static void get_ccgdm_data(const blender::OffsetIndices lores_polys, DerivedMesh *hidm, const int *index_mp_to_orig, const int lvl, - const MLoopTri *lt, + const int poly_index, const float u, const float v, float co[3], @@ -669,7 +676,6 @@ static void get_ccgdm_data(const blender::OffsetIndices lores_polys, float crn_x, crn_y; int grid_size, S, face_side; int *grid_offset, g_index; - int poly_index = lt->poly; grid_size = hidm->getGridSize(hidm); grid_data = hidm->getGridData(hidm); @@ -840,6 +846,7 @@ static void apply_heights_callback(const blender::Span vert_pos const blender::OffsetIndices polys, const blender::Span corner_verts, const blender::Span looptris, + const blender::Span looptri_polys, const blender::Span uv_map, DerivedMesh *hires_dm, void *thread_data_v, @@ -853,7 +860,8 @@ static void apply_heights_callback(const blender::Span vert_pos const int y) { const MLoopTri *lt = &looptris[tri_index]; - const blender::IndexRange poly = polys[lt->poly]; + const int poly_i = looptri_polys[tri_index]; + const blender::IndexRange poly = polys[poly_i]; MHeightBakeData *height_data = (MHeightBakeData *)bake_data; MultiresBakeThread *thread_data = (MultiresBakeThread *)thread_data_v; float uv[2]; @@ -880,11 +888,18 @@ static void apply_heights_callback(const blender::Span vert_pos clamp_v2(uv, 0.0f, 1.0f); get_ccgdm_data( - polys, hires_dm, height_data->orig_index_mp_to_orig, lvl, lt, uv[0], uv[1], p1, nullptr); + polys, hires_dm, height_data->orig_index_mp_to_orig, lvl, poly_i, uv[0], uv[1], p1, nullptr); if (height_data->ssdm) { - get_ccgdm_data( - polys, height_data->ssdm, height_data->orig_index_mp_to_orig, 0, lt, uv[0], uv[1], p0, n); + get_ccgdm_data(polys, + height_data->ssdm, + height_data->orig_index_mp_to_orig, + 0, + poly_i, + uv[0], + uv[1], + p0, + n); } else { if (poly.size() == 4) { @@ -954,6 +969,7 @@ static void apply_tangmat_callback(const blender::Span /*vert_p const blender::OffsetIndices polys, const blender::Span /*corner_verts*/, const blender::Span looptris, + const blender::Span looptri_polys, const blender::Span uv_map, DerivedMesh *hires_dm, void * /*thread_data*/, @@ -967,7 +983,8 @@ static void apply_tangmat_callback(const blender::Span /*vert_p const int y) { const MLoopTri *lt = &looptris[tri_index]; - const blender::IndexRange poly = polys[lt->poly]; + const int poly_i = looptri_polys[tri_index]; + const blender::IndexRange poly = polys[poly_i]; MNormalBakeData *normal_data = (MNormalBakeData *)bake_data; float uv[2]; const float *st0, *st1, *st2, *st3; @@ -993,7 +1010,7 @@ static void apply_tangmat_callback(const blender::Span /*vert_p clamp_v2(uv, 0.0f, 1.0f); get_ccgdm_data( - polys, hires_dm, normal_data->orig_index_mp_to_orig, lvl, lt, uv[0], uv[1], nullptr, n); + polys, hires_dm, normal_data->orig_index_mp_to_orig, lvl, poly_i, uv[0], uv[1], nullptr, n); mul_v3_m3v3(vec, tangmat, n); normalize_v3_length(vec, 0.5); diff --git a/source/blender/render/intern/texture_margin.cc b/source/blender/render/intern/texture_margin.cc index 309d9c36b04..da8e9ef1cce 100644 --- a/source/blender/render/intern/texture_margin.cc +++ b/source/blender/render/intern/texture_margin.cc @@ -483,6 +483,9 @@ static void generate_margin(ImBuf *ibuf, Array looptris(poly_to_tri_count(polys.size(), corner_edges.size())); bke::mesh::looptris_calc(vert_positions, polys, corner_verts, looptris); + Array looptri_polys(looptris.size()); + bke::mesh::looptris_calc_poly_indices(polys, looptri_polys); + TextureMarginMap map(ibuf->x, ibuf->y, uv_offset, edges_num, polys, corner_edges, mloopuv); bool draw_new_mask = false; @@ -512,9 +515,9 @@ static void generate_margin(ImBuf *ibuf, } /* NOTE: we need the top bit for the dijkstra distance map. */ - BLI_assert(lt->poly < 0x80000000); + BLI_assert(looptri_polys[i] < 0x80000000); - map.rasterize_tri(vec[0], vec[1], vec[2], lt->poly, draw_new_mask ? mask : nullptr); + map.rasterize_tri(vec[0], vec[1], vec[2], looptri_polys[i], draw_new_mask ? mask : nullptr); } char *tmpmask = (char *)MEM_dupallocN(mask);