diff --git a/intern/cycles/blender/mesh.cpp b/intern/cycles/blender/mesh.cpp index 678ee4b396a..bedd6e69bdb 100644 --- a/intern/cycles/blender/mesh.cpp +++ b/intern/cycles/blender/mesh.cpp @@ -246,11 +246,12 @@ static void fill_generic_attribute(BL::Mesh &b_mesh, if (polys_num == 0) { return; } - const MPoly *polys = static_cast(b_mesh.polygons[0].ptr.data); + const int *poly_offsets = static_cast(b_mesh.polygons[0].ptr.data); for (int i = 0; i < polys_num; i++) { - const MPoly &b_poly = polys[i]; - for (int j = 0; j < b_poly.totloop; j++) { - *data = get_value_at_index(b_poly.loopstart + j); + const int poly_start = poly_offsets[i]; + const int poly_size = poly_offsets[i + 1] - poly_start; + for (int j = 0; j < poly_size; j++) { + *data = get_value_at_index(poly_start + j); data++; } } @@ -600,7 +601,7 @@ static void attr_create_subd_uv_map(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, if (polys_num == 0) { return; } - const MPoly *polys = static_cast(b_mesh.polygons[0].ptr.data); + const int *poly_offsets = static_cast(b_mesh.polygons[0].ptr.data); if (!b_mesh.uv_layers.empty()) { BL::Mesh::uv_layers_iterator l; @@ -636,9 +637,10 @@ static void attr_create_subd_uv_map(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, float2 *fdata = uv_attr->data_float2(); for (int i = 0; i < polys_num; i++) { - const MPoly &b_poly = polys[i]; - for (int j = 0; j < b_poly.totloop; j++) { - *(fdata++) = get_float2(l->data[b_poly.loopstart + j].uv()); + const int poly_start = poly_offsets[i]; + const int poly_size = poly_offsets[i + 1] - poly_start; + for (int j = 0; j < poly_size; j++) { + *(fdata++) = get_float2(l->data[poly_start + j].uv()); } } } @@ -910,10 +912,9 @@ static void attr_create_random_per_island(Scene *scene, else { const int polys_num = b_mesh.polygons.length(); if (polys_num != 0) { - const MPoly *polys = static_cast(b_mesh.polygons[0].ptr.data); + const int *poly_offsets = static_cast(b_mesh.polygons[0].ptr.data); for (int i = 0; i < polys_num; i++) { - const MPoly &b_poly = polys[i]; - const int vert = corner_verts[b_poly.loopstart]; + const int vert = corner_verts[poly_offsets[i]]; data[i] = hash_uint_to_float(vertices_sets.find(vert)); } } @@ -1000,10 +1001,11 @@ static void create_mesh(Scene *scene, numtris = numfaces; } else { - const MPoly *polys = static_cast(b_mesh.polygons[0].ptr.data); + const int *poly_offsets = static_cast(b_mesh.polygons[0].ptr.data); for (int i = 0; i < polys_num; i++) { - const MPoly &b_poly = polys[i]; - numngons += (b_poly.totloop == 4) ? 0 : 1; + const int poly_start = poly_offsets[i]; + const int poly_size = poly_offsets[i + 1] - poly_start; + numngons += (poly_size == 4) ? 0 : 1; } } @@ -1132,14 +1134,16 @@ static void create_mesh(Scene *scene, std::copy(corner_verts, corner_verts + numcorners, subd_face_corners); - const MPoly *polys = static_cast(b_mesh.polygons[0].ptr.data); + const int *poly_offsets = static_cast(b_mesh.polygons[0].ptr.data); int ptex_offset = 0; for (int i = 0; i < numfaces; i++) { - const MPoly &b_poly = polys[i]; - subd_start_corner[i] = b_poly.loopstart; - subd_num_corners[i] = b_poly.totloop; + const int poly_start = poly_offsets[i]; + const int poly_size = poly_offsets[i + 1] - poly_start; + + subd_start_corner[i] = poly_start; + subd_num_corners[i] = poly_size; subd_ptex_offset[i] = ptex_offset; - const int num_ptex = (b_poly.totloop == 4) ? 1 : b_poly.totloop; + const int num_ptex = (poly_size == 4) ? 1 : poly_size; ptex_offset += num_ptex; } diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 3297226f9e8..14b6f2d73bb 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -68,10 +68,10 @@ struct Scene; /* * NOTE: all #MFace interfaces now officially operate on tessellated data. - * Also, the #MFace orig-index layer indexes #MPoly, not #MFace. + * Also, the #MFace orig-index layer indexes polys, not #MFace. */ -/* keep in sync with MFace/MPoly types */ +/* keep in sync with MFace type */ typedef struct DMFlagMat { short mat_nr; bool sharp; @@ -90,6 +90,8 @@ struct DerivedMesh { int needsFree; /* checked on ->release, is set to 0 for cached results */ int deformedOnly; /* set by modifier stack if only deformed from original */ DerivedMeshType type; + /* Always owned by this object. */ + int *poly_offsets; short tangent_mask; /* which tangent layers are calculated */ @@ -113,7 +115,7 @@ struct DerivedMesh { struct MEdge *(*getEdgeArray)(DerivedMesh *dm); int *(*getCornerVertArray)(DerivedMesh *dm); int *(*getCornerEdgeArray)(DerivedMesh *dm); - struct MPoly *(*getPolyArray)(DerivedMesh *dm); + int *(*getPolyArray)(DerivedMesh *dm); /** Copy all verts/edges/faces from the derived mesh into * *{vert/edge/face}_r (must point to a buffer large enough) @@ -122,7 +124,7 @@ struct DerivedMesh { void (*copyEdgeArray)(DerivedMesh *dm, struct MEdge *r_edge); void (*copyCornerVertArray)(DerivedMesh *dm, int *r_corner_verts); void (*copyCornerEdgeArray)(DerivedMesh *dm, int *r_corner_edges); - void (*copyPolyArray)(DerivedMesh *dm, struct MPoly *r_poly); + void (*copyPolyArray)(DerivedMesh *dm, int *r_poly_offsets); /** Return a pointer to the entire array of vert/edge/face custom data * from the derived mesh (this gives a pointer to the actual data, not diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h index 9516f524327..021f59d3422 100644 --- a/source/blender/blenkernel/BKE_deform.h +++ b/source/blender/blenkernel/BKE_deform.h @@ -3,6 +3,10 @@ #pragma once +#ifdef __cplusplus +# include "BLI_offset_indices.hh" +#endif + #ifdef __cplusplus extern "C" { #endif @@ -18,7 +22,6 @@ struct ID; struct ListBase; struct MDeformVert; struct MEdge; -struct MPoly; struct Object; struct bDeformGroup; @@ -273,16 +276,20 @@ void BKE_defvert_extract_vgroup_to_loopweights(const struct MDeformVert *dvert, int loops_num, bool invert_vgroup, float *r_weights); + +#ifdef __cplusplus + void BKE_defvert_extract_vgroup_to_polyweights(const struct MDeformVert *dvert, int defgroup, int verts_num, const int *corner_verts, int loops_num, - const struct MPoly *polys, - int polys_num, + blender::OffsetIndices polys, bool invert_vgroup, float *r_weights); +#endif + void BKE_defvert_weight_to_rgb(float r_rgb[3], float weight); void BKE_defvert_blend_write(struct BlendWriter *writer, diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 9344c2cd38e..c78879d48bd 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -34,7 +34,6 @@ struct MDisps; struct MEdge; struct MFace; struct MLoopTri; -struct MPoly; struct Main; struct MemArena; struct Mesh; @@ -142,6 +141,9 @@ void BKE_mesh_copy_parameters_for_eval(struct Mesh *me_dst, const struct Mesh *m void BKE_mesh_copy_parameters(struct Mesh *me_dst, const struct Mesh *me_src); void BKE_mesh_ensure_skin_customdata(struct Mesh *me); +/** Add poly offsets to describe faces to a new mesh. */ +void BKE_mesh_poly_offsets_ensure_alloc(struct Mesh *mesh); + struct Mesh *BKE_mesh_new_nomain(int verts_len, int edges_len, int loops_len, int polys_len); struct Mesh *BKE_mesh_new_nomain_from_template( const struct Mesh *me_src, int verts_len, int edges_len, int loops_len, int polys_len); @@ -298,7 +300,7 @@ void BKE_mesh_vert_coords_apply(struct Mesh *mesh, const float (*vert_coords)[3] * Calculate tessellation into #MLoopTri which exist only for this purpose. */ void BKE_mesh_recalc_looptri(const int *corner_verts, - const struct MPoly *polys, + const int *poly_offsets, const float (*vert_positions)[3], int totvert, int totloop, @@ -565,24 +567,27 @@ void BKE_mesh_mdisp_flip(struct MDisps *md, bool use_loop_mdisp_flip); * \param mloop: the full loops array. * \param ldata: the loops custom data. */ -void BKE_mesh_polygon_flip_ex(const struct MPoly *poly, +void BKE_mesh_polygon_flip_ex(int poly_offset, + int poly_size, int *corner_verts, int *corner_edges, struct CustomData *ldata, float (*lnors)[3], struct MDisps *mdisp, bool use_loop_mdisp_flip); -void BKE_mesh_polygon_flip(const struct MPoly *poly, +void BKE_mesh_polygon_flip(int poly_offset, + int poly_size, int *corner_verts, int *corner_edges, struct CustomData *ldata, int totloop); + /** * Flip (invert winding of) all polygons (used to inverse their normals). * * \note Invalidates tessellation, caller must handle that. */ -void BKE_mesh_polys_flip(const struct MPoly *polys, +void BKE_mesh_polys_flip(const int *poly_offsets, int *corner_verts, int *corner_edges, struct CustomData *ldata, @@ -619,7 +624,7 @@ void BKE_mesh_flush_select_from_verts(struct Mesh *me); * \param vert_cos_org: reference for the output location. * \param vert_cos_new: resulting coords. */ -void BKE_mesh_calc_relative_deform(const struct MPoly *polys, +void BKE_mesh_calc_relative_deform(const int *poly_offsets, int totpoly, const int *corner_verts, int totvert, @@ -674,7 +679,7 @@ bool BKE_mesh_validate_arrays(struct Mesh *me, int *corner_verts, int *corner_edges, unsigned int totloop, - struct MPoly *polys, + int *poly_offsets, unsigned int totpoly, struct MDeformVert *dverts, /* assume totvert length */ bool do_verbose, @@ -780,13 +785,13 @@ BLI_INLINE MEdge *BKE_mesh_edges_for_write(Mesh *mesh) return (MEdge *)CustomData_get_layer_for_write(&mesh->edata, CD_MEDGE, mesh->totedge); } -BLI_INLINE const MPoly *BKE_mesh_polys(const Mesh *mesh) +BLI_INLINE const int *BKE_mesh_poly_offsets(const Mesh *mesh) { - return (const MPoly *)CustomData_get_layer(&mesh->pdata, CD_MPOLY); + return mesh->poly_offset_indices; } -BLI_INLINE MPoly *BKE_mesh_polys_for_write(Mesh *mesh) +BLI_INLINE int *BKE_mesh_poly_offsets_for_write(Mesh *mesh) { - return (MPoly *)CustomData_get_layer_for_write(&mesh->pdata, CD_MPOLY, mesh->totpoly); + return mesh->poly_offset_indices; } BLI_INLINE const int *BKE_mesh_corner_verts(const Mesh *mesh) diff --git a/source/blender/blenkernel/BKE_mesh.hh b/source/blender/blenkernel/BKE_mesh.hh index 44dfaafa77d..f6fa5adcc93 100644 --- a/source/blender/blenkernel/BKE_mesh.hh +++ b/source/blender/blenkernel/BKE_mesh.hh @@ -21,7 +21,7 @@ float3 poly_normal_calc(Span vert_positions, Span poly_verts); * Calculate tessellation into #MLoopTri which exist only for this purpose. */ void looptris_calc(Span vert_positions, - Span polys, + OffsetIndices polys, Span corner_verts, MutableSpan looptris); /** @@ -32,7 +32,7 @@ void looptris_calc(Span vert_positions, * to calculate normals just to use this function. */ void looptris_calc_with_normals(Span vert_positions, - Span polys, + OffsetIndices polys, Span corner_verts, Span poly_normals, MutableSpan looptris); @@ -61,7 +61,7 @@ void poly_angles_calc(Span vert_positions, * since they may already be calculated and cached on the mesh. */ void normals_calc_polys(Span vert_positions, - Span polys, + OffsetIndices polys, Span corner_verts, MutableSpan poly_normals); @@ -72,7 +72,7 @@ void normals_calc_polys(Span vert_positions, * since they may already be calculated and cached on the mesh. */ void normals_calc_poly_vert(Span vert_positions, - Span polys, + OffsetIndices polys, Span corner_verts, MutableSpan poly_normals, MutableSpan vert_normals); @@ -88,7 +88,7 @@ void normals_calc_poly_vert(Span vert_positions, */ void normals_calc_loop(Span vert_positions, Span edges, - Span polys, + OffsetIndices polys, Span corner_verts, Span corner_edges, Span loop_to_poly_map, @@ -104,7 +104,7 @@ void normals_calc_loop(Span vert_positions, void normals_loop_custom_set(Span vert_positions, Span edges, - Span polys, + OffsetIndices polys, Span corner_verts, Span corner_edges, Span vert_normals, @@ -116,7 +116,7 @@ void normals_loop_custom_set(Span vert_positions, void normals_loop_custom_set_from_verts(Span vert_positions, Span edges, - Span polys, + OffsetIndices polys, Span corner_verts, Span corner_edges, Span vert_normals, @@ -134,7 +134,7 @@ void normals_loop_custom_set_from_verts(Span vert_positions, * * \param sharp_faces: Optional array used to mark specific faces for sharp shading. */ -void edges_sharp_from_angle_set(Span polys, +void edges_sharp_from_angle_set(OffsetIndices polys, Span corner_verts, Span corner_edges, Span poly_normals, @@ -152,19 +152,19 @@ void edges_sharp_from_angle_set(Span polys, * Find the index of the next corner in the polygon, looping to the start if necessary. * The indices are into the entire corners array, not just the polygon's corners. */ -inline int poly_corner_prev(const MPoly &poly, const int corner) +inline int poly_corner_prev(const IndexRange poly, const int corner) { - return corner - 1 + (corner == poly.loopstart) * poly.totloop; + return corner - 1 + (corner == poly.start()) * poly.size(); } /** * Find the index of the previous corner in the polygon, looping to the end if necessary. * The indices are into the entire corners array, not just the polygon's corners. */ -inline int poly_corner_next(const MPoly &poly, const int corner) +inline int poly_corner_next(const IndexRange poly, const int corner) { - if (corner == poly.loopstart + poly.totloop - 1) { - return poly.loopstart; + if (corner == poly.last()) { + return poly.start(); } return corner + 1; } @@ -173,18 +173,18 @@ inline int poly_corner_next(const MPoly &poly, const int corner) * Find the index of the corner in the polygon that uses the given vertex. * The index is into the entire corners array, not just the polygon's corners. */ -inline int poly_find_corner_from_vert(const MPoly &poly, +inline int poly_find_corner_from_vert(const IndexRange poly, const Span corner_verts, const int vert) { - return poly.loopstart + corner_verts.slice(poly.loopstart, poly.totloop).first_index(vert); + return poly[corner_verts.slice(poly).first_index(vert)]; } /** * Return the vertex indices on either side of the given vertex, ordered based on the winding * direction of the polygon. The vertex must be in the polygon. */ -inline int2 poly_find_adjecent_verts(const MPoly &poly, +inline int2 poly_find_adjecent_verts(const IndexRange poly, const Span corner_verts, const int vert) { @@ -235,13 +235,23 @@ inline blender::MutableSpan Mesh::edges_for_write() return {BKE_mesh_edges_for_write(this), this->totedge}; } -inline blender::Span Mesh::polys() const +inline blender::OffsetIndices Mesh::polys() const { - return {BKE_mesh_polys(this), this->totpoly}; + return blender::Span(BKE_mesh_poly_offsets(this), this->totpoly + 1); } -inline blender::MutableSpan Mesh::polys_for_write() +inline blender::Span Mesh::poly_offsets() const { - return {BKE_mesh_polys_for_write(this), this->totpoly}; + if (this->totpoly == 0) { + return {}; + } + return {BKE_mesh_poly_offsets(this), this->totpoly + 1}; +} +inline blender::MutableSpan Mesh::poly_offsets_for_write() +{ + if (this->totpoly == 0) { + return {}; + } + return {BKE_mesh_poly_offsets_for_write(this), this->totpoly + 1}; } inline blender::Span Mesh::corner_verts() const diff --git a/source/blender/blenkernel/BKE_mesh_legacy_convert.h b/source/blender/blenkernel/BKE_mesh_legacy_convert.h index 8a0ae63ce72..0dda5d78430 100644 --- a/source/blender/blenkernel/BKE_mesh_legacy_convert.h +++ b/source/blender/blenkernel/BKE_mesh_legacy_convert.h @@ -13,11 +13,9 @@ # include "BLI_resource_scope.hh" # include "BLI_span.hh" # include "BLI_vector.hh" -# include "DNA_customdata_types.h" -#endif -#ifdef __cplusplus -extern "C" { +# include "DNA_customdata_types.h" +# include "DNA_meshdata_types.h" #endif struct CustomData; @@ -63,7 +61,8 @@ void BKE_mesh_legacy_bevel_weight_to_layers(struct Mesh *mesh); /** * Convert the hidden element attributes to the old flag format for writing. */ -void BKE_mesh_legacy_convert_hide_layers_to_flags(struct Mesh *mesh); +void BKE_mesh_legacy_convert_hide_layers_to_flags(struct Mesh *mesh, + blender::MutableSpan legacy_polys); /** * Convert the old hide flags (#ME_HIDE) to the hidden element attribute for reading. * Only add the attributes when there are any elements in each domain hidden. @@ -73,7 +72,8 @@ void BKE_mesh_legacy_convert_flags_to_hide_layers(struct Mesh *mesh); /** * Convert the selected element attributes to the old flag format for writing. */ -void BKE_mesh_legacy_convert_selection_layers_to_flags(struct Mesh *mesh); +void BKE_mesh_legacy_convert_selection_layers_to_flags(struct Mesh *mesh, + blender::MutableSpan legacy_polys); /** * Convert the old selection flags (#SELECT/#ME_FACE_SEL) to the selected element attribute for * reading. Only add the attributes when there are any elements in each domain selected. @@ -83,7 +83,8 @@ void BKE_mesh_legacy_convert_flags_to_selection_layers(struct Mesh *mesh); /** * Move material indices from a generic attribute to #MPoly. */ -void BKE_mesh_legacy_convert_material_indices_to_mpoly(struct Mesh *mesh); +void BKE_mesh_legacy_convert_material_indices_to_mpoly(struct Mesh *mesh, + blender::MutableSpan legacy_polys); /** * Move material indices from the #MPoly struct to a generic attributes. * Only add the attribute when the indices are not all zero. @@ -96,7 +97,8 @@ void BKE_mesh_legacy_convert_loose_edges_to_flag(struct Mesh *mesh); void BKE_mesh_legacy_attribute_flags_to_strings(struct Mesh *mesh); void BKE_mesh_legacy_attribute_strings_to_flags(struct Mesh *mesh); -void BKE_mesh_legacy_sharp_faces_to_flags(struct Mesh *mesh); +void BKE_mesh_legacy_sharp_faces_to_flags(struct Mesh *mesh, + blender::MutableSpan legacy_polys); void BKE_mesh_legacy_sharp_faces_from_flags(struct Mesh *mesh); void BKE_mesh_legacy_sharp_edges_to_flags(struct Mesh *mesh); @@ -117,10 +119,21 @@ struct MLoop *BKE_mesh_legacy_convert_corners_to_loops( blender::ResourceScope &temp_arrays_for_convert, blender::Vector &loop_layers_to_write); -#endif +blender::MutableSpan BKE_mesh_legacy_convert_offsets_to_polys( + const Mesh *mesh, + blender::ResourceScope &temp_arrays_for_convert, + blender::Vector &poly_layers_to_write); + +void BKE_mesh_legacy_convert_polys_to_offsets(Mesh *mesh); void BKE_mesh_legacy_convert_loops_to_corners(struct Mesh *mesh); +#endif + +#ifdef __cplusplus +extern "C" { +#endif + /** * Recreate #MFace Tessellation. * diff --git a/source/blender/blenkernel/BKE_mesh_mapping.h b/source/blender/blenkernel/BKE_mesh_mapping.h index b4bf44e40c9..90e5693118e 100644 --- a/source/blender/blenkernel/BKE_mesh_mapping.h +++ b/source/blender/blenkernel/BKE_mesh_mapping.h @@ -8,6 +8,7 @@ #ifdef __cplusplus # include "BLI_array.hh" +# include "BLI_offset_indices.hh" #endif #ifdef __cplusplus @@ -16,7 +17,6 @@ extern "C" { struct MEdge; struct MLoopTri; -struct MPoly; /* UvVertMap */ #define STD_UV_CONNECT_LIMIT 0.0001f @@ -98,21 +98,27 @@ typedef struct MeshElemMap { int count; } MeshElemMap; +#ifdef __cplusplus + /* mapping */ -UvVertMap *BKE_mesh_uv_vert_map_create(const struct MPoly *polys, +UvVertMap *BKE_mesh_uv_vert_map_create(blender::OffsetIndices polys, const bool *hide_poly, const bool *select_poly, const int *corner_verts, const float (*mloopuv)[2], - unsigned int totpoly, unsigned int totvert, const float limit[2], bool selected, bool use_winding); + +#endif + UvMapVert *BKE_mesh_uv_vert_map_get_vert(UvVertMap *vmap, unsigned int v); void BKE_mesh_uv_vert_map_free(UvVertMap *vmap); +#ifdef __cplusplus + /** * Generates a map where the key is the vertex and the value * is a list of polys that use that vertex as a corner. @@ -120,11 +126,9 @@ void BKE_mesh_uv_vert_map_free(UvVertMap *vmap); */ void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map, int **r_mem, - const struct MPoly *polys, + blender::OffsetIndices polys, const int *corner_verts, - int totvert, - int totpoly, - int totloop); + int totvert); /** * Generates a map where the key is the vertex and the value * is a list of loops that use that vertex as a corner. @@ -132,11 +136,12 @@ void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map, */ void BKE_mesh_vert_loop_map_create(MeshElemMap **r_map, int **r_mem, - const struct MPoly *polys, + blender::OffsetIndices polys, const int *corner_verts, - int totvert, - int totpoly, - int totloop); + int totvert); + +#endif + /** * Generates a map where the key is the edge and the value * is a list of looptris that use that edge. @@ -162,6 +167,9 @@ void BKE_mesh_vert_edge_map_create( */ void BKE_mesh_vert_edge_vert_map_create( MeshElemMap **r_map, int **r_mem, const struct MEdge *edges, int totvert, int totedge); + +#ifdef __cplusplus + /** * Generates a map where the key is the edge and the value is a list of loops that use that edge. * Loops indices of a same poly are contiguous and in winding order. @@ -170,8 +178,7 @@ void BKE_mesh_vert_edge_vert_map_create( void BKE_mesh_edge_loop_map_create(MeshElemMap **r_map, int **r_mem, int totedge, - const struct MPoly *polys, - int totpoly, + blender::OffsetIndices polys, const int *corner_edges, int totloop); /** @@ -182,8 +189,7 @@ void BKE_mesh_edge_loop_map_create(MeshElemMap **r_map, void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map, int **r_mem, int totedge, - const struct MPoly *polys, - int totpoly, + blender::OffsetIndices polys, const int *corner_edges, int totloop); /** @@ -198,7 +204,7 @@ void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map, * * \note `totsource` could be `totpoly`, * `totfinal` could be `tottessface` and `final_origindex` its ORIGINDEX custom-data. - * This would allow an MPoly to loop over its tessfaces. + * This would allow a poly to loop over its tessfaces. */ void BKE_mesh_origindex_map_create( MeshElemMap **r_map, int **r_mem, int totsource, const int *final_origindex, int totfinal); @@ -208,8 +214,7 @@ void BKE_mesh_origindex_map_create( */ void BKE_mesh_origindex_map_create_looptri(MeshElemMap **r_map, int **r_mem, - const struct MPoly *polys, - int polys_num, + blender::OffsetIndices polys, const struct MLoopTri *looptri, int looptri_num); @@ -260,8 +265,7 @@ typedef bool (*MeshRemapIslandsCalc)(const float (*vert_positions)[3], const struct MEdge *edges, int totedge, const bool *uv_seams, - const struct MPoly *polys, - int totpoly, + blender::OffsetIndices polys, const int *corner_verts, const int *corner_edges, int totloop, @@ -279,8 +283,7 @@ bool BKE_mesh_calc_islands_loop_poly_edgeseam(const float (*vert_positions)[3], const struct MEdge *edges, int totedge, const bool *uv_seams, - const struct MPoly *polys, - int totpoly, + blender::OffsetIndices polys, const int *corner_verts, const int *corner_edges, int totloop, @@ -304,14 +307,15 @@ bool BKE_mesh_calc_islands_loop_poly_uvmap(float (*vert_positions)[3], struct MEdge *edges, int totedge, const bool *uv_seams, - struct MPoly *polys, - int totpoly, + blender::OffsetIndices polys, const int *corner_verts, const int *corner_edges, int totloop, const float (*luvs)[2], MeshIslandStore *r_island_store); +#endif + /** * Calculate smooth groups from sharp edges. * @@ -321,7 +325,7 @@ bool BKE_mesh_calc_islands_loop_poly_uvmap(float (*vert_positions)[3], * Note it's callers's responsibility to MEM_freeN returned array. */ int *BKE_mesh_calc_smoothgroups(int totedge, - const struct MPoly *polys, + const int *poly_offsets, int totpoly, const int *corner_edges, int totloop, @@ -346,19 +350,17 @@ int *BKE_mesh_calc_smoothgroups(int totedge, #ifdef __cplusplus -# include "DNA_meshdata_types.h" /* MPoly */ - namespace blender::bke::mesh_topology { -Array build_loop_to_poly_map(Span polys, int loops_num); +Array build_loop_to_poly_map(OffsetIndices polys); Array> build_vert_to_edge_map(Span edges, int verts_num); -Array> build_vert_to_poly_map(Span polys, +Array> build_vert_to_poly_map(OffsetIndices polys, Span corner_verts, int verts_num); Array> build_vert_to_loop_map(Span corner_verts, int verts_num); Array> build_edge_to_loop_map(Span corner_edges, int edges_num); -Array> build_edge_to_poly_map(Span polys, +Array> build_edge_to_poly_map(OffsetIndices polys, Span corner_edges, int edges_num); Vector> build_edge_to_loop_map_resizable(Span corner_edges, int edges_num); diff --git a/source/blender/blenkernel/BKE_mesh_remap.h b/source/blender/blenkernel/BKE_mesh_remap.h index 21f0efca684..b7041f62f68 100644 --- a/source/blender/blenkernel/BKE_mesh_remap.h +++ b/source/blender/blenkernel/BKE_mesh_remap.h @@ -6,6 +6,10 @@ * \ingroup bke */ +#ifdef __cplusplus +# include "BLI_offset_indices.hh" +#endif + #ifdef __cplusplus extern "C" { #endif @@ -193,6 +197,12 @@ void BKE_mesh_remap_calc_edges_from_mesh(int mode, struct Mesh *me_dst, MeshPairRemap *r_map); +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus + void BKE_mesh_remap_calc_loops_from_mesh(int mode, const struct SpaceTransform *space_transform, float max_dist, @@ -205,8 +215,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(int mode, const int *corner_verts_dst, const int *corner_edges_dst, int numloops_dst, - const struct MPoly *polys_dst, - int numpolys_dst, + const blender::OffsetIndices polys_dst, struct CustomData *ldata_dst, bool use_split_nors_dst, float split_angle_dst, @@ -224,11 +233,8 @@ void BKE_mesh_remap_calc_polys_from_mesh(int mode, const float (*vert_positions_dst)[3], int numverts_dst, const int *corner_verts, - const struct MPoly *polys_dst, - int numpolys_dst, + const blender::OffsetIndices polys_dst, const struct Mesh *me_src, struct MeshPairRemap *r_map); -#ifdef __cplusplus -} #endif diff --git a/source/blender/blenkernel/BKE_mesh_tangent.h b/source/blender/blenkernel/BKE_mesh_tangent.h index 47d43e984be..88c150ed261 100644 --- a/source/blender/blenkernel/BKE_mesh_tangent.h +++ b/source/blender/blenkernel/BKE_mesh_tangent.h @@ -6,9 +6,11 @@ */ #ifdef __cplusplus -extern "C" { +# include "BLI_offset_indices.hh" #endif +#ifdef __cplusplus + struct ReportList; /** @@ -25,9 +27,15 @@ void BKE_mesh_calc_loop_tangent_single_ex(const float (*vert_positions)[3], const float (*loop_normals)[3], const float (*loopuv)[2], int numLoops, - const struct MPoly *polys, - int numPolys, + blender::OffsetIndices polys, struct ReportList *reports); + +#endif + +#ifdef __cplusplus +extern "C" { +#endif + /** * Wrapper around BKE_mesh_calc_loop_tangent_single_ex, which takes care of most boilerplate code. * \note @@ -39,12 +47,17 @@ void BKE_mesh_calc_loop_tangent_single(struct Mesh *mesh, float (*r_looptangents)[4], struct ReportList *reports); +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus + /** * See: #BKE_editmesh_loop_tangent_calc (matching logic). */ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3], - const struct MPoly *polys, - uint polys_len, + blender::OffsetIndices polys, const int *corner_verts, const struct MLoopTri *looptri, uint looptri_len, @@ -74,7 +87,7 @@ void BKE_mesh_add_loop_tangent_named_layer_for_uv(struct CustomData *uv_data, int numLoopData, const char *layer_name); -#define DM_TANGENT_MASK_ORCO (1 << 9) +# define DM_TANGENT_MASK_ORCO (1 << 9) /** * Here we get some useful information such as active uv layer name and * search if it is already in tangent_names. @@ -93,6 +106,4 @@ void BKE_mesh_calc_loop_tangent_step_0(const struct CustomData *loopData, char *rren_uv_name, short *rtangent_mask); -#ifdef __cplusplus -} #endif diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index ffe1d75f052..db6d594cd64 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -25,7 +25,6 @@ struct Scene; struct SubdivCCG; struct MLoopTri; -struct MPoly; /** * Delete mesh mdisps and grid paint masks. @@ -154,8 +153,7 @@ void old_mdisps_bilinear(float out[3], float (*disps)[3], int st, float u, float /** * Find per-corner coordinate with given per-face UV coord. */ -int mdisp_rot_face_to_crn( - const struct MPoly *poly, int face_side, float u, float v, float *x, float *y); +int mdisp_rot_face_to_crn(int face_size, int face_side, float u, float v, float *x, float *y); /* Reshaping, define in multires_reshape.cc */ diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index cd6efddc606..358537ee4fe 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -579,7 +579,7 @@ typedef struct SculptSession { /* These are always assigned to base mesh data when using PBVH_FACES and PBVH_GRIDS. */ float (*vert_positions)[3]; - blender::Span polys; + blender::OffsetIndices polys; blender::Span corner_verts; /* These contain the vertex and poly counts of the final mesh. */ diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index ad7045a8c2e..8dc14d5c370 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -639,7 +639,7 @@ void psys_calc_dmcache(struct Object *ob, * This is slow and can be optimized but only for many lookups. * * \param mesh_final: Final mesh, it may not have the same topology as original mesh. - * \param mesh_original: Original mesh, use for accessing #MPoly to #MFace mapping. + * \param mesh_original: Original mesh, use for accessing poly to #MFace mapping. * \param findex_orig: The input tessface index. * \param fw: Face weights (position of the particle inside the \a findex_orig tessface). * \param poly_nodes: May be NULL, otherwise an array of linked list, diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index b1fea49d12b..1efb0be5bd6 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -10,6 +10,9 @@ #include "BLI_bitmap.h" #include "BLI_compiler_compat.h" #include "BLI_ghash.h" +#ifdef __cplusplus +# include "BLI_offset_indices.hh" +#endif #include "bmesh.h" @@ -30,7 +33,6 @@ struct CustomData; struct DMFlagMat; struct IsectRayPrecalc; struct MLoopTri; -struct MPoly; struct Mesh; struct MeshElemMap; struct PBVH; @@ -280,6 +282,9 @@ typedef void (*BKE_pbvh_SearchNearestCallback)(PBVHNode *node, void *data, float /* Building */ PBVH *BKE_pbvh_new(PBVHType type); + +#ifdef __cplusplus + /** * Do a full rebuild with on Mesh data structure. * @@ -288,7 +293,7 @@ PBVH *BKE_pbvh_new(PBVHType type); */ void BKE_pbvh_build_mesh(PBVH *pbvh, struct Mesh *mesh, - const struct MPoly *polys, + blender::OffsetIndices polys, const int *corner_verts, float (*vert_positions)[3], int totvert, @@ -297,6 +302,9 @@ void BKE_pbvh_build_mesh(PBVH *pbvh, struct CustomData *pdata, const struct MLoopTri *looptri, int looptri_num); + +#endif + /** * Do a full rebuild with on Grids data structure. */ @@ -735,7 +743,7 @@ typedef struct PBVHFaceIter { int cd_hide_poly_, cd_face_set_; bool *hide_poly_; int *face_sets_; - const struct MPoly *polys_; + const int *poly_offsets_; const struct MLoopTri *looptri_; const int *corner_verts_; int prim_index_; diff --git a/source/blender/blenkernel/BKE_shrinkwrap.h b/source/blender/blenkernel/BKE_shrinkwrap.h index fb24d7384eb..e02a087fe03 100644 --- a/source/blender/blenkernel/BKE_shrinkwrap.h +++ b/source/blender/blenkernel/BKE_shrinkwrap.h @@ -30,7 +30,6 @@ struct BVHTree; struct MDeformVert; struct Mesh; struct ModifierEvalContext; -struct MPoly; struct Object; struct ShrinkwrapGpencilModifierData; struct ShrinkwrapModifierData; @@ -73,7 +72,7 @@ typedef struct ShrinkwrapTreeData { BVHTree *bvh; BVHTreeFromMesh treeData; - const struct MPoly *polys; + const int *poly_offsets; const float (*vert_normals)[3]; const int *corner_edges; const float (*poly_normals)[3]; diff --git a/source/blender/blenkernel/BKE_subdiv_ccg.h b/source/blender/blenkernel/BKE_subdiv_ccg.h index 19aed7e3fa7..286dec82ccf 100644 --- a/source/blender/blenkernel/BKE_subdiv_ccg.h +++ b/source/blender/blenkernel/BKE_subdiv_ccg.h @@ -11,6 +11,10 @@ #include "BLI_bitmap.h" #include "BLI_sys_types.h" +#ifdef __cplusplus +# include "BLI_offset_indices.hh" +#endif + #ifdef __cplusplus extern "C" { #endif @@ -20,7 +24,6 @@ struct CCGFace; struct CCGKey; struct DMFlagMat; struct Mesh; -struct MPoly; struct Subdiv; /* -------------------------------------------------------------------- @@ -304,16 +307,20 @@ typedef enum SubdivCCGAdjacencyType { SUBDIV_CCG_ADJACENT_EDGE, } SubdivCCGAdjacencyType; +#ifdef __cplusplus + /* Returns if a grid coordinates is adjacent to a coarse mesh edge, vertex or nothing. If it is * adjacent to an edge, r_v1 and r_v2 will be set to the two vertices of that edge. If it is * adjacent to a vertex, r_v1 and r_v2 will be the index of that vertex. */ -SubdivCCGAdjacencyType BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(const SubdivCCG *subdiv_ccg, - const SubdivCCGCoord *coord, - const int *corner_verts, - int corners_num, - const struct MPoly *mpoly, - int *r_v1, - int *r_v2); +SubdivCCGAdjacencyType BKE_subdiv_ccg_coarse_mesh_adjacency_info_get( + const SubdivCCG *subdiv_ccg, + const SubdivCCGCoord *coord, + blender::Span corner_verts, + blender::OffsetIndices polys, + int *r_v1, + int *r_v2); + +#endif /* Get array which is indexed by face index and contains index of a first grid of the face. * diff --git a/source/blender/blenkernel/BKE_volume_to_mesh.hh b/source/blender/blenkernel/BKE_volume_to_mesh.hh index 33ff97b0fe9..40d4e3a73b5 100644 --- a/source/blender/blenkernel/BKE_volume_to_mesh.hh +++ b/source/blender/blenkernel/BKE_volume_to_mesh.hh @@ -63,7 +63,7 @@ void fill_mesh_from_openvdb_data(const Span vdb_verts, int poly_offset, int loop_offset, MutableSpan vert_positions, - MutableSpan polys, + MutableSpan poly_offsets, MutableSpan corner_verts); #endif diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c index 219e2c52684..f5d46236c39 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf.c +++ b/source/blender/blenkernel/intern/CCGSubSurf.c @@ -189,6 +189,7 @@ static CCGFace *_face_new( byte *userData; f->numVerts = numVerts; + BLI_assert(numVerts > 2); f->fHDL = fHDL; f->flags = 0; diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc index 381bd66dcf1..db1b0bd1a19 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.cc +++ b/source/blender/blenkernel/intern/DerivedMesh.cc @@ -148,19 +148,13 @@ static int *dm_getCornerEdgeArray(DerivedMesh *dm) return corner_edges; } -static MPoly *dm_getPolyArray(DerivedMesh *dm) +static int *dm_getPolyArray(DerivedMesh *dm) { - MPoly *mpoly = (MPoly *)CustomData_get_layer_for_write( - &dm->polyData, CD_MPOLY, dm->getNumPolys(dm)); - - if (!mpoly) { - mpoly = (MPoly *)CustomData_add_layer( - &dm->polyData, CD_MPOLY, CD_SET_DEFAULT, dm->getNumPolys(dm)); - CustomData_set_layer_flag(&dm->polyData, CD_MPOLY, CD_FLAG_TEMPORARY); - dm->copyPolyArray(dm, mpoly); + if (!dm->poly_offsets) { + dm->poly_offsets = MEM_cnew_array(dm->getNumPolys(dm) + 1, __func__); + dm->copyPolyArray(dm, dm->poly_offsets); } - - return mpoly; + return dm->poly_offsets; } void DM_init_funcs(DerivedMesh *dm) @@ -220,6 +214,7 @@ void DM_from_template(DerivedMesh *dm, CustomData_copy(&source->faceData, &dm->faceData, mask->fmask, CD_SET_DEFAULT, numTessFaces); CustomData_copy(&source->loopData, &dm->loopData, mask->lmask, CD_SET_DEFAULT, numLoops); CustomData_copy(&source->polyData, &dm->polyData, mask->pmask, CD_SET_DEFAULT, numPolys); + dm->poly_offsets = static_cast(MEM_dupallocN(source->poly_offsets)); dm->type = type; dm->numVertData = numVerts; @@ -235,6 +230,7 @@ void DM_from_template(DerivedMesh *dm, bool DM_release(DerivedMesh *dm) { + MEM_SAFE_FREE(dm->poly_offsets); if (dm->needsFree) { CustomData_free(&dm->vertData, dm->numVertData); CustomData_free(&dm->edgeData, dm->numEdgeData); @@ -1835,7 +1831,7 @@ static void mesh_init_origspace(Mesh *mesh) OrigSpaceLoop *lof_array = (OrigSpaceLoop *)CustomData_get_layer_for_write( &mesh->ldata, CD_ORIGSPACE_MLOOP, mesh->totloop); const Span positions = mesh->vert_positions(); - const Span polys = mesh->polys(); + const blender::OffsetIndices polys = mesh->polys(); const Span corner_verts = mesh->corner_verts(); int j, k; @@ -1843,11 +1839,11 @@ static void mesh_init_origspace(Mesh *mesh) blender::Vector vcos_2d; for (const int i : polys.index_range()) { - const MPoly &poly = polys[i]; - OrigSpaceLoop *lof = lof_array + poly.loopstart; + const blender::IndexRange poly = polys[i]; + OrigSpaceLoop *lof = lof_array + poly.start(); - if (ELEM(poly.totloop, 3, 4)) { - for (j = 0; j < poly.totloop; j++, lof++) { + if (ELEM(poly.size(), 3, 4)) { + for (j = 0; j < poly.size(); j++, lof++) { copy_v2_v2(lof->uv, default_osf[j]); } } @@ -1858,14 +1854,14 @@ static void mesh_init_origspace(Mesh *mesh) float min[2] = {FLT_MAX, FLT_MAX}, max[2] = {-FLT_MAX, -FLT_MAX}; float translate[2], scale[2]; - const float3 p_nor = blender::bke::mesh::poly_normal_calc( - positions, corner_verts.slice(poly.loopstart, poly.totloop)); + const float3 p_nor = blender::bke::mesh::poly_normal_calc(positions, + corner_verts.slice(poly)); axis_dominant_v3_to_m3(mat, p_nor); - vcos_2d.resize(poly.totloop); - for (j = 0; j < poly.totloop; j++) { - mul_v3_m3v3(co, mat, positions[corner_verts[poly.loopstart + j]]); + vcos_2d.resize(poly.size()); + for (j = 0; j < poly.size(); j++) { + mul_v3_m3v3(co, mat, positions[corner_verts[poly[j]]]); copy_v2_v2(vcos_2d[j], co); for (k = 0; k < 2; k++) { @@ -1893,7 +1889,7 @@ static void mesh_init_origspace(Mesh *mesh) /* Finally, transform all vcos_2d into ((0, 0), (1, 1)) * square and assign them as origspace. */ - for (j = 0; j < poly.totloop; j++, lof++) { + for (j = 0; j < poly.size(); j++, lof++) { add_v2_v2v2(lof->uv, vcos_2d[j], translate); mul_v2_v2(lof->uv, scale); } diff --git a/source/blender/blenkernel/intern/bvhutils.cc b/source/blender/blenkernel/intern/bvhutils.cc index 78fe85c3d9d..87b271bb5a0 100644 --- a/source/blender/blenkernel/intern/bvhutils.cc +++ b/source/blender/blenkernel/intern/bvhutils.cc @@ -1173,7 +1173,7 @@ static BitVector<> loose_edges_map_get(const Mesh &mesh, int *r_loose_edge_len) return loose_edges.is_loose_bits; } -static BitVector<> looptri_no_hidden_map_get(const Span polys, +static BitVector<> looptri_no_hidden_map_get(const blender::OffsetIndices polys, const VArray &hide_poly, const int looptri_len, int *r_looptri_active_len) @@ -1186,7 +1186,7 @@ static BitVector<> looptri_no_hidden_map_get(const Span polys, int looptri_no_hidden_len = 0; int looptri_index = 0; for (const int64_t i : polys.index_range()) { - const int triangles_num = ME_POLY_TRI_TOT(&polys[i]); + const int triangles_num = ME_POLY_TRI_TOT(polys[i].size()); if (hide_poly[i]) { looptri_index += triangles_num; } diff --git a/source/blender/blenkernel/intern/cdderivedmesh.cc b/source/blender/blenkernel/intern/cdderivedmesh.cc index a6638439c13..58442b3bda9 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.cc +++ b/source/blender/blenkernel/intern/cdderivedmesh.cc @@ -44,7 +44,6 @@ struct CDDerivedMesh { MFace *mface; int *corner_verts; int *corner_edges; - MPoly *mpoly; /* Cached */ struct PBVH *pbvh; @@ -100,10 +99,9 @@ static void cdDM_copyCornerEdgeArray(DerivedMesh *dm, int *r_corner_edges) memcpy(r_corner_edges, cddm->corner_edges, sizeof(*r_corner_edges) * dm->numLoopData); } -static void cdDM_copyPolyArray(DerivedMesh *dm, MPoly *r_poly) +static void cdDM_copyPolyArray(DerivedMesh *dm, int *r_poly_offsets) { - CDDerivedMesh *cddm = (CDDerivedMesh *)dm; - memcpy(r_poly, cddm->mpoly, sizeof(*r_poly) * dm->numPolyData); + memcpy(r_poly_offsets, dm->poly_offsets, sizeof(int) * (dm->numPolyData + 1)); } static void cdDM_getVertCo(DerivedMesh *dm, int index, float r_co[3]) @@ -213,8 +211,7 @@ static DerivedMesh *cdDM_from_mesh_ex(Mesh *mesh, &dm->loopData, CD_PROP_INT32, ".corner_vert", mesh->totloop)); cddm->corner_edges = static_cast(CustomData_get_layer_named_for_write( &dm->loopData, CD_PROP_INT32, ".corner_edge", mesh->totloop)); - cddm->mpoly = static_cast( - CustomData_get_layer_for_write(&dm->polyData, CD_MPOLY, mesh->totpoly)); + dm->poly_offsets = static_cast(MEM_dupallocN(mesh->poly_offset_indices)); #if 0 cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE); #else diff --git a/source/blender/blenkernel/intern/cloth.cc b/source/blender/blenkernel/intern/cloth.cc index e8a6c97fc6e..08741e88630 100644 --- a/source/blender/blenkernel/intern/cloth.cc +++ b/source/blender/blenkernel/intern/cloth.cc @@ -1289,7 +1289,7 @@ void cloth_parallel_transport_hair_frame(float mat[3][3], static bool cloth_add_shear_bend_spring(ClothModifierData *clmd, LinkNodePair *edgelist, const blender::Span corner_verts, - const blender::Span polys, + const blender::OffsetIndices polys, int i, int j, int k) @@ -1307,8 +1307,7 @@ static bool cloth_add_shear_bend_spring(ClothModifierData *clmd, return false; } - spring_verts_ordered_set( - spring, corner_verts[polys[i].loopstart + j], corner_verts[polys[i].loopstart + k]); + spring_verts_ordered_set(spring, corner_verts[polys[i][j]], corner_verts[polys[i][k]]); shrink_factor = cloth_shrink_factor(clmd, cloth->verts, spring->ij, spring->kl); spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest) * @@ -1328,7 +1327,7 @@ static bool cloth_add_shear_bend_spring(ClothModifierData *clmd, spring->type |= CLOTH_SPRING_TYPE_BENDING; spring->la = k - j + 1; - spring->lb = polys[i].totloop - k + j + 1; + spring->lb = polys[i].size() - k + j + 1; spring->pa = static_cast(MEM_mallocN(sizeof(*spring->pa) * spring->la, "spring poly")); if (!spring->pa) { @@ -1340,7 +1339,7 @@ static bool cloth_add_shear_bend_spring(ClothModifierData *clmd, return false; } - tmp_corner = &corner_verts[polys[i].loopstart]; + tmp_corner = &corner_verts[polys[i].start()]; for (x = 0; x < spring->la; x++) { spring->pa[x] = tmp_corner[j + x]; @@ -1350,7 +1349,7 @@ static bool cloth_add_shear_bend_spring(ClothModifierData *clmd, spring->pb[x] = tmp_corner[x]; } - for (y = k; y < polys[i].totloop; x++, y++) { + for (y = k; y < polys[i].size(); x++, y++) { spring->pb[x] = tmp_corner[y]; } @@ -1476,7 +1475,7 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) uint numpolys = uint(mesh->totpoly); float shrink_factor; const blender::Span edges = mesh->edges(); - const blender::Span polys = mesh->polys(); + const OffsetIndices polys = mesh->polys(); const Span corner_verts = mesh->corner_verts(); const Span corner_edges = mesh->corner_edges(); int index2 = 0; /* our second vertex index */ @@ -1671,8 +1670,8 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) for (int i = 0; i < numpolys; i++) { /* Shear springs. */ /* Triangle faces already have shear springs due to structural geometry. */ - if (polys[i].totloop > 3) { - for (int j = 1; j < polys[i].totloop - 1; j++) { + if (polys[i].size() > 3) { + for (int j = 1; j < polys[i].size() - 1; j++) { if (j > 1) { if (cloth_add_shear_bend_spring(clmd, edgelist, corner_verts, polys, i, 0, j)) { shear_springs++; @@ -1687,7 +1686,7 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) } } - for (int k = j + 2; k < polys[i].totloop; k++) { + for (int k = j + 2; k < polys[i].size(); k++) { if (cloth_add_shear_bend_spring(clmd, edgelist, corner_verts, polys, i, j, k)) { shear_springs++; @@ -1705,8 +1704,8 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) /* Angular bending springs along struct springs. */ if (clmd->sim_parms->bending_model == CLOTH_BENDING_ANGULAR) { - for (int j = 0; j < polys[i].totloop; j++) { - const int edge_i = corner_edges[polys[i].loopstart + j]; + for (int j = 0; j < polys[i].size(); j++) { + const int edge_i = corner_edges[polys[i][j]]; BendSpringRef *curr_ref = &spring_ref[edge_i]; curr_ref->polys++; @@ -1720,13 +1719,13 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) spring->type |= CLOTH_SPRING_TYPE_BENDING; - spring->la = polys[curr_ref->index].totloop; - spring->lb = polys[i].totloop; + spring->la = polys[curr_ref->index].size(); + spring->lb = polys[i].size(); if (!cloth_bend_set_poly_vert_array( - &spring->pa, spring->la, &corner_verts[polys[curr_ref->index].loopstart]) || + &spring->pa, spring->la, &corner_verts[polys[curr_ref->index].start()]) || !cloth_bend_set_poly_vert_array( - &spring->pb, spring->lb, &corner_verts[polys[i].loopstart])) { + &spring->pb, spring->lb, &corner_verts[polys[i].start()])) { cloth_free_errorsprings(cloth, edgelist, spring_ref); return false; } @@ -1897,11 +1896,11 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) } for (int i = 0; i < numpolys; i++) { /* edge springs */ - if (polys[i].totloop == 4) { + if (polys[i].size() == 4) { BLI_edgeset_add( - edgeset, corner_verts[polys[i].loopstart + 0], corner_verts[polys[i].loopstart + 2]); + edgeset, corner_verts[polys[i].start() + 0], corner_verts[polys[i].start() + 2]); BLI_edgeset_add( - edgeset, corner_verts[polys[i].loopstart + 1], corner_verts[polys[i].loopstart + 3]); + edgeset, corner_verts[polys[i].start() + 1], corner_verts[polys[i].start() + 3]); } } diff --git a/source/blender/blenkernel/intern/crazyspace.cc b/source/blender/blenkernel/intern/crazyspace.cc index adffefbade7..0dc5004cf2a 100644 --- a/source/blender/blenkernel/intern/crazyspace.cc +++ b/source/blender/blenkernel/intern/crazyspace.cc @@ -189,16 +189,16 @@ void BKE_crazyspace_set_quats_mesh(Mesh *me, /* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */ const Span positions = me->vert_positions(); - const Span polys = me->polys(); + const OffsetIndices polys = me->polys(); const Span corner_verts = me->corner_verts(); for (int i = 0; i < me->totpoly; i++) { - const MPoly &poly = polys[i]; - const int *corner_vert_next = &corner_verts[poly.loopstart]; - const int *corner_vert_curr = &corner_vert_next[poly.totloop - 1]; - const int *corner_vert_prev = &corner_vert_next[poly.totloop - 2]; + const IndexRange poly = polys[i]; + const int *corner_vert_next = &corner_verts[poly.start()]; + const int *corner_vert_curr = &corner_vert_next[poly.size() - 1]; + const int *corner_vert_prev = &corner_vert_next[poly.size() - 2]; - for (int j = 0; j < poly.totloop; j++) { + for (int j = 0; j < poly.size(); j++) { if (!BLI_BITMAP_TEST(vert_tag, *corner_vert_curr)) { const float *co_prev, *co_curr, *co_next; /* orig */ const float *vd_prev, *vd_curr, *vd_next; /* deform */ diff --git a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc index d6129e4ea8c..012237db5b4 100644 --- a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc +++ b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc @@ -30,7 +30,7 @@ static void fill_mesh_topology(const int vert_offset, MutableSpan edges, MutableSpan corner_verts, MutableSpan corner_edges, - MutableSpan polys) + MutableSpan poly_offsets) { const int main_segment_num = curves::segments_num(main_point_num, main_cyclic); const int profile_segment_num = curves::segments_num(profile_point_num, profile_cyclic); @@ -101,9 +101,7 @@ static void fill_mesh_topology(const int vert_offset, const int main_edge_start = main_edges_start + main_segment_num * i_profile; const int next_main_edge_start = main_edges_start + main_segment_num * i_next_profile; - MPoly &poly = polys[ring_poly_offset + i_profile]; - poly.loopstart = ring_segment_loop_offset; - poly.totloop = 4; + poly_offsets[ring_poly_offset + i_profile] = ring_segment_loop_offset; corner_verts[ring_segment_loop_offset] = ring_vert_offset + i_profile; corner_edges[ring_segment_loop_offset] = ring_edge_start + i_profile; @@ -125,12 +123,8 @@ static void fill_mesh_topology(const int vert_offset, const int cap_loop_offset = loop_offset + poly_num * 4; const int cap_poly_offset = poly_offset + poly_num; - MPoly &poly_start = polys[cap_poly_offset]; - poly_start.loopstart = cap_loop_offset; - poly_start.totloop = profile_segment_num; - MPoly &poly_end = polys[cap_poly_offset + 1]; - poly_end.loopstart = cap_loop_offset + profile_segment_num; - poly_end.totloop = profile_segment_num; + poly_offsets[cap_poly_offset] = cap_loop_offset; + poly_offsets[cap_poly_offset + 1] = cap_loop_offset + profile_segment_num; const int last_ring_index = main_point_num - 1; const int last_ring_vert_offset = vert_offset + profile_point_num * last_ring_index; @@ -702,7 +696,7 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main, mesh->smoothresh = DEG2RADF(180.0f); MutableSpan positions = mesh->vert_positions_for_write(); MutableSpan edges = mesh->edges_for_write(); - MutableSpan polys = mesh->polys_for_write(); + MutableSpan poly_offsets = mesh->poly_offsets_for_write(); MutableSpan corner_verts = mesh->corner_verts_for_write(); MutableSpan corner_edges = mesh->corner_edges_for_write(); MutableAttributeAccessor mesh_attributes = mesh->attributes_for_write(); @@ -720,7 +714,7 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main, edges, corner_verts, corner_edges, - polys); + poly_offsets); }); if (fill_caps) { diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc index 7fa8e1831ef..855694402cd 100644 --- a/source/blender/blenkernel/intern/customdata.cc +++ b/source/blender/blenkernel/intern/customdata.cc @@ -1768,7 +1768,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { {sizeof(float[3]), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}, /* 24: CD_RECAST */ {sizeof(MRecast), "MRecast", 1, N_("Recast"), nullptr, nullptr, nullptr, nullptr}, - /* 25: CD_MPOLY */ + /* 25: CD_MPOLY */ /* DEPRECATED */ {sizeof(MPoly), "MPoly", 1, N_("NGon Face"), nullptr, nullptr, nullptr, nullptr, nullptr}, /* 26: CD_MLOOP */ /* DEPRECATED*/ {sizeof(MLoop), @@ -2029,14 +2029,14 @@ const CustomData_MeshMasks CD_MASK_BAREMESH = { /*vmask*/ CD_MASK_PROP_FLOAT3, /*emask*/ CD_MASK_MEDGE, /*fmask*/ 0, - /*pmask*/ CD_MASK_MPOLY | CD_MASK_FACEMAP, + /*pmask*/ CD_MASK_FACEMAP, /*lmask*/ CD_MASK_PROP_INT32, }; const CustomData_MeshMasks CD_MASK_BAREMESH_ORIGINDEX = { /*vmask*/ CD_MASK_PROP_FLOAT3 | CD_MASK_ORIGINDEX, /*emask*/ CD_MASK_MEDGE | CD_MASK_ORIGINDEX, /*fmask*/ 0, - /*pmask*/ CD_MASK_MPOLY | CD_MASK_FACEMAP | CD_MASK_ORIGINDEX, + /*pmask*/ CD_MASK_FACEMAP | CD_MASK_ORIGINDEX, /*lmask*/ CD_MASK_PROP_INT32, }; const CustomData_MeshMasks CD_MASK_MESH = { @@ -2046,7 +2046,7 @@ const CustomData_MeshMasks CD_MASK_MESH = { (CD_MASK_MEDGE | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL | CD_MASK_BWEIGHT | CD_MASK_CREASE), /*fmask*/ 0, /*pmask*/ - (CD_MASK_MPOLY | CD_MASK_FACEMAP | CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL), + (CD_MASK_FACEMAP | CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL), /*lmask*/ (CD_MASK_MDISPS | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL), }; @@ -2086,8 +2086,8 @@ const CustomData_MeshMasks CD_MASK_EVERYTHING = { CD_MASK_ORIGSPACE | CD_MASK_TANGENT | CD_MASK_TESSLOOPNORMAL | CD_MASK_PREVIEW_MCOL | CD_MASK_PROP_ALL), /*pmask*/ - (CD_MASK_MPOLY | CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_FACEMAP | - CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL), + (CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_FACEMAP | CD_MASK_FREESTYLE_FACE | + CD_MASK_PROP_ALL), /*lmask*/ (CD_MASK_BM_ELEM_PYPTR | CD_MASK_MDISPS | CD_MASK_NORMAL | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_MLOOPTANGENT | CD_MASK_PREVIEW_MLOOPCOL | CD_MASK_ORIGSPACE_MLOOP | diff --git a/source/blender/blenkernel/intern/data_transfer.cc b/source/blender/blenkernel/intern/data_transfer.cc index 9253baa2c87..f8d5f783772 100644 --- a/source/blender/blenkernel/intern/data_transfer.cc +++ b/source/blender/blenkernel/intern/data_transfer.cc @@ -1567,7 +1567,7 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, const float(*positions_dst)[3] = BKE_mesh_vert_positions(me_dst); const int num_verts_dst = me_dst->totvert; const blender::Span edges_dst = me_dst->edges(); - const blender::Span polys_dst = me_dst->polys(); + const blender::OffsetIndices polys_dst = me_dst->polys(); const blender::Span corner_verts_dst = me_dst->corner_verts(); const blender::Span corner_edges_dst = me_dst->corner_edges(); CustomData *ldata_dst = &me_dst->ldata; @@ -1612,8 +1612,7 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, corner_verts_dst.data(), corner_edges_dst.data(), corner_verts_dst.size(), - polys_dst.data(), - polys_dst.size(), + polys_dst, ldata_dst, (me_dst->flag & ME_AUTOSMOOTH) != 0, me_dst->smoothresh, @@ -1668,7 +1667,7 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, if (DT_DATATYPE_IS_POLY(dtdata_type)) { const float(*positions_dst)[3] = BKE_mesh_vert_positions(me_dst); const int num_verts_dst = me_dst->totvert; - const blender::Span polys_dst = me_dst->polys(); + const blender::OffsetIndices polys_dst = me_dst->polys(); const blender::Span corner_verts_dst = me_dst->corner_verts(); if (!geom_map_init[PDATA]) { @@ -1704,8 +1703,7 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, positions_dst, num_verts_dst, corner_verts_dst.data(), - polys_dst.data(), - polys_dst.size(), + polys_dst, me_src, &geom_map[PDATA]); geom_map_init[PDATA] = true; @@ -1713,14 +1711,13 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, if (mdef && vg_idx != -1 && !weights[PDATA]) { weights[PDATA] = static_cast( - MEM_mallocN(sizeof(*weights[PDATA]) * size_t(polys_dst.size()), __func__)); + MEM_mallocN(sizeof(*weights[PDATA]) * polys_dst.size(), __func__)); BKE_defvert_extract_vgroup_to_polyweights(mdef, vg_idx, num_verts_dst, corner_verts_dst.data(), corner_verts_dst.size(), - polys_dst.data(), - polys_dst.size(), + polys_dst, invert_vgroup, weights[PDATA]); } diff --git a/source/blender/blenkernel/intern/deform.cc b/source/blender/blenkernel/intern/deform.cc index 4c7ddfe5877..b60aaf84848 100644 --- a/source/blender/blenkernel/intern/deform.cc +++ b/source/blender/blenkernel/intern/deform.cc @@ -1103,13 +1103,12 @@ void BKE_defvert_extract_vgroup_to_polyweights(const MDeformVert *dvert, const int verts_num, const int *corner_verts, const int /*loops_num*/, - const MPoly *polys, - const int polys_num, + const blender::OffsetIndices polys, const bool invert_vgroup, float *r_weights) { if (dvert && defgroup != -1) { - int i = polys_num; + int i = polys.size(); float *tmp_weights = static_cast( MEM_mallocN(sizeof(*tmp_weights) * size_t(verts_num), __func__)); @@ -1117,21 +1116,21 @@ void BKE_defvert_extract_vgroup_to_polyweights(const MDeformVert *dvert, dvert, defgroup, verts_num, invert_vgroup, tmp_weights); while (i--) { - const MPoly &poly = polys[i]; - const int *corner_vert = &corner_verts[poly.loopstart]; - int j = poly.totloop; + const blender::IndexRange poly = polys[i]; + const int *corner_vert = &corner_verts[poly.start()]; + int j = poly.size(); float w = 0.0f; for (; j--; corner_vert++) { w += tmp_weights[*corner_vert]; } - r_weights[i] = w / float(poly.totloop); + r_weights[i] = w / float(poly.size()); } MEM_freeN(tmp_weights); } else { - copy_vn_fl(r_weights, polys_num, 0.0f); + copy_vn_fl(r_weights, polys.size(), 0.0f); } } diff --git a/source/blender/blenkernel/intern/dynamicpaint.cc b/source/blender/blenkernel/intern/dynamicpaint.cc index 4388f1d2535..5681d0a49f8 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.cc +++ b/source/blender/blenkernel/intern/dynamicpaint.cc @@ -1415,7 +1415,7 @@ static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, const b int numOfEdges = mesh->totedge; int numOfPolys = mesh->totpoly; const blender::Span edges = mesh->edges(); - const blender::Span polys = mesh->polys(); + const blender::OffsetIndices polys = mesh->polys(); const blender::Span corner_verts = mesh->corner_verts(); /* count number of edges per vertex */ @@ -1430,8 +1430,8 @@ static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, const b /* also add number of vertices to temp_data * to locate points on "mesh edge" */ for (int i = 0; i < numOfPolys; i++) { - for (int j = 0; j < polys[i].totloop; j++) { - temp_data[corner_verts[polys[i].loopstart + j]]++; + for (const int vert : corner_verts.slice(polys[i])) { + temp_data[vert]++; } } @@ -1790,7 +1790,7 @@ struct DynamicPaintModifierApplyData { float (*vert_positions)[3]; blender::Span vert_normals; - blender::Span polys; + blender::OffsetIndices polys; blender::Span corner_verts; float (*fcolor)[4]; @@ -1859,7 +1859,6 @@ static void dynamic_paint_apply_surface_vpaint_cb(void *__restrict userdata, const DynamicPaintModifierApplyData *data = static_cast( userdata); - const blender::Span polys = data->polys; const blender::Span corner_verts = data->corner_verts; const DynamicPaintSurface *surface = data->surface; @@ -1869,8 +1868,7 @@ static void dynamic_paint_apply_surface_vpaint_cb(void *__restrict userdata, MLoopCol *mloopcol = data->mloopcol; MLoopCol *mloopcol_wet = data->mloopcol_wet; - for (int j = 0; j < polys[p_index].totloop; j++) { - const int l_index = polys[p_index].loopstart + j; + for (const int l_index : data->polys[p_index]) { const int v_index = corner_verts[l_index]; /* save layer data to output layer */ @@ -1928,7 +1926,7 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object * /* vertex color paint */ if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) { - const blender::Span polys = result->polys(); + const blender::OffsetIndices polys = result->polys(); const blender::Span corner_verts = result->corner_verts(); /* paint is stored on dry and wet layers, so mix final color first */ diff --git a/source/blender/blenkernel/intern/fluid.cc b/source/blender/blenkernel/intern/fluid.cc index 842a51131d0..32cdb4da630 100644 --- a/source/blender/blenkernel/intern/fluid.cc +++ b/source/blender/blenkernel/intern/fluid.cc @@ -3234,7 +3234,7 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *fds, return nullptr; } float(*positions)[3] = BKE_mesh_vert_positions_for_write(me); - blender::MutableSpan polys = me->polys_for_write(); + blender::MutableSpan poly_offsets = me->poly_offsets_for_write(); blender::MutableSpan corner_verts = me->corner_verts_for_write(); const bool is_sharp = orgmesh->attributes().lookup_or_default( @@ -3325,12 +3325,11 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *fds, int *material_indices = BKE_mesh_material_indices_for_write(me); /* Loop for triangles. */ - for (const int i : polys.index_range()) { + for (const int i : poly_offsets.index_range().drop_back(1)) { /* Initialize from existing face. */ material_indices[i] = mp_mat_nr; - polys[i].loopstart = i * 3; - polys[i].totloop = 3; + poly_offsets[i] = i * 3; corner_verts[i * 3 + 0] = manta_liquid_get_triangle_x_at(fds->fluid, i); corner_verts[i * 3 + 1] = manta_liquid_get_triangle_y_at(fds->fluid, i); @@ -3355,7 +3354,6 @@ static Mesh *create_smoke_geometry(FluidDomainSettings *fds, Mesh *orgmesh, Obje float min[3]; float max[3]; float *co; - MPoly *poly; int *corner_vert; int num_verts = 8; @@ -3370,7 +3368,7 @@ static Mesh *create_smoke_geometry(FluidDomainSettings *fds, Mesh *orgmesh, Obje result = BKE_mesh_new_nomain(num_verts, 0, num_faces * 4, num_faces); float(*positions)[3] = BKE_mesh_vert_positions_for_write(result); - blender::MutableSpan polys = result->polys_for_write(); + blender::MutableSpan poly_offsets = result->poly_offsets_for_write(); blender::MutableSpan corner_verts = result->corner_verts_for_write(); if (num_verts) { @@ -3414,57 +3412,42 @@ static Mesh *create_smoke_geometry(FluidDomainSettings *fds, Mesh *orgmesh, Obje co[1] = max[1]; co[2] = min[2]; + poly_offsets.fill(4); + blender::offset_indices::accumulate_counts_to_offsets(poly_offsets); + /* Create faces. */ /* Top side. */ - poly = &polys[0]; corner_vert = &corner_verts[0 * 4]; - poly->loopstart = 0 * 4; - poly->totloop = 4; corner_vert[0] = 0; corner_vert[1] = 1; corner_vert[2] = 2; corner_vert[3] = 3; /* Right side. */ - poly = &polys[1]; corner_vert = &corner_verts[1 * 4]; - poly->loopstart = 1 * 4; - poly->totloop = 4; corner_vert[0] = 2; corner_vert[1] = 1; corner_vert[2] = 5; corner_vert[3] = 6; /* Bottom side. */ - poly = &polys[2]; corner_vert = &corner_verts[2 * 4]; - poly->loopstart = 2 * 4; - poly->totloop = 4; corner_vert[0] = 7; corner_vert[1] = 6; corner_vert[2] = 5; corner_vert[3] = 4; /* Left side. */ - poly = &polys[3]; corner_vert = &corner_verts[3 * 4]; - poly->loopstart = 3 * 4; - poly->totloop = 4; corner_vert[0] = 0; corner_vert[1] = 3; corner_vert[2] = 7; corner_vert[3] = 4; /* Front side. */ - poly = &polys[4]; corner_vert = &corner_verts[4 * 4]; - poly->loopstart = 4 * 4; - poly->totloop = 4; corner_vert[0] = 3; corner_vert[1] = 2; corner_vert[2] = 6; corner_vert[3] = 7; /* Back side. */ - poly = &polys[5]; corner_vert = &corner_verts[5 * 4]; - poly->loopstart = 5 * 4; - poly->totloop = 4; corner_vert[0] = 1; corner_vert[1] = 0; corner_vert[2] = 4; diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc index f6d06ba17a4..c431f8e4ae0 100644 --- a/source/blender/blenkernel/intern/geometry_component_mesh.cc +++ b/source/blender/blenkernel/intern/geometry_component_mesh.cc @@ -250,7 +250,7 @@ static GVArray adapt_mesh_domain_point_to_corner(const Mesh &mesh, const GVArray static GVArray adapt_mesh_domain_corner_to_face(const Mesh &mesh, const GVArray &varray) { - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); GVArray new_varray; attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) { @@ -260,8 +260,7 @@ static GVArray adapt_mesh_domain_corner_to_face(const Mesh &mesh, const GVArray new_varray = VArray::ForFunc( polys.size(), [polys, varray = varray.typed()](const int face_index) { /* A face is selected if all of its corners were selected. */ - const MPoly &poly = polys[face_index]; - for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) { + for (const int loop_index : polys[face_index]) { if (!varray[loop_index]) { return false; } @@ -274,8 +273,7 @@ static GVArray adapt_mesh_domain_corner_to_face(const Mesh &mesh, const GVArray polys.size(), [polys, varray = varray.typed()](const int face_index) { T return_value; attribute_math::DefaultMixer mixer({&return_value, 1}); - const MPoly &poly = polys[face_index]; - for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) { + for (const int loop_index : polys[face_index]) { const T value = varray[loop_index]; mixer.mix_in(0, value); } @@ -294,19 +292,19 @@ static void adapt_mesh_domain_corner_to_edge_impl(const Mesh &mesh, MutableSpan r_values) { BLI_assert(r_values.size() == mesh.totedge); - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_edges = mesh.corner_edges(); attribute_math::DefaultMixer mixer(r_values); for (const int poly_index : polys.index_range()) { - const MPoly &poly = polys[poly_index]; + const IndexRange poly = polys[poly_index]; /* For every edge, mix values from the two adjacent corners (the current and next corner). */ - for (const int i : IndexRange(poly.totloop)) { - const int next_i = (i + 1) % poly.totloop; - const int loop_i = poly.loopstart + i; - const int next_loop_i = poly.loopstart + next_i; + for (const int i : IndexRange(poly.size())) { + const int next_i = (i + 1) % poly.size(); + const int loop_i = poly.start() + i; + const int next_loop_i = poly.start() + next_i; const int edge_index = corner_edges[loop_i]; mixer.mix_in(edge_index, old_values[loop_i]); mixer.mix_in(edge_index, old_values[next_loop_i]); @@ -323,17 +321,17 @@ void adapt_mesh_domain_corner_to_edge_impl(const Mesh &mesh, MutableSpan r_values) { BLI_assert(r_values.size() == mesh.totedge); - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_edges = mesh.corner_edges(); r_values.fill(true); for (const int poly_index : polys.index_range()) { - const MPoly &poly = polys[poly_index]; + const IndexRange poly = polys[poly_index]; - for (const int i : IndexRange(poly.totloop)) { - const int next_i = (i + 1) % poly.totloop; - const int loop_i = poly.loopstart + i; - const int next_loop_i = poly.loopstart + next_i; + for (const int i : IndexRange(poly.size())) { + const int next_i = (i + 1) % poly.size(); + const int loop_i = poly[i]; + const int next_loop_i = poly[next_i]; const int edge_index = corner_edges[loop_i]; if (!old_values[loop_i] || !old_values[next_loop_i]) { @@ -374,15 +372,14 @@ void adapt_mesh_domain_face_to_point_impl(const Mesh &mesh, MutableSpan r_values) { BLI_assert(r_values.size() == mesh.totvert); - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_verts = mesh.corner_verts(); attribute_math::DefaultMixer mixer(r_values); for (const int poly_index : polys.index_range()) { - const MPoly &poly = polys[poly_index]; const T value = old_values[poly_index]; - for (const int vert : corner_verts.slice(poly.loopstart, poly.totloop)) { + for (const int vert : corner_verts.slice(polys[poly_index])) { mixer.mix_in(vert, value); } } @@ -397,15 +394,14 @@ void adapt_mesh_domain_face_to_point_impl(const Mesh &mesh, MutableSpan r_values) { BLI_assert(r_values.size() == mesh.totvert); - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_verts = mesh.corner_verts(); r_values.fill(false); threading::parallel_for(polys.index_range(), 2048, [&](const IndexRange range) { for (const int poly_index : range) { if (old_values[poly_index]) { - const MPoly &poly = polys[poly_index]; - for (const int vert : corner_verts.slice(poly.loopstart, poly.totloop)) { + for (const int vert : corner_verts.slice(polys[poly_index])) { r_values[vert] = true; } } @@ -433,12 +429,11 @@ void adapt_mesh_domain_face_to_corner_impl(const Mesh &mesh, MutableSpan r_values) { BLI_assert(r_values.size() == mesh.totloop); - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); threading::parallel_for(polys.index_range(), 1024, [&](const IndexRange range) { for (const int poly_index : range) { - const MPoly &poly = polys[poly_index]; - MutableSpan poly_corner_values = r_values.slice(poly.loopstart, poly.totloop); + MutableSpan poly_corner_values = r_values.slice(polys[poly_index]); poly_corner_values.fill(old_values[poly_index]); } }); @@ -463,15 +458,14 @@ void adapt_mesh_domain_face_to_edge_impl(const Mesh &mesh, MutableSpan r_values) { BLI_assert(r_values.size() == mesh.totedge); - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_edges = mesh.corner_edges(); attribute_math::DefaultMixer mixer(r_values); for (const int poly_index : polys.index_range()) { - const MPoly &poly = polys[poly_index]; const T value = old_values[poly_index]; - for (const int edge : corner_edges.slice(poly.loopstart, poly.totloop)) { + for (const int edge : corner_edges.slice(polys[poly_index])) { mixer.mix_in(edge, value); } } @@ -485,15 +479,14 @@ void adapt_mesh_domain_face_to_edge_impl(const Mesh &mesh, MutableSpan r_values) { BLI_assert(r_values.size() == mesh.totedge); - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_edges = mesh.corner_edges(); r_values.fill(false); threading::parallel_for(polys.index_range(), 2048, [&](const IndexRange range) { for (const int poly_index : range) { if (old_values[poly_index]) { - const MPoly &poly = polys[poly_index]; - for (const int edge : corner_edges.slice(poly.loopstart, poly.totloop)) { + for (const int edge : corner_edges.slice(polys[poly_index])) { r_values[edge] = true; } } @@ -516,7 +509,7 @@ static GVArray adapt_mesh_domain_face_to_edge(const Mesh &mesh, const GVArray &v static GVArray adapt_mesh_domain_point_to_face(const Mesh &mesh, const GVArray &varray) { - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_verts = mesh.corner_verts(); GVArray new_varray; @@ -528,8 +521,7 @@ static GVArray adapt_mesh_domain_point_to_face(const Mesh &mesh, const GVArray & mesh.totpoly, [corner_verts, polys, varray = varray.typed()](const int face_index) { /* A face is selected if all of its vertices were selected. */ - const MPoly &poly = polys[face_index]; - for (const int vert : corner_verts.slice(poly.loopstart, poly.totloop)) { + for (const int vert : corner_verts.slice(polys[face_index])) { if (!varray[vert]) { return false; } @@ -542,8 +534,7 @@ static GVArray adapt_mesh_domain_point_to_face(const Mesh &mesh, const GVArray & mesh.totpoly, [corner_verts, polys, varray = varray.typed()](const int face_index) { T return_value; attribute_math::DefaultMixer mixer({&return_value, 1}); - const MPoly &poly = polys[face_index]; - for (const int vert : corner_verts.slice(poly.loopstart, poly.totloop)) { + for (const int vert : corner_verts.slice(polys[face_index])) { mixer.mix_in(0, varray[vert]); } mixer.finalize(); @@ -594,16 +585,16 @@ void adapt_mesh_domain_edge_to_corner_impl(const Mesh &mesh, MutableSpan r_values) { BLI_assert(r_values.size() == mesh.totloop); - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_edges = mesh.corner_edges(); attribute_math::DefaultMixer mixer(r_values); for (const int poly_index : polys.index_range()) { - const MPoly &poly = polys[poly_index]; + const IndexRange poly = polys[poly_index]; /* For every corner, mix the values from the adjacent edges on the face. */ - for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) { + for (const int loop_index : poly) { const int loop_index_prev = mesh::poly_corner_prev(poly, loop_index); const int edge = corner_edges[loop_index]; const int edge_prev = corner_edges[loop_index_prev]; @@ -622,15 +613,15 @@ void adapt_mesh_domain_edge_to_corner_impl(const Mesh &mesh, MutableSpan r_values) { BLI_assert(r_values.size() == mesh.totloop); - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_edges = mesh.corner_edges(); r_values.fill(false); threading::parallel_for(polys.index_range(), 2048, [&](const IndexRange range) { for (const int poly_index : range) { - const MPoly &poly = polys[poly_index]; - for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) { + const IndexRange poly = polys[poly_index]; + for (const int loop_index : poly) { const int loop_index_prev = mesh::poly_corner_prev(poly, loop_index); const int edge = corner_edges[loop_index]; const int edge_prev = corner_edges[loop_index_prev]; @@ -713,7 +704,7 @@ static GVArray adapt_mesh_domain_edge_to_point(const Mesh &mesh, const GVArray & static GVArray adapt_mesh_domain_edge_to_face(const Mesh &mesh, const GVArray &varray) { - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_edges = mesh.corner_edges(); GVArray new_varray; @@ -724,8 +715,7 @@ static GVArray adapt_mesh_domain_edge_to_face(const Mesh &mesh, const GVArray &v /* A face is selected if all of its edges are selected. */ new_varray = VArray::ForFunc( polys.size(), [corner_edges, polys, varray = varray.typed()](const int face_index) { - const MPoly &poly = polys[face_index]; - for (const int edge : corner_edges.slice(poly.loopstart, poly.totloop)) { + for (const int edge : corner_edges.slice(polys[face_index])) { if (!varray[edge]) { return false; } @@ -738,8 +728,7 @@ static GVArray adapt_mesh_domain_edge_to_face(const Mesh &mesh, const GVArray &v polys.size(), [corner_edges, polys, varray = varray.typed()](const int face_index) { T return_value; attribute_math::DefaultMixer mixer({&return_value, 1}); - const MPoly &poly = polys[face_index]; - for (const int edge : corner_edges.slice(poly.loopstart, poly.totloop)) { + for (const int edge : corner_edges.slice(polys[face_index])) { mixer.mix_in(0, varray[edge]); } mixer.finalize(); diff --git a/source/blender/blenkernel/intern/gpencil_geom_legacy.cc b/source/blender/blenkernel/intern/gpencil_geom_legacy.cc index 859762ec9a3..13f70cbf1bd 100644 --- a/source/blender/blenkernel/intern/gpencil_geom_legacy.cc +++ b/source/blender/blenkernel/intern/gpencil_geom_legacy.cc @@ -2715,7 +2715,7 @@ bool BKE_gpencil_convert_mesh(Main *bmain, Object *ob_eval = (Object *)DEG_get_evaluated_object(depsgraph, ob_mesh); const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval); const Span positions = me_eval->vert_positions(); - const Span polys = me_eval->polys(); + const OffsetIndices polys = me_eval->polys(); const Span corner_verts = me_eval->corner_verts(); int polys_len = me_eval->totpoly; char element_name[200]; @@ -2756,7 +2756,7 @@ bool BKE_gpencil_convert_mesh(Main *bmain, const VArray mesh_material_indices = me_eval->attributes().lookup_or_default( "material_index", ATTR_DOMAIN_FACE, 0); for (i = 0; i < polys_len; i++) { - const MPoly &poly = polys[i]; + const IndexRange poly = polys[i]; /* Find material. */ int mat_idx = 0; @@ -2776,19 +2776,19 @@ bool BKE_gpencil_convert_mesh(Main *bmain, gpencil_add_material(bmain, ob_gp, element_name, color, false, true, &mat_idx); } - bGPDstroke *gps_fill = BKE_gpencil_stroke_add(gpf_fill, mat_idx, poly.totloop, 10, false); + bGPDstroke *gps_fill = BKE_gpencil_stroke_add(gpf_fill, mat_idx, poly.size(), 10, false); gps_fill->flag |= GP_STROKE_CYCLIC; /* Create dvert data. */ const Span dverts = me_eval->deform_verts(); if (use_vgroups && !dverts.is_empty()) { - gps_fill->dvert = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * poly.totloop, + gps_fill->dvert = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * poly.size(), "gp_fill_dverts"); } /* Add points to strokes. */ - for (int j = 0; j < poly.totloop; j++) { - const int vert = corner_verts[poly.loopstart + j]; + for (int j = 0; j < poly.size(); j++) { + const int vert = corner_verts[poly[j]]; bGPDspoint *pt = &gps_fill->points[j]; copy_v3_v3(&pt->x, positions[vert]); @@ -2810,7 +2810,7 @@ bool BKE_gpencil_convert_mesh(Main *bmain, } } /* If has only 3 points subdivide. */ - if (poly.totloop == 3) { + if (poly.size() == 3) { BKE_gpencil_stroke_subdivide(gpd, gps_fill, 1, GP_SUBDIV_SIMPLE); } diff --git a/source/blender/blenkernel/intern/key.cc b/source/blender/blenkernel/intern/key.cc index 60fa4cfc474..f5d53b3514d 100644 --- a/source/blender/blenkernel/intern/key.cc +++ b/source/blender/blenkernel/intern/key.cc @@ -2234,7 +2234,7 @@ void BKE_keyblock_mesh_calc_normals(const KeyBlock *kb, float(*positions)[3] = static_cast(MEM_dupallocN(BKE_mesh_vert_positions(mesh))); BKE_keyblock_convert_to_mesh(kb, positions, mesh->totvert); const blender::Span edges = mesh->edges(); - const blender::Span polys = mesh->polys(); + const blender::OffsetIndices polys = mesh->polys(); const blender::Span corner_verts = mesh->corner_verts(); const blender::Span corner_edges = mesh->corner_edges(); diff --git a/source/blender/blenkernel/intern/mball_tessellate.cc b/source/blender/blenkernel/intern/mball_tessellate.cc index c4f720cf608..8c936cead41 100644 --- a/source/blender/blenkernel/intern/mball_tessellate.cc +++ b/source/blender/blenkernel/intern/mball_tessellate.cc @@ -1459,8 +1459,8 @@ Mesh *BKE_mball_polygonize(Depsgraph *depsgraph, Scene *scene, Object *ob) mesh->vert_positions_for_write().copy_from(process.co); mesh->totpoly = int(process.curindex); - MPoly *polys = static_cast( - CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_CONSTRUCT, mesh->totpoly)); + BKE_mesh_poly_offsets_ensure_alloc(mesh); + blender::MutableSpan poly_offsets = mesh->poly_offsets_for_write(); int *corner_verts = static_cast(CustomData_add_layer_named( &mesh->ldata, CD_PROP_INT32, CD_CONSTRUCT, mesh->totpoly * 4, ".corner_vert")); @@ -1469,8 +1469,7 @@ Mesh *BKE_mball_polygonize(Depsgraph *depsgraph, Scene *scene, Object *ob) const int *indices = process.indices[i]; const int count = indices[2] != indices[3] ? 4 : 3; - polys[i].loopstart = loop_offset; - polys[i].totloop = count; + poly_offsets[i] = loop_offset; corner_verts[loop_offset] = indices[0]; corner_verts[loop_offset + 1] = indices[1]; @@ -1492,6 +1491,7 @@ Mesh *BKE_mball_polygonize(Depsgraph *depsgraph, Scene *scene, Object *ob) BKE_mesh_vert_normals_clear_dirty(mesh); mesh->totloop = loop_offset; + poly_offsets.last() = loop_offset; BKE_mesh_calc_edges(mesh, false, false); diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index 79e03ccd933..8f7bbff61a7 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -156,6 +156,7 @@ static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int CustomData_copy(&mesh_src->edata, &mesh_dst->edata, mask.emask, alloc_type, mesh_dst->totedge); CustomData_copy(&mesh_src->ldata, &mesh_dst->ldata, mask.lmask, alloc_type, mesh_dst->totloop); CustomData_copy(&mesh_src->pdata, &mesh_dst->pdata, mask.pmask, alloc_type, mesh_dst->totpoly); + mesh_dst->poly_offset_indices = static_cast(MEM_dupallocN(mesh_src->poly_offset_indices)); if (do_tessface) { CustomData_copy(&mesh_src->fdata, &mesh_dst->fdata, mask.fmask, alloc_type, mesh_dst->totface); } @@ -250,6 +251,7 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address mesh->totpoly = 0; memset(&mesh->pdata, 0, sizeof(mesh->pdata)); + mesh->poly_offset_indices = nullptr; } else { Set names_to_skip; @@ -273,10 +275,15 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address mesh, temp_arrays_for_legacy_format, vert_layers); mesh->mloop = BKE_mesh_legacy_convert_corners_to_loops( mesh, temp_arrays_for_legacy_format, loop_layers); - BKE_mesh_legacy_convert_hide_layers_to_flags(mesh); - BKE_mesh_legacy_convert_selection_layers_to_flags(mesh); - BKE_mesh_legacy_convert_material_indices_to_mpoly(mesh); - BKE_mesh_legacy_sharp_faces_to_flags(mesh); + + MutableSpan legacy_polys = BKE_mesh_legacy_convert_offsets_to_polys( + mesh, temp_arrays_for_legacy_format, poly_layers); + mesh->poly_offset_indices = nullptr; + + BKE_mesh_legacy_convert_hide_layers_to_flags(mesh, legacy_polys); + BKE_mesh_legacy_convert_selection_layers_to_flags(mesh, legacy_polys); + BKE_mesh_legacy_convert_material_indices_to_mpoly(mesh, legacy_polys); + BKE_mesh_legacy_sharp_faces_to_flags(mesh, legacy_polys); BKE_mesh_legacy_bevel_weight_from_layers(mesh); BKE_mesh_legacy_edge_crease_from_layers(mesh); BKE_mesh_legacy_sharp_edges_to_flags(mesh); @@ -288,7 +295,7 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address /* Set deprecated mesh data pointers for forward compatibility. */ mesh->medge = const_cast(mesh->edges().data()); - mesh->mpoly = const_cast(mesh->polys().data()); + mesh->mpoly = legacy_polys.data(); mesh->dvert = const_cast(mesh->deform_verts().data()); } @@ -298,6 +305,12 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address CustomData_blend_write_prepare(mesh->pdata, poly_layers, names_to_skip); if (!BLO_write_is_undo(writer)) { + /* #CustomData expects the layers to be sorted in increasing order based on type. */ + std::stable_sort( + poly_layers.begin(), + poly_layers.end(), + [](const CustomDataLayer &a, const CustomDataLayer &b) { return a.type < b.type; }); + BKE_mesh_legacy_convert_uvs_to_struct(mesh, temp_arrays_for_legacy_format, loop_layers); BKE_mesh_legacy_face_set_from_generic(poly_layers); } @@ -330,6 +343,10 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address writer, &mesh->ldata, loop_layers, mesh->totloop, CD_MASK_MESH.lmask, &mesh->id); CustomData_blend_write( writer, &mesh->pdata, poly_layers, mesh->totpoly, CD_MASK_MESH.pmask, &mesh->id); + + if (mesh->poly_offset_indices) { + BLO_write_int32_array(writer, mesh->totpoly + 1, mesh->poly_offset_indices); + } } static void mesh_blend_read_data(BlendDataReader *reader, ID *id) @@ -355,6 +372,8 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id) BLO_read_list(reader, &mesh->vertex_group_names); + BLO_read_int32_array(reader, mesh->totpoly + 1, &mesh->poly_offset_indices); + CustomData_blend_read(reader, &mesh->vdata, mesh->totvert); CustomData_blend_read(reader, &mesh->edata, mesh->totedge); CustomData_blend_read(reader, &mesh->fdata, mesh->totface); @@ -525,7 +544,7 @@ static int customdata_compare( { CustomDataLayer *l1, *l2; int layer_count1 = 0, layer_count2 = 0, j; - const uint64_t cd_mask_non_generic = CD_MASK_MEDGE | CD_MASK_MPOLY | CD_MASK_MDEFORMVERT; + const uint64_t cd_mask_non_generic = CD_MASK_MEDGE | CD_MASK_MDEFORMVERT; const uint64_t cd_mask_all_attr = CD_MASK_PROP_ALL | cd_mask_non_generic; /* The uv selection / pin layers are ignored in the comparisons because @@ -601,18 +620,6 @@ static int customdata_compare( BLI_edgehash_free(eh, nullptr); break; } - case CD_MPOLY: { - MPoly *p1 = (MPoly *)l1->data; - MPoly *p2 = (MPoly *)l2->data; - int ptot = m1->totpoly; - - for (j = 0; j < ptot; j++, p1++, p2++) { - if (p1->totloop != p2->totloop) { - return MESHCMP_POLYMISMATCH; - } - } - break; - } case CD_PROP_BYTE_COLOR: { MLoopCol *lp1 = (MLoopCol *)l1->data; MLoopCol *lp2 = (MLoopCol *)l2->data; @@ -775,6 +782,11 @@ const char *BKE_mesh_cmp(Mesh *me1, Mesh *me2, float thresh) return "Number of loops don't match"; } + if (!std::equal( + me1->poly_offsets().begin(), me1->poly_offsets().end(), me2->poly_offsets().begin())) { + return "Face sizes don't match"; + } + if ((c = customdata_compare(&me1->vdata, &me2->vdata, me1->totvert, me1, thresh))) { return cmpcode_to_str(c); } @@ -903,6 +915,7 @@ static void mesh_clear_geometry(Mesh *mesh) CustomData_free(&mesh->fdata, mesh->totface); CustomData_free(&mesh->ldata, mesh->totloop); CustomData_free(&mesh->pdata, mesh->totpoly); + MEM_SAFE_FREE(mesh->poly_offset_indices); MEM_SAFE_FREE(mesh->mselect); @@ -944,6 +957,23 @@ Mesh *BKE_mesh_add(Main *bmain, const char *name) return me; } +void BKE_mesh_poly_offsets_ensure_alloc(Mesh *mesh) +{ + BLI_assert(mesh->poly_offset_indices == nullptr); + if (mesh->totpoly == 0) { + return; + } + if (!mesh->poly_offset_indices) { + mesh->poly_offset_indices = static_cast( + MEM_malloc_arrayN(mesh->totpoly + 1, sizeof(int), __func__)); + } +#ifdef DEBUG + /* Fill offsets with obviously bad values to simplify finding missing initialization. */ + mesh->poly_offsets_for_write().fill(-1); +#endif + mesh->poly_offsets_for_write().last() = mesh->totloop; +} + /* Custom data layer functions; those assume that totXXX are set correctly. */ static void mesh_ensure_cdlayers_primary(Mesh *mesh) { @@ -962,9 +992,6 @@ static void mesh_ensure_cdlayers_primary(Mesh *mesh) CustomData_add_layer_named( &mesh->ldata, CD_PROP_INT32, CD_SET_DEFAULT, mesh->totloop, ".corner_edge"); } - if (!CustomData_get_layer(&mesh->pdata, CD_MPOLY)) { - CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_SET_DEFAULT, mesh->totpoly); - } } Mesh *BKE_mesh_new_nomain(int verts_len, int edges_len, int loops_len, int polys_len) @@ -986,6 +1013,7 @@ Mesh *BKE_mesh_new_nomain(int verts_len, int edges_len, int loops_len, int polys mesh->totpoly = polys_len; mesh_ensure_cdlayers_primary(mesh); + BKE_mesh_poly_offsets_ensure_alloc(mesh); return mesh; } @@ -1082,6 +1110,7 @@ Mesh *BKE_mesh_new_nomain_from_template_ex(const Mesh *me_src, /* The destination mesh should at least have valid primary CD layers, * even in cases where the source mesh does not. */ mesh_ensure_cdlayers_primary(me_dst); + BKE_mesh_poly_offsets_ensure_alloc(me_dst); if (do_tessface && !CustomData_get_layer(&me_dst->fdata, CD_MFACE)) { CustomData_add_layer(&me_dst->fdata, CD_MFACE, CD_SET_DEFAULT, me_dst->totface); } diff --git a/source/blender/blenkernel/intern/mesh_boolean_convert.cc b/source/blender/blenkernel/intern/mesh_boolean_convert.cc index d2acb9ca220..a7de9980774 100644 --- a/source/blender/blenkernel/intern/mesh_boolean_convert.cc +++ b/source/blender/blenkernel/intern/mesh_boolean_convert.cc @@ -97,10 +97,10 @@ class MeshesToIMeshInfo { int input_mesh_for_imesh_vert(int imesh_v) const; int input_mesh_for_imesh_edge(int imesh_e) const; int input_mesh_for_imesh_face(int imesh_f) const; - const MPoly *input_mpoly_for_orig_index(int orig_index, - const Mesh **r_orig_mesh, - int *r_orig_mesh_index, - int *r_index_in_orig_mesh) const; + const IndexRange input_mpoly_for_orig_index(int orig_index, + const Mesh **r_orig_mesh, + int *r_orig_mesh_index, + int *r_index_in_orig_mesh) const; void input_mvert_for_orig_index(int orig_index, const Mesh **r_orig_mesh, int *r_index_in_orig_mesh) const; @@ -136,7 +136,7 @@ int MeshesToIMeshInfo::input_mesh_for_imesh_edge(int imesh_e) const } /* Given an index `imesh_f` in the `IMesh`, return the index of the - * input `Mesh` that contained the `MPoly` that it came from. */ + * input `Mesh` that contained the polygon that it came from. */ int MeshesToIMeshInfo::input_mesh_for_imesh_face(int imesh_f) const { int n = int(mesh_poly_offset.size()); @@ -151,20 +151,20 @@ int MeshesToIMeshInfo::input_mesh_for_imesh_face(int imesh_f) const /* Given an index of an original face in the `IMesh`, find out the input * `Mesh` that it came from and return it in `*r_orig_mesh`, * and also return the index of that `Mesh` in `*r_orig_mesh_index`. - * Finally, return the index of the corresponding `MPoly` in that `Mesh` + * Finally, return the index of the corresponding polygon in that `Mesh` * in `*r_index_in_orig_mesh`. */ -const MPoly *MeshesToIMeshInfo::input_mpoly_for_orig_index(int orig_index, - const Mesh **r_orig_mesh, - int *r_orig_mesh_index, - int *r_index_in_orig_mesh) const +const IndexRange MeshesToIMeshInfo::input_mpoly_for_orig_index(int orig_index, + const Mesh **r_orig_mesh, + int *r_orig_mesh_index, + int *r_index_in_orig_mesh) const { int orig_mesh_index = input_mesh_for_imesh_face(orig_index); BLI_assert(0 <= orig_mesh_index && orig_mesh_index < meshes.size()); const Mesh *me = meshes[orig_mesh_index]; - const Span polys = me->polys(); + const OffsetIndices polys = me->polys(); int index_in_mesh = orig_index - mesh_poly_offset[orig_mesh_index]; BLI_assert(0 <= index_in_mesh && index_in_mesh < me->totpoly); - const MPoly *poly = &polys[index_in_mesh]; + const IndexRange poly = polys[index_in_mesh]; if (r_orig_mesh) { *r_orig_mesh = me; } @@ -222,7 +222,7 @@ void MeshesToIMeshInfo::input_medge_for_orig_index(int orig_index, * first Mesh. To do this transformation, we also need the transformation * obmats corresponding to the Meshes, so they are in the `obmats` argument. * The 'original' indexes in the IMesh are the indexes you get by - * a scheme that offsets each vertex, MEdge, and MPoly index by the sum of the + * a scheme that offsets each vertex, MEdge, and polygon index by the sum of the * vertices, edges, and polys in the preceding Meshes in the mesh span. * The `*r_info class` is filled in with information needed to make the * correspondence between the Mesh MVerts/MPolys and the IMesh Verts/Faces. @@ -280,10 +280,10 @@ static IMesh meshes_to_imesh(Span meshes, const float4x4 inv_target_mat = math::invert(clean_transform(target_transform)); /* For each input `Mesh`, make `Vert`s and `Face`s for the corresponding - * vertices and `MPoly`s, and keep track of the original indices (using the + * vertices and polygons, and keep track of the original indices (using the * concatenating offset scheme) inside the `Vert`s and `Face`s. * When making `Face`s, we also put in the original indices for `MEdge`s that - * make up the `MPoly`s using the same scheme. */ + * make up the polygons using the same scheme. */ for (int mi : meshes.index_range()) { const Mesh *me = meshes[mi]; r_info->mesh_vert_offset[mi] = v; @@ -303,7 +303,7 @@ static IMesh meshes_to_imesh(Span meshes, Vector verts(me->totvert); const Span vert_positions = me->vert_positions(); - const Span polys = me->polys(); + const OffsetIndices polys = me->polys(); const Span corner_verts = me->corner_verts(); const Span corner_edges = me->corner_edges(); @@ -336,12 +336,13 @@ static IMesh meshes_to_imesh(Span meshes, ++v; } - for (const MPoly &poly : polys) { - int flen = poly.totloop; + for (const int poly_i : polys.index_range()) { + const IndexRange poly = polys[poly_i]; + int flen = poly.size(); face_vert.resize(flen); face_edge_orig.resize(flen); for (int i = 0; i < flen; ++i) { - const int corner_i = poly.loopstart + i; + const int corner_i = poly[i]; int mverti = r_info->mesh_vert_offset[mi] + corner_verts[corner_i]; const Vert *fv = r_info->mesh_to_imesh_vert[mverti]; if (need_face_flip) { @@ -401,9 +402,6 @@ static void copy_poly_attributes(Mesh *dest_mesh, const CustomData *source_cd = &orig_me->pdata; for (int source_layer_i = 0; source_layer_i < source_cd->totlayer; ++source_layer_i) { const eCustomDataType ty = eCustomDataType(source_cd->layers[source_layer_i].type); - if (ty == CD_MPOLY) { - continue; - } const char *name = source_cd->layers[source_layer_i].name; int target_layer_i = CustomData_get_named_layer_index(target_cd, ty, name); if (target_layer_i != -1) { @@ -459,7 +457,7 @@ static void copy_edge_attributes(Mesh *dest_mesh, * Return the number of non-null MLoops filled in. */ static int fill_orig_loops(const Face *f, - const MPoly *orig_poly, + const IndexRange orig_poly, const Mesh *orig_me, int orig_me_index, MeshesToIMeshInfo &mim, @@ -468,7 +466,7 @@ static int fill_orig_loops(const Face *f, r_orig_loops.fill(-1); const Span orig_corner_verts = orig_me->corner_verts(); - int orig_mplen = orig_poly->totloop; + int orig_mplen = orig_poly.size(); if (f->size() != orig_mplen) { return 0; } @@ -493,7 +491,7 @@ static int fill_orig_loops(const Face *f, /* Assume all vertices in an mpoly are unique. */ int offset = -1; for (int i = 0; i < orig_mplen; ++i) { - int loop_i = i + orig_poly->loopstart; + int loop_i = i + orig_poly.start(); if (orig_corner_verts[loop_i] == first_orig_v_in_orig_me) { offset = i; break; @@ -505,7 +503,7 @@ static int fill_orig_loops(const Face *f, int num_orig_loops_found = 0; for (int mp_loop_index = 0; mp_loop_index < orig_mplen; ++mp_loop_index) { int orig_mp_loop_index = (mp_loop_index + offset) % orig_mplen; - const int vert_i = orig_corner_verts[orig_poly->loopstart + orig_mp_loop_index]; + const int vert_i = orig_corner_verts[orig_poly.start() + orig_mp_loop_index]; int fv_orig = f->vert[mp_loop_index]->orig; if (fv_orig != NO_INDEX) { fv_orig -= orig_me_vert_offset; @@ -515,7 +513,7 @@ static int fill_orig_loops(const Face *f, } if (vert_i == fv_orig) { const int vert_next = - orig_corner_verts[orig_poly->loopstart + ((orig_mp_loop_index + 1) % orig_mplen)]; + orig_corner_verts[orig_poly.start() + ((orig_mp_loop_index + 1) % orig_mplen)]; int fvnext_orig = f->vert[(mp_loop_index + 1) % orig_mplen]->orig; if (fvnext_orig != NO_INDEX) { fvnext_orig -= orig_me_vert_offset; @@ -524,7 +522,7 @@ static int fill_orig_loops(const Face *f, } } if (vert_next == fvnext_orig) { - r_orig_loops[mp_loop_index] = orig_poly->loopstart + orig_mp_loop_index; + r_orig_loops[mp_loop_index] = orig_poly.start() + orig_mp_loop_index; ++num_orig_loops_found; } } @@ -532,19 +530,19 @@ static int fill_orig_loops(const Face *f, return num_orig_loops_found; } -/* Fill `cos_2d` with the 2d coordinates found by projection MPoly `poly` along +/* Fill `cos_2d` with the 2d coordinates found by projection polygon `poly` along * its normal. Also fill in r_axis_mat with the matrix that does that projection. * But before projecting, also transform the 3d coordinate by multiplying by trans_mat. - * `cos_2d` should have room for `poly->totloop` entries. */ + * `cos_2d` should have room for `poly.size()` entries. */ static void get_poly2d_cos(const Mesh *me, - const MPoly *poly, + const IndexRange poly, float (*cos_2d)[2], const float4x4 &trans_mat, float r_axis_mat[3][3]) { const Span positions = me->vert_positions(); const Span corner_verts = me->corner_verts(); - const Span poly_verts = corner_verts.slice(poly->loopstart, poly->totloop); + const Span poly_verts = corner_verts.slice(poly); /* Project coordinates to 2d in cos_2d, using normal as projection axis. */ const float3 axis_dominant = bke::mesh::poly_normal_calc(positions, poly_verts); @@ -561,13 +559,13 @@ static void get_poly2d_cos(const Mesh *me, * Otherwise, interpolate the Loop attributes in the face `orig_poly`. */ static void copy_or_interp_loop_attributes(Mesh *dest_mesh, const Face *f, - MPoly *poly, - const MPoly *orig_poly, + const IndexRange poly, + const IndexRange orig_poly, const Mesh *orig_me, int orig_me_index, MeshesToIMeshInfo &mim) { - Array orig_loops(poly->totloop); + Array orig_loops(poly.size()); int norig = fill_orig_loops(f, orig_poly, orig_me, orig_me_index, mim, orig_loops); /* We may need these arrays if we have to interpolate Loop attributes rather than just copy. * Right now, trying Array complains, so declare cos_2d a different way. */ @@ -575,22 +573,22 @@ static void copy_or_interp_loop_attributes(Mesh *dest_mesh, Array weights; Array src_blocks_ofs; float axis_mat[3][3]; - if (norig != poly->totloop) { + if (norig != poly.size()) { /* We will need to interpolate. Make `cos_2d` hold 2d-projected coordinates of `orig_poly`, * which are transformed into object 0's local space before projecting. * At this point we cannot yet calculate the interpolation weights, as they depend on * the coordinate where interpolation is to happen, but we can allocate the needed arrays, * so they don't have to be allocated per-layer. */ - cos_2d = (float(*)[2])BLI_array_alloca(cos_2d, orig_poly->totloop); - weights = Array(orig_poly->totloop); - src_blocks_ofs = Array(orig_poly->totloop); + cos_2d = (float(*)[2])BLI_array_alloca(cos_2d, orig_poly.size()); + weights = Array(orig_poly.size()); + src_blocks_ofs = Array(orig_poly.size()); get_poly2d_cos(orig_me, orig_poly, cos_2d, mim.to_target_transform[orig_me_index], axis_mat); } CustomData *target_cd = &dest_mesh->ldata; const Span dst_positions = dest_mesh->vert_positions(); const Span dst_corner_verts = dest_mesh->corner_verts(); - for (int i = 0; i < poly->totloop; ++i) { - int loop_index = poly->loopstart + i; + for (int i = 0; i < poly.size(); ++i) { + int loop_index = poly[i]; int orig_loop_index = norig > 0 ? orig_loops[i] : -1; const CustomData *source_cd = &orig_me->ldata; if (orig_loop_index == -1) { @@ -599,7 +597,7 @@ static void copy_or_interp_loop_attributes(Mesh *dest_mesh, * coordinates were. The `dest_mesh` coordinates are already in object 0 local space. */ float co[2]; mul_v2_m3v3(co, axis_mat, dst_positions[dst_corner_verts[loop_index]]); - interp_weights_poly_v2(weights.data(), cos_2d, orig_poly->totloop, co); + interp_weights_poly_v2(weights.data(), cos_2d, orig_poly.size(), co); } for (int source_layer_i = 0; source_layer_i < source_cd->totlayer; ++source_layer_i) { const eCustomDataType ty = eCustomDataType(source_cd->layers[source_layer_i].type); @@ -628,9 +626,9 @@ static void copy_or_interp_loop_attributes(Mesh *dest_mesh, int source_layer_type_index = source_layer_i - source_cd->typemap[ty]; BLI_assert(target_layer_type_index != -1 && source_layer_type_index >= 0); const int size = CustomData_sizeof(ty); - for (int j = 0; j < orig_poly->totloop; ++j) { + for (int j = 0; j < orig_poly.size(); ++j) { const void *layer = CustomData_get_layer_n(source_cd, ty, source_layer_type_index); - src_blocks_ofs[j] = POINTER_OFFSET(layer, size * (orig_poly->loopstart + j)); + src_blocks_ofs[j] = POINTER_OFFSET(layer, size * (orig_poly[j])); } void *dst_layer = CustomData_get_layer_n_for_write( target_cd, ty, target_layer_type_index, dest_mesh->totloop); @@ -639,7 +637,7 @@ static void copy_or_interp_loop_attributes(Mesh *dest_mesh, src_blocks_ofs.data(), weights.data(), nullptr, - orig_poly->totloop, + orig_poly.size(), dst_block_ofs, target_layer_i); } @@ -723,17 +721,15 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim) ATTR_DOMAIN_FACE); int cur_loop_index = 0; MutableSpan dst_corner_verts = result->corner_verts_for_write(); - MutableSpan dst_polys = result->polys_for_write(); + MutableSpan dst_poly_offsets = result->poly_offsets_for_write(); for (int fi : im->face_index_range()) { const Face *f = im->face(fi); const Mesh *orig_me; int index_in_orig_me; int orig_me_index; - const MPoly *orig_poly = mim.input_mpoly_for_orig_index( + const IndexRange orig_poly = mim.input_mpoly_for_orig_index( f->orig, &orig_me, &orig_me_index, &index_in_orig_me); - MPoly *poly = &dst_polys[fi]; - poly->totloop = f->size(); - poly->loopstart = cur_loop_index; + dst_poly_offsets[fi] = cur_loop_index; for (int j : f->index_range()) { const Vert *vf = f->vert[j]; const int vfi = im->lookup_vert(vf); @@ -749,7 +745,13 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim) mim.material_remaps[orig_me_index].as_span() : Span(), dst_material_indices.span); - copy_or_interp_loop_attributes(result, f, poly, orig_poly, orig_me, orig_me_index, mim); + copy_or_interp_loop_attributes(result, + f, + IndexRange(dst_poly_offsets[fi], f->size()), + orig_poly, + orig_me, + orig_me_index, + mim); } dst_material_indices.finish(); @@ -760,16 +762,17 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim) /* Now that the MEdges are populated, we can copy over the required attributes and custom layers. */ + const OffsetIndices dst_polys = result->polys(); const Span dst_corner_edges = result->corner_edges(); for (int fi : im->face_index_range()) { const Face *f = im->face(fi); - const MPoly &poly = dst_polys[fi]; + const IndexRange poly = dst_polys[fi]; for (int j : f->index_range()) { if (f->edge_orig[j] != NO_INDEX) { const Mesh *orig_me; int index_in_orig_me; mim.input_medge_for_orig_index(f->edge_orig[j], &orig_me, &index_in_orig_me); - int e_index = dst_corner_edges[poly.loopstart + j]; + int e_index = dst_corner_edges[poly[j]]; copy_edge_attributes(result, orig_me, e_index, index_in_orig_me); } } @@ -831,14 +834,14 @@ Mesh *direct_mesh_boolean(Span meshes, /* Store intersecting edge indices. */ if (r_intersecting_edges != nullptr) { - const Span polys = result->polys(); + const OffsetIndices polys = result->polys(); const Span corner_edges = result->corner_edges(); for (int fi : m_out.face_index_range()) { const Face &face = *m_out.face(fi); - const MPoly &poly = polys[fi]; - for (int corner_i : face.index_range()) { - if (face.is_intersect[corner_i]) { - int e_index = corner_edges[poly.loopstart + corner_i]; + const IndexRange poly = polys[fi]; + for (int i : face.index_range()) { + if (face.is_intersect[i]) { + int e_index = corner_edges[poly[i]]; r_intersecting_edges->append(e_index); } } diff --git a/source/blender/blenkernel/intern/mesh_calc_edges.cc b/source/blender/blenkernel/intern/mesh_calc_edges.cc index e2a889247a2..3b769e344d4 100644 --- a/source/blender/blenkernel/intern/mesh_calc_edges.cc +++ b/source/blender/blenkernel/intern/mesh_calc_edges.cc @@ -95,12 +95,12 @@ static void add_polygon_edges_to_hash_maps(Mesh *mesh, MutableSpan edge_maps, uint32_t parallel_mask) { - const Span polys = mesh->polys(); + const OffsetIndices polys = mesh->polys(); const Span corner_verts = mesh->corner_verts(); threading::parallel_for_each(edge_maps, [&](EdgeMap &edge_map) { const int task_index = &edge_map - edge_maps.data(); - for (const MPoly &poly : polys) { - const Span poly_verts = corner_verts.slice(poly.loopstart, poly.totloop); + for (const int i : polys.index_range()) { + const Span poly_verts = corner_verts.slice(polys[i]); int vert_prev = poly_verts.last(); for (const int vert : poly_verts) { /* Can only be the same when the mesh data is invalid. */ @@ -155,16 +155,14 @@ static void update_edge_indices_in_poly_loops(Mesh *mesh, Span edge_maps, uint32_t parallel_mask) { - const Span polys = mesh->polys(); + const OffsetIndices polys = mesh->polys(); const Span corner_verts = mesh->corner_verts(); MutableSpan corner_edges = mesh->corner_edges_for_write(); threading::parallel_for(IndexRange(mesh->totpoly), 100, [&](IndexRange range) { for (const int poly_index : range) { - const MPoly &poly = polys[poly_index]; - const IndexRange corners(poly.loopstart, poly.totloop); - - int prev_corner = corners.last(); - for (const int next_corner : corners) { + const IndexRange poly = polys[poly_index]; + int prev_corner = poly.last(); + for (const int next_corner : poly) { const int vert = corner_verts[next_corner]; const int vert_prev = corner_verts[prev_corner]; diff --git a/source/blender/blenkernel/intern/mesh_convert.cc b/source/blender/blenkernel/intern/mesh_convert.cc index 878edb31d8a..3b1906f3bb7 100644 --- a/source/blender/blenkernel/intern/mesh_convert.cc +++ b/source/blender/blenkernel/intern/mesh_convert.cc @@ -76,18 +76,18 @@ using blender::StringRefNull; static CLG_LogRef LOG = {"bke.mesh_convert"}; -static void poly_edgehash_insert(EdgeHash *ehash, const MPoly *poly, const Span corner_verts) +static void poly_edgehash_insert(EdgeHash *ehash, const Span poly_verts) { - int i = poly->totloop; + int i = poly_verts.size(); - int corner_next = poly->loopstart; /* first loop */ - int corner = corner_next + (i - 1); /* last loop */ + int next = 0; /* first loop */ + int poly_corner = (i - 1); /* last loop */ while (i-- != 0) { - BLI_edgehash_reinsert(ehash, corner_verts[corner], corner_verts[corner_next], nullptr); + BLI_edgehash_reinsert(ehash, poly_verts[poly_corner], poly_verts[next], nullptr); - corner = corner_next; - corner_next++; + poly_corner = next; + next++; } } @@ -98,15 +98,15 @@ static void make_edges_mdata_extend(Mesh &mesh) { int totedge = mesh.totedge; - const Span polys = mesh.polys(); + const blender::OffsetIndices polys = mesh.polys(); const Span corner_verts = mesh.corner_verts(); MutableSpan corner_edges = mesh.corner_edges_for_write(); const int eh_reserve = max_ii(totedge, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(mesh.totpoly)); EdgeHash *eh = BLI_edgehash_new_ex(__func__, eh_reserve); - for (const MPoly &poly : polys) { - poly_edgehash_insert(eh, &poly, corner_verts); + for (const int i : polys.index_range()) { + poly_edgehash_insert(eh, corner_verts.slice(polys[i])); } const int totedge_new = BLI_edgehash_len(eh); @@ -138,11 +138,11 @@ static void make_edges_mdata_extend(Mesh &mesh) BLI_edgehashIterator_free(ehi); for (const int i : polys.index_range()) { - const MPoly &poly = polys[i]; - int corner = poly.loopstart; - int corner_prev = poly.loopstart + (poly.totloop - 1); + const IndexRange poly = polys[i]; + int corner = poly.start(); + int corner_prev = poly.start() + (poly.size() - 1); int j; - for (j = 0; j < poly.totloop; j++, corner++) { + for (j = 0; j < poly.size(); j++, corner++) { /* lookup hashed edge index */ corner_edges[corner_prev] = POINTER_AS_UINT( BLI_edgehash_lookup(eh, corner_verts[corner_prev], corner_verts[corner])); @@ -206,7 +206,7 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba Mesh *mesh = BKE_mesh_new_nomain(totvert, totedge, totloop, totpoly); MutableSpan positions = mesh->vert_positions_for_write(); MutableSpan edges = mesh->edges_for_write(); - MutableSpan polys = mesh->polys_for_write(); + MutableSpan poly_offsets = mesh->poly_offsets_for_write(); MutableSpan corner_verts = mesh->corner_verts_for_write(); MutableAttributeAccessor attributes = mesh->attributes_for_write(); @@ -287,8 +287,7 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba corner_verts[dst_loop + 0] = startvert + index[0]; corner_verts[dst_loop + 1] = startvert + index[2]; corner_verts[dst_loop + 2] = startvert + index[1]; - polys[dst_poly].loopstart = dst_loop; - polys[dst_poly].totloop = 3; + poly_offsets[dst_poly] = dst_loop; material_indices.span[dst_poly] = dl->col; if (mloopuv) { @@ -345,8 +344,7 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba corner_verts[dst_loop + 1] = p3; corner_verts[dst_loop + 2] = p4; corner_verts[dst_loop + 3] = p2; - polys[dst_poly].loopstart = dst_loop; - polys[dst_poly].totloop = 4; + poly_offsets[dst_poly] = dst_loop; material_indices.span[dst_poly] = dl->col; if (mloopuv) { @@ -470,7 +468,7 @@ void BKE_mesh_to_curve_nurblist(const Mesh *me, ListBase *nurblist, const int ed { const Span positions = me->vert_positions(); const Span mesh_edges = me->edges(); - const Span polys = me->polys(); + const blender::OffsetIndices polys = me->polys(); const Span corner_edges = me->corner_edges(); /* only to detect edge polylines */ @@ -481,10 +479,8 @@ void BKE_mesh_to_curve_nurblist(const Mesh *me, ListBase *nurblist, const int ed /* get boundary edges */ edge_users = (int *)MEM_calloc_arrayN(mesh_edges.size(), sizeof(int), __func__); for (const int i : polys.index_range()) { - const MPoly &poly = polys[i]; - int j; - for (j = 0; j < poly.totloop; j++) { - edge_users[corner_edges[poly.loopstart + j]]++; + for (const int edge : corner_edges.slice(polys[i])) { + edge_users[edge]++; } } @@ -1139,6 +1135,8 @@ void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob) CustomData_copy(&mesh_src->edata, &mesh_dst->edata, mask.emask, CD_ASSIGN, mesh_src->totedge); CustomData_copy(&mesh_src->pdata, &mesh_dst->pdata, mask.pmask, CD_ASSIGN, mesh_src->totpoly); CustomData_copy(&mesh_src->ldata, &mesh_dst->ldata, mask.lmask, CD_ASSIGN, mesh_src->totloop); + mesh_dst->poly_offset_indices = static_cast(mesh_src->poly_offset_indices); + mesh_src->poly_offset_indices = nullptr; /* Make sure active/default color attribute (names) are brought over. */ if (mesh_src->active_color_attribute) { diff --git a/source/blender/blenkernel/intern/mesh_evaluate.cc b/source/blender/blenkernel/intern/mesh_evaluate.cc index 59134f32e27..d65bbb2b9e8 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.cc +++ b/source/blender/blenkernel/intern/mesh_evaluate.cc @@ -117,13 +117,12 @@ float BKE_mesh_calc_poly_area(const int *poly_verts, float BKE_mesh_calc_area(const Mesh *me) { const Span positions = me->vert_positions(); - const Span polys = me->polys(); + const blender::OffsetIndices polys = me->polys(); const Span corner_verts = me->corner_verts(); float total_area = 0.0f; - for (const MPoly &poly : polys) { - total_area += blender::bke::mesh::poly_area_calc( - positions, corner_verts.slice(poly.loopstart, poly.totloop)); + for (const int i : polys.index_range()) { + total_area += blender::bke::mesh::poly_area_calc(positions, corner_verts.slice(polys[i])); } return total_area; } @@ -285,15 +284,14 @@ bool BKE_mesh_center_median_from_polys(const Mesh *me, float r_cent[3]) { int tot = 0; const Span positions = me->vert_positions(); - const Span polys = me->polys(); + const blender::OffsetIndices polys = me->polys(); const Span corner_verts = me->corner_verts(); zero_v3(r_cent); - for (const MPoly &poly : polys) { - int loopend = poly.loopstart + poly.totloop; - for (int j = poly.loopstart; j < loopend; j++) { - add_v3_v3(r_cent, positions[corner_verts[j]]); + for (const int i : polys.index_range()) { + for (const int vert : corner_verts.slice(polys[i])) { + add_v3_v3(r_cent, positions[vert]); } - tot += poly.totloop; + tot += polys[i].size(); } /* otherwise we get NAN for 0 verts */ if (me->totpoly) { @@ -320,7 +318,7 @@ bool BKE_mesh_center_of_surface(const Mesh *me, float r_cent[3]) float total_area = 0.0f; float poly_cent[3]; const Span positions = me->vert_positions(); - const blender::Span polys = me->polys(); + const blender::OffsetIndices polys = me->polys(); const Span corner_verts = me->corner_verts(); zero_v3(r_cent); @@ -328,7 +326,7 @@ bool BKE_mesh_center_of_surface(const Mesh *me, float r_cent[3]) /* calculate a weighted average of polygon centroids */ for (const int i : polys.index_range()) { poly_area = blender::bke::mesh::poly_area_centroid_calc( - positions, corner_verts.slice(polys[i].loopstart, polys[i].totloop), poly_cent); + positions, corner_verts.slice(polys[i]), poly_cent); madd_v3_v3fl(r_cent, poly_cent, poly_area); total_area += poly_area; @@ -352,7 +350,7 @@ bool BKE_mesh_center_of_volume(const Mesh *me, float r_cent[3]) float total_volume = 0.0f; float poly_cent[3]; const Span positions = me->vert_positions(); - const blender::Span polys = me->polys(); + const blender::OffsetIndices polys = me->polys(); const Span corner_verts = me->corner_verts(); /* Use an initial center to avoid numeric instability of geometry far away from the center. */ @@ -364,7 +362,7 @@ bool BKE_mesh_center_of_volume(const Mesh *me, float r_cent[3]) /* calculate a weighted average of polyhedron centroids */ for (const int i : polys.index_range()) { poly_volume = blender::bke::mesh::mesh_calc_poly_volume_centroid_with_reference_center( - positions, corner_verts.slice(polys[i].loopstart, polys[i].totloop), init_cent, poly_cent); + positions, corner_verts.slice(polys[i]), init_cent, poly_cent); /* poly_cent is already volume-weighted, so no need to multiply by the volume */ add_v3_v3(r_cent, poly_cent); @@ -535,7 +533,8 @@ void BKE_mesh_mdisp_flip(MDisps *md, const bool use_loop_mdisp_flip) } } -void BKE_mesh_polygon_flip_ex(const MPoly *poly, +void BKE_mesh_polygon_flip_ex(const int poly_offset, + const int poly_size, int *corner_verts, int *corner_edges, CustomData *ldata, @@ -543,8 +542,8 @@ void BKE_mesh_polygon_flip_ex(const MPoly *poly, MDisps *mdisp, const bool use_loop_mdisp_flip) { - int loopstart = poly->loopstart; - int loopend = loopstart + poly->totloop - 1; + int loopstart = poly_offset; + int loopend = loopstart + poly_size - 1; const bool corner_verts_in_data = (CustomData_get_layer_named( ldata, CD_PROP_INT32, ".corner_vert") == corner_verts); const bool corner_edges_in_data = (CustomData_get_layer_named( @@ -585,19 +584,32 @@ void BKE_mesh_polygon_flip_ex(const MPoly *poly, } } -void BKE_mesh_polygon_flip( - const MPoly *poly, int *corner_verts, int *corner_edges, CustomData *ldata, const int totloop) +void BKE_mesh_polygon_flip(const int poly_offset, + const int poly_size, + int *corner_verts, + int *corner_edges, + CustomData *ldata, + const int totloop) { MDisps *mdisp = (MDisps *)CustomData_get_layer_for_write(ldata, CD_MDISPS, totloop); - BKE_mesh_polygon_flip_ex(poly, corner_verts, corner_edges, ldata, nullptr, mdisp, true); + BKE_mesh_polygon_flip_ex( + poly_offset, poly_size, corner_verts, corner_edges, ldata, nullptr, mdisp, true); } void BKE_mesh_polys_flip( - const MPoly *polys, int *corner_verts, int *corner_edges, CustomData *ldata, int totpoly) + const int *poly_offsets, int *corner_verts, int *corner_edges, CustomData *ldata, int totpoly) { + const blender::OffsetIndices polys(blender::Span(poly_offsets, totpoly + 1)); MDisps *mdisp = (MDisps *)CustomData_get_layer_for_write(ldata, CD_MDISPS, totpoly); - for (const int i : blender::IndexRange(totpoly)) { - BKE_mesh_polygon_flip_ex(&polys[i], corner_verts, corner_edges, ldata, nullptr, mdisp, true); + for (const int i : polys.index_range()) { + BKE_mesh_polygon_flip_ex(polys[i].start(), + polys[i].size(), + corner_verts, + corner_edges, + ldata, + nullptr, + mdisp, + true); } } @@ -620,7 +632,7 @@ void BKE_mesh_flush_hidden_from_verts(Mesh *me) } const VArraySpan hide_vert_span{hide_vert}; const Span edges = me->edges(); - const Span polys = me->polys(); + const OffsetIndices polys = me->polys(); const Span corner_verts = me->corner_verts(); /* Hide edges when either of their vertices are hidden. */ @@ -636,8 +648,7 @@ void BKE_mesh_flush_hidden_from_verts(Mesh *me) SpanAttributeWriter hide_poly = attributes.lookup_or_add_for_write_only_span( ".hide_poly", ATTR_DOMAIN_FACE); for (const int i : polys.index_range()) { - const MPoly &poly = polys[i]; - const Span poly_verts = corner_verts.slice(poly.loopstart, poly.totloop); + const Span poly_verts = corner_verts.slice(polys[i]); hide_poly.span[i] = std::any_of(poly_verts.begin(), poly_verts.end(), [&](const int vert) { return hide_vert_span[vert]; }); @@ -659,7 +670,7 @@ void BKE_mesh_flush_hidden_from_polys(Mesh *me) return; } const VArraySpan hide_poly_span{hide_poly}; - const Span polys = me->polys(); + const OffsetIndices polys = me->polys(); const Span corner_verts = me->corner_verts(); const Span corner_edges = me->corner_edges(); SpanAttributeWriter hide_vert = attributes.lookup_or_add_for_write_only_span( @@ -670,8 +681,7 @@ void BKE_mesh_flush_hidden_from_polys(Mesh *me) /* Hide all edges or vertices connected to hidden polygons. */ for (const int i : polys.index_range()) { if (hide_poly_span[i]) { - const MPoly &poly = polys[i]; - for (const int corner : IndexRange(poly.loopstart, poly.totloop)) { + for (const int corner : polys[i]) { hide_vert.span[corner_verts[corner]] = true; hide_edge.span[corner_edges[corner]] = true; } @@ -680,8 +690,7 @@ void BKE_mesh_flush_hidden_from_polys(Mesh *me) /* Unhide vertices and edges connected to visible polygons. */ for (const int i : polys.index_range()) { if (!hide_poly_span[i]) { - const MPoly &poly = polys[i]; - for (const int corner : IndexRange(poly.loopstart, poly.totloop)) { + for (const int corner : polys[i]) { hide_vert.span[corner_verts[corner]] = false; hide_edge.span[corner_edges[corner]] = false; } @@ -720,7 +729,7 @@ void BKE_mesh_flush_select_from_polys(Mesh *me) } static void mesh_flush_select_from_verts(const Span edges, - const Span polys, + const blender::OffsetIndices polys, const Span corner_verts, const VArray &hide_edge, const VArray &hide_poly, @@ -739,8 +748,7 @@ static void mesh_flush_select_from_verts(const Span edges, /* Select visible faces that have all of their vertices selected. */ for (const int i : polys.index_range()) { if (!hide_poly[i]) { - const MPoly &poly = polys[i]; - const Span poly_verts = corner_verts.slice(poly.loopstart, poly.totloop); + const Span poly_verts = corner_verts.slice(polys[i]); select_poly[i] = std::all_of( poly_verts.begin(), poly_verts.end(), [&](const int vert) { return select_vert[vert]; }); } @@ -781,7 +789,7 @@ void BKE_mesh_flush_select_from_verts(Mesh *me) /** \name Mesh Spatial Calculation * \{ */ -void BKE_mesh_calc_relative_deform(const MPoly *polys, +void BKE_mesh_calc_relative_deform(const int *poly_offsets, const int totpoly, const int *corner_verts, const int totvert, @@ -792,18 +800,20 @@ void BKE_mesh_calc_relative_deform(const MPoly *polys, const float (*vert_cos_org)[3], float (*vert_cos_new)[3]) { + const blender::OffsetIndices polys({poly_offsets, totpoly + 1}); + int *vert_accum = (int *)MEM_calloc_arrayN(size_t(totvert), sizeof(*vert_accum), __func__); memset(vert_cos_new, '\0', sizeof(*vert_cos_new) * size_t(totvert)); - for (const int i : blender::IndexRange(totpoly)) { - const MPoly &poly = polys[i]; - const int *poly_verts = &corner_verts[poly.loopstart]; + for (const int i : polys.index_range()) { + const blender::IndexRange poly = polys[i]; + const int *poly_verts = &corner_verts[poly.start()]; - for (int j = 0; j < poly.totloop; j++) { - const int v_prev = poly_verts[(poly.totloop + (j - 1)) % poly.totloop]; + for (int j = 0; j < poly.size(); j++) { + const int v_prev = poly_verts[(poly.size() + (j - 1)) % poly.size()]; const int v_curr = poly_verts[j]; - const int v_next = poly_verts[(j + 1) % poly.totloop]; + const int v_next = poly_verts[(j + 1) % poly.size()]; float tvec[3]; diff --git a/source/blender/blenkernel/intern/mesh_fair.cc b/source/blender/blenkernel/intern/mesh_fair.cc index 1b36e7dfd90..746ff6f2b24 100644 --- a/source/blender/blenkernel/intern/mesh_fair.cc +++ b/source/blender/blenkernel/intern/mesh_fair.cc @@ -202,13 +202,8 @@ class MeshFairingContext : public FairingContext { polys = mesh->polys(); corner_verts_ = mesh->corner_verts(); corner_edges_ = mesh->corner_edges(); - BKE_mesh_vert_loop_map_create(&vlmap_, - &vlmap_mem_, - polys.data(), - corner_verts_.data(), - mesh->totvert, - mesh->totpoly, - mesh->totloop); + BKE_mesh_vert_loop_map_create( + &vlmap_, &vlmap_mem_, polys, corner_verts_.data(), mesh->totvert); /* Deformation coords. */ co_.reserve(mesh->totvert); @@ -223,8 +218,7 @@ class MeshFairingContext : public FairingContext { } } - loop_to_poly_map_ = blender::bke::mesh_topology::build_loop_to_poly_map(polys, - corner_verts_.size()); + loop_to_poly_map_ = blender::bke::mesh_topology::build_loop_to_poly_map(polys); } ~MeshFairingContext() override @@ -239,7 +233,7 @@ class MeshFairingContext : public FairingContext { { using namespace blender; const int vert = corner_verts_[loop]; - const MPoly &poly = polys[loop_to_poly_map_[loop]]; + const blender::IndexRange poly = polys[loop_to_poly_map_[loop]]; const int2 adjecent_verts = bke::mesh::poly_find_adjecent_verts(poly, corner_verts_, vert); copy_v3_v3(r_adj_next, co_[adjecent_verts[0]]); copy_v3_v3(r_adj_prev, co_[adjecent_verts[1]]); @@ -258,7 +252,7 @@ class MeshFairingContext : public FairingContext { Mesh *mesh_; Span corner_verts_; Span corner_edges_; - Span polys; + blender::OffsetIndices polys; Span edges_; Array loop_to_poly_map_; }; diff --git a/source/blender/blenkernel/intern/mesh_iterators.cc b/source/blender/blenkernel/intern/mesh_iterators.cc index e971ea41f3c..d106e9951eb 100644 --- a/source/blender/blenkernel/intern/mesh_iterators.cc +++ b/source/blender/blenkernel/intern/mesh_iterators.cc @@ -193,7 +193,7 @@ void BKE_mesh_foreach_mapped_loop(Mesh *mesh, nullptr; const float(*positions)[3] = BKE_mesh_vert_positions(mesh); - const blender::Span polys = mesh->polys(); + const blender::OffsetIndices polys = mesh->polys(); const blender::Span corner_verts = mesh->corner_verts(); const int *v_index = static_cast( CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX)); @@ -202,7 +202,7 @@ void BKE_mesh_foreach_mapped_loop(Mesh *mesh, if (v_index || f_index) { for (const int poly_i : polys.index_range()) { - for (const int vert : corner_verts.slice(polys[poly_i].loopstart, polys[poly_i].totloop)) { + for (const int vert : corner_verts.slice(polys[poly_i])) { const int v_idx = v_index ? v_index[vert] : vert; const int f_idx = f_index ? f_index[poly_i] : poly_i; const float *no = loop_normals ? *loop_normals++ : nullptr; @@ -215,7 +215,7 @@ void BKE_mesh_foreach_mapped_loop(Mesh *mesh, } else { for (const int poly_i : polys.index_range()) { - for (const int vert : corner_verts.slice(polys[poly_i].loopstart, polys[poly_i].totloop)) { + for (const int vert : corner_verts.slice(polys[poly_i])) { const int v_idx = vert; const int f_idx = poly_i; const float *no = loop_normals ? *loop_normals++ : nullptr; @@ -268,7 +268,7 @@ void BKE_mesh_foreach_mapped_face_center( } else { const blender::Span positions = mesh->vert_positions(); - const blender::Span polys = mesh->polys(); + const blender::OffsetIndices polys = mesh->polys(); const blender::Span corner_verts = mesh->corner_verts(); const int *index = static_cast(CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX)); @@ -278,7 +278,7 @@ void BKE_mesh_foreach_mapped_face_center( if (orig == ORIGINDEX_NONE) { continue; } - const Span poly_verts = corner_verts.slice(polys[i].loopstart, polys[i].totloop); + const Span poly_verts = corner_verts.slice(polys[i]); const float3 center = bke::mesh::poly_center_calc(positions, poly_verts); if (flag & MESH_FOREACH_USE_NORMAL) { const float3 normal = bke::mesh::poly_normal_calc(positions, poly_verts); @@ -291,7 +291,7 @@ void BKE_mesh_foreach_mapped_face_center( } else { for (const int i : polys.index_range()) { - const Span poly_verts = corner_verts.slice(polys[i].loopstart, polys[i].totloop); + const Span poly_verts = corner_verts.slice(polys[i]); const float3 center = bke::mesh::poly_center_calc(positions, poly_verts); if (flag & MESH_FOREACH_USE_NORMAL) { const float3 normal = bke::mesh::poly_normal_calc(positions, poly_verts); @@ -312,7 +312,7 @@ void BKE_mesh_foreach_mapped_subdiv_face_center( MeshForeachFlag flag) { const float(*positions)[3] = BKE_mesh_vert_positions(mesh); - const blender::Span polys = mesh->polys(); + const blender::OffsetIndices polys = mesh->polys(); const blender::Span corner_verts = mesh->corner_verts(); blender::Span vert_normals; if (flag & MESH_FOREACH_USE_NORMAL) { @@ -327,7 +327,7 @@ void BKE_mesh_foreach_mapped_subdiv_face_center( if (orig == ORIGINDEX_NONE) { continue; } - for (const int vert : corner_verts.slice(polys[i].loopstart, polys[i].totloop)) { + for (const int vert : corner_verts.slice(polys[i])) { if (facedot_tags[vert]) { func(userData, orig, @@ -339,7 +339,7 @@ void BKE_mesh_foreach_mapped_subdiv_face_center( } else { for (const int i : polys.index_range()) { - for (const int vert : corner_verts.slice(polys[i].loopstart, polys[i].totloop)) { + for (const int vert : corner_verts.slice(polys[i])) { if (facedot_tags[vert]) { func(userData, i, diff --git a/source/blender/blenkernel/intern/mesh_legacy_convert.cc b/source/blender/blenkernel/intern/mesh_legacy_convert.cc index 7554ad30c89..d183fad5079 100644 --- a/source/blender/blenkernel/intern/mesh_legacy_convert.cc +++ b/source/blender/blenkernel/intern/mesh_legacy_convert.cc @@ -208,17 +208,16 @@ void BKE_mesh_calc_edges_legacy(Mesh *me) int totedge = 0; const Span verts(static_cast(CustomData_get_layer(&me->vdata, CD_MVERT)), me->totvert); - const Span polys = me->polys(); mesh_calc_edges_mdata( verts.data(), (MFace *)CustomData_get_layer(&me->fdata, CD_MFACE), static_cast(CustomData_get_layer_for_write(&me->ldata, CD_MLOOP, me->totloop)), - polys.data(), + static_cast(CustomData_get_layer(&me->pdata, CD_MPOLY)), verts.size(), me->totface, me->totloop, - polys.size(), + me->totpoly, &edges, &totedge); @@ -964,7 +963,6 @@ static int mesh_tessface_calc(Mesh &mesh, const int looptri_num = poly_to_tri_count(totpoly, totloop); - const MPoly *poly, *mpoly; MFace *mface, *mf; MemArena *arena = nullptr; int *mface_to_poly_map; @@ -972,7 +970,7 @@ static int mesh_tessface_calc(Mesh &mesh, int poly_index, mface_index; uint j; - mpoly = (const MPoly *)CustomData_get_layer(pdata, CD_MPOLY); + const blender::OffsetIndices polys = mesh.polys(); const Span corner_verts = mesh.corner_verts(); const int *material_indices = static_cast( CustomData_get_layer_named(pdata, CD_PROP_INT32, "material_index")); @@ -988,10 +986,9 @@ static int mesh_tessface_calc(Mesh &mesh, lindices = (uint(*)[4])MEM_malloc_arrayN(size_t(looptri_num), sizeof(*lindices), __func__); mface_index = 0; - poly = mpoly; - for (poly_index = 0; poly_index < totpoly; poly_index++, poly++) { - const uint mp_loopstart = uint(poly->loopstart); - const uint mp_totloop = uint(poly->totloop); + for (poly_index = 0; poly_index < totpoly; poly_index++) { + const uint mp_loopstart = uint(polys[poly_index].start()); + const uint mp_totloop = uint(polys[poly_index].size()); uint l1, l2, l3, l4; uint *lidx; if (mp_totloop < 3) { @@ -1220,21 +1217,20 @@ void BKE_mesh_tessface_ensure(struct Mesh *mesh) /** \name Sharp Edge Conversion * \{ */ -void BKE_mesh_legacy_sharp_faces_to_flags(Mesh *mesh) +void BKE_mesh_legacy_sharp_faces_to_flags(Mesh *mesh, blender::MutableSpan legacy_polys) { using namespace blender; - MutableSpan polys = mesh->polys_for_write(); if (const bool *sharp_faces = static_cast( CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, "sharp_face"))) { - threading::parallel_for(polys.index_range(), 4096, [&](const IndexRange range) { + threading::parallel_for(legacy_polys.index_range(), 4096, [&](const IndexRange range) { for (const int i : range) { - SET_FLAG_FROM_TEST(polys[i].flag_legacy, !sharp_faces[i], ME_SMOOTH); + SET_FLAG_FROM_TEST(legacy_polys[i].flag_legacy, !sharp_faces[i], ME_SMOOTH); } }); } else { - for (const int i : polys.index_range()) { - polys[i].flag_legacy |= ME_SMOOTH; + for (const int i : legacy_polys.index_range()) { + legacy_polys[i].flag_legacy |= ME_SMOOTH; } } } @@ -1243,11 +1239,12 @@ void BKE_mesh_legacy_sharp_faces_from_flags(Mesh *mesh) { using namespace blender; using namespace blender::bke; - const Span polys = mesh->polys(); MutableAttributeAccessor attributes = mesh->attributes_for_write(); if (attributes.contains("sharp_face")) { return; } + const Span polys(static_cast(CustomData_get_layer(&mesh->pdata, CD_MPOLY)), + mesh->totpoly); if (std::any_of(polys.begin(), polys.end(), [](const MPoly &poly) { return !(poly.flag_legacy & ME_SMOOTH); })) { @@ -1520,7 +1517,8 @@ void BKE_mesh_legacy_uv_seam_from_flags(Mesh *mesh) /** \name Hide Attribute and Legacy Flag Conversion * \{ */ -void BKE_mesh_legacy_convert_hide_layers_to_flags(Mesh *mesh) +void BKE_mesh_legacy_convert_hide_layers_to_flags(Mesh *mesh, + blender::MutableSpan legacy_polys) { using namespace blender; using namespace blender::bke; @@ -1544,12 +1542,11 @@ void BKE_mesh_legacy_convert_hide_layers_to_flags(Mesh *mesh) } }); - MutableSpan polys = mesh->polys_for_write(); const VArray hide_poly = attributes.lookup_or_default( ".hide_poly", ATTR_DOMAIN_FACE, false); - threading::parallel_for(polys.index_range(), 4096, [&](IndexRange range) { + threading::parallel_for(legacy_polys.index_range(), 4096, [&](IndexRange range) { for (const int i : range) { - SET_FLAG_FROM_TEST(polys[i].flag_legacy, hide_poly[i], ME_HIDE); + SET_FLAG_FROM_TEST(legacy_polys[i].flag_legacy, hide_poly[i], ME_HIDE); } }); } @@ -1591,7 +1588,8 @@ void BKE_mesh_legacy_convert_flags_to_hide_layers(Mesh *mesh) hide_edge.finish(); } - const Span polys = mesh->polys(); + const Span polys(static_cast(CustomData_get_layer(&mesh->pdata, CD_MPOLY)), + mesh->totpoly); if (std::any_of(polys.begin(), polys.end(), [](const MPoly &poly) { return poly.flag_legacy & ME_HIDE; })) { @@ -1612,17 +1610,17 @@ void BKE_mesh_legacy_convert_flags_to_hide_layers(Mesh *mesh) /** \name Material Index Conversion * \{ */ -void BKE_mesh_legacy_convert_material_indices_to_mpoly(Mesh *mesh) +void BKE_mesh_legacy_convert_material_indices_to_mpoly(Mesh *mesh, + blender::MutableSpan legacy_polys) { using namespace blender; using namespace blender::bke; const AttributeAccessor attributes = mesh->attributes(); - MutableSpan polys = mesh->polys_for_write(); const VArray material_indices = attributes.lookup_or_default( "material_index", ATTR_DOMAIN_FACE, 0); - threading::parallel_for(polys.index_range(), 4096, [&](IndexRange range) { + threading::parallel_for(legacy_polys.index_range(), 4096, [&](IndexRange range) { for (const int i : range) { - polys[i].mat_nr_legacy = material_indices[i]; + legacy_polys[i].mat_nr_legacy = material_indices[i]; } }); } @@ -1632,10 +1630,11 @@ void BKE_mesh_legacy_convert_mpoly_to_material_indices(Mesh *mesh) using namespace blender; using namespace blender::bke; MutableAttributeAccessor attributes = mesh->attributes_for_write(); - if (attributes.contains("material_index")) { + if (!mesh->mpoly || attributes.contains("material_index")) { return; } - const Span polys = mesh->polys(); + const Span polys(static_cast(CustomData_get_layer(&mesh->pdata, CD_MPOLY)), + mesh->totpoly); if (std::any_of( polys.begin(), polys.end(), [](const MPoly &poly) { return poly.mat_nr_legacy != 0; })) { SpanAttributeWriter material_indices = attributes.lookup_or_add_for_write_only_span( @@ -1849,7 +1848,8 @@ void BKE_mesh_legacy_convert_uvs_to_generic(Mesh *mesh) /** \name Selection Attribute and Legacy Flag Conversion * \{ */ -void BKE_mesh_legacy_convert_selection_layers_to_flags(Mesh *mesh) +void BKE_mesh_legacy_convert_selection_layers_to_flags(Mesh *mesh, + blender::MutableSpan legacy_polys) { using namespace blender; using namespace blender::bke; @@ -1873,12 +1873,11 @@ void BKE_mesh_legacy_convert_selection_layers_to_flags(Mesh *mesh) } }); - MutableSpan polys = mesh->polys_for_write(); const VArray select_poly = attributes.lookup_or_default( ".select_poly", ATTR_DOMAIN_FACE, false); - threading::parallel_for(polys.index_range(), 4096, [&](IndexRange range) { + threading::parallel_for(legacy_polys.index_range(), 4096, [&](IndexRange range) { for (const int i : range) { - SET_FLAG_FROM_TEST(polys[i].flag_legacy, select_poly[i], ME_FACE_SEL); + SET_FLAG_FROM_TEST(legacy_polys[i].flag_legacy, select_poly[i], ME_FACE_SEL); } }); } @@ -1921,7 +1920,8 @@ void BKE_mesh_legacy_convert_flags_to_selection_layers(Mesh *mesh) select_edge.finish(); } - const Span polys = mesh->polys(); + const Span polys(static_cast(CustomData_get_layer(&mesh->pdata, CD_MPOLY)), + mesh->totpoly); if (std::any_of(polys.begin(), polys.end(), [](const MPoly &poly) { return poly.flag_legacy & ME_FACE_SEL; })) { @@ -2196,3 +2196,89 @@ void BKE_mesh_legacy_convert_loops_to_corners(Mesh *mesh) } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Poly Offset Conversion + * \{ */ + +blender::MutableSpan BKE_mesh_legacy_convert_offsets_to_polys( + const Mesh *mesh, + blender::ResourceScope &temp_arrays_for_convert, + blender::Vector &poly_layers_to_write) +{ + using namespace blender; + const OffsetIndices polys = mesh->polys(); + + MutableSpan polys_legacy = temp_arrays_for_convert.construct>(mesh->totpoly); + threading::parallel_for(polys_legacy.index_range(), 2048, [&](IndexRange range) { + for (const int i : range) { + polys_legacy[i].loopstart = polys[i].start(); + polys_legacy[i].totloop = polys[i].size(); + } + }); + + CustomDataLayer layer{}; + layer.type = CD_MPOLY; + layer.data = polys_legacy.data(); + poly_layers_to_write.append(layer); + + return polys_legacy; +} + +static bool poly_loops_orders_match(const Span polys) +{ + for (const int i : polys.index_range().drop_back(1)) { + if (polys[i].loopstart > polys[i + 1].loopstart) { + return false; + } + } + return true; +} + +void BKE_mesh_legacy_convert_polys_to_offsets(Mesh *mesh) +{ + using namespace blender; + if (mesh->poly_offset_indices) { + return; + } + const Span polys(static_cast(CustomData_get_layer(&mesh->pdata, CD_MPOLY)), + mesh->totpoly); + + BKE_mesh_poly_offsets_ensure_alloc(mesh); + MutableSpan offsets = mesh->poly_offsets_for_write(); + + if (poly_loops_orders_match(polys)) { + for (const int i : polys.index_range()) { + offsets[i] = polys[i].loopstart; + } + } + else { + /* Reorder mesh polygons to match the order of their loops. */ + Array orig_indices(polys.size()); + std::iota(orig_indices.begin(), orig_indices.end(), 0); + std::stable_sort(orig_indices.begin(), orig_indices.end(), [polys](const int a, const int b) { + return polys[a].loopstart < polys[b].loopstart; + }); + CustomData old_poly_data = mesh->pdata; + CustomData_reset(&mesh->pdata); + CustomData_copy(&old_poly_data, &mesh->pdata, CD_MASK_MESH.pmask, CD_CONSTRUCT, mesh->totpoly); + + int offset = 0; + for (const int i : orig_indices.index_range()) { + offsets[i] = offset; + offset += polys[orig_indices[i]].totloop; + } + + threading::parallel_for(orig_indices.index_range(), 1024, [&](const IndexRange range) { + for (const int i : range) { + CustomData_copy_data(&old_poly_data, &mesh->pdata, orig_indices[i], i, 1); + } + }); + + CustomData_free(&old_poly_data, mesh->totloop); + } + + CustomData_free_layers(&mesh->pdata, CD_MPOLY, mesh->totpoly); +} + +/** \} */ diff --git a/source/blender/blenkernel/intern/mesh_mapping.cc b/source/blender/blenkernel/intern/mesh_mapping.cc index f3e53757758..b57164fae1e 100644 --- a/source/blender/blenkernel/intern/mesh_mapping.cc +++ b/source/blender/blenkernel/intern/mesh_mapping.cc @@ -21,6 +21,7 @@ #include "BLI_utildefines.h" #include "BKE_customdata.h" +#include "BKE_mesh.h" #include "BKE_mesh_mapping.h" #include "BLI_memarena.h" @@ -30,12 +31,11 @@ /** \name Mesh Connectivity Mapping * \{ */ -UvVertMap *BKE_mesh_uv_vert_map_create(const MPoly *polys, +UvVertMap *BKE_mesh_uv_vert_map_create(const blender::OffsetIndices polys, const bool *hide_poly, const bool *select_poly, const int *corner_verts, const float (*mloopuv)[2], - uint totpoly, uint totvert, const float limit[2], const bool selected, @@ -52,10 +52,9 @@ UvVertMap *BKE_mesh_uv_vert_map_create(const MPoly *polys, totuv = 0; /* generate UvMapVert array */ - for (const int64_t a : blender::IndexRange(totpoly)) { - const MPoly &poly = polys[a]; + for (const int64_t a : polys.index_range()) { if (!selected || (!(hide_poly && hide_poly[a]) && (select_poly && select_poly[a]))) { - totuv += poly.totloop; + totuv += int(polys[a].size()); } } @@ -74,29 +73,30 @@ UvVertMap *BKE_mesh_uv_vert_map_create(const MPoly *polys, bool *winding = nullptr; if (use_winding) { - winding = static_cast(MEM_callocN(sizeof(*winding) * totpoly, "winding")); + winding = static_cast( + MEM_calloc_arrayN(sizeof(*winding), size_t(polys.size()), "winding")); } - for (const int64_t a : blender::IndexRange(totpoly)) { - const MPoly &poly = polys[a]; + for (const int64_t a : polys.index_range()) { + const blender::IndexRange poly = polys[a]; if (!selected || (!(hide_poly && hide_poly[a]) && (select_poly && select_poly[a]))) { float(*tf_uv)[2] = nullptr; if (use_winding) { - tf_uv = (float(*)[2])BLI_buffer_reinit_data(&tf_uv_buf, vec2f, size_t(poly.totloop)); + tf_uv = (float(*)[2])BLI_buffer_reinit_data(&tf_uv_buf, vec2f, size_t(poly.size())); } - nverts = poly.totloop; + nverts = int(poly.size()); for (i = 0; i < nverts; i++) { buf->loop_of_poly_index = ushort(i); buf->poly_index = uint(a); buf->separate = false; - buf->next = vmap->vert[corner_verts[poly.loopstart + i]]; - vmap->vert[corner_verts[poly.loopstart + i]] = buf; + buf->next = vmap->vert[corner_verts[poly[i]]]; + vmap->vert[corner_verts[poly[i]]] = buf; if (use_winding) { - copy_v2_v2(tf_uv[i], mloopuv[poly.loopstart + i]); + copy_v2_v2(tf_uv[i], mloopuv[poly[i]]); } buf++; @@ -121,14 +121,14 @@ UvVertMap *BKE_mesh_uv_vert_map_create(const MPoly *polys, v->next = newvlist; newvlist = v; - uv = mloopuv[polys[v->poly_index].loopstart + v->loop_of_poly_index]; + uv = mloopuv[polys[v->poly_index].start() + v->loop_of_poly_index]; lastv = nullptr; iterv = vlist; while (iterv) { next = iterv->next; - uv2 = mloopuv[polys[iterv->poly_index].loopstart + iterv->loop_of_poly_index]; + uv2 = mloopuv[polys[iterv->poly_index].start() + iterv->loop_of_poly_index]; sub_v2_v2v2(uvdiff, uv2, uv); if (fabsf(uv[0] - uv2[0]) < limit[0] && fabsf(uv[1] - uv2[1]) < limit[1] && @@ -191,31 +191,26 @@ void BKE_mesh_uv_vert_map_free(UvVertMap *vmap) */ static void mesh_vert_poly_or_loop_map_create(MeshElemMap **r_map, int **r_mem, - const MPoly *polys, + const blender::OffsetIndices polys, const int *corner_verts, int totvert, - int totpoly, - int totloop, const bool do_loops) { MeshElemMap *map = MEM_cnew_array(size_t(totvert), __func__); int *indices, *index_iter; - int i, j; - indices = static_cast(MEM_mallocN(sizeof(int) * size_t(totloop), __func__)); + indices = static_cast(MEM_mallocN(sizeof(int) * size_t(polys.total_size()), __func__)); index_iter = indices; /* Count number of polys for each vertex */ - for (i = 0; i < totpoly; i++) { - const MPoly &poly = polys[i]; - - for (j = 0; j < poly.totloop; j++) { - map[corner_verts[poly.loopstart + j]].count++; + for (const int64_t i : polys.index_range()) { + for (const int64_t corner : polys[i]) { + map[corner_verts[corner]].count++; } } /* Assign indices mem */ - for (i = 0; i < totvert; i++) { + for (int64_t i = 0; i < totvert; i++) { map[i].indices = index_iter; index_iter += map[i].count; @@ -224,13 +219,11 @@ static void mesh_vert_poly_or_loop_map_create(MeshElemMap **r_map, } /* Find the users */ - for (i = 0; i < totpoly; i++) { - const MPoly &poly = polys[i]; + for (const int64_t i : polys.index_range()) { + for (const int64_t corner : polys[i]) { + const int v = corner_verts[corner]; - for (j = 0; j < poly.totloop; j++) { - const int v = corner_verts[poly.loopstart + j]; - - map[v].indices[map[v].count] = do_loops ? poly.loopstart + j : i; + map[v].indices[map[v].count] = do_loops ? int(corner) : int(i); map[v].count++; } } @@ -241,26 +234,20 @@ static void mesh_vert_poly_or_loop_map_create(MeshElemMap **r_map, void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map, int **r_mem, - const MPoly *polys, + const blender::OffsetIndices polys, const int *corner_verts, - int totvert, - int totpoly, - int totloop) + int totvert) { - mesh_vert_poly_or_loop_map_create( - r_map, r_mem, polys, corner_verts, totvert, totpoly, totloop, false); + mesh_vert_poly_or_loop_map_create(r_map, r_mem, polys, corner_verts, totvert, false); } void BKE_mesh_vert_loop_map_create(MeshElemMap **r_map, int **r_mem, - const MPoly *polys, + const blender::OffsetIndices polys, const int *corner_verts, - int totvert, - int totpoly, - int totloop) + int totvert) { - mesh_vert_poly_or_loop_map_create( - r_map, r_mem, polys, corner_verts, totvert, totpoly, totloop, true); + mesh_vert_poly_or_loop_map_create(r_map, r_mem, polys, corner_verts, totvert, true); } void BKE_mesh_vert_looptri_map_create(MeshElemMap **r_map, @@ -387,8 +374,7 @@ void BKE_mesh_vert_edge_vert_map_create( void BKE_mesh_edge_loop_map_create(MeshElemMap **r_map, int **r_mem, const int totedge, - const MPoly *polys, - const int totpoly, + const blender::OffsetIndices polys, const int *corner_edges, const int totloop) { @@ -413,17 +399,15 @@ void BKE_mesh_edge_loop_map_create(MeshElemMap **r_map, } /* assign loop-edge users */ - for (const int64_t i : blender::IndexRange(totpoly)) { - const MPoly &poly = polys[i]; + for (const int64_t i : polys.index_range()) { MeshElemMap *map_ele; - const int max_loop = poly.loopstart + poly.totloop; - for (int j = poly.loopstart; j < max_loop; j++) { - map_ele = &map[corner_edges[j]]; - map_ele->indices[map_ele->count++] = j; - map_ele->indices[map_ele->count++] = j + 1; + for (const int64_t corner : polys[i]) { + map_ele = &map[corner_edges[corner]]; + map_ele->indices[map_ele->count++] = int(corner); + map_ele->indices[map_ele->count++] = int(corner) + 1; } /* last edge/loop of poly, must point back to first loop! */ - map_ele->indices[map_ele->count - 1] = poly.loopstart; + map_ele->indices[map_ele->count - 1] = int(polys[i].start()); } *r_map = map; @@ -433,8 +417,7 @@ void BKE_mesh_edge_loop_map_create(MeshElemMap **r_map, void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map, int **r_mem, const int totedge, - const MPoly *polys, - const int totpoly, + const blender::OffsetIndices polys, const int *corner_edges, const int totloop) { @@ -458,10 +441,9 @@ void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map, } /* assign poly-edge users */ - for (const int64_t i : blender::IndexRange(totpoly)) { - const MPoly &poly = polys[i]; - for (int j = 0; j < poly.totloop; j++) { - const int edge_i = corner_edges[poly.loopstart + j]; + for (const int64_t i : polys.index_range()) { + for (const int64_t corner : polys[i]) { + const int edge_i = corner_edges[corner]; MeshElemMap *map_ele = &map[edge_i]; map_ele->indices[map_ele->count++] = int(i); } @@ -514,25 +496,23 @@ void BKE_mesh_origindex_map_create(MeshElemMap **r_map, void BKE_mesh_origindex_map_create_looptri(MeshElemMap **r_map, int **r_mem, - const MPoly *polys, - const int polys_num, + const blender::OffsetIndices polys, const MLoopTri *looptri, const int looptri_num) { - MeshElemMap *map = MEM_cnew_array(size_t(polys_num), __func__); + MeshElemMap *map = MEM_cnew_array(size_t(polys.size()), __func__); int *indices = static_cast(MEM_mallocN(sizeof(int) * size_t(looptri_num), __func__)); int *index_step; - int i; /* create offsets */ index_step = indices; - for (i = 0; i < polys_num; i++) { + for (const int64_t i : polys.index_range()) { map[i].indices = index_step; - index_step += ME_POLY_TRI_TOT(&polys[i]); + index_step += ME_POLY_TRI_TOT(polys[i].size()); } /* assign poly-tessface users */ - for (i = 0; i < looptri_num; i++) { + for (int i = 0; i < looptri_num; i++) { MeshElemMap *map_ele = &map[looptri[i].poly]; map_ele->indices[map_ele->count++] = i; } @@ -543,13 +523,12 @@ void BKE_mesh_origindex_map_create_looptri(MeshElemMap **r_map, namespace blender::bke::mesh_topology { -Array build_loop_to_poly_map(const Span polys, const int loops_num) +Array build_loop_to_poly_map(const OffsetIndices polys) { - Array map(loops_num); + Array map(polys.total_size()); threading::parallel_for(polys.index_range(), 1024, [&](IndexRange range) { for (const int64_t poly_i : range) { - const MPoly &poly = polys[poly_i]; - map.as_mutable_span().slice(poly.loopstart, poly.totloop).fill(int(poly_i)); + map.as_mutable_span().slice(polys[poly_i]).fill(int(poly_i)); } }); return map; @@ -565,14 +544,13 @@ Array> build_vert_to_edge_map(const Span edges, const int ver return map; } -Array> build_vert_to_poly_map(const Span polys, +Array> build_vert_to_poly_map(const OffsetIndices polys, const Span corner_verts, int verts_num) { Array> map(verts_num); for (const int64_t i : polys.index_range()) { - const MPoly &poly = polys[i]; - for (const int64_t vert_i : corner_verts.slice(poly.loopstart, poly.totloop)) { + for (const int64_t vert_i : corner_verts.slice(polys[i])) { map[int(vert_i)].append(int(i)); } } @@ -597,14 +575,13 @@ Array> build_edge_to_loop_map(const Span corner_edges, const in return map; } -Array> build_edge_to_poly_map(const Span polys, +Array> build_edge_to_poly_map(const OffsetIndices polys, const Span corner_edges, const int edges_num) { Array> map(edges_num); for (const int64_t i : polys.index_range()) { - const MPoly &poly = polys[i]; - for (const int edge : corner_edges.slice(poly.loopstart, poly.totloop)) { + for (const int edge : corner_edges.slice(polys[i])) { map[edge].append(int(i)); } } @@ -642,7 +619,7 @@ using MeshRemap_CheckIslandBoundary = const MeshElemMap &edge_poly_map_elem)>; static void poly_edge_loop_islands_calc(const int totedge, - const blender::Span polys, + const blender::OffsetIndices polys, const blender::Span corner_edges, MeshElemMap *edge_poly_map, const bool use_bitflags, @@ -689,8 +666,7 @@ static void poly_edge_loop_islands_calc(const int totedge, BKE_mesh_edge_poly_map_create(&edge_poly_map, &edge_poly_mem, totedge, - polys.data(), - int(polys.size()), + polys, corner_edges.data(), int(corner_edges.size())); } @@ -727,7 +703,7 @@ static void poly_edge_loop_islands_calc(const int totedge, poly = poly_stack[ps_curr_idx++]; BLI_assert(poly_groups[poly] == poly_group_id); - for (const int64_t loop : blender::IndexRange(polys[poly].loopstart, polys[poly].totloop)) { + for (const int64_t loop : polys[poly]) { const int edge = corner_edges[loop]; /* loop over poly users */ const MeshElemMap &map_ele = edge_poly_map[edge]; @@ -832,7 +808,7 @@ static void poly_edge_loop_islands_calc(const int totedge, } int *BKE_mesh_calc_smoothgroups(const int totedge, - const MPoly *polys, + const int *poly_offsets, const int totpoly, const int *corner_edges, const int totloop, @@ -864,7 +840,7 @@ int *BKE_mesh_calc_smoothgroups(const int totedge, }; poly_edge_loop_islands_calc(totedge, - {polys, totpoly}, + blender::Span(poly_offsets, totpoly + 1), {corner_edges, totloop}, nullptr, use_bitflags, @@ -994,8 +970,7 @@ void BKE_mesh_loop_islands_add(MeshIslandStore *island_store, static bool mesh_calc_islands_loop_poly_uv(const int totedge, const bool *uv_seams, - const MPoly *polys, - const int totpoly, + const blender::OffsetIndices polys, const int *corner_verts, const int *corner_edges, const int totloop, @@ -1025,18 +1000,18 @@ static bool mesh_calc_islands_loop_poly_uv(const int totedge, int *edge_innercut_indices = nullptr; int num_einnercuts = 0; - int grp_idx, p_idx, pl_idx, l_idx; + int grp_idx; BKE_mesh_loop_islands_clear(r_island_store); BKE_mesh_loop_islands_init( r_island_store, MISLAND_TYPE_LOOP, totloop, MISLAND_TYPE_POLY, MISLAND_TYPE_EDGE); BKE_mesh_edge_poly_map_create( - &edge_poly_map, &edge_poly_mem, totedge, polys, totpoly, corner_edges, totloop); + &edge_poly_map, &edge_poly_mem, totedge, polys, corner_edges, totloop); if (luvs) { BKE_mesh_edge_loop_map_create( - &edge_loop_map, &edge_loop_mem, totedge, polys, totpoly, corner_edges, totloop); + &edge_loop_map, &edge_loop_mem, totedge, polys, corner_edges, totloop); } /* TODO: I'm not sure edge seam flag is enough to define UV islands? @@ -1083,7 +1058,7 @@ static bool mesh_calc_islands_loop_poly_uv(const int totedge, }; poly_edge_loop_islands_calc(totedge, - {polys, totpoly}, + polys, {corner_edges, totloop}, edge_poly_map, false, @@ -1112,7 +1087,7 @@ static bool mesh_calc_islands_loop_poly_uv(const int totedge, } poly_indices = static_cast( - MEM_mallocN(sizeof(*poly_indices) * size_t(totpoly), __func__)); + MEM_mallocN(sizeof(*poly_indices) * size_t(polys.size()), __func__)); loop_indices = static_cast( MEM_mallocN(sizeof(*loop_indices) * size_t(totloop), __func__)); @@ -1124,15 +1099,14 @@ static bool mesh_calc_islands_loop_poly_uv(const int totedge, memset(edge_border_count, 0, sizeof(*edge_border_count) * size_t(totedge)); } - for (p_idx = 0; p_idx < totpoly; p_idx++) { + for (const int64_t p_idx : polys.index_range()) { if (poly_groups[p_idx] != grp_idx) { continue; } - const MPoly &poly = polys[p_idx]; - poly_indices[num_pidx++] = p_idx; - for (l_idx = poly.loopstart, pl_idx = 0; pl_idx < poly.totloop; l_idx++, pl_idx++) { - const int edge_i = corner_edges[l_idx]; - loop_indices[num_lidx++] = l_idx; + poly_indices[num_pidx++] = int(p_idx); + for (const int64_t corner : polys[p_idx]) { + const int edge_i = corner_edges[corner]; + loop_indices[num_lidx++] = int(corner); if (num_edge_borders && BLI_BITMAP_TEST(edge_borders, edge_i) && (edge_border_count[edge_i] < 2)) { edge_border_count[edge_i]++; @@ -1180,23 +1154,15 @@ bool BKE_mesh_calc_islands_loop_poly_edgeseam(const float (*vert_positions)[3], const MEdge *edges, const int totedge, const bool *uv_seams, - const MPoly *polys, - const int totpoly, + const blender::OffsetIndices polys, const int *corner_verts, const int *corner_edges, const int totloop, MeshIslandStore *r_island_store) { UNUSED_VARS(vert_positions, totvert, edges); - return mesh_calc_islands_loop_poly_uv(totedge, - uv_seams, - polys, - totpoly, - corner_verts, - corner_edges, - totloop, - nullptr, - r_island_store); + return mesh_calc_islands_loop_poly_uv( + totedge, uv_seams, polys, corner_verts, corner_edges, totloop, nullptr, r_island_store); } bool BKE_mesh_calc_islands_loop_poly_uvmap(float (*vert_positions)[3], @@ -1204,8 +1170,7 @@ bool BKE_mesh_calc_islands_loop_poly_uvmap(float (*vert_positions)[3], MEdge *edges, const int totedge, const bool *uv_seams, - MPoly *polys, - const int totpoly, + const blender::OffsetIndices polys, const int *corner_verts, const int *corner_edges, const int totloop, @@ -1214,15 +1179,8 @@ bool BKE_mesh_calc_islands_loop_poly_uvmap(float (*vert_positions)[3], { UNUSED_VARS(vert_positions, totvert, edges); BLI_assert(luvs != nullptr); - return mesh_calc_islands_loop_poly_uv(totedge, - uv_seams, - polys, - totpoly, - corner_verts, - corner_edges, - totloop, - luvs, - r_island_store); + return mesh_calc_islands_loop_poly_uv( + totedge, uv_seams, polys, corner_verts, corner_edges, totloop, luvs, r_island_store); } /** \} */ diff --git a/source/blender/blenkernel/intern/mesh_merge_customdata.cc b/source/blender/blenkernel/intern/mesh_merge_customdata.cc index c91850c971b..a4d9524b612 100644 --- a/source/blender/blenkernel/intern/mesh_merge_customdata.cc +++ b/source/blender/blenkernel/intern/mesh_merge_customdata.cc @@ -114,13 +114,8 @@ void BKE_mesh_merge_customdata_for_apply_modifier(Mesh *me) int *vert_map_mem; struct MeshElemMap *vert_to_loop; - BKE_mesh_vert_loop_map_create(&vert_to_loop, - &vert_map_mem, - me->polys().data(), - me->corner_verts().data(), - me->totvert, - me->totpoly, - me->totloop); + BKE_mesh_vert_loop_map_create( + &vert_to_loop, &vert_map_mem, me->polys(), me->corner_verts().data(), me->totvert); Vector mloopuv_layers; mloopuv_layers.reserve(mloopuv_layers_num); diff --git a/source/blender/blenkernel/intern/mesh_mirror.cc b/source/blender/blenkernel/intern/mesh_mirror.cc index f0575f21232..566b2c1fbd2 100644 --- a/source/blender/blenkernel/intern/mesh_mirror.cc +++ b/source/blender/blenkernel/intern/mesh_mirror.cc @@ -187,7 +187,7 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd, const int src_verts_num = mesh->totvert; const int src_edges_num = mesh->totedge; - const blender::Span src_polys = mesh->polys(); + const blender::OffsetIndices src_polys = mesh->polys(); const int src_loops_num = mesh->totloop; Mesh *result = BKE_mesh_new_nomain_from_template( @@ -287,7 +287,7 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd, } blender::MutableSpan result_edges = result->edges_for_write(); - blender::MutableSpan result_polys = result->polys_for_write(); + blender::MutableSpan result_poly_offsets = result->poly_offsets_for_write(); blender::MutableSpan result_corner_verts = result->corner_verts_for_write(); blender::MutableSpan result_corner_edges = result->corner_edges_for_write(); @@ -297,16 +297,17 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd, result_edges[i].v2 += src_verts_num; } - for (const int i : result_polys.index_range().drop_front(src_polys.size())) { - result_polys[i].loopstart += src_loops_num; + result_poly_offsets.take_front(src_polys.size()).copy_from(mesh->poly_offsets().drop_back(1)); + for (const int i : src_polys.index_range()) { + result_poly_offsets[src_polys.size() + i] = src_polys[i].start() + src_loops_num; } + const blender::OffsetIndices result_polys = result->polys(); /* reverse loop order (normals) */ for (const int i : src_polys.index_range()) { - const blender::IndexRange src_poly(src_polys[i].loopstart, src_polys[i].totloop); + const blender::IndexRange src_poly = src_polys[i]; const int mirror_i = src_polys.size() + i; - const blender::IndexRange mirror_poly(result_polys[mirror_i].loopstart, - result_polys[mirror_i].totloop); + const blender::IndexRange mirror_poly = result_polys[mirror_i]; /* reverse the loop, but we keep the first vertex in the face the same, * to ensure that quads are split the same way as on the other side */ @@ -412,13 +413,13 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd, /* mirroring has to account for loops being reversed in polys in second half */ for (const int i : src_polys.index_range()) { - const blender::IndexRange src_poly(src_polys[i].loopstart, src_polys[i].totloop); + const blender::IndexRange src_poly = src_polys[i]; const int mirror_i = src_polys.size() + i; for (const int j : src_poly) { - int mirrorj = result_polys[mirror_i].loopstart; + int mirrorj = result_polys[mirror_i].start(); if (j > src_poly.start()) { - mirrorj += result_polys[mirror_i].totloop - (j - src_poly.start()); + mirrorj += result_polys[mirror_i].size() - (j - src_poly.start()); } copy_v3_v3(loop_normals[mirrorj], loop_normals[j]); mul_m4_v3(mtx_nor, loop_normals[mirrorj]); diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc index cb94e306470..608fbc10001 100644 --- a/source/blender/blenkernel/intern/mesh_normals.cc +++ b/source/blender/blenkernel/intern/mesh_normals.cc @@ -196,16 +196,14 @@ void BKE_mesh_calc_poly_normal(const int *poly_verts, namespace blender::bke::mesh { void normals_calc_polys(const Span positions, - const Span polys, + const OffsetIndices polys, const Span corner_verts, MutableSpan poly_normals) { BLI_assert(polys.size() == poly_normals.size()); threading::parallel_for(polys.index_range(), 1024, [&](const IndexRange range) { for (const int i : range) { - const MPoly &poly = polys[i]; - poly_normals[i] = poly_normal_calc(positions, - corner_verts.slice(poly.loopstart, poly.totloop)); + poly_normals[i] = poly_normal_calc(positions, corner_verts.slice(polys[i])); } }); } @@ -220,7 +218,7 @@ void normals_calc_polys(const Span positions, * \{ */ void normals_calc_poly_vert(const Span positions, - const Span polys, + const OffsetIndices polys, const Span corner_verts, MutableSpan poly_normals, MutableSpan vert_normals) @@ -235,12 +233,11 @@ void normals_calc_poly_vert(const Span positions, { threading::parallel_for(polys.index_range(), 1024, [&](const IndexRange range) { for (const int poly_i : range) { - const MPoly &poly = polys[poly_i]; - const Span poly_verts = corner_verts.slice(poly.loopstart, poly.totloop); + const Span poly_verts = corner_verts.slice(polys[poly_i]); float3 &pnor = poly_normals[poly_i]; - const int i_end = poly.totloop - 1; + const int i_end = poly_verts.size() - 1; /* Polygon Normal and edge-vector. */ /* Inline version of #poly_normal_calc, also does edge-vectors. */ @@ -332,7 +329,7 @@ blender::Span Mesh::vert_normals() const /* Isolate task because a mutex is locked and computing normals is multi-threaded. */ blender::threading::isolate_task([&]() { const Span positions = this->vert_positions(); - const Span polys = this->polys(); + const blender::OffsetIndices polys = this->polys(); const Span corner_verts = this->corner_verts(); this->runtime->vert_normals.reinitialize(positions.size()); @@ -363,7 +360,7 @@ blender::Span Mesh::poly_normals() const /* Isolate task because a mutex is locked and computing normals is multi-threaded. */ blender::threading::isolate_task([&]() { const Span positions = this->vert_positions(); - const Span polys = this->polys(); + const blender::OffsetIndices polys = this->polys(); const Span corner_verts = this->corner_verts(); this->runtime->poly_normals.reinitialize(polys.size()); @@ -707,7 +704,7 @@ struct LoopSplitTaskDataCommon { Span edges; Span corner_verts; Span corner_edges; - Span polys; + blender::OffsetIndices polys; Span edge_to_loops; Span loop_to_poly; Span poly_normals; @@ -721,7 +718,7 @@ struct LoopSplitTaskDataCommon { namespace blender::bke::mesh { -static void mesh_edges_sharp_tag(const Span polys, +static void mesh_edges_sharp_tag(const OffsetIndices polys, const Span corner_verts, const Span corner_edges, const Span loop_to_poly_map, @@ -739,8 +736,7 @@ static void mesh_edges_sharp_tag(const Span polys, }; for (const int poly_i : polys.index_range()) { - const MPoly &poly = polys[poly_i]; - for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) { + for (const int loop_index : polys[poly_i]) { const int vert_i = corner_verts[loop_index]; const int edge_i = corner_edges[loop_index]; @@ -793,7 +789,7 @@ static void mesh_edges_sharp_tag(const Span polys, } } -void edges_sharp_from_angle_set(const Span polys, +void edges_sharp_from_angle_set(const OffsetIndices polys, const Span corner_verts, const Span corner_edges, const Span poly_normals, @@ -810,8 +806,7 @@ void edges_sharp_from_angle_set(const Span polys, Array edge_to_loops(sharp_edges.size(), int2(0)); /* Simple mapping from a loop to its polygon index. */ - const Array loop_to_poly = mesh_topology::build_loop_to_poly_map(polys, - corner_verts.size()); + const Array loop_to_poly = mesh_topology::build_loop_to_poly_map(polys); mesh_edges_sharp_tag(polys, corner_verts, @@ -827,7 +822,7 @@ void edges_sharp_from_angle_set(const Span polys, } static void loop_manifold_fan_around_vert_next(const Span corner_verts, - const Span polys, + const blender::OffsetIndices polys, const Span loop_to_poly, const int *e2lfan_curr, const uint mv_pivot_index, @@ -852,19 +847,19 @@ static void loop_manifold_fan_around_vert_next(const Span corner_verts, BLI_assert(*r_mpfan_curr_index >= 0); const uint vert_fan_next = corner_verts[*r_mlfan_curr_index]; - const MPoly &mpfan_next = polys[*r_mpfan_curr_index]; + const blender::IndexRange mpfan_next = polys[*r_mpfan_curr_index]; if ((vert_fan_orig == vert_fan_next && vert_fan_orig == mv_pivot_index) || !ELEM(vert_fan_orig, vert_fan_next, mv_pivot_index)) { /* We need the previous loop, but current one is our vertex's loop. */ *r_mlfan_vert_index = *r_mlfan_curr_index; - if (--(*r_mlfan_curr_index) < mpfan_next.loopstart) { - *r_mlfan_curr_index = mpfan_next.loopstart + mpfan_next.totloop - 1; + if (--(*r_mlfan_curr_index) < mpfan_next.start()) { + *r_mlfan_curr_index = mpfan_next.start() + mpfan_next.size() - 1; } } else { /* We need the next loop, which is also our vertex's loop. */ - if (++(*r_mlfan_curr_index) >= mpfan_next.loopstart + mpfan_next.totloop) { - *r_mlfan_curr_index = mpfan_next.loopstart; + if (++(*r_mlfan_curr_index) >= mpfan_next.start() + mpfan_next.size()) { + *r_mlfan_curr_index = mpfan_next.start(); } *r_mlfan_vert_index = *r_mlfan_curr_index; } @@ -937,7 +932,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, const Span positions = common_data->positions; const Span edges = common_data->edges; - const Span polys = common_data->polys; + const blender::OffsetIndices polys = common_data->polys; const Span corner_verts = common_data->corner_verts; const Span corner_edges = common_data->corner_edges; const Span edge_to_loops = common_data->edge_to_loops; @@ -1172,7 +1167,7 @@ static void loop_split_worker(TaskPool *__restrict pool, void *taskdata) */ static bool loop_split_generator_check_cyclic_smooth_fan(const Span corner_verts, const Span corner_edges, - const Span polys, + const blender::OffsetIndices polys, const Span edge_to_loops, const Span loop_to_poly, const int *e2l_prev, @@ -1242,7 +1237,7 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common const Span corner_verts = common_data->corner_verts; const Span corner_edges = common_data->corner_edges; - const Span polys = common_data->polys; + const OffsetIndices polys = common_data->polys; const Span loop_to_poly = common_data->loop_to_poly; const Span edge_to_loops = common_data->edge_to_loops; @@ -1269,18 +1264,18 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common * and edges that will be hard! Now, time to generate the normals. */ for (const int poly_index : polys.index_range()) { - const MPoly &poly = polys[poly_index]; + const IndexRange poly = polys[poly_index]; - for (const int ml_curr_index : IndexRange(poly.loopstart, poly.totloop)) { + for (const int ml_curr_index : poly) { const int ml_prev_index = mesh::poly_corner_prev(poly, ml_curr_index); #if 0 printf("Checking loop %d / edge %u / vert %u (sharp edge: %d, skiploop: %d)", - ml_curr_index, - corner_edges[ml_curr_index], - corner_verts[ml_curr_index], - IS_EDGE_SHARP(edge_to_loops[corner_edges[ml_curr_index]]), - skip_loops[ml_curr_index]); + ml_curr_index, + corner_edges[ml_curr_index], + corner_verts[ml_curr_index], + IS_EDGE_SHARP(edge_to_loops[corner_edges[ml_curr_index]]), + skip_loops[ml_curr_index]); #endif /* A smooth edge, we have to check for cyclic smooth fan case. @@ -1376,7 +1371,7 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common void normals_calc_loop(const Span vert_positions, const Span edges, - const Span polys, + const OffsetIndices polys, const Span corner_verts, const Span corner_edges, const Span loop_to_poly_map, @@ -1402,17 +1397,13 @@ void normals_calc_loop(const Span vert_positions, * (see e.g. mesh mapping code). As usual, we could handle that on case-by-case basis, * but simpler to keep it well confined here. */ for (const int poly_index : polys.index_range()) { - const MPoly *poly = &polys[poly_index]; - int ml_index = poly->loopstart; - const int ml_index_end = ml_index + poly->totloop; const bool is_poly_flat = sharp_faces && sharp_faces[poly_index]; - - for (; ml_index < ml_index_end; ml_index++) { + for (const int corner : polys[poly_index]) { if (is_poly_flat) { - copy_v3_v3(r_loop_normals[ml_index], poly_normals[poly_index]); + copy_v3_v3(r_loop_normals[corner], poly_normals[poly_index]); } else { - copy_v3_v3(r_loop_normals[ml_index], vert_normals[corner_verts[ml_index]]); + copy_v3_v3(r_loop_normals[corner], vert_normals[corner_verts[corner]]); } } } @@ -1439,7 +1430,7 @@ void normals_calc_loop(const Span vert_positions, Span loop_to_poly; Array local_loop_to_poly_map; if (loop_to_poly_map.is_empty()) { - local_loop_to_poly_map = mesh_topology::build_loop_to_poly_map(polys, corner_verts.size()); + local_loop_to_poly_map = mesh_topology::build_loop_to_poly_map(polys); loop_to_poly = local_loop_to_poly_map; } else { @@ -1483,8 +1474,7 @@ void normals_calc_loop(const Span vert_positions, * This way we don't have to compute those later! */ threading::parallel_for(polys.index_range(), 1024, [&](const IndexRange range) { for (const int poly_i : range) { - const MPoly &poly = polys[poly_i]; - for (const int loop_i : IndexRange(poly.loopstart, poly.totloop)) { + for (const int loop_i : polys[poly_i]) { copy_v3_v3(r_loop_normals[loop_i], vert_normals[corner_verts[loop_i]]); } } @@ -1540,7 +1530,7 @@ void normals_calc_loop(const Span vert_positions, static void mesh_normals_loop_custom_set(Span positions, Span edges, - Span polys, + const OffsetIndices polys, Span corner_verts, Span corner_edges, Span vert_normals, @@ -1559,8 +1549,7 @@ static void mesh_normals_loop_custom_set(Span positions, MLoopNorSpaceArray lnors_spacearr = {nullptr}; BitVector<> done_loops(corner_verts.size(), false); Array loop_normals(corner_verts.size()); - const Array loop_to_poly = mesh_topology::build_loop_to_poly_map(polys, - corner_verts.size()); + const Array loop_to_poly = mesh_topology::build_loop_to_poly_map(polys); /* In this case we always consider split nors as ON, * and do not want to use angle to define smooth fans! */ const bool use_split_normals = true; @@ -1658,8 +1647,8 @@ static void mesh_normals_loop_custom_set(Span positions, * previous loop's face and current's one as sharp. * We know those two loops do not point to the same edge, * since we do not allow reversed winding in a same smooth fan. */ - const MPoly &poly = polys[loop_to_poly[lidx]]; - const int mlp = (lidx == poly.loopstart) ? poly.loopstart + poly.totloop - 1 : lidx - 1; + const IndexRange poly = polys[loop_to_poly[lidx]]; + const int mlp = (lidx == poly.start()) ? poly.start() + poly.size() - 1 : lidx - 1; const int edge = corner_edges[lidx]; const int edge_p = corner_edges[mlp]; const int prev_edge = corner_edges[prev_corner]; @@ -1683,8 +1672,8 @@ static void mesh_normals_loop_custom_set(Span positions, float *nor = r_custom_loop_normals[lidx]; if (dot_v3v3(org_nor, nor) < LNOR_SPACE_TRIGO_THRESHOLD) { - const MPoly &poly = polys[loop_to_poly[lidx]]; - const int mlp = (lidx == poly.loopstart) ? poly.loopstart + poly.totloop - 1 : lidx - 1; + const IndexRange poly = polys[loop_to_poly[lidx]]; + const int mlp = (lidx == poly.start()) ? poly.start() + poly.size() - 1 : lidx - 1; const int edge = corner_edges[lidx]; const int edge_p = corner_edges[mlp]; const int prev_edge = corner_edges[prev_corner]; @@ -1772,7 +1761,7 @@ static void mesh_normals_loop_custom_set(Span positions, void normals_loop_custom_set(const Span vert_positions, const Span edges, - const Span polys, + const OffsetIndices polys, const Span corner_verts, const Span corner_edges, const Span vert_normals, @@ -1798,7 +1787,7 @@ void normals_loop_custom_set(const Span vert_positions, void normals_loop_custom_set_from_verts(const Span vert_positions, const Span edges, - const Span polys, + const OffsetIndices polys, const Span corner_verts, const Span corner_edges, const Span vert_normals, diff --git a/source/blender/blenkernel/intern/mesh_remap.cc b/source/blender/blenkernel/intern/mesh_remap.cc index 2c4d3c2f328..1d1c5c67f7d 100644 --- a/source/blender/blenkernel/intern/mesh_remap.cc +++ b/source/blender/blenkernel/intern/mesh_remap.cc @@ -368,7 +368,7 @@ void BKE_mesh_remap_item_define_invalid(MeshPairRemap *map, const int index) mesh_remap_item_define(map, index, FLT_MAX, 0, 0, nullptr, nullptr); } -static int mesh_remap_interp_poly_data_get(const MPoly &poly, +static int mesh_remap_interp_poly_data_get(const blender::IndexRange poly, const blender::Span corner_verts, const float (*vcos_src)[3], const float point[3], @@ -383,7 +383,7 @@ static int mesh_remap_interp_poly_data_get(const MPoly &poly, float(*vco)[3]; float ref_dist_sq = FLT_MAX; int *index; - const int sources_num = poly.totloop; + const int sources_num = int(poly.size()); int i; if (size_t(sources_num) > *buff_size) { @@ -396,8 +396,8 @@ static int mesh_remap_interp_poly_data_get(const MPoly &poly, } for (i = 0, vco = *vcos, index = *indices; i < sources_num; i++, vco++, index++) { - const int vert = corner_verts[poly.loopstart + i]; - *index = use_loops ? int(poly.loopstart) + i : vert; + const int vert = corner_verts[poly[i]]; + *index = use_loops ? int(poly[i]) : vert; copy_v3_v3(*vco, vcos_src[vert]); if (r_closest_index) { /* Find closest vert/loop in this case. */ @@ -562,7 +562,7 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode, MREMAP_MODE_VERT_POLY_NEAREST, MREMAP_MODE_VERT_POLYINTERP_NEAREST, MREMAP_MODE_VERT_POLYINTERP_VNORPROJ)) { - const blender::Span polys_src = me_src->polys(); + const blender::OffsetIndices polys_src = me_src->polys(); const blender::Span corner_verts_src = me_src->corner_verts(); const float(*vcos_src)[3] = BKE_mesh_vert_positions(me_src); const blender::Span vert_normals_dst = me_dst->vert_normals(); @@ -865,7 +865,7 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode, } else if (mode == MREMAP_MODE_EDGE_POLY_NEAREST) { const blender::Span edges_src = me_src->edges(); - const blender::Span polys_src = me_src->polys(); + const blender::OffsetIndices polys_src = me_src->polys(); const blender::Span corner_edges_src = me_src->corner_edges(); const float(*vcos_src)[3] = BKE_mesh_vert_positions(me_src); @@ -885,9 +885,9 @@ 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 MPoly &poly_src = polys_src[lt->poly]; - const int *corner_edge_src = &corner_edges_src[poly_src.loopstart]; - int nloops = poly_src.totloop; + const blender::IndexRange poly_src = polys_src[lt->poly]; + const int *corner_edge_src = &corner_edges_src[poly_src.start()]; + int nloops = int(poly_src.size()); float best_dist_sq = FLT_MAX; int best_eidx_src = -1; @@ -1035,7 +1035,7 @@ static void mesh_island_to_astar_graph_edge_process(MeshIslandStore *islands, const int island_index, BLI_AStarGraph *as_graph, const blender::Span positions, - const blender::Span polys, + const blender::OffsetIndices polys, const blender::Span corner_verts, const int edge_idx, BLI_bitmap *done_edges, @@ -1050,11 +1050,11 @@ static void mesh_island_to_astar_graph_edge_process(MeshIslandStore *islands, for (i = 0; i < edge_to_poly_map[edge_idx].count; i++) { const int pidx = edge_to_poly_map[edge_idx].indices[i]; - const MPoly &poly = polys[pidx]; + const blender::IndexRange poly = polys[pidx]; const int pidx_isld = islands ? poly_island_index_map[pidx] : pidx; void *custom_data = is_edge_innercut ? POINTER_FROM_INT(edge_idx) : POINTER_FROM_INT(-1); - if (UNLIKELY(islands && (islands->items_to_islands[poly.loopstart] != island_index))) { + if (UNLIKELY(islands && (islands->items_to_islands[poly.start()] != island_index))) { /* poly not in current island, happens with border edges... */ poly_island_indices[i] = -1; continue; @@ -1067,8 +1067,7 @@ static void mesh_island_to_astar_graph_edge_process(MeshIslandStore *islands, if (poly_status[pidx_isld] == POLY_UNSET) { copy_v3_v3(poly_centers[pidx_isld], - blender::bke::mesh::poly_center_calc( - positions, corner_verts.slice(poly.loopstart, poly.totloop))); + blender::bke::mesh::poly_center_calc(positions, corner_verts.slice(poly))); BLI_astar_node_init(as_graph, pidx_isld, poly_centers[pidx_isld]); poly_status[pidx_isld] = POLY_CENTER_INIT; } @@ -1096,10 +1095,9 @@ static void mesh_island_to_astar_graph(MeshIslandStore *islands, const blender::Span positions, MeshElemMap *edge_to_poly_map, const int numedges, - const blender::Span polys, + const blender::OffsetIndices polys, const blender::Span corner_verts, const blender::Span corner_edges, - const int numpolys, BLI_AStarGraph *r_as_graph) { MeshElemMap *island_poly_map = islands ? islands->islands[island_index] : nullptr; @@ -1108,7 +1106,7 @@ static void mesh_island_to_astar_graph(MeshIslandStore *islands, int *poly_island_index_map = nullptr; BLI_bitmap *done_edges = BLI_BITMAP_NEW(numedges, __func__); - const int node_num = islands ? island_poly_map->count : numpolys; + const int node_num = islands ? island_poly_map->count : int(polys.size()); uchar *poly_status = static_cast( MEM_callocN(sizeof(*poly_status) * size_t(node_num), __func__)); float(*poly_centers)[3]; @@ -1123,8 +1121,8 @@ static void mesh_island_to_astar_graph(MeshIslandStore *islands, if (islands) { /* poly_island_index_map is owned by graph memarena. */ - poly_island_index_map = static_cast( - BLI_memarena_calloc(r_as_graph->mem, sizeof(*poly_island_index_map) * size_t(numpolys))); + poly_island_index_map = static_cast(BLI_memarena_calloc( + r_as_graph->mem, sizeof(*poly_island_index_map) * size_t(polys.size()))); for (i = island_poly_map->count; i--;) { poly_island_index_map[island_poly_map->indices[i]] = i; } @@ -1150,16 +1148,12 @@ static void mesh_island_to_astar_graph(MeshIslandStore *islands, for (pidx_isld = node_num; pidx_isld--;) { const int pidx = islands ? island_poly_map->indices[pidx_isld] : pidx_isld; - const MPoly &poly = polys[pidx]; - int pl_idx, l_idx; if (poly_status[pidx_isld] == POLY_COMPLETE) { continue; } - for (pl_idx = 0, l_idx = poly.loopstart; pl_idx < poly.totloop; pl_idx++, l_idx++) { - const int edge = corner_edges[l_idx]; - + for (const int edge : corner_edges.slice(polys[pidx])) { if (BLI_BITMAP_TEST(done_edges, edge)) { continue; } @@ -1233,8 +1227,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, const int *corner_verts_dst, const int *corner_edges_dst, const int numloops_dst, - const MPoly *polys_dst, - const int numpolys_dst, + const blender::OffsetIndices polys_dst, CustomData *ldata_dst, const bool use_split_nors_dst, const float split_angle_dst, @@ -1297,13 +1290,13 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, int *poly_to_looptri_map_src_buff = nullptr; /* Unlike above, those are one-to-one mappings, simpler! */ - int *loop_to_poly_map_src = nullptr; + blender::Array loop_to_poly_map_src; const blender::Span positions_src = me_src->vert_positions(); const int num_verts_src = me_src->totvert; const float(*vcos_src)[3] = nullptr; const blender::Span edges_src = me_src->edges(); - const blender::Span polys_src = me_src->polys(); + const blender::OffsetIndices polys_src = me_src->polys(); const blender::Span corner_verts_src = me_src->corner_verts(); const blender::Span corner_edges_src = me_src->corner_edges(); blender::Span looptris_src; @@ -1313,7 +1306,6 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, int *indices_interp = nullptr; float *weights_interp = nullptr; - const MPoly *mp_dst; int tindex, pidx_dst, lidx_dst, plidx_dst, pidx_src, lidx_src, plidx_src; IslandResult **islands_res; @@ -1362,7 +1354,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, blender::bke::mesh::normals_calc_loop( {reinterpret_cast(vert_positions_dst), numverts_dst}, {edges_dst, numedges_dst}, - {polys_dst, numpolys_dst}, + polys_dst, {corner_verts_dst, numloops_dst}, {corner_edges_dst, numloops_dst}, {}, @@ -1393,19 +1385,15 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, if (use_from_vert) { BKE_mesh_vert_loop_map_create(&vert_to_loop_map_src, &vert_to_loop_map_src_buff, - polys_src.data(), + polys_src, corner_verts_src.data(), - num_verts_src, - int(polys_src.size()), - int(corner_verts_src.size())); + num_verts_src); if (mode & MREMAP_USE_POLY) { BKE_mesh_vert_poly_map_create(&vert_to_poly_map_src, &vert_to_poly_map_src_buff, - polys_src.data(), + polys_src, corner_verts_src.data(), - num_verts_src, - int(polys_src.size()), - int(corner_verts_src.size())); + num_verts_src); } } @@ -1413,22 +1401,15 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, BKE_mesh_edge_poly_map_create(&edge_to_poly_map_src, &edge_to_poly_map_src_buff, int(edges_src.size()), - polys_src.data(), - int(polys_src.size()), + polys_src, corner_edges_src.data(), int(corner_edges_src.size())); if (use_from_vert) { - loop_to_poly_map_src = static_cast( - MEM_mallocN(sizeof(*loop_to_poly_map_src) * size_t(corner_verts_src.size()), __func__)); + loop_to_poly_map_src = blender::bke::mesh_topology::build_loop_to_poly_map(polys_src); poly_cents_src.reinitialize(polys_src.size()); - for (pidx_src = 0; pidx_src < polys_src.size(); pidx_src++) { - const MPoly &poly = polys_src[pidx_src]; - for (plidx_src = 0, lidx_src = poly.loopstart; plidx_src < poly.totloop; - plidx_src++, lidx_src++) { - loop_to_poly_map_src[lidx_src] = pidx_src; - } - poly_cents_src[pidx_src] = blender::bke::mesh::poly_center_calc( - positions_src, corner_verts_src.slice(poly.loopstart, poly.totloop)); + for (const int64_t i : polys_src.index_range()) { + poly_cents_src[i] = blender::bke::mesh::poly_center_calc( + positions_src, corner_verts_src.slice(polys_src[i])); } } @@ -1448,8 +1429,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, edges_src.data(), int(edges_src.size()), uv_seams, - polys_src.data(), - int(polys_src.size()), + polys_src, corner_verts_src.data(), corner_edges_src.data(), int(corner_verts_src.size()), @@ -1491,7 +1471,6 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, polys_src, corner_verts_src, corner_edges_src, - int(polys_src.size()), &as_graphdata[tindex]); } } @@ -1506,9 +1485,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, int num_verts_active = 0; verts_active.fill(false); for (int i = 0; i < isld->count; i++) { - const MPoly &poly = polys_src[isld->indices[i]]; - for (lidx_src = poly.loopstart; lidx_src < poly.loopstart + poly.totloop; lidx_src++) { - const int vidx_src = corner_verts_src[lidx_src]; + for (const int vidx_src : corner_verts_src.slice(polys_src[isld->indices[i]])) { if (!verts_active[vidx_src]) { verts_active[vidx_src].set(); num_verts_active++; @@ -1539,8 +1516,8 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, int num_looptri_active = 0; looptri_active.fill(false); for (const int64_t i : looptris_src.index_range()) { - const MPoly &poly = polys_src[looptris_src[i].poly]; - if (island_store.items_to_islands[poly.loopstart] == tindex) { + const blender::IndexRange poly = polys_src[looptris_src[i].poly]; + if (island_store.items_to_islands[poly.start()] == tindex) { looptri_active[i].set(); num_looptri_active++; } @@ -1571,7 +1548,8 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, MEM_mallocN(sizeof(**islands_res) * islands_res_buff_size, __func__)); } - for (pidx_dst = 0, mp_dst = polys_dst; pidx_dst < numpolys_dst; pidx_dst++, mp_dst++) { + for (pidx_dst = 0; pidx_dst < polys_dst.size(); pidx_dst++) { + const blender::IndexRange poly_dst = polys_dst[pidx_dst]; float pnor_dst[3]; /* Only in use_from_vert case, we may need polys' centers as fallback @@ -1586,8 +1564,8 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, } } - if (size_t(mp_dst->totloop) > islands_res_buff_size) { - islands_res_buff_size = size_t(mp_dst->totloop) + MREMAP_DEFAULT_BUFSIZE; + if (size_t(poly_dst.size()) > islands_res_buff_size) { + islands_res_buff_size = size_t(poly_dst.size()) + MREMAP_DEFAULT_BUFSIZE; for (tindex = 0; tindex < num_trees; tindex++) { islands_res[tindex] = static_cast( MEM_reallocN(islands_res[tindex], sizeof(**islands_res) * islands_res_buff_size)); @@ -1597,8 +1575,8 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, for (tindex = 0; tindex < num_trees; tindex++) { BVHTreeFromMesh *tdata = &treedata[tindex]; - for (plidx_dst = 0; plidx_dst < mp_dst->totloop; plidx_dst++) { - const int vert_dst = corner_verts_dst[mp_dst->loopstart + plidx_dst]; + for (plidx_dst = 0; plidx_dst < poly_dst.size(); plidx_dst++) { + const int vert_dst = corner_verts_dst[poly_dst.start() + plidx_dst]; if (use_from_vert) { MeshElemMap *vert_to_refelem_map_src = nullptr; @@ -1619,7 +1597,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, int best_index_src = -1; if (mode == MREMAP_MODE_LOOP_NEAREST_LOOPNOR) { - copy_v3_v3(tmp_no, loop_normals_dst[plidx_dst + mp_dst->loopstart]); + copy_v3_v3(tmp_no, loop_normals_dst[plidx_dst + poly_dst.start()]); if (space_transform) { BLI_space_transform_apply_normal(space_transform, tmp_no); } @@ -1646,7 +1624,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, * on same island!). */ lidx_src = ((mode == MREMAP_MODE_LOOP_NEAREST_LOOPNOR) ? index_src : - polys_src[pidx_src].loopstart); + int(polys_src[pidx_src].start())); /* A same vert may be at the boundary of several islands! Hence, we have to ensure * poly/loop we are currently considering *belongs* to current island! */ @@ -1664,7 +1642,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, pcent_dst = blender::bke::mesh::poly_center_calc( {reinterpret_cast(vert_positions_dst), numverts_dst}, - {&corner_verts_dst[mp_dst->loopstart], mp_dst->totloop}); + corner_verts_src.slice(poly_dst)); pcent_dst_valid = true; } pcent_src = poly_cents_src[pidx_src]; @@ -1685,11 +1663,11 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, else if (mode == MREMAP_MODE_LOOP_NEAREST_POLYNOR) { /* Our best_index_src is a poly one for now! * Have to find its loop matching our closest vertex. */ - const MPoly &poly = polys_src[best_index_src]; - for (plidx_src = 0; plidx_src < poly.totloop; plidx_src++) { - const int vert_src = corner_verts_src[poly.loopstart + plidx_src]; + const blender::IndexRange poly_src = polys_src[best_index_src]; + for (plidx_src = 0; plidx_src < poly_src.size(); plidx_src++) { + const int vert_src = corner_verts_src[poly_src.start() + plidx_src]; if (vert_src == nearest.index) { - best_index_src = plidx_src + poly.loopstart; + best_index_src = plidx_src + int(poly_src.start()); break; } } @@ -1711,7 +1689,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, float w = 1.0f; copy_v3_v3(tmp_co, vert_positions_dst[vert_dst]); - copy_v3_v3(tmp_no, loop_normals_dst[plidx_dst + mp_dst->loopstart]); + copy_v3_v3(tmp_no, loop_normals_dst[plidx_dst + poly_dst.start()]); /* We do our transform here, since we may do several raycast/nearest queries. */ if (space_transform) { @@ -1813,10 +1791,10 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, for (tindex = 0; tindex < num_trees; tindex++) { float island_fac = 0.0f; - for (plidx_dst = 0; plidx_dst < mp_dst->totloop; plidx_dst++) { + for (plidx_dst = 0; plidx_dst < poly_dst.size(); plidx_dst++) { island_fac += islands_res[tindex][plidx_dst].factor; } - island_fac /= float(mp_dst->totloop); + island_fac /= float(poly_dst.size()); if (island_fac > best_island_fac) { best_island_fac = island_fac; @@ -1831,9 +1809,9 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, BLI_astar_solution_init(as_graph, &as_solution, nullptr); } - for (plidx_dst = 0; plidx_dst < mp_dst->totloop; plidx_dst++) { + for (plidx_dst = 0; plidx_dst < poly_dst.size(); plidx_dst++) { IslandResult *isld_res; - lidx_dst = plidx_dst + mp_dst->loopstart; + lidx_dst = plidx_dst + int(poly_dst.start()); if (best_island_index == -1) { /* No source for any loops of our dest poly in any source islands. */ @@ -1890,7 +1868,6 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, if (last_valid_pidx_isld_src != -1) { /* Find a new valid loop in that new poly (nearest one for now). * Note we could be much more subtle here, again that's for later... */ - int j; float best_dist_sq = FLT_MAX; copy_v3_v3(tmp_co, vert_positions_dst[corner_verts_dst[lidx_dst]]); @@ -1903,13 +1880,13 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, pidx_src = (use_islands ? best_island->indices[last_valid_pidx_isld_src] : last_valid_pidx_isld_src); - const MPoly &poly = polys_src[pidx_src]; - for (j = 0; j < poly.totloop; j++) { - const int vert_src = corner_verts_src[poly.loopstart + j]; + const blender::IndexRange poly_src = polys_src[pidx_src]; + for (const int64_t corner : poly_src) { + const int vert_src = corner_verts_src[corner]; const float dist_sq = len_squared_v3v3(positions_src[vert_src], tmp_co); if (dist_sq < best_dist_sq) { best_dist_sq = dist_sq; - lidx_src = poly.loopstart + j; + lidx_src = int(corner); } } } @@ -1939,7 +1916,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, float *hit_co = isld_res->hit_point; int best_loop_index_src; - const MPoly &poly = polys_src[pidx_src]; + const blender::IndexRange poly_src = polys_src[pidx_src]; /* If prev and curr poly are the same, no need to do anything more!!! */ if (!ELEM(pidx_src_prev, -1, pidx_src) && isld_steps_src) { int pidx_isld_src, pidx_isld_src_prev; @@ -2001,8 +1978,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, if (poly_to_looptri_map_src == nullptr) { BKE_mesh_origindex_map_create_looptri(&poly_to_looptri_map_src, &poly_to_looptri_map_src_buff, - polys_src.data(), - int(polys_src.size()), + polys_src, looptris_src.data(), int(looptris_src.size())); } @@ -2029,7 +2005,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, } if (mode == MREMAP_MODE_LOOP_POLY_NEAREST) { - mesh_remap_interp_poly_data_get(poly, + mesh_remap_interp_poly_data_get(poly_src, corner_verts_src, vcos_src, hit_co, @@ -2050,7 +2026,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, &full_weight); } else { - const int sources_num = mesh_remap_interp_poly_data_get(poly, + const int sources_num = mesh_remap_interp_poly_data_get(poly_src, corner_verts_src, vcos_src, hit_co, @@ -2126,9 +2102,6 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, if (poly_to_looptri_map_src_buff) { MEM_freeN(poly_to_looptri_map_src_buff); } - if (loop_to_poly_map_src) { - MEM_freeN(loop_to_poly_map_src); - } if (vcos_interp) { MEM_freeN(vcos_interp); } @@ -2149,8 +2122,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode, const float (*vert_positions_dst)[3], const int numverts_dst, const int *corner_verts_dst, - const MPoly *polys_dst, - const int numpolys_dst, + const blender::OffsetIndices polys_dst, const Mesh *me_src, MeshPairRemap *r_map) { @@ -2158,7 +2130,6 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode, const float max_dist_sq = max_dist * max_dist; blender::Span poly_normals_dst; blender::float3 tmp_co, tmp_no; - int i; BLI_assert(mode & MREMAP_MODE_POLY); @@ -2166,12 +2137,13 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode, poly_normals_dst = mesh_dst->poly_normals(); } - BKE_mesh_remap_init(r_map, numpolys_dst); + BKE_mesh_remap_init(r_map, int(polys_dst.size())); if (mode == MREMAP_MODE_TOPOLOGY) { - BLI_assert(numpolys_dst == me_src->totpoly); - for (i = 0; i < numpolys_dst; i++) { - mesh_remap_item_define(r_map, i, FLT_MAX, 0, 1, &i, &full_weight); + BLI_assert(polys_dst.size() == me_src->totpoly); + for (const int64_t i : polys_dst.index_range()) { + const int index = int(i); + mesh_remap_item_define(r_map, int(i), FLT_MAX, 0, 1, &index, &full_weight); } } else { @@ -2185,11 +2157,11 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode, if (mode == MREMAP_MODE_POLY_NEAREST) { nearest.index = -1; - for (i = 0; i < numpolys_dst; i++) { - const MPoly &poly = polys_dst[i]; + for (const int64_t i : polys_dst.index_range()) { + const blender::IndexRange poly = polys_dst[i]; tmp_co = blender::bke::mesh::poly_center_calc( {reinterpret_cast(vert_positions_dst), numverts_dst}, - {&corner_verts_dst[poly.loopstart], poly.totloop}); + {&corner_verts_dst[poly.start()], poly.size()}); /* Convert the vertex to tree coordinates, if needed. */ if (space_transform) { @@ -2200,21 +2172,21 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode, &treedata, &nearest, tmp_co, max_dist_sq, &hit_dist)) { const MLoopTri *lt = &treedata.looptri[nearest.index]; const int poly_index = int(lt->poly); - mesh_remap_item_define(r_map, i, hit_dist, 0, 1, &poly_index, &full_weight); + mesh_remap_item_define(r_map, int(i), hit_dist, 0, 1, &poly_index, &full_weight); } else { /* No source for this dest poly! */ - BKE_mesh_remap_item_define_invalid(r_map, i); + BKE_mesh_remap_item_define_invalid(r_map, int(i)); } } } else if (mode == MREMAP_MODE_POLY_NOR) { - for (i = 0; i < numpolys_dst; i++) { - const MPoly &poly = polys_dst[i]; + for (const int64_t i : polys_dst.index_range()) { + const blender::IndexRange poly = polys_dst[i]; tmp_co = blender::bke::mesh::poly_center_calc( {reinterpret_cast(vert_positions_dst), numverts_dst}, - {&corner_verts_dst[poly.loopstart], poly.totloop}); + {&corner_verts_dst[poly.start()], poly.size()}); copy_v3_v3(tmp_no, poly_normals_dst[i]); /* Convert the vertex to tree coordinates, if needed. */ @@ -2228,11 +2200,11 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode, const MLoopTri *lt = &treedata.looptri[rayhit.index]; const int poly_index = int(lt->poly); - mesh_remap_item_define(r_map, i, hit_dist, 0, 1, &poly_index, &full_weight); + mesh_remap_item_define(r_map, int(i), hit_dist, 0, 1, &poly_index, &full_weight); } else { /* No source for this dest poly! */ - BKE_mesh_remap_item_define_invalid(r_map, i); + BKE_mesh_remap_item_define_invalid(r_map, int(i)); } } } @@ -2257,11 +2229,11 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode, int(*tri_vidx_2d)[3] = static_cast( MEM_mallocN(sizeof(*tri_vidx_2d) * (tmp_poly_size - 2), __func__)); - for (i = 0; i < numpolys_dst; i++) { + for (const int64_t i : polys_dst.index_range()) { /* For each dst poly, we sample some rays from it (2D grid in pnor space) * and use their hits to interpolate from source polys. */ /* NOTE: dst poly is early-converted into src space! */ - const MPoly &poly = polys_dst[i]; + const blender::IndexRange poly = polys_dst[i]; int tot_rays, done_rays = 0; float poly_area_2d_inv, done_area = 0.0f; @@ -2274,12 +2246,12 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode, float totweights = 0.0f; float hit_dist_accum = 0.0f; int sources_num = 0; - const int tris_num = poly.totloop - 2; + const int tris_num = int(poly.size()) - 2; int j; pcent_dst = blender::bke::mesh::poly_center_calc( {reinterpret_cast(vert_positions_dst), numverts_dst}, - {&corner_verts_dst[poly.loopstart], poly.totloop}); + {&corner_verts_dst[poly.start()], poly.size()}); copy_v3_v3(tmp_no, poly_normals_dst[i]); @@ -2291,8 +2263,8 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode, copy_vn_fl(weights, int(numpolys_src), 0.0f); - if (UNLIKELY(size_t(poly.totloop) > tmp_poly_size)) { - tmp_poly_size = size_t(poly.totloop); + if (UNLIKELY(size_t(poly.size()) > tmp_poly_size)) { + tmp_poly_size = size_t(poly.size()); poly_vcos_2d = static_cast( MEM_reallocN(poly_vcos_2d, sizeof(*poly_vcos_2d) * tmp_poly_size)); tri_vidx_2d = static_cast( @@ -2308,8 +2280,8 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode, /* Get (2D) bounding square of our poly. */ INIT_MINMAX2(poly_dst_2d_min, poly_dst_2d_max); - for (j = 0; j < poly.totloop; j++) { - const int vert = corner_verts_dst[poly.loopstart + j]; + for (j = 0; j < poly.size(); j++) { + const int vert = corner_verts_dst[poly[j]]; copy_v3_v3(tmp_co, vert_positions_dst[vert]); if (space_transform) { BLI_space_transform_apply(space_transform, tmp_co); @@ -2332,17 +2304,17 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode, } tot_rays *= tot_rays; - poly_area_2d_inv = area_poly_v2(poly_vcos_2d, uint(poly.totloop)); + poly_area_2d_inv = area_poly_v2(poly_vcos_2d, uint(poly.size())); /* In case we have a null-area degenerated poly... */ poly_area_2d_inv = 1.0f / max_ff(poly_area_2d_inv, 1e-9f); /* Tessellate our poly. */ - if (poly.totloop == 3) { + if (poly.size() == 3) { tri_vidx_2d[0][0] = 0; tri_vidx_2d[0][1] = 1; tri_vidx_2d[0][2] = 2; } - if (poly.totloop == 4) { + if (poly.size() == 4) { tri_vidx_2d[0][0] = 0; tri_vidx_2d[0][1] = 1; tri_vidx_2d[0][2] = 2; @@ -2351,7 +2323,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode, tri_vidx_2d[1][2] = 3; } else { - BLI_polyfill_calc(poly_vcos_2d, uint(poly.totloop), -1, (uint(*)[3])tri_vidx_2d); + BLI_polyfill_calc(poly_vcos_2d, uint(poly.size()), -1, (uint(*)[3])tri_vidx_2d); } for (j = 0; j < tris_num; j++) { @@ -2404,11 +2376,11 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode, sources_num++; } mesh_remap_item_define( - r_map, i, hit_dist_accum / totweights, 0, sources_num, indices, weights); + r_map, int(i), hit_dist_accum / totweights, 0, sources_num, indices, weights); } else { /* No source for this dest poly! */ - BKE_mesh_remap_item_define_invalid(r_map, i); + BKE_mesh_remap_item_define_invalid(r_map, int(i)); } } @@ -2420,7 +2392,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode, } else { CLOG_WARN(&LOG, "Unsupported mesh-to-mesh poly mapping mode (%d)!", mode); - memset(r_map->items, 0, sizeof(*r_map->items) * size_t(numpolys_dst)); + memset(r_map->items, 0, sizeof(*r_map->items) * size_t(polys_dst.size())); } free_bvhtree_from_mesh(&treedata); diff --git a/source/blender/blenkernel/intern/mesh_remesh_voxel.cc b/source/blender/blenkernel/intern/mesh_remesh_voxel.cc index 91968d1a65c..d21949a9e3b 100644 --- a/source/blender/blenkernel/intern/mesh_remesh_voxel.cc +++ b/source/blender/blenkernel/intern/mesh_remesh_voxel.cc @@ -119,17 +119,17 @@ static Mesh *remesh_quadriflow(const Mesh *input_mesh, /* Construct the new output mesh */ Mesh *mesh = BKE_mesh_new_nomain(qrd.out_totverts, 0, qrd.out_totfaces * 4, qrd.out_totfaces); BKE_mesh_copy_parameters(mesh, input_mesh); - MutableSpan polys = mesh->polys_for_write(); + MutableSpan poly_offsets = mesh->poly_offsets_for_write(); MutableSpan corner_verts = mesh->corner_verts_for_write(); + poly_offsets.fill(4); + blender::offset_indices::accumulate_counts_to_offsets(poly_offsets); + mesh->vert_positions_for_write().copy_from( Span(reinterpret_cast(qrd.out_verts), qrd.out_totverts)); for (const int i : IndexRange(qrd.out_totfaces)) { - MPoly &poly = polys[i]; const int loopstart = i * 4; - poly.loopstart = loopstart; - poly.totloop = 4; corner_verts[loopstart] = qrd.out_faces[loopstart]; corner_verts[loopstart + 1] = qrd.out_faces[loopstart + 1]; corner_verts[loopstart + 2] = qrd.out_faces[loopstart + 2]; @@ -224,18 +224,19 @@ static Mesh *remesh_voxel_volume_to_mesh(const openvdb::FloatGrid::Ptr level_set Mesh *mesh = BKE_mesh_new_nomain( vertices.size(), 0, quads.size() * 4 + tris.size() * 3, quads.size() + tris.size()); MutableSpan vert_positions = mesh->vert_positions_for_write(); - MutableSpan mesh_polys = mesh->polys_for_write(); + MutableSpan poly_offsets = mesh->poly_offsets_for_write(); MutableSpan mesh_corner_verts = mesh->corner_verts_for_write(); + poly_offsets.take_front(quads.size()).fill(4); + poly_offsets.drop_front(quads.size()).fill(3); + blender::offset_indices::accumulate_counts_to_offsets(poly_offsets); + for (const int i : vert_positions.index_range()) { vert_positions[i] = float3(vertices[i].x(), vertices[i].y(), vertices[i].z()); } for (const int i : IndexRange(quads.size())) { - MPoly &poly = mesh_polys[i]; const int loopstart = i * 4; - poly.loopstart = loopstart; - poly.totloop = 4; mesh_corner_verts[loopstart] = quads[i][0]; mesh_corner_verts[loopstart + 1] = quads[i][3]; mesh_corner_verts[loopstart + 2] = quads[i][2]; @@ -244,10 +245,7 @@ static Mesh *remesh_voxel_volume_to_mesh(const openvdb::FloatGrid::Ptr level_set const int triangle_loop_start = quads.size() * 4; for (const int i : IndexRange(tris.size())) { - MPoly &poly = mesh_polys[quads.size() + i]; const int loopstart = triangle_loop_start + i * 3; - poly.loopstart = loopstart; - poly.totloop = 3; mesh_corner_verts[loopstart] = tris[i][2]; mesh_corner_verts[loopstart + 1] = tris[i][1]; mesh_corner_verts[loopstart + 2] = tris[i][0]; @@ -316,7 +314,7 @@ void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, const Mesh *source) const AttributeAccessor src_attributes = source->attributes(); MutableAttributeAccessor dst_attributes = target->attributes_for_write(); const Span target_positions = target->vert_positions(); - const Span target_polys = target->polys(); + const OffsetIndices target_polys = target->polys(); const Span target_corner_verts = target->corner_verts(); const VArray src_face_sets = src_attributes.lookup(".sculpt_face_set", @@ -342,9 +340,8 @@ void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, const Mesh *source) BVHTreeNearest nearest; nearest.index = -1; nearest.dist_sq = FLT_MAX; - const MPoly &poly = target_polys[i]; - const float3 from_co = mesh::poly_center_calc( - target_positions, target_corner_verts.slice(poly.loopstart, poly.totloop)); + const float3 from_co = mesh::poly_center_calc(target_positions, + target_corner_verts.slice(target_polys[i])); BLI_bvhtree_find_nearest( bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree); if (nearest.index != -1) { @@ -416,19 +413,15 @@ void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source) if (!source_lmap) { BKE_mesh_vert_loop_map_create(&source_lmap, &source_lmap_mem, - source->polys().data(), + source->polys(), source->corner_verts().data(), - source->totvert, - source->totpoly, - source->totloop); + source->totvert); BKE_mesh_vert_loop_map_create(&target_lmap, &target_lmap_mem, - target->polys().data(), + target->polys(), target->corner_verts().data(), - target->totvert, - target->totpoly, - target->totloop); + target->totvert); } blender::threading::parallel_for( diff --git a/source/blender/blenkernel/intern/mesh_runtime.cc b/source/blender/blenkernel/intern/mesh_runtime.cc index 49b5c015c6d..85c391503b6 100644 --- a/source/blender/blenkernel/intern/mesh_runtime.cc +++ b/source/blender/blenkernel/intern/mesh_runtime.cc @@ -145,7 +145,7 @@ blender::Span Mesh::looptris() const { this->runtime->looptris_cache.ensure([&](blender::Array &r_data) { const Span positions = this->vert_positions(); - const Span polys = this->polys(); + const blender::OffsetIndices polys = this->polys(); const Span corner_verts = this->corner_verts(); r_data.reinitialize(poly_to_tri_count(polys.size(), corner_verts.size())); @@ -324,7 +324,7 @@ bool BKE_mesh_runtime_is_valid(Mesh *me_eval) MutableSpan positions = me_eval->vert_positions_for_write(); MutableSpan edges = me_eval->edges_for_write(); - MutableSpan polys = me_eval->polys_for_write(); + MutableSpan poly_offsets = me_eval->poly_offsets_for_write(); MutableSpan corner_verts = me_eval->corner_verts_for_write(); MutableSpan corner_edges = me_eval->corner_edges_for_write(); @@ -353,8 +353,8 @@ bool BKE_mesh_runtime_is_valid(Mesh *me_eval) corner_verts.data(), corner_edges.data(), corner_verts.size(), - polys.data(), - polys.size(), + poly_offsets.data(), + me_eval->totpoly, me_eval->deform_verts_for_write().data(), do_verbose, do_fixes, diff --git a/source/blender/blenkernel/intern/mesh_tangent.cc b/source/blender/blenkernel/intern/mesh_tangent.cc index 7a7a8a78dd7..9b2b5702b39 100644 --- a/source/blender/blenkernel/intern/mesh_tangent.cc +++ b/source/blender/blenkernel/intern/mesh_tangent.cc @@ -44,39 +44,39 @@ struct BKEMeshToTangent { uint GetNumVerticesOfFace(const uint face_num) { - return uint(polys[face_num].totloop); + return uint(polys[face_num].size()); } mikk::float3 GetPosition(const uint face_num, const uint vert_num) { - const uint loop_idx = uint(polys[face_num].loopstart) + vert_num; + const uint loop_idx = uint(polys[face_num].start()) + vert_num; return mikk::float3(positions[corner_verts[loop_idx]]); } mikk::float3 GetTexCoord(const uint face_num, const uint vert_num) { - const float *uv = luvs[uint(polys[face_num].loopstart) + vert_num]; + const float *uv = luvs[uint(polys[face_num].start()) + vert_num]; return mikk::float3(uv[0], uv[1], 1.0f); } mikk::float3 GetNormal(const uint face_num, const uint vert_num) { - return mikk::float3(loop_normals[uint(polys[face_num].loopstart) + vert_num]); + return mikk::float3(loop_normals[uint(polys[face_num].start()) + vert_num]); } void SetTangentSpace(const uint face_num, const uint vert_num, mikk::float3 T, bool orientation) { - float *p_res = tangents[uint(polys[face_num].loopstart) + vert_num]; + float *p_res = tangents[uint(polys[face_num].start()) + vert_num]; copy_v4_fl4(p_res, T.x, T.y, T.z, orientation ? 1.0f : -1.0f); } - const MPoly *polys; /* faces */ - const int *corner_verts; /* faces vertices */ - const float (*positions)[3]; /* vertices */ - const float (*luvs)[2]; /* texture coordinates */ - const float (*loop_normals)[3]; /* loops' normals */ - float (*tangents)[4]; /* output tangents */ - int num_polys; /* number of polygons */ + blender::OffsetIndices polys; /* faces */ + const int *corner_verts; /* faces vertices */ + const float (*positions)[3]; /* vertices */ + const float (*luvs)[2]; /* texture coordinates */ + const float (*loop_normals)[3]; /* loops' normals */ + float (*tangents)[4]; /* output tangents */ + int num_polys; /* number of polygons */ }; void BKE_mesh_calc_loop_tangent_single_ex(const float (*vert_positions)[3], @@ -86,8 +86,7 @@ void BKE_mesh_calc_loop_tangent_single_ex(const float (*vert_positions)[3], const float (*loop_normals)[3], const float (*loop_uvs)[2], const int /*numLoops*/, - const MPoly *polys, - const int numPolys, + const blender::OffsetIndices polys, ReportList *reports) { /* Compute Mikktspace's tangent normals. */ @@ -98,13 +97,13 @@ void BKE_mesh_calc_loop_tangent_single_ex(const float (*vert_positions)[3], mesh_to_tangent.luvs = loop_uvs; mesh_to_tangent.loop_normals = loop_normals; mesh_to_tangent.tangents = r_looptangent; - mesh_to_tangent.num_polys = numPolys; + mesh_to_tangent.num_polys = int(polys.size()); mikk::Mikktspace mikk(mesh_to_tangent); /* First check we do have a tris/quads only mesh. */ - for (int i = 0; i < numPolys; i++) { - if (polys[i].totloop > 4) { + for (const int64_t i : polys.index_range()) { + if (polys[i].size() > 4) { BKE_report( reports, RPT_ERROR, "Tangent space can only be computed for tris/quads, aborting"); return; @@ -151,8 +150,7 @@ void BKE_mesh_calc_loop_tangent_single(Mesh *mesh, loop_normals, reinterpret_cast(uv_map.data()), mesh->totloop, - mesh->polys().data(), - mesh->totpoly, + mesh->polys(), reports); } @@ -180,8 +178,7 @@ struct SGLSLMeshToTangent { #ifdef USE_LOOPTRI_DETECT_QUADS if (face_as_quad_map) { const MLoopTri *lt = &looptri[face_as_quad_map[face_num]]; - const MPoly &poly = polys[lt->poly]; - if (poly.totloop == 4) { + if (polys[lt->poly].size() == 4) { return 4; } } @@ -197,9 +194,8 @@ struct SGLSLMeshToTangent { #ifdef USE_LOOPTRI_DETECT_QUADS if (face_as_quad_map) { lt = &looptri[face_as_quad_map[face_num]]; - const MPoly &poly = polys[lt->poly]; - if (poly.totloop == 4) { - return (uint(poly.loopstart) + vert_num); + if (polys[lt->poly].size() == 4) { + return uint(polys[lt->poly][vert_num]); } /* fall through to regular triangle */ } @@ -245,14 +241,14 @@ struct SGLSLMeshToTangent { return mikk::float3(precomputedFaceNormals[lt->poly]); } #ifdef USE_LOOPTRI_DETECT_QUADS - const MPoly &poly = polys[lt->poly]; + const blender::IndexRange poly = polys[lt->poly]; float normal[3]; - if (poly.totloop == 4) { + if (poly.size() == 4) { normal_quad_v3(normal, - positions[corner_verts[poly.loopstart + 0]], - positions[corner_verts[poly.loopstart + 1]], - positions[corner_verts[poly.loopstart + 2]], - positions[corner_verts[poly.loopstart + 3]]); + positions[corner_verts[poly[0]]], + positions[corner_verts[poly[1]]], + positions[corner_verts[poly[2]]], + positions[corner_verts[poly[3]]]); } else #endif @@ -278,8 +274,8 @@ struct SGLSLMeshToTangent { const float (*precomputedFaceNormals)[3]; const float (*precomputedLoopNormals)[3]; const MLoopTri *looptri; - const float2 *mloopuv; /* texture coordinates */ - const MPoly *polys; /* indices */ + const float2 *mloopuv; /* texture coordinates */ + blender::OffsetIndices polys; const int *corner_verts; /* indices */ const float (*positions)[3]; /* vertex coordinates */ const float (*vert_normals)[3]; @@ -389,8 +385,7 @@ void BKE_mesh_calc_loop_tangent_step_0(const CustomData *loopData, } void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3], - const MPoly *polys, - const uint polys_len, + const blender::OffsetIndices polys, const int *corner_verts, const MLoopTri *looptri, const uint looptri_len, @@ -457,7 +452,7 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3], int *face_as_quad_map = nullptr; /* map faces to quads */ - if (looptri_len != polys_len) { + if (looptri_len != uint(polys.size())) { /* Over allocate, since we don't know how many ngon or quads we have. */ /* map fake face index to looptri */ @@ -466,7 +461,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].totloop == 4) { + if (polys[looptri[j].poly].size() == 4) { j++; /* skips the nest looptri */ } } @@ -580,8 +575,7 @@ void BKE_mesh_calc_loop_tangents(Mesh *me_eval, short tangent_mask = 0; BKE_mesh_calc_loop_tangent_ex( BKE_mesh_vert_positions(me_eval), - me_eval->polys().data(), - uint(me_eval->totpoly), + me_eval->polys(), me_eval->corner_verts().data(), looptris.data(), uint(looptris.size()), diff --git a/source/blender/blenkernel/intern/mesh_tessellate.cc b/source/blender/blenkernel/intern/mesh_tessellate.cc index 57089bde8a1..e2220f0e794 100644 --- a/source/blender/blenkernel/intern/mesh_tessellate.cc +++ b/source/blender/blenkernel/intern/mesh_tessellate.cc @@ -35,7 +35,7 @@ namespace blender::bke::mesh { * \param face_normal: This will be optimized out as a constant. */ BLI_INLINE void mesh_calc_tessellation_for_face_impl(const Span corner_verts, - const Span polys, + const blender::OffsetIndices polys, const Span positions, uint poly_index, MLoopTri *mlt, @@ -43,8 +43,8 @@ BLI_INLINE void mesh_calc_tessellation_for_face_impl(const Span corner_vert const bool face_normal, const float normal_precalc[3]) { - const uint mp_loopstart = uint(polys[poly_index].loopstart); - const uint mp_totloop = uint(polys[poly_index].totloop); + const uint mp_loopstart = uint(polys[poly_index].start()); + const uint mp_totloop = uint(polys[poly_index].size()); auto create_tri = [&](uint i1, uint i2, uint i3) { mlt->tri[0] = mp_loopstart + i1; @@ -142,7 +142,7 @@ BLI_INLINE void mesh_calc_tessellation_for_face_impl(const Span corner_vert } static void mesh_calc_tessellation_for_face(const Span corner_verts, - const Span polys, + const blender::OffsetIndices polys, const Span positions, uint poly_index, MLoopTri *mlt, @@ -153,7 +153,7 @@ static void mesh_calc_tessellation_for_face(const Span corner_verts, } static void mesh_calc_tessellation_for_face_with_normal(const Span corner_verts, - const Span polys, + const blender::OffsetIndices polys, const Span positions, uint poly_index, MLoopTri *mlt, @@ -165,34 +165,31 @@ static void mesh_calc_tessellation_for_face_with_normal(const Span corner_v } static void mesh_recalc_looptri__single_threaded(const Span corner_verts, - const Span polys, + const blender::OffsetIndices polys, const Span positions, - int totloop, - int totpoly, MLoopTri *mlooptri, const float (*poly_normals)[3]) { MemArena *pf_arena = nullptr; - const MPoly *poly = polys.data(); uint tri_index = 0; if (poly_normals != nullptr) { - for (uint poly_index = 0; poly_index < uint(totpoly); poly_index++, poly++) { + for (const int64_t i : polys.index_range()) { mesh_calc_tessellation_for_face_with_normal(corner_verts, polys, positions, - poly_index, + uint(i), &mlooptri[tri_index], &pf_arena, - poly_normals[poly_index]); - tri_index += uint(poly->totloop - 2); + poly_normals[i]); + tri_index += uint(polys[i].size() - 2); } } else { - for (uint poly_index = 0; poly_index < uint(totpoly); poly_index++, poly++) { + for (const int64_t i : polys.index_range()) { mesh_calc_tessellation_for_face( - corner_verts, polys, positions, poly_index, &mlooptri[tri_index], &pf_arena); - tri_index += uint(poly->totloop - 2); + corner_verts, polys, positions, uint(i), &mlooptri[tri_index], &pf_arena); + tri_index += uint(polys[i].size() - 2); } } @@ -200,13 +197,12 @@ static void mesh_recalc_looptri__single_threaded(const Span corner_verts, BLI_memarena_free(pf_arena); pf_arena = nullptr; } - BLI_assert(tri_index == uint(poly_to_tri_count(totpoly, totloop))); - UNUSED_VARS_NDEBUG(totloop); + BLI_assert(tri_index == uint(poly_to_tri_count(int(polys.size()), int(corner_verts.size())))); } struct TessellationUserData { Span corner_verts; - Span polys; + blender::OffsetIndices polys; Span positions; /** Output array. */ @@ -226,7 +222,7 @@ static void mesh_calc_tessellation_for_face_fn(void *__restrict userdata, { const TessellationUserData *data = static_cast(userdata); TessellationUserTLS *tls_data = static_cast(tls->userdata_chunk); - const int tri_index = poly_to_tri_count(index, data->polys[index].loopstart); + const int tri_index = poly_to_tri_count(index, int(data->polys[index].start())); mesh_calc_tessellation_for_face_impl(data->corner_verts, data->polys, data->positions, @@ -243,7 +239,7 @@ static void mesh_calc_tessellation_for_face_with_normal_fn(void *__restrict user { const TessellationUserData *data = static_cast(userdata); TessellationUserTLS *tls_data = static_cast(tls->userdata_chunk); - const int tri_index = poly_to_tri_count(index, data->polys[index].loopstart); + const int tri_index = poly_to_tri_count(index, int(data->polys[index].start())); mesh_calc_tessellation_for_face_impl(data->corner_verts, data->polys, data->positions, @@ -264,7 +260,7 @@ static void mesh_calc_tessellation_for_face_free_fn(const void *__restrict /*use } static void looptris_calc_all(const Span positions, - const Span polys, + const blender::OffsetIndices polys, const Span corner_verts, const Span poly_normals, MutableSpan looptris) @@ -273,8 +269,6 @@ static void looptris_calc_all(const Span positions, mesh_recalc_looptri__single_threaded(corner_verts, polys, positions, - int(corner_verts.size()), - int(polys.size()), looptris.data(), reinterpret_cast(poly_normals.data())); return; @@ -306,7 +300,7 @@ static void looptris_calc_all(const Span positions, } void looptris_calc(const Span vert_positions, - const Span polys, + const OffsetIndices polys, const Span corner_verts, MutableSpan looptris) { @@ -314,19 +308,19 @@ void looptris_calc(const Span vert_positions, } void looptris_calc_with_normals(const Span vert_positions, - const Span polys, + const OffsetIndices polys, const Span corner_verts, const Span poly_normals, MutableSpan looptris) { - BLI_assert(!poly_normals.is_empty() || polys.is_empty()); + BLI_assert(!poly_normals.is_empty() || polys.size() == 0); looptris_calc_all(vert_positions, polys, corner_verts, poly_normals, looptris); } } // namespace blender::bke::mesh void BKE_mesh_recalc_looptri(const int *corner_verts, - const MPoly *polys, + const int *poly_offsets, const float (*vert_positions)[3], int totvert, int totloop, @@ -335,7 +329,7 @@ void BKE_mesh_recalc_looptri(const int *corner_verts, { blender::bke::mesh::looptris_calc( {reinterpret_cast(vert_positions), totvert}, - {polys, totpoly}, + blender::Span(poly_offsets, totpoly + 1), {corner_verts, totloop}, {mlooptri, poly_to_tri_count(totpoly, totloop)}); } diff --git a/source/blender/blenkernel/intern/mesh_validate.cc b/source/blender/blenkernel/intern/mesh_validate.cc index 9cb502b7121..c7596b1b2dc 100644 --- a/source/blender/blenkernel/intern/mesh_validate.cc +++ b/source/blender/blenkernel/intern/mesh_validate.cc @@ -42,7 +42,7 @@ using blender::Span; static CLG_LogRef LOG = {"bke.mesh"}; -void mesh_strip_polysloops(Mesh *me); +void strip_loose_polysloops(Mesh *me, blender::BitSpan polys_to_remove); void mesh_strip_edges(Mesh *me); /* -------------------------------------------------------------------- */ @@ -219,7 +219,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, int *corner_verts, int *corner_edges, uint totloop, - MPoly *polys, + int *poly_offsets, uint totpoly, MDeformVert *dverts, /* assume totvert length */ const bool do_verbose, @@ -240,17 +240,19 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, free_flag.polyloops = do_fixes; \ } \ (void)0 -#define REMOVE_POLY_TAG(_mp) \ - { \ - _mp->totloop *= -1; \ - free_flag.polyloops = do_fixes; \ - } \ - (void)0 + blender::BitVector<> polys_to_remove(totpoly); blender::bke::AttributeWriter material_indices = mesh->attributes_for_write().lookup_for_write("material_index"); blender::MutableVArraySpan material_indices_span(material_indices.varray); +#if 0 + const blender::OffsetIndices polys({poly_offsets, totpoly + 1}); + for (const int i : polys.index_range()) { + BLI_assert(polys[i].size() > 2); + } +#endif + MEdge *edge; uint i, j; int *v; @@ -346,7 +348,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, } } - if (mfaces && !polys) { + if (mfaces && !poly_offsets) { #define REMOVE_FACE_TAG(_mf) \ { \ _mf->v3 = 0; \ @@ -531,8 +533,8 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, int prev_end; for (const int64_t i : blender::IndexRange(totpoly)) { - const MPoly &poly = polys[i]; - + const int poly_start = poly_offsets[i]; + const int poly_size = poly_offsets[i + 1] - poly_start; sp->index = i; /* Material index, isolated from other tests here. While large indices are clamped, @@ -545,22 +547,20 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, } } - if (poly.loopstart < 0 || poly.totloop < 3) { + if (poly_start < 0 || poly_size < 3) { /* Invalid loop data. */ - PRINT_ERR("\tPoly %u is invalid (loopstart: %d, totloop: %d)", - sp->index, - poly.loopstart, - poly.totloop); + PRINT_ERR( + "\tPoly %u is invalid (loopstart: %d, totloop: %d)", sp->index, poly_start, poly_size); sp->invalid = true; } - else if (poly.loopstart + poly.totloop > totloop) { + else if (poly_start + poly_size > totloop) { /* Invalid loop data. */ PRINT_ERR( "\tPoly %u uses loops out of range " "(loopstart: %d, loopend: %d, max number of loops: %u)", sp->index, - poly.loopstart, - poly.loopstart + poly.totloop - 1, + poly_start, + poly_start + poly_size - 1, totloop - 1); sp->invalid = true; } @@ -568,14 +568,14 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, /* Poly itself is valid, for now. */ int v1, v2; /* v1 is prev loop vert idx, v2 is current loop one. */ sp->invalid = false; - sp->verts = v = (int *)MEM_mallocN(sizeof(int) * poly.totloop, "Vert idx of SortPoly"); - sp->numverts = poly.totloop; - sp->loopstart = poly.loopstart; + sp->verts = v = (int *)MEM_mallocN(sizeof(int) * poly_size, "Vert idx of SortPoly"); + sp->numverts = poly_size; + sp->loopstart = poly_start; /* Ideally we would only have to do that once on all vertices * before we start checking each poly, but several polys can use same vert, * so we have to ensure here all verts of current poly are cleared. */ - for (j = 0; j < poly.totloop; j++) { + for (j = 0; j < poly_size; j++) { const int vert = corner_verts[sp->loopstart + j]; if (vert < totvert) { BLI_BITMAP_DISABLE(vert_tag, vert); @@ -583,7 +583,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, } /* Test all poly's loops' vert idx. */ - for (j = 0; j < poly.totloop; j++, v++) { + for (j = 0; j < poly_size; j++, v++) { const int vert = corner_verts[sp->loopstart + j]; if (vert >= totvert) { /* Invalid vert idx. */ @@ -606,12 +606,12 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, } /* Test all poly's loops. */ - for (j = 0; j < poly.totloop; j++) { + for (j = 0; j < poly_size; j++) { const int corner = sp->loopstart + j; const int vert = corner_verts[corner]; const int edge_i = corner_edges[corner]; v1 = vert; - v2 = corner_verts[sp->loopstart + (j + 1) % poly.totloop]; + v2 = corner_verts[sp->loopstart + (j + 1) % poly_size]; if (!BLI_edgehash_haskey(edge_hash, v1, v2)) { /* Edge not existing. */ PRINT_ERR("\tPoly %u needs missing edge (%d, %d)", sp->index, v1, v2); @@ -726,7 +726,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, */ if (sp->invalid) { if (do_fixes) { - REMOVE_POLY_TAG((&polys[sp->index])); + polys_to_remove[sp->index].set(); /* DO NOT REMOVE ITS LOOPS!!! * As already invalid polys are at the end of the SortPoly list, the loops they * were the only users have already been tagged as "to remove" during previous @@ -757,7 +757,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, prev_end, sp->index); if (do_fixes) { - REMOVE_POLY_TAG((&polys[sp->index])); + polys_to_remove[sp->index].set(); /* DO NOT REMOVE ITS LOOPS!!! * They might be used by some next, valid poly! * Just not updating prev_end/prev_sp vars is enough to ensure the loops @@ -843,7 +843,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, } if (free_flag.polyloops) { - mesh_strip_polysloops(mesh); + strip_loose_polysloops(mesh, polys_to_remove); } if (free_flag.edges) { @@ -1091,7 +1091,7 @@ bool BKE_mesh_validate(Mesh *me, const bool do_verbose, const bool cddata_check_ &changed); MutableSpan positions = me->vert_positions_for_write(); MutableSpan edges = me->edges_for_write(); - MutableSpan polys = me->polys_for_write(); + MutableSpan poly_offsets = me->poly_offsets_for_write(); MutableSpan corner_verts = me->corner_verts_for_write(); MutableSpan corner_edges = me->corner_edges_for_write(); @@ -1106,8 +1106,8 @@ bool BKE_mesh_validate(Mesh *me, const bool do_verbose, const bool cddata_check_ corner_verts.data(), corner_edges.data(), corner_verts.size(), - polys.data(), - polys.size(), + poly_offsets.data(), + me->totpoly, me->deform_verts_for_write().data(), do_verbose, true, @@ -1145,7 +1145,7 @@ bool BKE_mesh_is_valid(Mesh *me) MutableSpan positions = me->vert_positions_for_write(); MutableSpan edges = me->edges_for_write(); - MutableSpan polys = me->polys_for_write(); + MutableSpan poly_offsets = me->poly_offsets_for_write(); MutableSpan corner_verts = me->corner_verts_for_write(); MutableSpan corner_edges = me->corner_edges_for_write(); @@ -1160,8 +1160,8 @@ bool BKE_mesh_is_valid(Mesh *me) corner_verts.data(), corner_edges.data(), corner_verts.size(), - polys.data(), - polys.size(), + poly_offsets.data(), + me->totpoly, me->deform_verts_for_write().data(), do_verbose, do_fixes, @@ -1225,9 +1225,9 @@ void BKE_mesh_strip_loose_faces(Mesh *me) } } -void mesh_strip_polysloops(Mesh *me) +void strip_loose_polysloops(Mesh *me, blender::BitSpan polys_to_remove) { - MutableSpan polys = me->polys_for_write(); + MutableSpan poly_offsets = me->poly_offsets_for_write(); MutableSpan corner_edges = me->corner_edges_for_write(); int a, b; @@ -1235,26 +1235,26 @@ void mesh_strip_polysloops(Mesh *me) int *new_idx = (int *)MEM_mallocN(sizeof(int) * me->totloop, __func__); for (a = b = 0; a < me->totpoly; a++) { - const MPoly &poly = polys[a]; bool invalid = false; - int i = poly.loopstart; - int stop = i + poly.totloop; + int start = poly_offsets[a]; + int size = poly_offsets[a + 1] - start; + int stop = start + size; - if (stop > me->totloop || stop < i || poly.loopstart < 0) { + if (polys_to_remove[a]) { + invalid = true; + } + else if (stop > me->totloop || stop < start || size < 0) { invalid = true; } else { /* If one of the poly's loops is invalid, the whole poly is invalid! */ - if (corner_edges.slice(poly.loopstart, poly.totloop) - .as_span() - .contains(INVALID_LOOP_EDGE_MARKER)) { + if (corner_edges.slice(start, size).as_span().contains(INVALID_LOOP_EDGE_MARKER)) { invalid = true; } } - if (poly.totloop >= 3 && !invalid) { + if (size >= 3 && !invalid) { if (a != b) { - memcpy(&polys[b], &poly, sizeof(polys[b])); CustomData_copy_data(&me->pdata, &me->pdata, a, b, 1); } b++; @@ -1286,10 +1286,13 @@ void mesh_strip_polysloops(Mesh *me) me->totloop = b; } + poly_offsets[me->totpoly] = me->totloop; + /* And now, update polys' start loop index. */ /* NOTE: At this point, there should never be any poly using a striped loop! */ - for (const int i : polys.index_range()) { - polys[i].loopstart = new_idx[polys[i].loopstart]; + for (const int i : blender::IndexRange(me->totpoly)) { + poly_offsets[i] = new_idx[poly_offsets[i]]; + BLI_assert(poly_offsets[i] >= 0); } MEM_freeN(new_idx); diff --git a/source/blender/blenkernel/intern/mesh_wrapper.cc b/source/blender/blenkernel/intern/mesh_wrapper.cc index 659710a1892..7beed9da463 100644 --- a/source/blender/blenkernel/intern/mesh_wrapper.cc +++ b/source/blender/blenkernel/intern/mesh_wrapper.cc @@ -7,7 +7,7 @@ * output of a modified mesh. * * This API handles the case when the modifier stack outputs a mesh which does not have - * #Mesh data (#MPoly, corner verts, corner edges, #MEdge, etc). + * #Mesh data (#Mesh::polys(), corner verts, corner edges, #MEdge, etc). * Currently this is used so the resulting mesh can have #BMEditMesh data, * postponing the converting until it's needed or avoiding conversion entirely * which can be an expensive operation. diff --git a/source/blender/blenkernel/intern/multires.cc b/source/blender/blenkernel/intern/multires.cc index a3c88309898..fde8f8b842f 100644 --- a/source/blender/blenkernel/intern/multires.cc +++ b/source/blender/blenkernel/intern/multires.cc @@ -183,7 +183,7 @@ static BLI_bitmap *multires_mdisps_downsample_hidden(const BLI_bitmap *old_hidde static void multires_output_hidden_to_ccgdm(CCGDerivedMesh *ccgdm, Mesh *me, int level) { - const blender::Span polys = me->polys(); + const blender::OffsetIndices polys = me->polys(); const MDisps *mdisps = static_cast(CustomData_get_layer(&me->ldata, CD_MDISPS)); BLI_bitmap **grid_hidden = ccgdm->gridHidden; int *gridOffset; @@ -192,7 +192,7 @@ static void multires_output_hidden_to_ccgdm(CCGDerivedMesh *ccgdm, Mesh *me, int gridOffset = ccgdm->dm.getGridOffset(&ccgdm->dm); for (const int i : polys.index_range()) { - for (j = 0; j < polys[i].totloop; j++) { + for (j = 0; j < polys[i].size(); j++) { int g = gridOffset[i] + j; const MDisps *md = &mdisps[g]; BLI_bitmap *gh = md->hidden; @@ -487,15 +487,14 @@ void multires_force_external_reload(Object *object) static int get_levels_from_disps(Object *ob) { Mesh *me = static_cast(ob->data); - const blender::Span polys = me->polys(); - int j, totlvl = 0; + const blender::OffsetIndices polys = me->polys(); + int totlvl = 0; const MDisps *mdisp = static_cast(CustomData_get_layer(&me->ldata, CD_MDISPS)); for (const int i : polys.index_range()) { - const MDisps *md = mdisp + polys[i].loopstart; - - for (j = 0; j < polys[i].totloop; j++, md++) { + for (const int corner : polys[i]) { + const MDisps *md = &mdisp[corner]; if (md->totdisp == 0) { continue; } @@ -657,7 +656,7 @@ static void multires_grid_paint_mask_downsample(GridPaintMask *gpm, int level) static void multires_del_higher(MultiresModifierData *mmd, Object *ob, int lvl) { Mesh *me = (Mesh *)ob->data; - const blender::Span polys = me->polys(); + const blender::OffsetIndices polys = me->polys(); int levels = mmd->totlvl - lvl; MDisps *mdisps; GridPaintMask *gpm; @@ -675,12 +674,10 @@ static void multires_del_higher(MultiresModifierData *mmd, Object *ob, int lvl) if (lvl > 0) { int nsize = multires_side_tot[lvl]; int hsize = multires_side_tot[mmd->totlvl]; - int j; for (const int i : polys.index_range()) { - for (j = 0; j < polys[i].totloop; j++) { - int g = polys[i].loopstart + j; - MDisps *mdisp = &mdisps[g]; + for (const int corner : polys[i]) { + MDisps *mdisp = &mdisps[corner]; float(*disps)[3], (*ndisps)[3], (*hdisps)[3]; int totdisp = multires_grid_tot[lvl]; @@ -706,7 +703,7 @@ static void multires_del_higher(MultiresModifierData *mmd, Object *ob, int lvl) mdisp->level = lvl; if (gpm) { - multires_grid_paint_mask_downsample(&gpm[g], lvl); + multires_grid_paint_mask_downsample(&gpm[corner], lvl); } } } @@ -855,7 +852,7 @@ struct MultiresThreadedData { CCGElem **gridData, **subGridData; CCGKey *key; CCGKey *sub_key; - const MPoly *polys; + blender::OffsetIndices polys; MDisps *mdisps; GridPaintMask *grid_paint_mask; int *gridOffset; @@ -873,7 +870,7 @@ static void multires_disp_run_cb(void *__restrict userdata, CCGElem **gridData = tdata->gridData; CCGElem **subGridData = tdata->subGridData; CCGKey *key = tdata->key; - const MPoly *polys = tdata->polys; + blender::OffsetIndices polys = tdata->polys; MDisps *mdisps = tdata->mdisps; GridPaintMask *grid_paint_mask = tdata->grid_paint_mask; int *gridOffset = tdata->gridOffset; @@ -881,12 +878,12 @@ static void multires_disp_run_cb(void *__restrict userdata, int dGridSize = tdata->dGridSize; int dSkip = tdata->dSkip; - const int numVerts = polys[pidx].totloop; + const int numVerts = polys[pidx].size(); int S, x, y, gIndex = gridOffset[pidx]; for (S = 0; S < numVerts; S++, gIndex++) { GridPaintMask *gpm = grid_paint_mask ? &grid_paint_mask[gIndex] : nullptr; - MDisps *mdisp = &mdisps[polys[pidx].loopstart + S]; + MDisps *mdisp = &mdisps[polys[pidx][S]]; CCGElem *grid = gridData[gIndex]; CCGElem *subgrid = subGridData[gIndex]; float(*dispgrid)[3] = nullptr; @@ -967,7 +964,7 @@ static void multiresModifier_disp_run( CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm; CCGElem **gridData, **subGridData; CCGKey key; - const MPoly *polys = me->polys().data(); + blender::OffsetIndices polys = me->polys(); MDisps *mdisps = static_cast( CustomData_get_layer_for_write(&me->ldata, CD_MDISPS, me->totloop)); GridPaintMask *grid_paint_mask = nullptr; @@ -977,8 +974,8 @@ static void multiresModifier_disp_run( /* this happens in the dm made by bmesh_mdisps_space_set */ if (dm2 && CustomData_has_layer(&dm2->loopData, CD_MDISPS)) { - polys = static_cast( - CustomData_get_layer_for_write(&dm2->polyData, CD_MPOLY, dm2->getNumPolys(dm))); + polys = blender::OffsetIndices( + blender::Span(dm2->getPolyArray(dm2), dm2->getNumPolys(dm2) + 1)); mdisps = static_cast( CustomData_get_layer_for_write(&dm2->loopData, CD_MDISPS, dm2->getNumLoops(dm))); totloop = dm2->numLoopData; @@ -1555,12 +1552,12 @@ void multiresModifier_ensure_external_read(struct Mesh *mesh, const MultiresModi /***************** Multires interpolation stuff *****************/ int mdisp_rot_face_to_crn( - const MPoly *poly, const int face_side, const float u, const float v, float *x, float *y) + const int face_size, const int face_side, const float u, const float v, float *x, float *y) { const float offset = face_side * 0.5f - 0.5f; int S = 0; - if (poly->totloop == 4) { + if (face_size == 4) { if (u <= offset && v <= offset) { S = 0; } @@ -1591,7 +1588,7 @@ int mdisp_rot_face_to_crn( *y = v - offset; } } - else if (poly->totloop == 3) { + else if (face_size == 3) { int grid_size = offset; float w = (face_side - 1) - u - v; float W1, W2; diff --git a/source/blender/blenkernel/intern/multires_reshape.hh b/source/blender/blenkernel/intern/multires_reshape.hh index d7185c08939..11c938c7ac5 100644 --- a/source/blender/blenkernel/intern/multires_reshape.hh +++ b/source/blender/blenkernel/intern/multires_reshape.hh @@ -7,6 +7,7 @@ #pragma once +#include "BLI_offset_indices.hh" #include "BLI_span.hh" #include "BLI_sys_types.h" @@ -17,7 +18,6 @@ struct GridPaintMask; struct MDisps; struct MEdge; struct Mesh; -struct MPoly; struct MultiresModifierData; struct Object; struct Subdiv; @@ -35,7 +35,7 @@ struct MultiresReshapeContext { Mesh *base_mesh; const float (*base_positions)[3]; blender::Span base_edges; - blender::Span base_polys; + blender::OffsetIndices base_polys; blender::Span base_corner_verts; blender::Span base_corner_edges; diff --git a/source/blender/blenkernel/intern/multires_reshape_apply_base.cc b/source/blender/blenkernel/intern/multires_reshape_apply_base.cc index 0cb8327d3c2..359e271b44b 100644 --- a/source/blender/blenkernel/intern/multires_reshape_apply_base.cc +++ b/source/blender/blenkernel/intern/multires_reshape_apply_base.cc @@ -74,11 +74,9 @@ void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape int *pmap_mem; BKE_mesh_vert_poly_map_create(&pmap, &pmap_mem, - reshape_context->base_polys.data(), + reshape_context->base_polys, reshape_context->base_corner_verts.data(), - base_mesh->totvert, - base_mesh->totpoly, - base_mesh->totloop); + base_mesh->totvert); float(*origco)[3] = static_cast( MEM_calloc_arrayN(base_mesh->totvert, sizeof(float[3]), __func__)); @@ -97,11 +95,11 @@ void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape /* Find center. */ int tot = 0; for (int j = 0; j < pmap[i].count; j++) { - const MPoly &poly = reshape_context->base_polys[pmap[i].indices[j]]; + const blender::IndexRange poly = reshape_context->base_polys[pmap[i].indices[j]]; /* This double counts, not sure if that's bad or good. */ - for (int k = 0; k < poly.totloop; k++) { - const int vndx = reshape_context->base_corner_verts[poly.loopstart + k]; + for (const int corner : poly) { + const int vndx = reshape_context->base_corner_verts[corner]; if (vndx != i) { add_v3_v3(center, origco[vndx]); tot++; @@ -112,14 +110,14 @@ void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape /* Find normal. */ for (int j = 0; j < pmap[i].count; j++) { - const MPoly &poly = reshape_context->base_polys[pmap[i].indices[j]]; + const blender::IndexRange poly = reshape_context->base_polys[pmap[i].indices[j]]; /* Set up poly, loops, and coords in order to call #bke::mesh::poly_normal_calc(). */ - blender::Array poly_verts(poly.totloop); - blender::Array fake_co(poly.totloop); + blender::Array poly_verts(poly.size()); + blender::Array fake_co(poly.size()); - for (int k = 0; k < poly.totloop; k++) { - const int vndx = reshape_context->base_corner_verts[poly.loopstart + k]; + for (int k = 0; k < poly.size(); k++) { + const int vndx = reshape_context->base_corner_verts[poly[k]]; poly_verts[k] = k; diff --git a/source/blender/blenkernel/intern/multires_reshape_smooth.cc b/source/blender/blenkernel/intern/multires_reshape_smooth.cc index 1864165e4ab..e88f61d3b87 100644 --- a/source/blender/blenkernel/intern/multires_reshape_smooth.cc +++ b/source/blender/blenkernel/intern/multires_reshape_smooth.cc @@ -648,8 +648,7 @@ static void foreach_vertex(const SubdivForeachContext *foreach_context, const int face_index = multires_reshape_grid_to_face_index(reshape_context, grid_coord.grid_index); - const MPoly &base_poly = reshape_context->base_polys[face_index]; - const int num_corners = base_poly.totloop; + const int num_corners = reshape_context->base_polys[face_index].size(); const int start_grid_index = reshape_context->face_start_grid_index[face_index]; const int corner = grid_coord.grid_index - start_grid_index; @@ -849,7 +848,7 @@ static void geometry_init_loose_information(MultiresReshapeSmoothContext *reshap { const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context; const Mesh *base_mesh = reshape_context->base_mesh; - const blender::Span base_polys = reshape_context->base_polys; + const blender::OffsetIndices base_polys = reshape_context->base_polys; const blender::Span base_corner_edges = reshape_context->base_corner_edges; reshape_smooth_context->non_loose_base_edge_map = BLI_BITMAP_NEW(base_mesh->totedge, @@ -857,8 +856,7 @@ static void geometry_init_loose_information(MultiresReshapeSmoothContext *reshap int num_used_edges = 0; for (const int poly_index : base_polys.index_range()) { - const MPoly &base_poly = base_polys[poly_index]; - for (const int edge : base_corner_edges.slice(base_poly.loopstart, base_poly.totloop)) { + for (const int edge : base_corner_edges.slice(base_polys[poly_index])) { if (!BLI_BITMAP_TEST_BOOL(reshape_smooth_context->non_loose_base_edge_map, edge)) { BLI_BITMAP_ENABLE(reshape_smooth_context->non_loose_base_edge_map, edge); diff --git a/source/blender/blenkernel/intern/multires_reshape_subdivide.cc b/source/blender/blenkernel/intern/multires_reshape_subdivide.cc index 05c44597b4e..beac99e0a7c 100644 --- a/source/blender/blenkernel/intern/multires_reshape_subdivide.cc +++ b/source/blender/blenkernel/intern/multires_reshape_subdivide.cc @@ -31,24 +31,23 @@ static void multires_subdivide_create_object_space_linear_grids(Mesh *mesh) using namespace blender; using namespace blender::bke; const Span positions = mesh->vert_positions(); - const blender::Span polys = mesh->polys(); + const blender::OffsetIndices polys = mesh->polys(); const blender::Span corner_verts = mesh->corner_verts(); MDisps *mdisps = static_cast( CustomData_get_layer_for_write(&mesh->ldata, CD_MDISPS, mesh->totloop)); for (const int p : polys.index_range()) { - const MPoly &poly = polys[p]; - const float3 poly_center = mesh::poly_center_calc( - positions, corner_verts.slice(poly.loopstart, poly.totloop)); - for (int l = 0; l < poly.totloop; l++) { - const int loop_index = poly.loopstart + l; + const blender::IndexRange poly = polys[p]; + const float3 poly_center = mesh::poly_center_calc(positions, corner_verts.slice(poly)); + for (int l = 0; l < poly.size(); l++) { + const int loop_index = poly[l]; float(*disps)[3] = mdisps[loop_index].disps; mdisps[loop_index].totdisp = 4; mdisps[loop_index].level = 1; - int prev_loop_index = l - 1 >= 0 ? loop_index - 1 : loop_index + poly.totloop - 1; - int next_loop_index = l + 1 < poly.totloop ? loop_index + 1 : poly.loopstart; + int prev_loop_index = l - 1 >= 0 ? loop_index - 1 : loop_index + poly.size() - 1; + int next_loop_index = l + 1 < poly.size() ? loop_index + 1 : poly.start(); const int vert = corner_verts[loop_index]; const int vert_next = corner_verts[next_loop_index]; diff --git a/source/blender/blenkernel/intern/multires_reshape_util.cc b/source/blender/blenkernel/intern/multires_reshape_util.cc index efe30ea8604..697b6a4e063 100644 --- a/source/blender/blenkernel/intern/multires_reshape_util.cc +++ b/source/blender/blenkernel/intern/multires_reshape_util.cc @@ -67,7 +67,7 @@ static void context_zero(MultiresReshapeContext *reshape_context) static void context_init_lookup(MultiresReshapeContext *reshape_context) { const Mesh *base_mesh = reshape_context->base_mesh; - const blender::Span polys = reshape_context->base_polys; + const blender::OffsetIndices polys = reshape_context->base_polys; const int num_faces = base_mesh->totpoly; reshape_context->face_start_grid_index = static_cast( @@ -75,7 +75,7 @@ static void context_init_lookup(MultiresReshapeContext *reshape_context) int num_grids = 0; int num_ptex_faces = 0; for (int face_index = 0; face_index < num_faces; ++face_index) { - const int num_corners = polys[face_index].totloop; + const int num_corners = polys[face_index].size(); reshape_context->face_start_grid_index[face_index] = num_grids; num_grids += num_corners; num_ptex_faces += (num_corners == 4) ? 1 : num_corners; @@ -86,7 +86,7 @@ static void context_init_lookup(MultiresReshapeContext *reshape_context) reshape_context->ptex_start_grid_index = static_cast( MEM_malloc_arrayN(num_ptex_faces, sizeof(int), "ptex_start_grid_index")); for (int face_index = 0, grid_index = 0, ptex_index = 0; face_index < num_faces; ++face_index) { - const int num_corners = polys[face_index].totloop; + const int num_corners = polys[face_index].size(); const int num_face_ptex_faces = (num_corners == 4) ? 1 : num_corners; for (int i = 0; i < num_face_ptex_faces; ++i) { reshape_context->ptex_start_grid_index[ptex_index + i] = grid_index + i; @@ -372,8 +372,7 @@ int multires_reshape_grid_to_corner(const MultiresReshapeContext *reshape_contex bool multires_reshape_is_quad_face(const MultiresReshapeContext *reshape_context, int face_index) { - const MPoly &base_poly = reshape_context->base_polys[face_index]; - return (base_poly.totloop == 4); + return reshape_context->base_polys[face_index].size() == 4; } int multires_reshape_grid_to_ptex_index(const MultiresReshapeContext *reshape_context, @@ -669,11 +668,11 @@ static void foreach_grid_face_coordinate_task(void *__restrict userdata_v, const MultiresReshapeContext *reshape_context = data->reshape_context; - const blender::Span polys = reshape_context->base_polys; + const blender::OffsetIndices polys = reshape_context->base_polys; const int grid_size = data->grid_size; const float grid_size_1_inv = 1.0f / (float(grid_size) - 1.0f); - const int num_corners = polys[face_index].totloop; + const int num_corners = polys[face_index].size(); int grid_index = reshape_context->face_start_grid_index[face_index]; for (int corner = 0; corner < num_corners; ++corner, ++grid_index) { for (int y = 0; y < grid_size; ++y) { diff --git a/source/blender/blenkernel/intern/multires_reshape_vertcos.cc b/source/blender/blenkernel/intern/multires_reshape_vertcos.cc index 0f731026336..fd54b712368 100644 --- a/source/blender/blenkernel/intern/multires_reshape_vertcos.cc +++ b/source/blender/blenkernel/intern/multires_reshape_vertcos.cc @@ -54,8 +54,7 @@ static void multires_reshape_vertcos_foreach_vertex(const SubdivForeachContext * const int face_index = multires_reshape_grid_to_face_index(reshape_context, grid_coord.grid_index); - const MPoly &base_poly = reshape_context->base_polys[face_index]; - const int num_corners = base_poly.totloop; + const int num_corners = reshape_context->base_polys[face_index].size(); const int start_grid_index = reshape_context->face_start_grid_index[face_index]; const int corner = grid_coord.grid_index - start_grid_index; diff --git a/source/blender/blenkernel/intern/multires_unsubdivide.cc b/source/blender/blenkernel/intern/multires_unsubdivide.cc index 26355932b73..cb1cc5f713e 100644 --- a/source/blender/blenkernel/intern/multires_unsubdivide.cc +++ b/source/blender/blenkernel/intern/multires_unsubdivide.cc @@ -642,17 +642,17 @@ static void store_grid_data(MultiresUnsubdivideContext *context, int grid_y) { Mesh *original_mesh = context->original_mesh; - const blender::Span polys = original_mesh->polys(); + const blender::OffsetIndices polys = original_mesh->polys(); const blender::Span corner_verts = original_mesh->corner_verts(); - const MPoly &poly = polys[BM_elem_index_get(f)]; + const blender::IndexRange poly = polys[BM_elem_index_get(f)]; const int corner_vertex_index = BM_elem_index_get(v); /* Calculates an offset to write the grids correctly oriented in the main * #MultiresUnsubdivideGrid. */ int loop_offset = 0; - for (int i = 0; i < poly.totloop; i++) { - const int loop_index = poly.loopstart + i; + for (int i = 0; i < poly.size(); i++) { + const int loop_index = poly[i]; if (corner_verts[loop_index] == corner_vertex_index) { loop_offset = i; break; @@ -666,8 +666,8 @@ static void store_grid_data(MultiresUnsubdivideContext *context, float(*face_grid)[3] = static_cast( MEM_calloc_arrayN(face_grid_area, sizeof(float[3]), "face_grid")); - for (int i = 0; i < poly.totloop; i++) { - const int loop_index = poly.loopstart + i; + for (int i = 0; i < poly.size(); i++) { + const int loop_index = poly[i]; MDisps *mdisp = &context->original_mdisp[loop_index]; int quad_loop = i - loop_offset; if (quad_loop < 0) { @@ -920,7 +920,7 @@ static void multires_unsubdivide_prepare_original_bmesh_for_extract( MultiresUnsubdivideContext *context) { Mesh *original_mesh = context->original_mesh; - const blender::Span original_polys = original_mesh->polys(); + const blender::OffsetIndices original_polys = original_mesh->polys(); Mesh *base_mesh = context->base_mesh; @@ -953,10 +953,8 @@ static void multires_unsubdivide_prepare_original_bmesh_for_extract( MEM_calloc_arrayN(original_mesh->totloop, sizeof(int), "loop map")); for (int i = 0; i < original_mesh->totpoly; i++) { - const MPoly &poly = original_polys[i]; - for (int l = 0; l < poly.totloop; l++) { - int original_loop_index = l + poly.loopstart; - context->loop_to_face_map[original_loop_index] = i; + for (const int corner : original_polys[i]) { + context->loop_to_face_map[corner] = i; } } } @@ -965,21 +963,21 @@ static void multires_unsubdivide_prepare_original_bmesh_for_extract( * Checks the orientation of the loops to flip the x and y axis when extracting the grid if * necessary. */ -static bool multires_unsubdivide_flip_grid_x_axis(const blender::Span polys, +static bool multires_unsubdivide_flip_grid_x_axis(const blender::OffsetIndices polys, const blender::Span corner_verts, int poly_index, int loop, int v_x) { - const MPoly &poly = polys[poly_index]; + const blender::IndexRange poly = polys[poly_index]; - const int v_first = corner_verts[poly.loopstart]; - if ((loop == (poly.loopstart + (poly.totloop - 1))) && v_first == v_x) { + const int v_first = corner_verts[poly.start()]; + if ((loop == (poly.start() + (poly.size() - 1))) && v_first == v_x) { return true; } int next_l_index = loop + 1; - if (next_l_index < poly.loopstart + poly.totloop) { + if (next_l_index < poly.start() + poly.size()) { const int v_next = corner_verts[next_l_index]; if (v_next == v_x) { return true; @@ -1043,7 +1041,7 @@ static void multires_unsubdivide_extract_grids(MultiresUnsubdivideContext *conte const int base_l_offset = CustomData_get_n_offset( &bm_base_mesh->ldata, CD_PROP_INT32, base_l_layer_index); - const blender::Span polys = base_mesh->polys(); + const blender::OffsetIndices polys = base_mesh->polys(); const blender::Span corner_verts = base_mesh->corner_verts(); /* Main loop for extracting the grids. Iterates over the base mesh vertices. */ diff --git a/source/blender/blenkernel/intern/object_dupli.cc b/source/blender/blenkernel/intern/object_dupli.cc index 2b7bce2e8a4..f394e81eae9 100644 --- a/source/blender/blenkernel/intern/object_dupli.cc +++ b/source/blender/blenkernel/intern/object_dupli.cc @@ -1056,8 +1056,8 @@ struct FaceDupliData_Mesh { FaceDupliData_Params params; int totface; - const MPoly *polys; - const int *corner_verts; + blender::OffsetIndices polys; + Span corner_verts; Span vert_positions; const float (*orco)[3]; const float2 *mloopuv; @@ -1155,14 +1155,12 @@ static DupliObject *face_dupli_from_mesh(const DupliContext *ctx, const float scale_fac, /* Mesh variables. */ - const MPoly &poly, - const int *poly_verts, + const Span poly_verts, const Span vert_positions) { - const int coords_len = poly.totloop; - Array coords(coords_len); + Array coords(poly_verts.size()); - for (int i = 0; i < coords_len; i++) { + for (int i = 0; i < poly_verts.size(); i++) { coords[i] = vert_positions[poly_verts[i]]; } @@ -1205,8 +1203,6 @@ static void make_child_duplis_faces_from_mesh(const DupliContext *ctx, Object *inst_ob) { FaceDupliData_Mesh *fdd = (FaceDupliData_Mesh *)userdata; - const MPoly *polys = fdd->polys; - const int *corner_verts = fdd->corner_verts; const float(*orco)[3] = fdd->orco; const float2 *mloopuv = fdd->mloopuv; const int totface = fdd->totface; @@ -1220,27 +1216,26 @@ static void make_child_duplis_faces_from_mesh(const DupliContext *ctx, const float scale_fac = ctx->object->instance_faces_scale; for (const int a : blender::IndexRange(totface)) { - const MPoly &poly = polys[a]; - const int *poly_verts = &corner_verts[poly.loopstart]; + const blender::IndexRange poly = fdd->polys[a]; + const Span poly_verts = fdd->corner_verts.slice(poly); DupliObject *dob = face_dupli_from_mesh(fdd->params.ctx, inst_ob, child_imat, a, use_scale, scale_fac, - poly, poly_verts, fdd->vert_positions); - const float w = 1.0f / float(poly.totloop); + const float w = 1.0f / float(poly.size()); if (orco) { - for (int j = 0; j < poly.totloop; j++) { + for (int j = 0; j < poly.size(); j++) { madd_v3_v3fl(dob->orco, orco[poly_verts[j]], w); } } if (mloopuv) { - for (int j = 0; j < poly.totloop; j++) { - madd_v2_v2fl(dob->uv, mloopuv[poly.loopstart + j], w); + for (int j = 0; j < poly.size(); j++) { + madd_v2_v2fl(dob->uv, mloopuv[poly[j]], w); } } } @@ -1318,8 +1313,8 @@ static void make_duplis_faces(const DupliContext *ctx) FaceDupliData_Mesh fdd{}; fdd.params = fdd_params; fdd.totface = me_eval->totpoly; - fdd.polys = me_eval->polys().data(); - fdd.corner_verts = me_eval->corner_verts().data(); + fdd.polys = me_eval->polys(); + fdd.corner_verts = me_eval->corner_verts(); fdd.vert_positions = me_eval->vert_positions(); fdd.mloopuv = (uv_idx != -1) ? (const float2 *)CustomData_get_layer_n( &me_eval->ldata, CD_PROP_FLOAT2, uv_idx) : diff --git a/source/blender/blenkernel/intern/paint.cc b/source/blender/blenkernel/intern/paint.cc index 44484493867..abfbb020b6c 100644 --- a/source/blender/blenkernel/intern/paint.cc +++ b/source/blender/blenkernel/intern/paint.cc @@ -1763,13 +1763,8 @@ static void sculpt_update_object( sculpt_update_persistent_base(ob); if (need_pmap && ob->type == OB_MESH && !ss->pmap) { - BKE_mesh_vert_poly_map_create(&ss->pmap, - &ss->pmap_mem, - me->polys().data(), - me->corner_verts().data(), - me->totvert, - me->totpoly, - me->totloop); + BKE_mesh_vert_poly_map_create( + &ss->pmap, &ss->pmap_mem, me->polys(), me->corner_verts().data(), me->totvert); if (ss->pbvh) { BKE_pbvh_pmap_set(ss->pbvh, ss->pmap); @@ -1992,7 +1987,7 @@ int BKE_sculpt_mask_layers_ensure(Depsgraph *depsgraph, MultiresModifierData *mmd) { Mesh *me = static_cast(ob->data); - const Span polys = me->polys(); + const blender::OffsetIndices polys = me->polys(); const Span corner_verts = me->corner_verts(); int ret = 0; @@ -2021,17 +2016,17 @@ int BKE_sculpt_mask_layers_ensure(Depsgraph *depsgraph, /* If vertices already have mask, copy into multires data. */ if (paint_mask) { for (const int i : polys.index_range()) { - const MPoly &poly = polys[i]; + const blender::IndexRange poly = polys[i]; /* Mask center. */ float avg = 0.0f; - for (const int vert : corner_verts.slice(poly.loopstart, poly.totloop)) { + for (const int vert : corner_verts.slice(poly)) { avg += paint_mask[vert]; } - avg /= float(poly.totloop); + avg /= float(poly.size()); /* Fill in multires mask corner. */ - for (const int corner : blender::IndexRange(poly.loopstart, poly.totloop)) { + for (const int corner : poly) { GridPaintMask *gpm = &gmask[corner]; const int vert = corner_verts[corner]; const int prev = corner_verts[blender::bke::mesh::poly_corner_prev(poly, vert)]; @@ -2187,7 +2182,7 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform, bool BKE_pbvh_respect_hide_set(pbvh, respect_hide); MutableSpan positions = me->vert_positions_for_write(); - const Span polys = me->polys(); + const blender::OffsetIndices polys = me->polys(); const Span corner_verts = me->corner_verts(); MLoopTri *looptri = static_cast( @@ -2197,7 +2192,7 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform, bool BKE_pbvh_build_mesh(pbvh, me, - polys.data(), + polys, corner_verts.data(), reinterpret_cast(positions.data()), me->totvert, diff --git a/source/blender/blenkernel/intern/pbvh.cc b/source/blender/blenkernel/intern/pbvh.cc index 86a19b30c88..a5d5a16cfc2 100644 --- a/source/blender/blenkernel/intern/pbvh.cc +++ b/source/blender/blenkernel/intern/pbvh.cc @@ -825,7 +825,7 @@ static void pbvh_validate_node_prims(PBVH *pbvh) void BKE_pbvh_build_mesh(PBVH *pbvh, Mesh *mesh, - const MPoly *polys, + const blender::OffsetIndices polys, const int *corner_verts, float (*vert_positions)[3], int totvert, @@ -941,9 +941,9 @@ void BKE_pbvh_build_grids(PBVH *pbvh, /* Find maximum number of grids per face. */ int max_grids = 1; - const blender::Span polys = me->polys(); + const blender::OffsetIndices polys = me->polys(); for (const int i : polys.index_range()) { - max_grids = max_ii(max_grids, polys[i].totloop); + max_grids = max_ii(max_grids, polys[i].size()); } /* Ensure leaf limit is at least 4 so there's room @@ -957,7 +957,7 @@ void BKE_pbvh_build_grids(PBVH *pbvh, pbvh->ldata = &me->ldata; pbvh->pdata = &me->pdata; - pbvh->polys = me->polys().data(); + pbvh->polys = polys; pbvh->corner_verts = me->corner_verts().data(); /* We also need the base mesh for PBVH draw. */ @@ -1002,7 +1002,7 @@ void BKE_pbvh_build_grids(PBVH *pbvh, PBVH *BKE_pbvh_new(PBVHType type) { - PBVH *pbvh = MEM_cnew(__func__); + PBVH *pbvh = MEM_new(__func__); pbvh->respect_hide = true; pbvh->draw_cache_invalid = true; pbvh->header.type = type; @@ -1429,10 +1429,10 @@ static void pbvh_update_normals_accum_task_cb(void *__restrict userdata, /* Face normal and mask */ if (lt->poly != mpoly_prev) { - const MPoly &poly = pbvh->polys[lt->poly]; + const blender::IndexRange poly = pbvh->polys[lt->poly]; fn = blender::bke::mesh::poly_normal_calc( {reinterpret_cast(pbvh->vert_positions), pbvh->totvert}, - {&pbvh->corner_verts[poly.loopstart], poly.totloop}); + {&pbvh->corner_verts[poly.start()], poly.size()}); mpoly_prev = lt->poly; } @@ -3730,7 +3730,8 @@ static void pbvh_face_iter_step(PBVHFaceIter *fd, bool do_step) } fd->last_face_index_ = face_index; - const MPoly &poly = fd->polys_[face_index]; + const int poly_start = fd->poly_offsets_[face_index]; + const int poly_size = fd->poly_offsets_[face_index + 1] - poly_start; fd->face.i = fd->index = face_index; @@ -3741,15 +3742,15 @@ static void pbvh_face_iter_step(PBVHFaceIter *fd, bool do_step) fd->hide = fd->hide_poly_ + face_index; } - pbvh_face_iter_verts_reserve(fd, poly.totloop); + pbvh_face_iter_verts_reserve(fd, poly_size); - const int *poly_verts = &fd->corner_verts_[poly.loopstart]; + const int *poly_verts = &fd->corner_verts_[poly_start]; const int grid_area = fd->subdiv_key_.grid_area; - for (int i = 0; i < poly.totloop; i++) { + for (int i = 0; i < poly_size; i++) { if (fd->pbvh_type_ == PBVH_GRIDS) { /* Grid corners. */ - fd->verts[i].i = (poly.loopstart + i) * grid_area + grid_area - 1; + fd->verts[i].i = (poly_start + i) * grid_area + grid_area - 1; } else { fd->verts[i].i = poly_verts[i]; @@ -3780,7 +3781,7 @@ void BKE_pbvh_face_iter_init(PBVH *pbvh, PBVHNode *node, PBVHFaceIter *fd) fd->subdiv_key_ = pbvh->gridkey; ATTR_FALLTHROUGH; case PBVH_FACES: - fd->polys_ = pbvh->polys; + fd->poly_offsets_ = pbvh->polys.data(); fd->corner_verts_ = pbvh->corner_verts; fd->looptri_ = pbvh->looptri; fd->hide_poly_ = pbvh->hide_poly; @@ -3862,7 +3863,7 @@ void BKE_pbvh_sync_visibility_from_verts(PBVH *pbvh, Mesh *mesh) break; } case PBVH_GRIDS: { - const blender::Span polys = mesh->polys(); + const blender::OffsetIndices polys = mesh->polys(); CCGKey key = pbvh->gridkey; bool *hide_poly = static_cast(CustomData_get_layer_named_for_write( @@ -3870,10 +3871,11 @@ void BKE_pbvh_sync_visibility_from_verts(PBVH *pbvh, Mesh *mesh) bool delete_hide_poly = true; for (const int face_index : polys.index_range()) { + const blender::IndexRange poly = polys[face_index]; bool hidden = false; - for (int loop_index = 0; !hidden && loop_index < polys[face_index].totloop; loop_index++) { - int grid_index = polys[face_index].loopstart + loop_index; + for (int loop_index = 0; !hidden && loop_index < poly.size(); loop_index++) { + int grid_index = poly[loop_index]; if (pbvh->grid_hidden[grid_index] && BLI_BITMAP_TEST(pbvh->grid_hidden[grid_index], key.grid_area - 1)) { diff --git a/source/blender/blenkernel/intern/pbvh_colors.cc b/source/blender/blenkernel/intern/pbvh_colors.cc index 507d3ed9315..8ac45e9863f 100644 --- a/source/blender/blenkernel/intern/pbvh_colors.cc +++ b/source/blender/blenkernel/intern/pbvh_colors.cc @@ -94,12 +94,11 @@ static void pbvh_vertex_color_get(const PBVH &pbvh, PBVHVertRef vertex, float r_ int count = 0; zero_v4(r_color); for (const int i_poly : Span(melem.indices, melem.count)) { - const MPoly &poly = pbvh.polys[i_poly]; - Span colors{static_cast(pbvh.color_layer->data) + poly.loopstart, - poly.totloop}; - Span poly_verts{pbvh.corner_verts + poly.loopstart, poly.totloop}; + const IndexRange poly = pbvh.polys[i_poly]; + Span colors{static_cast(pbvh.color_layer->data) + poly.start(), poly.size()}; + Span poly_verts{pbvh.corner_verts + poly.start(), poly.size()}; - for (const int i : poly_verts.index_range()) { + for (const int i : IndexRange(poly.size())) { if (poly_verts[i] == index) { float temp[4]; to_float(colors[i], temp); @@ -128,12 +127,11 @@ static void pbvh_vertex_color_set(PBVH &pbvh, PBVHVertRef vertex, const float co const MeshElemMap &melem = pbvh.pmap[index]; for (const int i_poly : Span(melem.indices, melem.count)) { - const MPoly &poly = pbvh.polys[i_poly]; - MutableSpan colors{static_cast(pbvh.color_layer->data) + poly.loopstart, - poly.totloop}; - Span poly_verts{pbvh.corner_verts + poly.loopstart, poly.totloop}; + const IndexRange poly = pbvh.polys[i_poly]; + MutableSpan colors{static_cast(pbvh.color_layer->data) + poly.start(), poly.size()}; + Span poly_verts{pbvh.corner_verts + poly.start(), poly.size()}; - for (const int i : poly_verts.index_range()) { + for (const int i : IndexRange(poly.size())) { if (poly_verts[i] == index) { from_float(color, colors[i]); } diff --git a/source/blender/blenkernel/intern/pbvh_intern.hh b/source/blender/blenkernel/intern/pbvh_intern.hh index 0936c333c48..3a4d73d3712 100644 --- a/source/blender/blenkernel/intern/pbvh_intern.hh +++ b/source/blender/blenkernel/intern/pbvh_intern.hh @@ -8,7 +8,6 @@ struct PBVHGPUFormat; struct MLoopTri; -struct MPoly; struct MeshElemMap; /* Axis-aligned bounding box */ @@ -156,7 +155,7 @@ struct PBVH { float (*vert_normals)[3]; bool *hide_vert; float (*vert_positions)[3]; - const MPoly *polys; + blender::OffsetIndices polys; bool *hide_poly; /** Material indices. Only valid for polygon meshes. */ const int *material_indices; diff --git a/source/blender/blenkernel/intern/shrinkwrap.cc b/source/blender/blenkernel/intern/shrinkwrap.cc index a1d8e0fd3d2..6c70e9250fc 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.cc +++ b/source/blender/blenkernel/intern/shrinkwrap.cc @@ -114,7 +114,7 @@ bool BKE_shrinkwrap_init_tree( } data->mesh = mesh; - data->polys = mesh->polys().data(); + data->poly_offsets = mesh->poly_offsets().data(); data->corner_edges = mesh->corner_edges().data(); data->vert_normals = reinterpret_cast(mesh->vert_normals().data()), data->sharp_faces = static_cast( diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index f6201eb8981..b2d04ad709e 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -566,11 +566,12 @@ static void ccd_update_deflector_hash(Depsgraph *depsgraph, static int count_mesh_quads(Mesh *me) { - int a, result = 0; - const MPoly *polys = BKE_mesh_polys(me); - if (polys) { - for (a = me->totpoly; a > 0; a--) { - if (polys[a].totloop == 4) { + int result = 0; + const int *poly_offsets = BKE_mesh_poly_offsets(me); + if (poly_offsets) { + for (int i = 0; i < me->totpoly; i++) { + const int poly_size = poly_offsets[i + 1] - poly_offsets[i]; + if (poly_size == 4) { result++; } } @@ -589,7 +590,7 @@ static void add_mesh_quad_diag_springs(Object *ob) nofquads = count_mesh_quads(me); if (nofquads) { const int *corner_verts = BKE_mesh_corner_verts(me); - const MPoly *polys = BKE_mesh_polys(me); + const int *poly_offsets = BKE_mesh_poly_offsets(me); BodySpring *bs; /* resize spring-array to hold additional quad springs */ @@ -600,14 +601,14 @@ static void add_mesh_quad_diag_springs(Object *ob) bs = &ob->soft->bspring[ob->soft->totspring]; // bp = ob->soft->bpoint; /* UNUSED */ for (int a = 0; a < me->totpoly; a++) { - const MPoly *poly = &polys[a]; - if (poly->totloop == 4) { - bs->v1 = corner_verts[poly->loopstart + 0]; - bs->v2 = corner_verts[poly->loopstart + 2]; + const int poly_size = poly_offsets[a + 1] - poly_offsets[a]; + if (poly_size == 4) { + bs->v1 = corner_verts[poly_offsets[a] + 0]; + bs->v2 = corner_verts[poly_offsets[a] + 2]; bs->springtype = SB_STIFFQUAD; bs++; - bs->v1 = corner_verts[poly->loopstart + 1]; - bs->v2 = corner_verts[poly->loopstart + 3]; + bs->v1 = corner_verts[poly_offsets[a] + 1]; + bs->v2 = corner_verts[poly_offsets[a] + 3]; bs->springtype = SB_STIFFQUAD; bs++; } @@ -2752,7 +2753,7 @@ static void mesh_faces_to_scratch(Object *ob) BodyFace *bodyface; int a; const float(*vert_positions)[3] = BKE_mesh_vert_positions(me); - const MPoly *polys = BKE_mesh_polys(me); + const int *poly_offsets = BKE_mesh_poly_offsets(me); const int *corner_verts = BKE_mesh_corner_verts(me); /* Allocate and copy faces. */ @@ -2760,7 +2761,7 @@ static void mesh_faces_to_scratch(Object *ob) sb->scratch->totface = poly_to_tri_count(me->totpoly, me->totloop); looptri = lt = MEM_mallocN(sizeof(*looptri) * sb->scratch->totface, __func__); BKE_mesh_recalc_looptri( - corner_verts, polys, vert_positions, me->totvert, me->totloop, me->totpoly, looptri); + corner_verts, poly_offsets, vert_positions, me->totvert, me->totloop, me->totpoly, looptri); bodyface = sb->scratch->bodyface = MEM_mallocN(sizeof(BodyFace) * sb->scratch->totface, "SB_body_Faces"); diff --git a/source/blender/blenkernel/intern/subdiv_ccg.cc b/source/blender/blenkernel/intern/subdiv_ccg.cc index 6ddc9356637..2f3a42c7590 100644 --- a/source/blender/blenkernel/intern/subdiv_ccg.cc +++ b/source/blender/blenkernel/intern/subdiv_ccg.cc @@ -1987,13 +1987,13 @@ const int *BKE_subdiv_ccg_start_face_grid_index_get(const SubdivCCG *subdiv_ccg) static void adjacet_vertices_index_from_adjacent_edge(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord, const blender::Span corner_verts, - const MPoly *polys, + const blender::OffsetIndices polys, int *r_v1, int *r_v2) { const int grid_size_1 = subdiv_ccg->grid_size - 1; const int poly_index = BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, coord->grid_index); - const MPoly &poly = polys[poly_index]; + const blender::IndexRange poly = polys[poly_index]; *r_v1 = corner_verts[coord->grid_index]; const int corner = blender::bke::mesh::poly_find_corner_from_vert(poly, corner_verts, *r_v1); @@ -2007,13 +2007,13 @@ static void adjacet_vertices_index_from_adjacent_edge(const SubdivCCG *subdiv_cc } } -SubdivCCGAdjacencyType BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(const SubdivCCG *subdiv_ccg, - const SubdivCCGCoord *coord, - const int *corner_verts, - const int corners_num, - const MPoly *polys, - int *r_v1, - int *r_v2) +SubdivCCGAdjacencyType BKE_subdiv_ccg_coarse_mesh_adjacency_info_get( + const SubdivCCG *subdiv_ccg, + const SubdivCCGCoord *coord, + const blender::Span corner_verts, + const blender::OffsetIndices polys, + int *r_v1, + int *r_v2) { const int grid_size_1 = subdiv_ccg->grid_size - 1; @@ -2028,8 +2028,7 @@ SubdivCCGAdjacencyType BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(const Subdi return SUBDIV_CCG_ADJACENT_VERTEX; } /* Grid corner adjacent to the middle of a coarse mesh edge. */ - adjacet_vertices_index_from_adjacent_edge( - subdiv_ccg, coord, {corner_verts, corners_num}, polys, r_v1, r_v2); + adjacet_vertices_index_from_adjacent_edge(subdiv_ccg, coord, corner_verts, polys, r_v1, r_v2); return SUBDIV_CCG_ADJACENT_EDGE; } @@ -2037,7 +2036,7 @@ SubdivCCGAdjacencyType BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(const Subdi if (!is_inner_edge_grid_coordinate(subdiv_ccg, coord)) { /* Grid boundary adjacent to a coarse mesh edge. */ adjacet_vertices_index_from_adjacent_edge( - subdiv_ccg, coord, {corner_verts, corners_num}, polys, r_v1, r_v2); + subdiv_ccg, coord, corner_verts, polys, r_v1, r_v2); return SUBDIV_CCG_ADJACENT_EDGE; } } diff --git a/source/blender/blenkernel/intern/subdiv_ccg_mask.cc b/source/blender/blenkernel/intern/subdiv_ccg_mask.cc index 8ef99bb7341..070a3bccf43 100644 --- a/source/blender/blenkernel/intern/subdiv_ccg_mask.cc +++ b/source/blender/blenkernel/intern/subdiv_ccg_mask.cc @@ -29,7 +29,7 @@ struct PolyCornerIndex { struct GridPaintMaskData { // int grid_size; - blender::Span polys; + blender::OffsetIndices polys; const GridPaintMask *grid_paint_mask; /* Indexed by ptex face index, contains polygon/corner which corresponds * to it. @@ -50,10 +50,10 @@ static int mask_get_grid_and_coord(SubdivCCGMaskEvaluator *mask_evaluator, { GridPaintMaskData *data = static_cast(mask_evaluator->user_data); const PolyCornerIndex *poly_corner = &data->ptex_poly_corner[ptex_face_index]; - const MPoly &poly = data->polys[poly_corner->poly_index]; - const int start_grid_index = poly.loopstart + poly_corner->corner; + const blender::IndexRange poly = data->polys[poly_corner->poly_index]; + const int start_grid_index = poly.start() + poly_corner->corner; int corner = 0; - if (poly.totloop == 4) { + if (poly.size() == 4) { float corner_u, corner_v; corner = BKE_subdiv_rotate_quad_to_corner(u, v, &corner_u, &corner_v); *r_mask_grid = &data->grid_paint_mask[start_grid_index + corner]; @@ -103,10 +103,9 @@ static void free_mask_data(SubdivCCGMaskEvaluator *mask_evaluator) static int count_num_ptex_faces(const Mesh *mesh) { int num_ptex_faces = 0; - const blender::Span polys = mesh->polys(); - for (int poly_index = 0; poly_index < mesh->totpoly; poly_index++) { - const MPoly &poly = polys[poly_index]; - num_ptex_faces += (poly.totloop == 4) ? 1 : poly.totloop; + const blender::OffsetIndices polys = mesh->polys(); + for (const int poly_index : polys.index_range()) { + num_ptex_faces += (polys[poly_index].size() == 4) ? 1 : polys[poly_index].size(); } return num_ptex_faces; } @@ -114,7 +113,7 @@ static int count_num_ptex_faces(const Mesh *mesh) static void mask_data_init_mapping(SubdivCCGMaskEvaluator *mask_evaluator, const Mesh *mesh) { GridPaintMaskData *data = static_cast(mask_evaluator->user_data); - const blender::Span polys = mesh->polys(); + const blender::OffsetIndices polys = mesh->polys(); const int num_ptex_faces = count_num_ptex_faces(mesh); /* Allocate memory. */ data->ptex_poly_corner = static_cast( @@ -122,15 +121,15 @@ static void mask_data_init_mapping(SubdivCCGMaskEvaluator *mask_evaluator, const /* Fill in offsets. */ int ptex_face_index = 0; PolyCornerIndex *ptex_poly_corner = data->ptex_poly_corner; - for (int poly_index = 0; poly_index < mesh->totpoly; poly_index++) { - const MPoly &poly = polys[poly_index]; - if (poly.totloop == 4) { + for (const int poly_index : polys.index_range()) { + const blender::IndexRange poly = polys[poly_index]; + if (poly.size() == 4) { ptex_poly_corner[ptex_face_index].poly_index = poly_index; ptex_poly_corner[ptex_face_index].corner = 0; ptex_face_index++; } else { - for (int corner = 0; corner < poly.totloop; corner++) { + for (int corner = 0; corner < poly.size(); corner++) { ptex_poly_corner[ptex_face_index].poly_index = poly_index; ptex_poly_corner[ptex_face_index].corner = corner; ptex_face_index++; @@ -160,7 +159,7 @@ bool BKE_subdiv_ccg_mask_init_from_paint(SubdivCCGMaskEvaluator *mask_evaluator, return false; } /* Allocate all required memory. */ - mask_evaluator->user_data = MEM_callocN(sizeof(GridPaintMaskData), "mask from grid data"); + mask_evaluator->user_data = MEM_new("mask from grid data"); mask_init_data(mask_evaluator, mesh); mask_init_functions(mask_evaluator); return true; diff --git a/source/blender/blenkernel/intern/subdiv_converter_mesh.cc b/source/blender/blenkernel/intern/subdiv_converter_mesh.cc index 6a4fe8d5a5b..bf80ce407f6 100644 --- a/source/blender/blenkernel/intern/subdiv_converter_mesh.cc +++ b/source/blender/blenkernel/intern/subdiv_converter_mesh.cc @@ -36,7 +36,7 @@ struct ConverterStorage { const Mesh *mesh; const float (*vert_positions)[3]; blender::Span edges; - blender::Span polys; + blender::OffsetIndices polys; blender::Span corner_verts; blender::Span corner_edges; @@ -127,7 +127,7 @@ static int get_num_vertices(const OpenSubdiv_Converter *converter) static int get_num_face_vertices(const OpenSubdiv_Converter *converter, int manifold_face_index) { ConverterStorage *storage = static_cast(converter->user_data); - return storage->polys[manifold_face_index].totloop; + return storage->polys[manifold_face_index].size(); } static void get_face_vertices(const OpenSubdiv_Converter *converter, @@ -135,9 +135,9 @@ static void get_face_vertices(const OpenSubdiv_Converter *converter, int *manifold_face_vertices) { ConverterStorage *storage = static_cast(converter->user_data); - const MPoly &poly = storage->polys[manifold_face_index]; - for (int i = 0; i < poly.totloop; i++) { - const int vert = storage->corner_verts[poly.loopstart + i]; + const blender::IndexRange poly = storage->polys[manifold_face_index]; + for (int i = 0; i < poly.size(); i++) { + const int vert = storage->corner_verts[poly[i]]; manifold_face_vertices[i] = storage->manifold_vertex_index[vert]; } } @@ -204,7 +204,6 @@ static void precalc_uv_layer(const OpenSubdiv_Converter *converter, const int la const Mesh *mesh = storage->mesh; const float(*mloopuv)[2] = static_cast( CustomData_get_layer_n(&mesh->ldata, CD_PROP_FLOAT2, layer_index)); - const int num_poly = mesh->totpoly; const int num_vert = mesh->totvert; const float limit[2] = {STD_UV_CONNECT_LIMIT, STD_UV_CONNECT_LIMIT}; /* Initialize memory required for the operations. */ @@ -213,12 +212,11 @@ static void precalc_uv_layer(const OpenSubdiv_Converter *converter, const int la MEM_malloc_arrayN(mesh->totloop, sizeof(int), "loop uv vertex index")); } UvVertMap *uv_vert_map = BKE_mesh_uv_vert_map_create( - storage->polys.data(), + storage->polys, (const bool *)CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, ".hide_poly"), (const bool *)CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, ".select_poly"), storage->corner_verts.data(), mloopuv, - num_poly, num_vert, limit, false, @@ -231,8 +229,8 @@ static void precalc_uv_layer(const OpenSubdiv_Converter *converter, const int la if (uv_vert->separate) { storage->num_uv_coordinates++; } - const MPoly &poly = storage->polys[uv_vert->poly_index]; - const int global_loop_index = poly.loopstart + uv_vert->loop_of_poly_index; + const blender::IndexRange poly = storage->polys[uv_vert->poly_index]; + const int global_loop_index = poly.start() + uv_vert->loop_of_poly_index; storage->loop_uv_indices[global_loop_index] = storage->num_uv_coordinates; uv_vert = uv_vert->next; } @@ -257,8 +255,8 @@ static int get_face_corner_uv_index(const OpenSubdiv_Converter *converter, const int corner) { ConverterStorage *storage = static_cast(converter->user_data); - const MPoly &poly = storage->polys[face_index]; - return storage->loop_uv_indices[poly.loopstart + corner]; + const blender::IndexRange poly = storage->polys[face_index]; + return storage->loop_uv_indices[poly.start() + corner]; } static void free_user_data(const OpenSubdiv_Converter *converter) @@ -353,16 +351,14 @@ static void initialize_manifold_indices(ConverterStorage *storage) { const Mesh *mesh = storage->mesh; const blender::Span edges = storage->edges; - const blender::Span polys = storage->polys; + const blender::OffsetIndices polys = storage->polys; const blender::Span corner_verts = storage->corner_verts; const blender::Span corner_edges = storage->corner_edges; /* Set bits of elements which are not loose. */ BLI_bitmap *vert_used_map = BLI_BITMAP_NEW(mesh->totvert, "vert used map"); BLI_bitmap *edge_used_map = BLI_BITMAP_NEW(mesh->totedge, "edge used map"); for (int poly_index = 0; poly_index < mesh->totpoly; poly_index++) { - const MPoly &poly = polys[poly_index]; - for (int i = 0; i < poly.totloop; i++) { - const int corner = poly.loopstart + i; + for (const int corner : polys[poly_index]) { BLI_BITMAP_ENABLE(vert_used_map, corner_verts[corner]); BLI_BITMAP_ENABLE(edge_used_map, corner_edges[corner]); } @@ -395,8 +391,7 @@ static void init_user_data(OpenSubdiv_Converter *converter, const SubdivSettings *settings, const Mesh *mesh) { - ConverterStorage *user_data = static_cast( - MEM_mallocN(sizeof(ConverterStorage), __func__)); + ConverterStorage *user_data = MEM_new(__func__); user_data->settings = *settings; user_data->mesh = mesh; user_data->vert_positions = BKE_mesh_vert_positions(mesh); diff --git a/source/blender/blenkernel/intern/subdiv_displacement_multires.cc b/source/blender/blenkernel/intern/subdiv_displacement_multires.cc index 66297ef7afb..4868ed74fe0 100644 --- a/source/blender/blenkernel/intern/subdiv_displacement_multires.cc +++ b/source/blender/blenkernel/intern/subdiv_displacement_multires.cc @@ -35,7 +35,7 @@ struct MultiresDisplacementData { /* Mesh is used to read external displacement. */ Mesh *mesh; const MultiresModifierData *mmd; - blender::Span polys; + blender::OffsetIndices polys; const MDisps *mdisps; /* Indexed by ptex face index, contains polygon/corner which corresponds * to it. @@ -71,10 +71,10 @@ static int displacement_get_grid_and_coord(SubdivDisplacement *displacement, MultiresDisplacementData *data = static_cast( displacement->user_data); const PolyCornerIndex *poly_corner = &data->ptex_poly_corner[ptex_face_index]; - const MPoly &poly = data->polys[poly_corner->poly_index]; - const int start_grid_index = poly.loopstart + poly_corner->corner; + const blender::IndexRange poly = data->polys[poly_corner->poly_index]; + const int start_grid_index = poly.start() + poly_corner->corner; int corner = 0; - if (poly.totloop == 4) { + if (poly.size() == 4) { float corner_u, corner_v; corner = BKE_subdiv_rotate_quad_to_corner(u, v, &corner_u, &corner_v); *r_displacement_grid = &data->mdisps[start_grid_index + corner]; @@ -95,10 +95,10 @@ static const MDisps *displacement_get_other_grid(SubdivDisplacement *displacemen MultiresDisplacementData *data = static_cast( displacement->user_data); const PolyCornerIndex *poly_corner = &data->ptex_poly_corner[ptex_face_index]; - const MPoly &poly = data->polys[poly_corner->poly_index]; - const int effective_corner = (poly.totloop == 4) ? corner : poly_corner->corner; - const int next_corner = (effective_corner + corner_delta + poly.totloop) % poly.totloop; - return &data->mdisps[poly.loopstart + next_corner]; + const blender::IndexRange poly = data->polys[poly_corner->poly_index]; + const int effective_corner = (poly.size() == 4) ? corner : poly_corner->corner; + const int next_corner = (effective_corner + corner_delta + poly.size()) % poly.size(); + return &data->mdisps[poly[next_corner]]; } BLI_INLINE eAverageWith read_displacement_grid(const MDisps *displacement_grid, @@ -126,14 +126,14 @@ BLI_INLINE eAverageWith read_displacement_grid(const MDisps *displacement_grid, return AVERAGE_WITH_NONE; } -static void average_convert_grid_coord_to_ptex(const MPoly &poly, +static void average_convert_grid_coord_to_ptex(const int num_corners, const int corner, const float grid_u, const float grid_v, float *r_ptex_face_u, float *r_ptex_face_v) { - if (poly.totloop == 4) { + if (num_corners == 4) { BKE_subdiv_rotate_grid_to_quad(corner, grid_u, grid_v, r_ptex_face_u, r_ptex_face_v); } else { @@ -142,14 +142,14 @@ static void average_convert_grid_coord_to_ptex(const MPoly &poly, } static void average_construct_tangent_matrix(Subdiv *subdiv, - const MPoly &poly, + const int num_corners, const int ptex_face_index, const int corner, const float u, const float v, float r_tangent_matrix[3][3]) { - const bool is_quad = (poly.totloop == 4); + const bool is_quad = num_corners == 4; const int quad_corner = is_quad ? corner : 0; float dummy_P[3], dPdu[3], dPdv[3]; BKE_subdiv_eval_limit_point_and_derivatives(subdiv, ptex_face_index, u, v, dummy_P, dPdu, dPdv); @@ -174,16 +174,16 @@ static void average_read_displacement_object(MultiresDisplacementData *data, float r_D[3]) { const PolyCornerIndex *poly_corner = &data->ptex_poly_corner[ptex_face_index]; - const MPoly &poly = data->polys[poly_corner->poly_index]; + const int num_corners = data->polys[poly_corner->poly_index].size(); /* Get (u, v) coordinate within the other ptex face which corresponds to * the grid coordinates. */ float u, v; - average_convert_grid_coord_to_ptex(poly, corner_index, grid_u, grid_v, &u, &v); + average_convert_grid_coord_to_ptex(num_corners, corner_index, grid_u, grid_v, &u, &v); /* Construct tangent matrix which corresponds to partial derivatives * calculated for the other ptex face. */ float tangent_matrix[3][3]; average_construct_tangent_matrix( - data->subdiv, poly, ptex_face_index, corner_index, u, v, tangent_matrix); + data->subdiv, num_corners, ptex_face_index, corner_index, u, v, tangent_matrix); /* Read displacement from other grid in a tangent space. */ float tangent_D[3]; average_read_displacement_tangent(data, displacement_grid, grid_u, grid_v, tangent_D); @@ -199,10 +199,10 @@ static void average_get_other_ptex_and_corner(MultiresDisplacementData *data, int *r_other_corner_index) { const PolyCornerIndex *poly_corner = &data->ptex_poly_corner[ptex_face_index]; - const MPoly &poly = data->polys[poly_corner->poly_index]; - const int num_corners = poly.totloop; + const int poly_index = poly_corner->poly_index; + const int num_corners = data->polys[poly_corner->poly_index].size(); const bool is_quad = (num_corners == 4); - const int start_ptex_face_index = data->face_ptex_offset[poly_corner->poly_index]; + const int start_ptex_face_index = data->face_ptex_offset[poly_index]; *r_other_corner_index = (corner + corner_delta + num_corners) % num_corners; *r_other_ptex_face_index = is_quad ? start_ptex_face_index : start_ptex_face_index + *r_other_corner_index; @@ -248,8 +248,7 @@ static void average_with_all(SubdivDisplacement *displacement, MultiresDisplacementData *data = static_cast( displacement->user_data); const PolyCornerIndex *poly_corner = &data->ptex_poly_corner[ptex_face_index]; - const MPoly &poly = data->polys[poly_corner->poly_index]; - const int num_corners = poly.totloop; + const int num_corners = data->polys[poly_corner->poly_index].size(); for (int corner_delta = 1; corner_delta < num_corners; corner_delta++) { average_with_other(displacement, ptex_face_index, corner, 0.0f, 0.0f, corner_delta, r_D); } @@ -304,8 +303,7 @@ static int displacement_get_face_corner(MultiresDisplacementData *data, const float v) { const PolyCornerIndex *poly_corner = &data->ptex_poly_corner[ptex_face_index]; - const MPoly &poly = data->polys[poly_corner->poly_index]; - const int num_corners = poly.totloop; + const int num_corners = data->polys[poly_corner->poly_index].size(); const bool is_quad = (num_corners == 4); if (is_quad) { float dummy_corner_u, dummy_corner_v; @@ -367,10 +365,9 @@ static void free_displacement(SubdivDisplacement *displacement) static int count_num_ptex_faces(const Mesh *mesh) { int num_ptex_faces = 0; - const blender::Span polys = mesh->polys(); + const blender::OffsetIndices polys = mesh->polys(); for (int poly_index = 0; poly_index < mesh->totpoly; poly_index++) { - const MPoly &poly = polys[poly_index]; - num_ptex_faces += (poly.totloop == 4) ? 1 : poly.totloop; + num_ptex_faces += (polys[poly_index].size() == 4) ? 1 : polys[poly_index].size(); } return num_ptex_faces; } @@ -379,7 +376,7 @@ static void displacement_data_init_mapping(SubdivDisplacement *displacement, con { MultiresDisplacementData *data = static_cast( displacement->user_data); - const blender::Span polys = mesh->polys(); + const blender::OffsetIndices polys = mesh->polys(); const int num_ptex_faces = count_num_ptex_faces(mesh); /* Allocate memory. */ data->ptex_poly_corner = static_cast( @@ -388,14 +385,14 @@ static void displacement_data_init_mapping(SubdivDisplacement *displacement, con int ptex_face_index = 0; PolyCornerIndex *ptex_poly_corner = data->ptex_poly_corner; for (int poly_index = 0; poly_index < mesh->totpoly; poly_index++) { - const MPoly &poly = polys[poly_index]; - if (poly.totloop == 4) { + const blender::IndexRange poly = polys[poly_index]; + if (poly.size() == 4) { ptex_poly_corner[ptex_face_index].poly_index = poly_index; ptex_poly_corner[ptex_face_index].corner = 0; ptex_face_index++; } else { - for (int corner = 0; corner < poly.totloop; corner++) { + for (int corner = 0; corner < poly.size(); corner++) { ptex_poly_corner[ptex_face_index].poly_index = poly_index; ptex_poly_corner[ptex_face_index].corner = corner; ptex_face_index++; diff --git a/source/blender/blenkernel/intern/subdiv_eval.cc b/source/blender/blenkernel/intern/subdiv_eval.cc index f92ff5924cf..07256229491 100644 --- a/source/blender/blenkernel/intern/subdiv_eval.cc +++ b/source/blender/blenkernel/intern/subdiv_eval.cc @@ -82,17 +82,16 @@ static void set_coarse_positions(Subdiv *subdiv, const float (*coarse_vertex_cos)[3]) { const float(*positions)[3] = BKE_mesh_vert_positions(mesh); - const blender::Span polys = mesh->polys(); + const blender::OffsetIndices polys = mesh->polys(); const blender::Span corner_verts = mesh->corner_verts(); /* Mark vertices which needs new coordinates. */ /* TODO(sergey): This is annoying to calculate this on every update, * maybe it's better to cache this mapping. Or make it possible to have * OpenSubdiv's vertices match mesh ones? */ BLI_bitmap *vertex_used_map = BLI_BITMAP_NEW(mesh->totvert, "vert used map"); - for (int poly_index = 0; poly_index < mesh->totpoly; poly_index++) { - const MPoly &poly = polys[poly_index]; - for (int i = 0; i < poly.totloop; i++) { - BLI_BITMAP_ENABLE(vertex_used_map, corner_verts[poly.loopstart + i]); + for (const int i : polys.index_range()) { + for (const int vert : corner_verts.slice(polys[i])) { + BLI_BITMAP_ENABLE(vertex_used_map, vert); } } /* Use a temporary buffer so we do not upload vertices one at a time to the GPU. */ @@ -125,7 +124,7 @@ static void set_coarse_positions(Subdiv *subdiv, struct FaceVaryingDataFromUVContext { OpenSubdiv_TopologyRefiner *topology_refiner; const Mesh *mesh; - blender::Span polys; + blender::OffsetIndices polys; const float (*mloopuv)[2]; float (*buffer)[2]; int layer_index; @@ -138,8 +137,7 @@ static void set_face_varying_data_from_uv_task(void *__restrict userdata, FaceVaryingDataFromUVContext *ctx = static_cast(userdata); OpenSubdiv_TopologyRefiner *topology_refiner = ctx->topology_refiner; const int layer_index = ctx->layer_index; - const MPoly &poly = ctx->polys[face_index]; - const float(*mluv)[2] = &ctx->mloopuv[poly.loopstart]; + const float(*mluv)[2] = &ctx->mloopuv[ctx->polys[face_index].start()]; /* TODO(sergey): OpenSubdiv's C-API converter can change winding of * loops of a face, need to watch for that, to prevent wrong UVs assigned. diff --git a/source/blender/blenkernel/intern/subdiv_foreach.cc b/source/blender/blenkernel/intern/subdiv_foreach.cc index 34892511154..4c84990721c 100644 --- a/source/blender/blenkernel/intern/subdiv_foreach.cc +++ b/source/blender/blenkernel/intern/subdiv_foreach.cc @@ -24,14 +24,16 @@ #include "MEM_guardedalloc.h" +using blender::IndexRange; + /* -------------------------------------------------------------------- */ /** \name General helpers * \{ */ /* Number of ptex faces for a given polygon. */ -BLI_INLINE int num_ptex_faces_per_poly_get(const MPoly &poly) +BLI_INLINE int num_ptex_faces_per_poly_get(const IndexRange poly) { - return (poly.totloop == 4) ? 1 : poly.totloop; + return (poly.size() == 4) ? 1 : poly.size(); } BLI_INLINE int num_edges_per_ptex_face_get(const int resolution) @@ -54,9 +56,9 @@ BLI_INLINE int num_polys_per_ptex_get(const int resolution) } /* Subdivision resolution per given polygon's ptex faces. */ -BLI_INLINE int ptex_face_resolution_get(const MPoly &poly, int resolution) +BLI_INLINE int ptex_face_resolution_get(const IndexRange poly, int resolution) { - return (poly.totloop == 4) ? (resolution) : ((resolution >> 1) + 1); + return (poly.size() == 4) ? (resolution) : ((resolution >> 1) + 1); } /** \} */ @@ -68,7 +70,7 @@ BLI_INLINE int ptex_face_resolution_get(const MPoly &poly, int resolution) struct SubdivForeachTaskContext { const Mesh *coarse_mesh; blender::Span coarse_edges; - blender::Span coarse_polys; + blender::OffsetIndices coarse_polys; blender::Span coarse_corner_verts; blender::Span coarse_corner_edges; const SubdivToMeshSettings *settings; @@ -166,7 +168,7 @@ static void subdiv_foreach_ctx_count(SubdivForeachTaskContext *ctx) ctx->num_subdiv_edges = coarse_mesh->totedge * (num_subdiv_vertices_per_coarse_edge + 1); /* Calculate extra vertices and edges created by non-loose geometry. */ for (int poly_index = 0; poly_index < coarse_mesh->totpoly; poly_index++) { - const MPoly &coarse_poly = ctx->coarse_polys[poly_index]; + const IndexRange coarse_poly = ctx->coarse_polys[poly_index]; const int num_ptex_faces_per_poly = num_ptex_faces_per_poly_get(coarse_poly); /* Inner vertices of polygon. */ if (num_ptex_faces_per_poly == 1) { @@ -183,7 +185,7 @@ static void subdiv_foreach_ctx_count(SubdivForeachTaskContext *ctx) (no_quad_patch_resolution - 2) + num_subdiv_vertices_per_coarse_edge); if (no_quad_patch_resolution >= 3) { - ctx->num_subdiv_edges += coarse_poly.totloop; + ctx->num_subdiv_edges += coarse_poly.size(); } ctx->num_subdiv_polygons += num_ptex_faces_per_poly * num_polys_per_ptex_get(no_quad_patch_resolution); @@ -220,7 +222,7 @@ static void subdiv_foreach_ctx_init_offsets(SubdivForeachTaskContext *ctx) int edge_offset = 0; int polygon_offset = 0; for (int poly_index = 0; poly_index < coarse_mesh->totpoly; poly_index++) { - const MPoly &coarse_poly = ctx->coarse_polys[poly_index]; + const IndexRange coarse_poly = ctx->coarse_polys[poly_index]; const int num_ptex_faces_per_poly = num_ptex_faces_per_poly_get(coarse_poly); ctx->subdiv_vertex_offset[poly_index] = vertex_offset; ctx->subdiv_edge_offset[poly_index] = edge_offset; @@ -237,7 +239,7 @@ static void subdiv_foreach_ctx_init_offsets(SubdivForeachTaskContext *ctx) (num_inner_edges_per_ptex_face_get(no_quad_patch_resolution - 1) + (no_quad_patch_resolution - 2) + num_subdiv_vertices_per_coarse_edge); if (no_quad_patch_resolution >= 3) { - edge_offset += coarse_poly.totloop; + edge_offset += coarse_poly.size(); } polygon_offset += num_ptex_faces_per_poly * num_polys_per_ptex_get(no_quad_patch_resolution); } @@ -283,15 +285,15 @@ static void subdiv_foreach_ctx_free(SubdivForeachTaskContext *ctx) static void subdiv_foreach_corner_vertices_regular_do( SubdivForeachTaskContext *ctx, void *tls, - const MPoly *coarse_poly, + const int coarse_poly_index, SubdivForeachVertexFromCornerCb vertex_corner, bool check_usage) { const float weights[4][2] = {{0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}}; - const int coarse_poly_index = coarse_poly - ctx->coarse_polys.data(); + const IndexRange coarse_poly = ctx->coarse_polys[coarse_poly_index]; const int ptex_face_index = ctx->face_ptex_offset[coarse_poly_index]; - for (int corner = 0; corner < coarse_poly->totloop; corner++) { - const int coarse_vert = ctx->coarse_corner_verts[coarse_poly->loopstart + corner]; + for (int corner = 0; corner < coarse_poly.size(); corner++) { + const int coarse_vert = ctx->coarse_corner_verts[coarse_poly[corner]]; if (check_usage && BLI_BITMAP_TEST_AND_SET_ATOMIC(ctx->coarse_vertices_used_map, coarse_vert)) { continue; @@ -314,23 +316,23 @@ static void subdiv_foreach_corner_vertices_regular_do( static void subdiv_foreach_corner_vertices_regular(SubdivForeachTaskContext *ctx, void *tls, - const MPoly *coarse_poly) + const int coarse_poly_index) { subdiv_foreach_corner_vertices_regular_do( - ctx, tls, coarse_poly, ctx->foreach_context->vertex_corner, true); + ctx, tls, coarse_poly_index, ctx->foreach_context->vertex_corner, true); } static void subdiv_foreach_corner_vertices_special_do( SubdivForeachTaskContext *ctx, void *tls, - const MPoly *coarse_poly, + const int coarse_poly_index, SubdivForeachVertexFromCornerCb vertex_corner, bool check_usage) { - const int coarse_poly_index = coarse_poly - ctx->coarse_polys.data(); + const IndexRange coarse_poly = ctx->coarse_polys[coarse_poly_index]; int ptex_face_index = ctx->face_ptex_offset[coarse_poly_index]; - for (int corner = 0; corner < coarse_poly->totloop; corner++, ptex_face_index++) { - const int coarse_vert = ctx->coarse_corner_verts[coarse_poly->loopstart + corner]; + for (int corner = 0; corner < coarse_poly.size(); corner++, ptex_face_index++) { + const int coarse_vert = ctx->coarse_corner_verts[coarse_poly[corner]]; if (check_usage && BLI_BITMAP_TEST_AND_SET_ATOMIC(ctx->coarse_vertices_used_map, coarse_vert)) { continue; @@ -351,38 +353,38 @@ static void subdiv_foreach_corner_vertices_special_do( static void subdiv_foreach_corner_vertices_special(SubdivForeachTaskContext *ctx, void *tls, - const MPoly *coarse_poly) + const int coarse_poly_index) { subdiv_foreach_corner_vertices_special_do( - ctx, tls, coarse_poly, ctx->foreach_context->vertex_corner, true); + ctx, tls, coarse_poly_index, ctx->foreach_context->vertex_corner, true); } static void subdiv_foreach_corner_vertices(SubdivForeachTaskContext *ctx, void *tls, - const MPoly *coarse_poly) + const int coarse_poly_index) { - if (coarse_poly->totloop == 4) { - subdiv_foreach_corner_vertices_regular(ctx, tls, coarse_poly); + if (ctx->coarse_polys[coarse_poly_index].size() == 4) { + subdiv_foreach_corner_vertices_regular(ctx, tls, coarse_poly_index); } else { - subdiv_foreach_corner_vertices_special(ctx, tls, coarse_poly); + subdiv_foreach_corner_vertices_special(ctx, tls, coarse_poly_index); } } static void subdiv_foreach_every_corner_vertices_regular(SubdivForeachTaskContext *ctx, void *tls, - const MPoly *coarse_poly) + const int coarse_poly_index) { subdiv_foreach_corner_vertices_regular_do( - ctx, tls, coarse_poly, ctx->foreach_context->vertex_every_corner, false); + ctx, tls, coarse_poly_index, ctx->foreach_context->vertex_every_corner, false); } static void subdiv_foreach_every_corner_vertices_special(SubdivForeachTaskContext *ctx, void *tls, - const MPoly *coarse_poly) + const int coarse_poly_index) { subdiv_foreach_corner_vertices_special_do( - ctx, tls, coarse_poly, ctx->foreach_context->vertex_every_corner, false); + ctx, tls, coarse_poly_index, ctx->foreach_context->vertex_every_corner, false); } static void subdiv_foreach_every_corner_vertices(SubdivForeachTaskContext *ctx, void *tls) @@ -392,12 +394,11 @@ static void subdiv_foreach_every_corner_vertices(SubdivForeachTaskContext *ctx, } const Mesh *coarse_mesh = ctx->coarse_mesh; for (int poly_index = 0; poly_index < coarse_mesh->totpoly; poly_index++) { - const MPoly &coarse_poly = ctx->coarse_polys[poly_index]; - if (coarse_poly.totloop == 4) { - subdiv_foreach_every_corner_vertices_regular(ctx, tls, &coarse_poly); + if (ctx->coarse_polys[poly_index].size() == 4) { + subdiv_foreach_every_corner_vertices_regular(ctx, tls, poly_index); } else { - subdiv_foreach_every_corner_vertices_special(ctx, tls, &coarse_poly); + subdiv_foreach_every_corner_vertices_special(ctx, tls, poly_index); } } } @@ -406,19 +407,19 @@ static void subdiv_foreach_every_corner_vertices(SubdivForeachTaskContext *ctx, static void subdiv_foreach_edge_vertices_regular_do(SubdivForeachTaskContext *ctx, void *tls, - const MPoly *coarse_poly, + const int coarse_poly_index, SubdivForeachVertexFromEdgeCb vertex_edge, bool check_usage) { + const IndexRange coarse_poly = ctx->coarse_polys[coarse_poly_index]; const int resolution = ctx->settings->resolution; const int resolution_1 = resolution - 1; const float inv_resolution_1 = 1.0f / float(resolution_1); const int num_subdiv_vertices_per_coarse_edge = resolution - 2; - const int coarse_poly_index = coarse_poly - ctx->coarse_polys.data(); const int ptex_face_index = ctx->face_ptex_offset[coarse_poly_index]; - for (int corner = 0; corner < coarse_poly->totloop; corner++) { - const int coarse_vert = ctx->coarse_corner_verts[coarse_poly->loopstart + corner]; - const int coarse_edge_index = ctx->coarse_corner_edges[coarse_poly->loopstart + corner]; + for (int corner = 0; corner < coarse_poly.size(); corner++) { + const int coarse_vert = ctx->coarse_corner_verts[coarse_poly[corner]]; + const int coarse_edge_index = ctx->coarse_corner_edges[coarse_poly[corner]]; if (check_usage && BLI_BITMAP_TEST_AND_SET_ATOMIC(ctx->coarse_edges_used_map, coarse_edge_index)) { continue; @@ -460,28 +461,28 @@ static void subdiv_foreach_edge_vertices_regular_do(SubdivForeachTaskContext *ct static void subdiv_foreach_edge_vertices_regular(SubdivForeachTaskContext *ctx, void *tls, - const MPoly *coarse_poly) + const int coarse_poly_index) { subdiv_foreach_edge_vertices_regular_do( - ctx, tls, coarse_poly, ctx->foreach_context->vertex_edge, true); + ctx, tls, coarse_poly_index, ctx->foreach_context->vertex_edge, true); } static void subdiv_foreach_edge_vertices_special_do(SubdivForeachTaskContext *ctx, void *tls, - const MPoly *coarse_poly, + const int coarse_poly_index, SubdivForeachVertexFromEdgeCb vertex_edge, bool check_usage) { + const IndexRange coarse_poly = ctx->coarse_polys[coarse_poly_index]; const int resolution = ctx->settings->resolution; const int num_subdiv_vertices_per_coarse_edge = resolution - 2; const int num_vertices_per_ptex_edge = ((resolution >> 1) + 1); const float inv_ptex_resolution_1 = 1.0f / float(num_vertices_per_ptex_edge - 1); - const int coarse_poly_index = coarse_poly - ctx->coarse_polys.data(); const int ptex_face_start_index = ctx->face_ptex_offset[coarse_poly_index]; int ptex_face_index = ptex_face_start_index; - for (int corner = 0; corner < coarse_poly->totloop; corner++, ptex_face_index++) { - const int coarse_vert = ctx->coarse_corner_verts[coarse_poly->loopstart + corner]; - const int coarse_edge_index = ctx->coarse_corner_edges[coarse_poly->loopstart + corner]; + for (int corner = 0; corner < coarse_poly.size(); corner++, ptex_face_index++) { + const int coarse_vert = ctx->coarse_corner_verts[coarse_poly[corner]]; + const int coarse_edge_index = ctx->coarse_corner_edges[coarse_poly[corner]]; if (check_usage && BLI_BITMAP_TEST_AND_SET_ATOMIC(ctx->coarse_edges_used_map, coarse_edge_index)) { continue; @@ -508,7 +509,7 @@ static void subdiv_foreach_edge_vertices_special_do(SubdivForeachTaskContext *ct corner, subdiv_vertex_index); } - const int next_corner = (corner + 1) % coarse_poly->totloop; + const int next_corner = (corner + 1) % coarse_poly.size(); const int next_ptex_face_index = ptex_face_start_index + next_corner; for (int vertex_index = 1; vertex_index < num_vertices_per_ptex_edge - 1; vertex_index++, subdiv_vertex_index += vertex_delta) { @@ -528,38 +529,38 @@ static void subdiv_foreach_edge_vertices_special_do(SubdivForeachTaskContext *ct static void subdiv_foreach_edge_vertices_special(SubdivForeachTaskContext *ctx, void *tls, - const MPoly *coarse_poly) + const int coarse_poly_index) { subdiv_foreach_edge_vertices_special_do( - ctx, tls, coarse_poly, ctx->foreach_context->vertex_edge, true); + ctx, tls, coarse_poly_index, ctx->foreach_context->vertex_edge, true); } static void subdiv_foreach_edge_vertices(SubdivForeachTaskContext *ctx, void *tls, - const MPoly *coarse_poly) + const int coarse_poly_index) { - if (coarse_poly->totloop == 4) { - subdiv_foreach_edge_vertices_regular(ctx, tls, coarse_poly); + if (ctx->coarse_polys[coarse_poly_index].size() == 4) { + subdiv_foreach_edge_vertices_regular(ctx, tls, coarse_poly_index); } else { - subdiv_foreach_edge_vertices_special(ctx, tls, coarse_poly); + subdiv_foreach_edge_vertices_special(ctx, tls, coarse_poly_index); } } static void subdiv_foreach_every_edge_vertices_regular(SubdivForeachTaskContext *ctx, void *tls, - const MPoly *coarse_poly) + const int coarse_poly_index) { subdiv_foreach_edge_vertices_regular_do( - ctx, tls, coarse_poly, ctx->foreach_context->vertex_every_edge, false); + ctx, tls, coarse_poly_index, ctx->foreach_context->vertex_every_edge, false); } static void subdiv_foreach_every_edge_vertices_special(SubdivForeachTaskContext *ctx, void *tls, - const MPoly *coarse_poly) + const int coarse_poly_index) { subdiv_foreach_edge_vertices_special_do( - ctx, tls, coarse_poly, ctx->foreach_context->vertex_every_edge, false); + ctx, tls, coarse_poly_index, ctx->foreach_context->vertex_every_edge, false); } static void subdiv_foreach_every_edge_vertices(SubdivForeachTaskContext *ctx, void *tls) @@ -569,12 +570,11 @@ static void subdiv_foreach_every_edge_vertices(SubdivForeachTaskContext *ctx, vo } const Mesh *coarse_mesh = ctx->coarse_mesh; for (int poly_index = 0; poly_index < coarse_mesh->totpoly; poly_index++) { - const MPoly &coarse_poly = ctx->coarse_polys[poly_index]; - if (coarse_poly.totloop == 4) { - subdiv_foreach_every_edge_vertices_regular(ctx, tls, &coarse_poly); + if (ctx->coarse_polys[poly_index].size() == 4) { + subdiv_foreach_every_edge_vertices_regular(ctx, tls, poly_index); } else { - subdiv_foreach_every_edge_vertices_special(ctx, tls, &coarse_poly); + subdiv_foreach_every_edge_vertices_special(ctx, tls, poly_index); } } } @@ -583,11 +583,10 @@ static void subdiv_foreach_every_edge_vertices(SubdivForeachTaskContext *ctx, vo static void subdiv_foreach_inner_vertices_regular(SubdivForeachTaskContext *ctx, void *tls, - const MPoly *coarse_poly) + const int coarse_poly_index) { const int resolution = ctx->settings->resolution; const float inv_resolution_1 = 1.0f / float(resolution - 1); - const int coarse_poly_index = coarse_poly - ctx->coarse_polys.data(); const int ptex_face_index = ctx->face_ptex_offset[coarse_poly_index]; const int start_vertex_index = ctx->subdiv_vertex_offset[coarse_poly_index]; int subdiv_vertex_index = ctx->vertices_inner_offset + start_vertex_index; @@ -609,12 +608,12 @@ static void subdiv_foreach_inner_vertices_regular(SubdivForeachTaskContext *ctx, static void subdiv_foreach_inner_vertices_special(SubdivForeachTaskContext *ctx, void *tls, - const MPoly *coarse_poly) + const int coarse_poly_index) { const int resolution = ctx->settings->resolution; - const int ptex_face_resolution = ptex_face_resolution_get(*coarse_poly, resolution); + const IndexRange coarse_poly = ctx->coarse_polys[coarse_poly_index]; + const int ptex_face_resolution = ptex_face_resolution_get(coarse_poly, resolution); const float inv_ptex_face_resolution_1 = 1.0f / float(ptex_face_resolution - 1); - const int coarse_poly_index = coarse_poly - ctx->coarse_polys.data(); int ptex_face_index = ctx->face_ptex_offset[coarse_poly_index]; const int start_vertex_index = ctx->subdiv_vertex_offset[coarse_poly_index]; int subdiv_vertex_index = ctx->vertices_inner_offset + start_vertex_index; @@ -627,7 +626,7 @@ static void subdiv_foreach_inner_vertices_special(SubdivForeachTaskContext *ctx, 0, subdiv_vertex_index); subdiv_vertex_index++; - for (int corner = 0; corner < coarse_poly->totloop; corner++, ptex_face_index++) { + for (int corner = 0; corner < coarse_poly.size(); corner++, ptex_face_index++) { for (int y = 1; y < ptex_face_resolution - 1; y++) { const float v = y * inv_ptex_face_resolution_1; for (int x = 1; x < ptex_face_resolution; x++, subdiv_vertex_index++) { @@ -647,13 +646,13 @@ static void subdiv_foreach_inner_vertices_special(SubdivForeachTaskContext *ctx, static void subdiv_foreach_inner_vertices(SubdivForeachTaskContext *ctx, void *tls, - const MPoly *coarse_poly) + const int coarse_poly_index) { - if (coarse_poly->totloop == 4) { - subdiv_foreach_inner_vertices_regular(ctx, tls, coarse_poly); + if (ctx->coarse_polys[coarse_poly_index].size() == 4) { + subdiv_foreach_inner_vertices_regular(ctx, tls, coarse_poly_index); } else { - subdiv_foreach_inner_vertices_special(ctx, tls, coarse_poly); + subdiv_foreach_inner_vertices_special(ctx, tls, coarse_poly_index); } } @@ -661,7 +660,7 @@ static void subdiv_foreach_inner_vertices(SubdivForeachTaskContext *ctx, static void subdiv_foreach_vertices(SubdivForeachTaskContext *ctx, void *tls, const int poly_index) { if (ctx->foreach_context->vertex_inner != nullptr) { - subdiv_foreach_inner_vertices(ctx, tls, &ctx->coarse_polys[poly_index]); + subdiv_foreach_inner_vertices(ctx, tls, poly_index); } } @@ -739,14 +738,14 @@ static int subdiv_foreach_edges_column(SubdivForeachTaskContext *ctx, static void subdiv_foreach_edges_all_patches_regular(SubdivForeachTaskContext *ctx, void *tls, - const MPoly *coarse_poly) + const int coarse_poly_index) { - const int poly_index = coarse_poly - ctx->coarse_polys.data(); + const IndexRange coarse_poly = ctx->coarse_polys[coarse_poly_index]; const int resolution = ctx->settings->resolution; const int start_vertex_index = ctx->vertices_inner_offset + - ctx->subdiv_vertex_offset[poly_index]; + ctx->subdiv_vertex_offset[coarse_poly_index]; const int num_subdiv_vertices_per_coarse_edge = resolution - 2; - int subdiv_edge_index = ctx->edge_inner_offset + ctx->subdiv_edge_offset[poly_index]; + int subdiv_edge_index = ctx->edge_inner_offset + ctx->subdiv_edge_offset[coarse_poly_index]; /* Traverse bottom row of edges (0-1, 1-2). */ subdiv_edge_index = subdiv_foreach_edges_row( ctx, tls, ORIGINDEX_NONE, subdiv_edge_index, start_vertex_index, resolution - 2); @@ -778,9 +777,9 @@ static void subdiv_foreach_edges_all_patches_regular(SubdivForeachTaskContext *c resolution - 2); } /* Connect inner part of patch to boundary. */ - for (int corner = 0; corner < coarse_poly->totloop; corner++) { - const int coarse_vert_index = ctx->coarse_corner_verts[coarse_poly->loopstart + corner]; - const int coarse_edge_index = ctx->coarse_corner_edges[coarse_poly->loopstart + corner]; + for (int corner = 0; corner < coarse_poly.size(); corner++) { + const int coarse_vert_index = ctx->coarse_corner_verts[coarse_poly[corner]]; + const int coarse_edge_index = ctx->coarse_corner_edges[coarse_poly[corner]]; const MEdge *coarse_edge = &ctx->coarse_edges[coarse_edge_index]; const int start_edge_vertex = ctx->vertices_edge_offset + coarse_edge_index * num_subdiv_vertices_per_coarse_edge; @@ -817,20 +816,20 @@ static void subdiv_foreach_edges_all_patches_regular(SubdivForeachTaskContext *c static void subdiv_foreach_edges_all_patches_special(SubdivForeachTaskContext *ctx, void *tls, - const MPoly *coarse_poly) + const int coarse_poly_index) { - const int poly_index = coarse_poly - ctx->coarse_polys.data(); const int resolution = ctx->settings->resolution; - const int ptex_face_resolution = ptex_face_resolution_get(*coarse_poly, resolution); + const IndexRange coarse_poly = ctx->coarse_polys[coarse_poly_index]; + const int ptex_face_resolution = ptex_face_resolution_get(coarse_poly, resolution); const int ptex_face_inner_resolution = ptex_face_resolution - 2; const int num_inner_vertices_per_ptex = (ptex_face_resolution - 1) * (ptex_face_resolution - 2); const int num_subdiv_vertices_per_coarse_edge = resolution - 2; const int center_vertex_index = ctx->vertices_inner_offset + - ctx->subdiv_vertex_offset[poly_index]; + ctx->subdiv_vertex_offset[coarse_poly_index]; const int start_vertex_index = center_vertex_index + 1; - int subdiv_edge_index = ctx->edge_inner_offset + ctx->subdiv_edge_offset[poly_index]; + int subdiv_edge_index = ctx->edge_inner_offset + ctx->subdiv_edge_offset[coarse_poly_index]; /* Traverse inner ptex edges. */ - for (int corner = 0; corner < coarse_poly->totloop; corner++) { + for (int corner = 0; corner < coarse_poly.size(); corner++) { const int start_ptex_face_vertex_index = start_vertex_index + corner * num_inner_vertices_per_ptex; /* Similar steps to regular patch case. */ @@ -860,8 +859,8 @@ static void subdiv_foreach_edges_all_patches_special(SubdivForeachTaskContext *c } } /* Create connections between ptex faces. */ - for (int corner = 0; corner < coarse_poly->totloop; corner++) { - const int next_corner = (corner + 1) % coarse_poly->totloop; + for (int corner = 0; corner < coarse_poly.size(); corner++) { + const int next_corner = (corner + 1) % coarse_poly.size(); int current_patch_vertex_index = start_vertex_index + corner * num_inner_vertices_per_ptex + ptex_face_inner_resolution; int next_path_vertex_index = start_vertex_index + next_corner * num_inner_vertices_per_ptex + @@ -877,7 +876,7 @@ static void subdiv_foreach_edges_all_patches_special(SubdivForeachTaskContext *c } /* Create edges from center. */ if (ptex_face_resolution >= 3) { - for (int corner = 0; corner < coarse_poly->totloop; corner++, subdiv_edge_index++) { + for (int corner = 0; corner < coarse_poly.size(); corner++, subdiv_edge_index++) { const int current_patch_end_vertex_index = start_vertex_index + corner * num_inner_vertices_per_ptex + num_inner_vertices_per_ptex - 1; @@ -888,11 +887,11 @@ static void subdiv_foreach_edges_all_patches_special(SubdivForeachTaskContext *c } } /* Connect inner path of patch to boundary. */ - int prev_corner = coarse_poly->totloop - 1; - for (int corner = 0; corner < coarse_poly->totloop; corner++) { - const int coarse_vert = ctx->coarse_corner_verts[coarse_poly->loopstart + corner]; - const int coarse_edge_i = ctx->coarse_corner_edges[coarse_poly->loopstart + corner]; - const int coarse_prev_edge = ctx->coarse_corner_edges[coarse_poly->loopstart + prev_corner]; + int prev_corner = coarse_poly.size() - 1; + for (int corner = 0; corner < coarse_poly.size(); corner++) { + const int coarse_vert = ctx->coarse_corner_verts[coarse_poly[corner]]; + const int coarse_edge_i = ctx->coarse_corner_edges[coarse_poly[corner]]; + const int coarse_prev_edge = ctx->coarse_corner_edges[coarse_poly[prev_corner]]; { const MEdge *coarse_edge = &ctx->coarse_edges[coarse_edge_i]; const int start_edge_vertex = ctx->vertices_edge_offset + @@ -933,19 +932,19 @@ static void subdiv_foreach_edges_all_patches_special(SubdivForeachTaskContext *c static void subdiv_foreach_edges_all_patches(SubdivForeachTaskContext *ctx, void *tls, - const MPoly *coarse_poly) + const int coarse_poly_index) { - if (coarse_poly->totloop == 4) { - subdiv_foreach_edges_all_patches_regular(ctx, tls, coarse_poly); + if (ctx->coarse_polys[coarse_poly_index].size() == 4) { + subdiv_foreach_edges_all_patches_regular(ctx, tls, coarse_poly_index); } else { - subdiv_foreach_edges_all_patches_special(ctx, tls, coarse_poly); + subdiv_foreach_edges_all_patches_special(ctx, tls, coarse_poly_index); } } static void subdiv_foreach_edges(SubdivForeachTaskContext *ctx, void *tls, int poly_index) { - subdiv_foreach_edges_all_patches(ctx, tls, &ctx->coarse_polys[poly_index]); + subdiv_foreach_edges_all_patches(ctx, tls, poly_index); } static void subdiv_foreach_boundary_edges(SubdivForeachTaskContext *ctx, @@ -1077,12 +1076,12 @@ static int subdiv_foreach_loops_corner_index(const float u, static void subdiv_foreach_loops_regular(SubdivForeachTaskContext *ctx, void *tls, - const MPoly *coarse_poly) + const int coarse_poly_index) { const int resolution = ctx->settings->resolution; /* Base/coarse mesh information. */ - const int coarse_poly_index = coarse_poly - ctx->coarse_polys.data(); - const int ptex_resolution = ptex_face_resolution_get(*coarse_poly, resolution); + const IndexRange coarse_poly = ctx->coarse_polys[coarse_poly_index]; + const int ptex_resolution = ptex_face_resolution_get(coarse_poly, resolution); const int ptex_inner_resolution = ptex_resolution - 2; const int num_subdiv_edges_per_coarse_edge = resolution - 1; const int num_subdiv_vertices_per_coarse_edge = resolution - 2; @@ -1137,14 +1136,12 @@ static void subdiv_foreach_loops_regular(SubdivForeachTaskContext *ctx, } } /* Loops for faces connecting inner ptex part with boundary. */ - int prev_corner_index = coarse_poly->totloop - 1; - for (int corner = 0; corner < coarse_poly->totloop; corner++) { - const int coarse_vert = ctx->coarse_corner_verts[coarse_poly->loopstart + corner]; - const int coarse_edge_i = ctx->coarse_corner_edges[coarse_poly->loopstart + corner]; - const int coase_prev_vert = - ctx->coarse_corner_verts[coarse_poly->loopstart + prev_corner_index]; - const int coarse_prev_edge = - ctx->coarse_corner_edges[coarse_poly->loopstart + prev_corner_index]; + int prev_corner_index = coarse_poly.size() - 1; + for (int corner = 0; corner < coarse_poly.size(); corner++) { + const int coarse_vert = ctx->coarse_corner_verts[coarse_poly[corner]]; + const int coarse_edge_i = ctx->coarse_corner_edges[coarse_poly[corner]]; + const int coase_prev_vert = ctx->coarse_corner_verts[coarse_poly[prev_corner_index]]; + const int coarse_prev_edge = ctx->coarse_corner_edges[coarse_poly[prev_corner_index]]; const MEdge *coarse_edge = &ctx->coarse_edges[coarse_edge_i]; const MEdge *prev_coarse_edge = &ctx->coarse_edges[coarse_prev_edge]; @@ -1233,7 +1230,7 @@ static void subdiv_foreach_loops_regular(SubdivForeachTaskContext *ctx, int e2; if (i == 0) { e2 = start_edge_index + num_edges_per_ptex_face_get(resolution - 2) + - ((corner - 1 + coarse_poly->totloop) % coarse_poly->totloop) * + ((corner - 1 + coarse_poly.size()) % coarse_poly.size()) * num_subdiv_vertices_per_coarse_edge + num_subdiv_vertices_per_coarse_edge - 1; } @@ -1273,12 +1270,12 @@ static void subdiv_foreach_loops_regular(SubdivForeachTaskContext *ctx, static void subdiv_foreach_loops_special(SubdivForeachTaskContext *ctx, void *tls, - const MPoly *coarse_poly) + const int coarse_poly_index) { const int resolution = ctx->settings->resolution; /* Base/coarse mesh information. */ - const int coarse_poly_index = coarse_poly - ctx->coarse_polys.data(); - const int ptex_face_resolution = ptex_face_resolution_get(*coarse_poly, resolution); + const IndexRange coarse_poly = ctx->coarse_polys[coarse_poly_index]; + const int ptex_face_resolution = ptex_face_resolution_get(coarse_poly, resolution); const int ptex_face_inner_resolution = ptex_face_resolution - 2; const float inv_ptex_resolution_1 = 1.0f / float(ptex_face_resolution - 1); const int num_inner_vertices_per_ptex = (ptex_face_resolution - 1) * (ptex_face_resolution - 2); @@ -1298,7 +1295,7 @@ static void subdiv_foreach_loops_special(SubdivForeachTaskContext *ctx, const float dv = inv_ptex_resolution_1; /* Hi-poly subdivided mesh. */ int subdiv_loop_index = start_loop_index; - for (int corner = 0; corner < coarse_poly->totloop; corner++) { + for (int corner = 0; corner < coarse_poly.size(); corner++) { const int corner_vertex_index = start_vertex_index + corner * num_inner_vertices_per_ptex; const int corner_edge_index = start_edge_index + corner * num_inner_edges_per_ptex_face; for (int y = 1; y < ptex_face_inner_resolution; y++) { @@ -1342,8 +1339,8 @@ static void subdiv_foreach_loops_special(SubdivForeachTaskContext *ctx, } } /* Create connections between ptex faces. */ - for (int corner = 0; corner < coarse_poly->totloop; corner++) { - const int next_corner = (corner + 1) % coarse_poly->totloop; + for (int corner = 0; corner < coarse_poly.size(); corner++) { + const int next_corner = (corner + 1) % coarse_poly.size(); const int corner_edge_index = start_edge_index + corner * num_inner_edges_per_ptex_face; const int next_corner_edge_index = start_edge_index + next_corner * num_inner_edges_per_ptex_face; @@ -1357,7 +1354,7 @@ static void subdiv_foreach_loops_special(SubdivForeachTaskContext *ctx, int v1 = next_path_vertex_index; current_patch_vertex_index += ptex_face_inner_resolution + 1; next_path_vertex_index += 1; - int e0 = start_edge_index + coarse_poly->totloop * num_inner_edges_per_ptex_face + + int e0 = start_edge_index + coarse_poly.size() * num_inner_edges_per_ptex_face + corner * (ptex_face_resolution - 2); int e1 = next_corner_edge_index + num_inner_edges_per_ptex_face - ptex_face_resolution + 2; int e3 = corner_edge_index + 2 * ptex_face_resolution - 4; @@ -1399,11 +1396,11 @@ static void subdiv_foreach_loops_special(SubdivForeachTaskContext *ctx, if (ptex_face_resolution >= 3) { const int start_center_edge_index = start_edge_index + (num_inner_edges_per_ptex_face + ptex_face_inner_resolution) * - coarse_poly->totloop; + coarse_poly.size(); const int start_boundary_edge = start_edge_index + - coarse_poly->totloop * num_inner_edges_per_ptex_face + + coarse_poly.size() * num_inner_edges_per_ptex_face + ptex_face_inner_resolution - 1; - for (int corner = 0, prev_corner = coarse_poly->totloop - 1; corner < coarse_poly->totloop; + for (int corner = 0, prev_corner = coarse_poly.size() - 1; corner < coarse_poly.size(); prev_corner = corner, corner++, subdiv_loop_index += 4) { const int corner_edge_index = start_edge_index + corner * num_inner_edges_per_ptex_face; const int current_patch_end_vertex_index = start_vertex_index + @@ -1444,12 +1441,12 @@ static void subdiv_foreach_loops_special(SubdivForeachTaskContext *ctx, } } /* Loops for faces connecting inner ptex part with boundary. */ - for (int prev_corner = coarse_poly->totloop - 1, corner = 0; corner < coarse_poly->totloop; + for (int prev_corner = coarse_poly.size() - 1, corner = 0; corner < coarse_poly.size(); prev_corner = corner, corner++) { - const int coarse_vert = ctx->coarse_corner_verts[coarse_poly->loopstart + corner]; - const int coarse_edge_i = ctx->coarse_corner_edges[coarse_poly->loopstart + corner]; - const int coase_prev_vert = ctx->coarse_corner_verts[coarse_poly->loopstart + prev_corner]; - const int coarse_prev_edge = ctx->coarse_corner_edges[coarse_poly->loopstart + prev_corner]; + const int coarse_vert = ctx->coarse_corner_verts[coarse_poly[corner]]; + const int coarse_edge_i = ctx->coarse_corner_edges[coarse_poly[corner]]; + const int coase_prev_vert = ctx->coarse_corner_verts[coarse_poly[prev_corner]]; + const int coarse_prev_edge = ctx->coarse_corner_edges[coarse_poly[prev_corner]]; const MEdge *coarse_edge = &ctx->coarse_edges[coarse_edge_i]; const MEdge *prev_coarse_edge = &ctx->coarse_edges[coarse_prev_edge]; @@ -1496,14 +1493,14 @@ static void subdiv_foreach_loops_special(SubdivForeachTaskContext *ctx, } int e1 = start_edge_index + corner * (2 * ptex_face_inner_resolution + 1); if (ptex_face_resolution >= 3) { - e1 += coarse_poly->totloop * + e1 += coarse_poly.size() * (num_inner_edges_per_ptex_face + ptex_face_inner_resolution + 1) + i; } int e2 = 0; if (i == 0 && ptex_face_resolution >= 3) { e2 = start_edge_index + - coarse_poly->totloop * + coarse_poly.size() * (num_inner_edges_per_ptex_face + ptex_face_inner_resolution + 1) + corner * (2 * ptex_face_inner_resolution + 1) + ptex_face_inner_resolution + 1; } @@ -1549,7 +1546,7 @@ static void subdiv_foreach_loops_special(SubdivForeachTaskContext *ctx, v3 = ctx->vertices_edge_offset + coarse_prev_edge * num_subdiv_vertices_per_coarse_edge; } e3 = start_edge_index + - coarse_poly->totloop * (num_inner_edges_per_ptex_face + ptex_face_inner_resolution + 1) + + coarse_poly.size() * (num_inner_edges_per_ptex_face + ptex_face_inner_resolution + 1) + corner * (2 * ptex_face_inner_resolution + 1) + ptex_face_inner_resolution + 1; for (int i = 0; i <= ptex_face_inner_resolution - 1; i++, subdiv_loop_index += 4) { int v1; @@ -1558,10 +1555,10 @@ static void subdiv_foreach_loops_special(SubdivForeachTaskContext *ctx, v1 = start_vertex_index + prev_corner * num_inner_vertices_per_ptex + ptex_face_inner_resolution; e1 = start_edge_index + - coarse_poly->totloop * + coarse_poly.size() * (num_inner_edges_per_ptex_face + ptex_face_inner_resolution + 1) + prev_corner * (2 * ptex_face_inner_resolution + 1) + ptex_face_inner_resolution; - e0 = start_edge_index + coarse_poly->totloop * num_inner_edges_per_ptex_face + + e0 = start_edge_index + coarse_poly.size() * num_inner_edges_per_ptex_face + prev_corner * ptex_face_inner_resolution; } else { @@ -1610,12 +1607,11 @@ static void subdiv_foreach_loops_special(SubdivForeachTaskContext *ctx, static void subdiv_foreach_loops(SubdivForeachTaskContext *ctx, void *tls, int poly_index) { - const MPoly &coarse_poly = ctx->coarse_polys[poly_index]; - if (coarse_poly.totloop == 4) { - subdiv_foreach_loops_regular(ctx, tls, &coarse_poly); + if (ctx->coarse_polys[poly_index].size() == 4) { + subdiv_foreach_loops_regular(ctx, tls, poly_index); } else { - subdiv_foreach_loops_special(ctx, tls, &coarse_poly); + subdiv_foreach_loops_special(ctx, tls, poly_index); } } @@ -1630,7 +1626,7 @@ static void subdiv_foreach_polys(SubdivForeachTaskContext *ctx, void *tls, int p const int resolution = ctx->settings->resolution; const int start_poly_index = ctx->subdiv_polygon_offset[poly_index]; /* Base/coarse mesh information. */ - const MPoly &coarse_poly = ctx->coarse_polys[poly_index]; + const IndexRange coarse_poly = ctx->coarse_polys[poly_index]; const int num_ptex_faces_per_poly = num_ptex_faces_per_poly_get(coarse_poly); const int ptex_resolution = ptex_face_resolution_get(coarse_poly, resolution); const int num_polys_per_ptex = num_polys_per_ptex_get(ptex_resolution); @@ -1721,22 +1717,17 @@ static void subdiv_foreach_single_geometry_vertices(SubdivForeachTaskContext *ct } const Mesh *coarse_mesh = ctx->coarse_mesh; for (int poly_index = 0; poly_index < coarse_mesh->totpoly; poly_index++) { - const MPoly &coarse_poly = ctx->coarse_polys[poly_index]; - subdiv_foreach_corner_vertices(ctx, tls, &coarse_poly); - subdiv_foreach_edge_vertices(ctx, tls, &coarse_poly); + subdiv_foreach_corner_vertices(ctx, tls, poly_index); + subdiv_foreach_edge_vertices(ctx, tls, poly_index); } } static void subdiv_foreach_mark_non_loose_geometry(SubdivForeachTaskContext *ctx) { - const Mesh *coarse_mesh = ctx->coarse_mesh; - for (int poly_index = 0; poly_index < coarse_mesh->totpoly; poly_index++) { - const MPoly &coarse_poly = ctx->coarse_polys[poly_index]; - for (int corner = 0; corner < coarse_poly.totloop; corner++) { - BLI_BITMAP_ENABLE(ctx->coarse_vertices_used_map, - ctx->coarse_corner_verts[coarse_poly.loopstart + corner]); - BLI_BITMAP_ENABLE(ctx->coarse_edges_used_map, - ctx->coarse_corner_verts[coarse_poly.loopstart + corner]); + for (const int poly_index : ctx->coarse_polys.index_range()) { + for (const int corner : ctx->coarse_polys[poly_index]) { + BLI_BITMAP_ENABLE(ctx->coarse_vertices_used_map, ctx->coarse_corner_verts[corner]); + BLI_BITMAP_ENABLE(ctx->coarse_edges_used_map, ctx->coarse_corner_verts[corner]); } } } diff --git a/source/blender/blenkernel/intern/subdiv_mesh.cc b/source/blender/blenkernel/intern/subdiv_mesh.cc index e8d1a2e674d..320678be9da 100644 --- a/source/blender/blenkernel/intern/subdiv_mesh.cc +++ b/source/blender/blenkernel/intern/subdiv_mesh.cc @@ -32,6 +32,7 @@ using blender::float2; using blender::float3; +using blender::IndexRange; using blender::MutableSpan; using blender::Span; @@ -44,14 +45,14 @@ struct SubdivMeshContext { const Mesh *coarse_mesh; const float (*coarse_positions)[3]; blender::Span coarse_edges; - blender::Span coarse_polys; + blender::OffsetIndices coarse_polys; blender::Span coarse_corner_verts; Subdiv *subdiv; Mesh *subdiv_mesh; blender::MutableSpan subdiv_positions; blender::MutableSpan subdiv_edges; - blender::MutableSpan subdiv_polys; + blender::MutableSpan subdiv_poly_offsets; blender::MutableSpan subdiv_corner_verts; blender::MutableSpan subdiv_corner_edges; @@ -96,7 +97,7 @@ static void subdiv_mesh_ctx_cache_custom_data_layers(SubdivMeshContext *ctx) Mesh *subdiv_mesh = ctx->subdiv_mesh; ctx->subdiv_positions = subdiv_mesh->vert_positions_for_write(); ctx->subdiv_edges = subdiv_mesh->edges_for_write(); - ctx->subdiv_polys = subdiv_mesh->polys_for_write(); + ctx->subdiv_poly_offsets = subdiv_mesh->poly_offsets_for_write(); ctx->subdiv_corner_verts = subdiv_mesh->corner_verts_for_write(); ctx->subdiv_corner_edges = subdiv_mesh->corner_edges_for_write(); /* Pointers to original indices layers. */ @@ -150,20 +151,20 @@ struct LoopsOfPtex { }; static void loops_of_ptex_get(LoopsOfPtex *loops_of_ptex, - const MPoly *coarse_poly, + const IndexRange coarse_poly, const int ptex_of_poly_index) { - const int first_ptex_loop_index = coarse_poly->loopstart + ptex_of_poly_index; + const int first_ptex_loop_index = coarse_poly.start() + ptex_of_poly_index; /* Loop which look in the (opposite) V direction of the current * ptex face. * * TODO(sergey): Get rid of using module on every iteration. */ - const int last_ptex_loop_index = coarse_poly->loopstart + - (ptex_of_poly_index + coarse_poly->totloop - 1) % - coarse_poly->totloop; + const int last_ptex_loop_index = coarse_poly.start() + + (ptex_of_poly_index + coarse_poly.size() - 1) % + coarse_poly.size(); loops_of_ptex->first_loop = first_ptex_loop_index; loops_of_ptex->last_loop = last_ptex_loop_index; - if (coarse_poly->totloop == 4) { + if (coarse_poly.size() == 4) { loops_of_ptex->second_loop = loops_of_ptex->first_loop + 1; loops_of_ptex->third_loop = loops_of_ptex->first_loop + 2; } @@ -205,15 +206,15 @@ struct VerticesForInterpolation { static void vertex_interpolation_init(const SubdivMeshContext *ctx, VerticesForInterpolation *vertex_interpolation, - const MPoly &coarse_poly) + const IndexRange coarse_poly) { const Mesh *coarse_mesh = ctx->coarse_mesh; - if (coarse_poly.totloop == 4) { + if (coarse_poly.size() == 4) { vertex_interpolation->vertex_data = &coarse_mesh->vdata; - vertex_interpolation->vertex_indices[0] = ctx->coarse_corner_verts[coarse_poly.loopstart + 0]; - vertex_interpolation->vertex_indices[1] = ctx->coarse_corner_verts[coarse_poly.loopstart + 1]; - vertex_interpolation->vertex_indices[2] = ctx->coarse_corner_verts[coarse_poly.loopstart + 2]; - vertex_interpolation->vertex_indices[3] = ctx->coarse_corner_verts[coarse_poly.loopstart + 3]; + vertex_interpolation->vertex_indices[0] = ctx->coarse_corner_verts[coarse_poly.start() + 0]; + vertex_interpolation->vertex_indices[1] = ctx->coarse_corner_verts[coarse_poly.start() + 1]; + vertex_interpolation->vertex_indices[2] = ctx->coarse_corner_verts[coarse_poly.start() + 2]; + vertex_interpolation->vertex_indices[3] = ctx->coarse_corner_verts[coarse_poly.start() + 3]; vertex_interpolation->vertex_data_storage_allocated = false; } else { @@ -232,29 +233,29 @@ static void vertex_interpolation_init(const SubdivMeshContext *ctx, vertex_interpolation->vertex_data_storage_allocated = true; /* Interpolate center of poly right away, it stays unchanged for all * ptex faces. */ - const float weight = 1.0f / float(coarse_poly.totloop); - blender::Array weights(coarse_poly.totloop); - blender::Array indices(coarse_poly.totloop); - for (int i = 0; i < coarse_poly.totloop; i++) { + const float weight = 1.0f / float(coarse_poly.size()); + blender::Array weights(coarse_poly.size()); + blender::Array indices(coarse_poly.size()); + for (int i = 0; i < coarse_poly.size(); i++) { weights[i] = weight; - indices[i] = ctx->coarse_corner_verts[coarse_poly.loopstart + i]; + indices[i] = ctx->coarse_corner_verts[coarse_poly.start() + i]; } CustomData_interp(&coarse_mesh->vdata, &vertex_interpolation->vertex_data_storage, indices.data(), weights.data(), nullptr, - coarse_poly.totloop, + coarse_poly.size(), 2); } } static void vertex_interpolation_from_corner(const SubdivMeshContext *ctx, VerticesForInterpolation *vertex_interpolation, - const MPoly *coarse_poly, + const IndexRange coarse_poly, const int corner) { - if (coarse_poly->totloop == 4) { + if (coarse_poly.size() == 4) { /* Nothing to do, all indices and data is already assigned. */ } else { @@ -264,7 +265,7 @@ static void vertex_interpolation_from_corner(const SubdivMeshContext *ctx, /* Ptex face corner corresponds to a poly loop with same index. */ CustomData_copy_data(vertex_data, &vertex_interpolation->vertex_data_storage, - ctx->coarse_corner_verts[coarse_poly->loopstart + corner], + ctx->coarse_corner_verts[coarse_poly.start() + corner], 0, 1); /* Interpolate remaining ptex face corners, which hits loops @@ -277,9 +278,9 @@ static void vertex_interpolation_from_corner(const SubdivMeshContext *ctx, const int last_loop_index = loops_of_ptex.last_loop; const int first_indices[2] = { ctx->coarse_corner_verts[first_loop_index], - ctx->coarse_corner_verts[coarse_poly->loopstart + - (first_loop_index - coarse_poly->loopstart + 1) % - coarse_poly->totloop]}; + ctx->coarse_corner_verts[coarse_poly.start() + + (first_loop_index - coarse_poly.start() + 1) % + coarse_poly.size()]}; const int last_indices[2] = {ctx->coarse_corner_verts[first_loop_index], ctx->coarse_corner_verts[last_loop_index]}; CustomData_interp(vertex_data, @@ -335,15 +336,15 @@ struct LoopsForInterpolation { static void loop_interpolation_init(const SubdivMeshContext *ctx, LoopsForInterpolation *loop_interpolation, - const MPoly *coarse_poly) + const IndexRange coarse_poly) { const Mesh *coarse_mesh = ctx->coarse_mesh; - if (coarse_poly->totloop == 4) { + if (coarse_poly.size() == 4) { loop_interpolation->loop_data = &coarse_mesh->ldata; - loop_interpolation->loop_indices[0] = coarse_poly->loopstart + 0; - loop_interpolation->loop_indices[1] = coarse_poly->loopstart + 1; - loop_interpolation->loop_indices[2] = coarse_poly->loopstart + 2; - loop_interpolation->loop_indices[3] = coarse_poly->loopstart + 3; + loop_interpolation->loop_indices[0] = coarse_poly.start() + 0; + loop_interpolation->loop_indices[1] = coarse_poly.start() + 1; + loop_interpolation->loop_indices[2] = coarse_poly.start() + 2; + loop_interpolation->loop_indices[3] = coarse_poly.start() + 3; loop_interpolation->loop_data_storage_allocated = false; } else { @@ -362,29 +363,29 @@ static void loop_interpolation_init(const SubdivMeshContext *ctx, loop_interpolation->loop_data_storage_allocated = true; /* Interpolate center of poly right away, it stays unchanged for all * ptex faces. */ - const float weight = 1.0f / float(coarse_poly->totloop); - blender::Array weights(coarse_poly->totloop); - blender::Array indices(coarse_poly->totloop); - for (int i = 0; i < coarse_poly->totloop; i++) { + const float weight = 1.0f / float(coarse_poly.size()); + blender::Array weights(coarse_poly.size()); + blender::Array indices(coarse_poly.size()); + for (int i = 0; i < coarse_poly.size(); i++) { weights[i] = weight; - indices[i] = coarse_poly->loopstart + i; + indices[i] = coarse_poly.start() + i; } CustomData_interp(&coarse_mesh->ldata, &loop_interpolation->loop_data_storage, indices.data(), weights.data(), nullptr, - coarse_poly->totloop, + coarse_poly.size(), 2); } } static void loop_interpolation_from_corner(const SubdivMeshContext *ctx, LoopsForInterpolation *loop_interpolation, - const MPoly *coarse_poly, + const IndexRange coarse_poly, const int corner) { - if (coarse_poly->totloop == 4) { + if (coarse_poly.size() == 4) { /* Nothing to do, all indices and data is already assigned. */ } else { @@ -394,17 +395,17 @@ static void loop_interpolation_from_corner(const SubdivMeshContext *ctx, /* Ptex face corner corresponds to a poly loop with same index. */ CustomData_free_elem(&loop_interpolation->loop_data_storage, 0, 1); CustomData_copy_data( - loop_data, &loop_interpolation->loop_data_storage, coarse_poly->loopstart + corner, 0, 1); + loop_data, &loop_interpolation->loop_data_storage, coarse_poly.start() + corner, 0, 1); /* Interpolate remaining ptex face corners, which hits loops * middle points. * * TODO(sergey): Re-use one of interpolation results from previous * iteration. */ const float weights[2] = {0.5f, 0.5f}; - const int base_loop_index = coarse_poly->loopstart; + const int base_loop_index = coarse_poly.start(); const int first_loop_index = loops_of_ptex.first_loop; const int second_loop_index = base_loop_index + - (first_loop_index - base_loop_index + 1) % coarse_poly->totloop; + (first_loop_index - base_loop_index + 1) % coarse_poly.size(); const int first_indices[2] = {first_loop_index, second_loop_index}; const int last_indices[2] = {loops_of_ptex.last_loop, loops_of_ptex.first_loop}; CustomData_interp( @@ -430,12 +431,12 @@ static void loop_interpolation_end(LoopsForInterpolation *loop_interpolation) struct SubdivMeshTLS { bool vertex_interpolation_initialized; VerticesForInterpolation vertex_interpolation; - const MPoly *vertex_interpolation_coarse_poly; + int vertex_interpolation_coarse_poly_index; int vertex_interpolation_coarse_corner; bool loop_interpolation_initialized; LoopsForInterpolation loop_interpolation; - const MPoly *loop_interpolation_coarse_poly; + int loop_interpolation_coarse_poly_index; int loop_interpolation_coarse_corner; }; @@ -686,12 +687,13 @@ static void subdiv_mesh_vertex_corner(const SubdivForeachContext *foreach_contex static void subdiv_mesh_ensure_vertex_interpolation(SubdivMeshContext *ctx, SubdivMeshTLS *tls, - const MPoly *coarse_poly, + const int coarse_poly_index, const int coarse_corner) { + const IndexRange coarse_poly = ctx->coarse_polys[coarse_poly_index]; /* Check whether we've moved to another corner or polygon. */ if (tls->vertex_interpolation_initialized) { - if (tls->vertex_interpolation_coarse_poly != coarse_poly || + if (tls->vertex_interpolation_coarse_poly_index != coarse_poly_index || tls->vertex_interpolation_coarse_corner != coarse_corner) { vertex_interpolation_end(&tls->vertex_interpolation); tls->vertex_interpolation_initialized = false; @@ -699,7 +701,7 @@ static void subdiv_mesh_ensure_vertex_interpolation(SubdivMeshContext *ctx, } /* Initialize the interpolation. */ if (!tls->vertex_interpolation_initialized) { - vertex_interpolation_init(ctx, &tls->vertex_interpolation, *coarse_poly); + vertex_interpolation_init(ctx, &tls->vertex_interpolation, coarse_poly); } /* Update it for a new corner if needed. */ if (!tls->vertex_interpolation_initialized || @@ -708,7 +710,7 @@ static void subdiv_mesh_ensure_vertex_interpolation(SubdivMeshContext *ctx, } /* Store settings used for the current state of interpolator. */ tls->vertex_interpolation_initialized = true; - tls->vertex_interpolation_coarse_poly = coarse_poly; + tls->vertex_interpolation_coarse_poly_index = coarse_poly_index; tls->vertex_interpolation_coarse_corner = coarse_corner; } @@ -724,15 +726,16 @@ static void subdiv_mesh_vertex_edge(const SubdivForeachContext *foreach_context, { SubdivMeshContext *ctx = static_cast(foreach_context->user_data); SubdivMeshTLS *tls = static_cast(tls_v); - const MPoly &coarse_poly = ctx->coarse_polys[coarse_poly_index]; - subdiv_mesh_ensure_vertex_interpolation(ctx, tls, &coarse_poly, coarse_corner); + subdiv_mesh_ensure_vertex_interpolation(ctx, tls, coarse_poly_index, coarse_corner); evaluate_vertex_and_apply_displacement_interpolate( ctx, ptex_face_index, u, v, &tls->vertex_interpolation, subdiv_vertex_index); } -static bool subdiv_mesh_is_center_vertex(const MPoly &coarse_poly, const float u, const float v) +static bool subdiv_mesh_is_center_vertex(const IndexRange coarse_poly, + const float u, + const float v) { - if (coarse_poly.totloop == 4) { + if (coarse_poly.size() == 4) { if (u == 0.5f && v == 0.5f) { return true; } @@ -745,7 +748,7 @@ static bool subdiv_mesh_is_center_vertex(const MPoly &coarse_poly, const float u return false; } -static void subdiv_mesh_tag_center_vertex(const MPoly &coarse_poly, +static void subdiv_mesh_tag_center_vertex(const IndexRange coarse_poly, const int subdiv_vertex_index, const float u, const float v, @@ -768,10 +771,10 @@ static void subdiv_mesh_vertex_inner(const SubdivForeachContext *foreach_context SubdivMeshContext *ctx = static_cast(foreach_context->user_data); SubdivMeshTLS *tls = static_cast(tls_v); Subdiv *subdiv = ctx->subdiv; - const MPoly &coarse_poly = ctx->coarse_polys[coarse_poly_index]; + const IndexRange coarse_poly = ctx->coarse_polys[coarse_poly_index]; Mesh *subdiv_mesh = ctx->subdiv_mesh; float3 &subdiv_position = ctx->subdiv_positions[subdiv_vertex_index]; - subdiv_mesh_ensure_vertex_interpolation(ctx, tls, &coarse_poly, coarse_corner); + subdiv_mesh_ensure_vertex_interpolation(ctx, tls, coarse_poly_index, coarse_corner); subdiv_vertex_data_interpolate(ctx, subdiv_vertex_index, &tls->vertex_interpolation, u, v); BKE_subdiv_eval_final_point(subdiv, ptex_face_index, u, v, subdiv_position); subdiv_mesh_tag_center_vertex(coarse_poly, subdiv_vertex_index, u, v, subdiv_mesh); @@ -856,12 +859,13 @@ static void subdiv_eval_uv_layer(SubdivMeshContext *ctx, static void subdiv_mesh_ensure_loop_interpolation(SubdivMeshContext *ctx, SubdivMeshTLS *tls, - const MPoly *coarse_poly, + const int coarse_poly_index, const int coarse_corner) { + const IndexRange coarse_poly = ctx->coarse_polys[coarse_poly_index]; /* Check whether we've moved to another corner or polygon. */ if (tls->loop_interpolation_initialized) { - if (tls->loop_interpolation_coarse_poly != coarse_poly || + if (tls->loop_interpolation_coarse_poly_index != coarse_poly_index || tls->loop_interpolation_coarse_corner != coarse_corner) { loop_interpolation_end(&tls->loop_interpolation); tls->loop_interpolation_initialized = false; @@ -878,7 +882,7 @@ static void subdiv_mesh_ensure_loop_interpolation(SubdivMeshContext *ctx, } /* Store settings used for the current state of interpolator. */ tls->loop_interpolation_initialized = true; - tls->loop_interpolation_coarse_poly = coarse_poly; + tls->loop_interpolation_coarse_poly_index = coarse_poly_index; tls->loop_interpolation_coarse_corner = coarse_corner; } @@ -896,8 +900,7 @@ static void subdiv_mesh_loop(const SubdivForeachContext *foreach_context, { SubdivMeshContext *ctx = static_cast(foreach_context->user_data); SubdivMeshTLS *tls = static_cast(tls_v); - const MPoly &coarse_poly = ctx->coarse_polys[coarse_poly_index]; - subdiv_mesh_ensure_loop_interpolation(ctx, tls, &coarse_poly, coarse_corner); + subdiv_mesh_ensure_loop_interpolation(ctx, tls, coarse_poly_index, coarse_corner); subdiv_interpolate_loop_data(ctx, subdiv_loop_index, &tls->loop_interpolation, u, v); subdiv_eval_uv_layer(ctx, subdiv_loop_index, ptex_face_index, u, v); ctx->subdiv_corner_verts[subdiv_loop_index] = subdiv_vertex_index; @@ -910,26 +913,18 @@ static void subdiv_mesh_loop(const SubdivForeachContext *foreach_context, /** \name Polygons subdivision process * \{ */ -static void subdiv_copy_poly_data(const SubdivMeshContext *ctx, - const int subdiv_poly, - const int coarse_poly) -{ - CustomData_copy_data( - &ctx->coarse_mesh->pdata, &ctx->subdiv_mesh->pdata, coarse_poly, subdiv_poly, 1); -} - static void subdiv_mesh_poly(const SubdivForeachContext *foreach_context, void * /*tls*/, const int coarse_poly_index, const int subdiv_poly_index, const int start_loop_index, - const int num_loops) + const int /*num_loops*/) { BLI_assert(coarse_poly_index != ORIGINDEX_NONE); SubdivMeshContext *ctx = static_cast(foreach_context->user_data); - subdiv_copy_poly_data(ctx, subdiv_poly_index, coarse_poly_index); - ctx->subdiv_polys[subdiv_poly_index].loopstart = start_loop_index; - ctx->subdiv_polys[subdiv_poly_index].totloop = num_loops; + CustomData_copy_data( + &ctx->coarse_mesh->pdata, &ctx->subdiv_mesh->pdata, coarse_poly_index, subdiv_poly_index, 1); + ctx->subdiv_poly_offsets[subdiv_poly_index] = start_loop_index; } /** \} */ diff --git a/source/blender/blenkernel/intern/subsurf_ccg.cc b/source/blender/blenkernel/intern/subsurf_ccg.cc index 779c247c234..aa240dda97e 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.cc +++ b/source/blender/blenkernel/intern/subsurf_ccg.cc @@ -228,13 +228,13 @@ static int getFaceIndex( } static void get_face_uv_map_vert(UvVertMap *vmap, - const blender::Span polys, + const blender::OffsetIndices polys, const int *poly_verts, int fi, CCGVertHDL *fverts) { UvMapVert *v, *nv; - int j, nverts = polys[fi].totloop; + int j, nverts = polys[fi].size(); for (j = 0; j < nverts; j++) { for (nv = v = BKE_mesh_uv_vert_map_get_vert(vmap, poly_verts[j]); v; v = v->next) { @@ -246,7 +246,7 @@ static void get_face_uv_map_vert(UvVertMap *vmap, } } - fverts[j] = POINTER_FROM_UINT(polys[nv->poly_index].loopstart + nv->loop_of_poly_index); + fverts[j] = POINTER_FROM_UINT(polys[nv->poly_index].start() + nv->loop_of_poly_index); } } @@ -255,7 +255,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, DerivedMesh *dm, const float (*mloopuv)[2]) { - const blender::Span polys(dm->getPolyArray(dm), dm->getNumPolys(dm)); + const blender::OffsetIndices polys(blender::Span(dm->getPolyArray(dm), dm->getNumPolys(dm) + 1)); int *corner_verts = dm->getCornerVertArray(dm); int totvert = dm->getNumVerts(dm); int totface = dm->getNumPolys(dm); @@ -273,7 +273,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, * Also, initially intention is to treat merged vertices from mirror modifier as seams. * This fixes a very old regression (2.49 was correct here) */ vmap = BKE_mesh_uv_vert_map_create( - polys.data(), nullptr, nullptr, corner_verts, mloopuv, totface, totvert, limit, false, true); + polys, nullptr, nullptr, corner_verts, mloopuv, totvert, limit, false, true); if (!vmap) { return 0; } @@ -297,7 +297,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, for (v = BKE_mesh_uv_vert_map_get_vert(vmap, i); v; v = v->next) { if (v->separate) { CCGVert *ssv; - int loopid = polys[v->poly_index].loopstart + v->loop_of_poly_index; + int loopid = polys[v->poly_index].start() + v->loop_of_poly_index; CCGVertHDL vhdl = POINTER_FROM_INT(loopid); copy_v2_v2(uv, mloopuv[loopid]); @@ -311,15 +311,15 @@ static int ss_sync_from_uv(CCGSubSurf *ss, eset = BLI_edgeset_new_ex(__func__, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(totface)); for (i = 0; i < totface; i++) { - const MPoly &poly = polys[i]; - int nverts = poly.totloop; + const blender::IndexRange poly = polys[i]; + int nverts = poly.size(); int j, j_next; CCGFace *origf = ccgSubSurf_getFace(origss, POINTER_FROM_INT(i)); // uint *fv = &poly.v1; fverts.reinitialize(nverts); - get_face_uv_map_vert(vmap, polys, &corner_verts[poly.loopstart], i, fverts.data()); + get_face_uv_map_vert(vmap, polys, &corner_verts[poly.start()], i, fverts.data()); for (j = 0, j_next = nverts - 1; j < nverts; j_next = j++) { uint v0 = POINTER_AS_UINT(fverts[j_next]); @@ -327,7 +327,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, if (BLI_edgeset_add(eset, v0, v1)) { CCGEdge *e, *orige = ccgSubSurf_getFaceEdge(origf, j_next); - CCGEdgeHDL ehdl = POINTER_FROM_INT(poly.loopstart + j_next); + CCGEdgeHDL ehdl = POINTER_FROM_INT(poly[j_next]); float crease = ccgSubSurf_getEdgeCrease(orige); ccgSubSurf_syncEdge(ss, ehdl, fverts[j_next], fverts[j], crease, &e); @@ -339,13 +339,13 @@ static int ss_sync_from_uv(CCGSubSurf *ss, /* create faces */ for (i = 0; i < totface; i++) { - const MPoly &poly = polys[i]; - int nverts = poly.totloop; + const blender::IndexRange poly = polys[i]; + int nverts = poly.size(); CCGFace *f; fverts.reinitialize(nverts); - get_face_uv_map_vert(vmap, polys, &corner_verts[poly.loopstart], i, fverts.data()); + get_face_uv_map_vert(vmap, polys, &corner_verts[poly.start()], i, fverts.data()); ccgSubSurf_syncFace(ss, POINTER_FROM_INT(i), nverts, fverts.data(), &f); } @@ -541,7 +541,7 @@ static void ss_sync_ccg_from_derivedmesh(CCGSubSurf *ss, MEdge *edges = dm->getEdgeArray(dm); MEdge *edge; int *corner_verts = dm->getCornerVertArray(dm); - MPoly *polys = dm->getPolyArray(dm); + const blender::OffsetIndices polys(blender::Span(dm->getPolyArray(dm), dm->getNumPolys(dm) + 1)); int totvert = dm->getNumVerts(dm); int totedge = dm->getNumEdges(dm); int i, j; @@ -584,21 +584,21 @@ static void ss_sync_ccg_from_derivedmesh(CCGSubSurf *ss, index = (int *)dm->getPolyDataArray(dm, CD_ORIGINDEX); for (i = 0; i < dm->numPolyData; i++) { - const MPoly &poly = polys[i]; + const blender::IndexRange poly = polys[i]; + CCGFace *f; - fverts.reinitialize(poly.totloop); + fverts.reinitialize(poly.size()); - int corner = poly.loopstart; - for (j = 0; j < poly.totloop; j++, corner++) { - fverts[j] = POINTER_FROM_UINT(corner_verts[corner]); + for (j = 0; j < poly.size(); j++) { + fverts[j] = POINTER_FROM_UINT(corner_verts[poly[j]]); } /* This is very bad, means mesh is internally inconsistent. * it is not really possible to continue without modifying * other parts of code significantly to handle missing faces. * since this really shouldn't even be possible we just bail. */ - if (ccgSubSurf_syncFace(ss, POINTER_FROM_INT(i), poly.totloop, fverts.data(), &f) == + if (ccgSubSurf_syncFace(ss, POINTER_FROM_INT(i), poly.size(), fverts.data(), &f) == eCCGError_InvalidValue) { static int hasGivenError = 0; @@ -1108,7 +1108,7 @@ static void ccgDM_copyFinalCornerEdgeArray(DerivedMesh *dm, int *r_corner_edges) 0, ccgSubSurf_getNumFaces(ss), &data, copyFinalLoopArray_task_cb, &settings); } -static void ccgDM_copyFinalPolyArray(DerivedMesh *dm, MPoly *polys) +static void ccgDM_copyFinalPolyArray(DerivedMesh *dm, int *r_poly_offsets) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm; CCGSubSurf *ss = ccgdm->ss; @@ -1126,15 +1126,14 @@ static void ccgDM_copyFinalPolyArray(DerivedMesh *dm, MPoly *polys) for (S = 0; S < numVerts; S++) { for (y = 0; y < gridSize - 1; y++) { for (x = 0; x < gridSize - 1; x++) { - polys[i].loopstart = k; - polys[i].totloop = 4; - + r_poly_offsets[i] = k; k += 4; i++; } } } } + r_poly_offsets[i] = k; } static void ccgDM_release(DerivedMesh *dm) @@ -1553,7 +1552,7 @@ static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm, gridInternalEdges = (gridSideEdges - 1) * gridSideEdges * 2; const int *material_indices = static_cast( - CustomData_get_layer_named(&dm->polyData, CD_MPOLY, "material_index")); + CustomData_get_layer_named(&dm->polyData, CD_PROP_INT32, "material_index")); const bool *sharp_faces = static_cast( CustomData_get_layer_named(&dm->polyData, CD_PROP_BOOL, "sharp_face")); @@ -1827,6 +1826,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, &ccgdm->dm.loopData, ".corner_vert", ccgSubSurf_getNumFinalFaces(ss) * 4); CustomData_free_layer_named( &ccgdm->dm.loopData, ".corner_edge", ccgSubSurf_getNumFinalFaces(ss) * 4); + MEM_SAFE_FREE(ccgdm->dm.poly_offsets); ccgdm->reverseFaceMap = static_cast( MEM_callocN(sizeof(int) * ccgSubSurf_getNumFinalFaces(ss), "reverseFaceMap")); diff --git a/source/blender/blenkernel/intern/volume_to_mesh.cc b/source/blender/blenkernel/intern/volume_to_mesh.cc index 69d8bb0f12f..f2a7d9472a9 100644 --- a/source/blender/blenkernel/intern/volume_to_mesh.cc +++ b/source/blender/blenkernel/intern/volume_to_mesh.cc @@ -114,7 +114,7 @@ void fill_mesh_from_openvdb_data(const Span vdb_verts, const int poly_offset, const int loop_offset, MutableSpan vert_positions, - MutableSpan polys, + MutableSpan poly_offsets, MutableSpan corner_verts) { /* Write vertices. */ @@ -122,8 +122,7 @@ void fill_mesh_from_openvdb_data(const Span vdb_verts, /* Write triangles. */ for (const int i : vdb_tris.index_range()) { - polys[poly_offset + i].loopstart = loop_offset + 3 * i; - polys[poly_offset + i].totloop = 3; + poly_offsets[poly_offset + i] = loop_offset + 3 * i; for (int j = 0; j < 3; j++) { /* Reverse vertex order to get correct normals. */ corner_verts[loop_offset + 3 * i + j] = vert_offset + vdb_tris[i][2 - j]; @@ -134,8 +133,7 @@ void fill_mesh_from_openvdb_data(const Span vdb_verts, const int quad_offset = poly_offset + vdb_tris.size(); const int quad_loop_offset = loop_offset + vdb_tris.size() * 3; for (const int i : vdb_quads.index_range()) { - polys[quad_offset + i].loopstart = quad_loop_offset + 4 * i; - polys[quad_offset + i].totloop = 4; + poly_offsets[quad_offset + i] = quad_loop_offset + 4 * i; for (int j = 0; j < 4; j++) { /* Reverse vertex order to get correct normals. */ corner_verts[quad_loop_offset + 4 * i + j] = vert_offset + vdb_quads[i][3 - j]; @@ -176,7 +174,7 @@ Mesh *volume_to_mesh(const openvdb::GridBase &grid, 0, 0, mesh->vert_positions_for_write(), - mesh->polys_for_write(), + mesh->poly_offsets_for_write(), mesh->corner_verts_for_write()); BKE_mesh_calc_edges(mesh, false, false); diff --git a/source/blender/blenlib/BLI_offset_indices.hh b/source/blender/blenlib/BLI_offset_indices.hh index 22c7666fd67..b374be8c43b 100644 --- a/source/blender/blenlib/BLI_offset_indices.hh +++ b/source/blender/blenlib/BLI_offset_indices.hh @@ -2,6 +2,8 @@ #pragma once +#include + #include "BLI_index_range.hh" #include "BLI_span.hh" @@ -33,7 +35,7 @@ template class OffsetIndices { /** Return the total number of elements in the referenced arrays. */ T total_size() const { - return offsets_.last(); + return offsets_.size() == 1 ? 0 : offsets_.last(); } /** @@ -42,7 +44,7 @@ template class OffsetIndices { */ int64_t size() const { - return offsets_.size() - 1; + return std::max(offsets_.size() - 1, 0); } bool is_empty() const @@ -83,6 +85,11 @@ template class OffsetIndices { BLI_assert(offsets_.index_range().drop_back(1).contains(range.last())); return OffsetIndices(offsets_.slice(range.start(), range.one_after_last())); } + + const T *data() const + { + return offsets_.data(); + } }; /** diff --git a/source/blender/blenloader/intern/versioning_290.cc b/source/blender/blenloader/intern/versioning_290.cc index 718bd66f746..08b60bf919e 100644 --- a/source/blender/blenloader/intern/versioning_290.cc +++ b/source/blender/blenloader/intern/versioning_290.cc @@ -817,11 +817,12 @@ void blo_do_versions_290(FileData *fd, Library * /*lib*/, Main *bmain) if (MAIN_VERSION_ATLEAST(bmain, 290, 2) && MAIN_VERSION_OLDER(bmain, 291, 1)) { /* In this range, the extrude manifold could generate meshes with degenerated face. */ LISTBASE_FOREACH (Mesh *, me, &bmain->meshes) { - blender::MutableSpan polys = me->polys_for_write(); - for (const int i : polys.index_range()) { + const MPoly *polys = static_cast(CustomData_get_layer(&me->pdata, CD_MPOLY)); + for (const int i : blender::IndexRange(me->totpoly)) { if (polys[i].totloop == 2) { bool changed; BKE_mesh_legacy_convert_loops_to_corners(me); + BKE_mesh_legacy_convert_polys_to_offsets(me); BKE_mesh_validate_arrays( me, BKE_mesh_vert_positions_for_write(me), @@ -832,8 +833,8 @@ void blo_do_versions_290(FileData *fd, Library * /*lib*/, Main *bmain) me->totface, me->corner_verts_for_write().data(), me->corner_edges_for_write().data(), - polys.size(), - polys.data(), + me->totloop, + BKE_mesh_poly_offsets_for_write(me), me->totpoly, BKE_mesh_deform_verts_for_write(me), false, diff --git a/source/blender/blenloader/intern/versioning_400.cc b/source/blender/blenloader/intern/versioning_400.cc index 5aab24d4eb5..c56c8a2608d 100644 --- a/source/blender/blenloader/intern/versioning_400.cc +++ b/source/blender/blenloader/intern/versioning_400.cc @@ -40,6 +40,7 @@ static void version_mesh_legacy_to_struct_of_array_format(Mesh &mesh) BKE_mesh_legacy_convert_verts_to_positions(&mesh); BKE_mesh_legacy_attribute_flags_to_strings(&mesh); BKE_mesh_legacy_convert_loops_to_corners(&mesh); + BKE_mesh_legacy_convert_polys_to_offsets(&mesh); } static void version_motion_tracking_legacy_camera_object(MovieClip &movieclip) diff --git a/source/blender/bmesh/intern/bmesh_mesh_convert.cc b/source/blender/bmesh/intern/bmesh_mesh_convert.cc index 98e63e799ac..e0cc433835b 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_convert.cc +++ b/source/blender/bmesh/intern/bmesh_mesh_convert.cc @@ -487,7 +487,7 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar bm->elem_index_dirty &= ~BM_EDGE; /* Added in order, clear dirty flag. */ } - const Span polys = me->polys(); + const blender::OffsetIndices polys = me->polys(); const Span corner_verts = me->corner_verts(); const Span corner_edges = me->corner_edges(); @@ -500,11 +500,9 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar int totloops = 0; for (const int i : polys.index_range()) { - BMFace *f = bm_face_create_from_mpoly(*bm, - corner_verts.slice(polys[i].loopstart, polys[i].totloop), - corner_edges.slice(polys[i].loopstart, polys[i].totloop), - vtable, - etable); + const IndexRange poly = polys[i]; + BMFace *f = bm_face_create_from_mpoly( + *bm, corner_verts.slice(poly), corner_edges.slice(poly), vtable, etable); if (!ftable.is_empty()) { ftable[i] = f; } @@ -538,7 +536,7 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar bm->act_face = f; } - int j = polys[i].loopstart; + int j = poly.start(); BMLoop *l_first = BM_FACE_FIRST_LOOP(f); BMLoop *l_iter = l_first; do { @@ -1328,15 +1326,13 @@ static void bm_to_mesh_faces(const BMesh &bm, MutableSpan sharp_faces, MutableSpan material_indices) { - CustomData_add_layer(&mesh.pdata, CD_MPOLY, CD_CONSTRUCT, mesh.totpoly); + BKE_mesh_poly_offsets_ensure_alloc(&mesh); const Vector info = bm_to_mesh_copy_info_calc(bm.pdata, mesh.pdata); - MutableSpan dst_polys = mesh.polys_for_write(); - threading::parallel_for(dst_polys.index_range(), 1024, [&](const IndexRange range) { + MutableSpan dst_poly_offsets = mesh.poly_offsets_for_write(); + threading::parallel_for(bm_faces.index_range(), 1024, [&](const IndexRange range) { for (const int face_i : range) { const BMFace &src_face = *bm_faces[face_i]; - MPoly &dst_poly = dst_polys[face_i]; - dst_poly.totloop = src_face.len; - dst_poly.loopstart = BM_elem_index_get(BM_FACE_FIRST_LOOP(&src_face)); + dst_poly_offsets[face_i] = BM_elem_index_get(BM_FACE_FIRST_LOOP(&src_face)); bmesh_block_copy_to_mesh_attributes(info, face_i, src_face.head.data); } if (!select_poly.is_empty()) { @@ -1391,6 +1387,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh CustomData_free(&me->fdata, me->totface); CustomData_free(&me->ldata, me->totloop); CustomData_free(&me->pdata, me->totpoly); + MEM_SAFE_FREE(me->poly_offset_indices); BKE_mesh_runtime_clear_geometry(me); me->totvert = bm->totvert; diff --git a/source/blender/draw/DRW_pbvh.hh b/source/blender/draw/DRW_pbvh.hh index 58a32944337..3c393526284 100644 --- a/source/blender/draw/DRW_pbvh.hh +++ b/source/blender/draw/DRW_pbvh.hh @@ -10,6 +10,7 @@ /* Needed for BKE_ccg.h. */ #include "BLI_assert.h" #include "BLI_bitmap.h" +#include "BLI_offset_indices.hh" #include "BLI_span.hh" #include "BKE_ccg.h" @@ -24,7 +25,6 @@ struct DMFlagMat; struct Mesh; struct MLoopTri; struct CustomData; -struct MPoly; struct SubdivCCG; struct BMesh; @@ -34,9 +34,9 @@ struct PBVH_GPU_Args { BMesh *bm; const Mesh *me; const float (*vert_positions)[3]; + blender::OffsetIndices polys; blender::Span corner_verts; blender::Span corner_edges; - const MPoly *polys; int mesh_verts_num, mesh_faces_num, mesh_grids_num; CustomData *vdata, *ldata, *pdata; const float (*vert_normals)[3]; diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.cc b/source/blender/draw/intern/draw_cache_extract_mesh.cc index 9da2d004363..3578f6269e3 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh.cc @@ -303,10 +303,9 @@ static void extract_range_iter_poly_mesh(void *__restrict userdata, const ExtractorIterData *data = static_cast(userdata); const MeshRenderData *mr = data->mr; - const MPoly *poly = &((const MPoly *)data->elems)[iter]; for (const ExtractorRunData &run_data : data->extractors) { run_data.extractor->iter_poly_mesh( - mr, poly, iter, POINTER_OFFSET(extract_data, run_data.data_offset)); + mr, iter, POINTER_OFFSET(extract_data, run_data.data_offset)); } } @@ -886,8 +885,7 @@ void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache *cache, /* Multiply by 4 to have the start index of the quad's loop, as subdiv_loop_poly_index is * based on the subdivision loops. */ const int poly_origindex = subdiv_loop_poly_index[i * 4]; - const MPoly &poly = mr->polys[poly_origindex]; - extractor->iter_subdiv_mesh(subdiv_cache, mr, data, i, &poly); + extractor->iter_subdiv_mesh(subdiv_cache, mr, data, i, poly_origindex); } } } 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 6c04fed4a94..e35192cfd43 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 @@ -191,12 +191,11 @@ static void mesh_render_data_mat_tri_len_mesh_range_fn(void *__restrict userdata MeshRenderData *mr = static_cast(userdata); int *mat_tri_len = static_cast(tls->userdata_chunk); - const MPoly &poly = mr->polys[iter]; if (!(mr->use_hide && mr->hide_poly && mr->hide_poly[iter])) { const int mat = mr->material_indices ? clamp_i(mr->material_indices[iter], 0, mr->mat_len - 1) : 0; - mat_tri_len[mat] += poly.totloop - 2; + mat_tri_len[mat] += mr->polys[iter].size() - 2; } } @@ -282,10 +281,9 @@ static void mesh_render_data_polys_sorted_build(MeshRenderData *mr, MeshBufferCa else { for (int i = 0; i < mr->poly_len; i++) { if (!(mr->use_hide && mr->hide_poly && mr->hide_poly[i])) { - const MPoly &poly = mr->polys[i]; const int mat = mr->material_indices ? clamp_i(mr->material_indices[i], 0, mat_last) : 0; tri_first_index[i] = mat_tri_offs[mat]; - mat_tri_offs[mat] += poly.totloop - 2; + mat_tri_offs[mat] += mr->polys[i].size() - 2; } else { tri_first_index[i] = -1; diff --git a/source/blender/draw/intern/draw_cache_impl_subdivision.cc b/source/blender/draw/intern/draw_cache_impl_subdivision.cc index c1cd510328a..390a341f235 100644 --- a/source/blender/draw/intern/draw_cache_impl_subdivision.cc +++ b/source/blender/draw/intern/draw_cache_impl_subdivision.cc @@ -754,7 +754,7 @@ static void draw_subdiv_cache_extra_coarse_face_data_mesh(const MeshRenderData * Mesh *mesh, uint32_t *flags_data) { - const Span polys = mesh->polys(); + const blender::OffsetIndices polys = mesh->polys(); for (const int i : polys.index_range()) { uint32_t flag = 0; if (!(mr->sharp_faces && mr->sharp_faces[i])) { @@ -766,7 +766,7 @@ static void draw_subdiv_cache_extra_coarse_face_data_mesh(const MeshRenderData * if (mr->hide_poly && mr->hide_poly[i]) { flag |= SUBDIV_COARSE_FACE_FLAG_HIDDEN; } - flags_data[i] = uint(polys[i].loopstart) | (flag << SUBDIV_COARSE_FACE_FLAG_OFFSET); + flags_data[i] = uint(polys[i].start()) | (flag << SUBDIV_COARSE_FACE_FLAG_OFFSET); } } @@ -780,7 +780,7 @@ static void draw_subdiv_cache_extra_coarse_face_data_mapped(Mesh *mesh, return; } - const Span polys = mesh->polys(); + const blender::OffsetIndices polys = mesh->polys(); for (const int i : polys.index_range()) { BMFace *f = bm_original_face_get(mr, i); /* Selection and hiding from bmesh. */ @@ -789,7 +789,7 @@ static void draw_subdiv_cache_extra_coarse_face_data_mapped(Mesh *mesh, if (!(mr->sharp_faces && mr->sharp_faces[i])) { flag |= SUBDIV_COARSE_FACE_FLAG_SMOOTH; } - flags_data[i] = uint(polys[i].loopstart) | (flag << SUBDIV_COARSE_FACE_FLAG_OFFSET); + flags_data[i] = uint(polys[i].start()) | (flag << SUBDIV_COARSE_FACE_FLAG_OFFSET); } } @@ -1209,7 +1209,7 @@ static bool draw_subdiv_build_cache(DRWSubdivCache *cache, } /* Only build polygon related data if we have polygons. */ - const Span polys = mesh_eval->polys(); + const blender::OffsetIndices polys = mesh_eval->polys(); if (cache->num_subdiv_loops != 0) { /* Build buffers for the PatchMap. */ draw_patch_map_build(&cache->gpu_patch_map, subdiv); @@ -1223,7 +1223,7 @@ static bool draw_subdiv_build_cache(DRWSubdivCache *cache, GPU_vertbuf_get_data(cache->fdots_patch_coords); for (int i = 0; i < mesh_eval->totpoly; i++) { const int ptex_face_index = cache->face_ptex_offset[i]; - if (polys[i].totloop == 4) { + if (polys[i].size() == 4) { /* For quads, the center coordinate of the coarse face has `u = v = 0.5`. */ blender_fdots_patch_coords[i] = make_patch_coord(ptex_face_index, 0.5f, 0.5f); } diff --git a/source/blender/draw/intern/draw_pbvh.cc b/source/blender/draw/intern/draw_pbvh.cc index d5b72a4204f..e6741c6474f 100644 --- a/source/blender/draw/intern/draw_pbvh.cc +++ b/source/blender/draw/intern/draw_pbvh.cc @@ -342,10 +342,9 @@ struct PBVHBatches { last_poly = tri->poly; flat = sharp_faces && sharp_faces[tri->poly]; if (flat) { - const MPoly &poly = args->polys[tri->poly]; const float3 fno = blender::bke::mesh::poly_normal_calc( {reinterpret_cast(args->vert_positions), args->mesh_verts_num}, - {&args->corner_verts[poly.loopstart], poly.totloop}); + args->corner_verts.slice(args->polys[tri->poly])); normal_float_to_short_v3(no, fno); } } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh.hh b/source/blender/draw/intern/mesh_extractors/extract_mesh.hh index 21c31c2c950..6d856fa09cf 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh.hh +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh.hh @@ -77,7 +77,7 @@ struct MeshRenderData { Mesh *me; blender::Span vert_positions; blender::Span edges; - blender::Span polys; + blender::OffsetIndices polys; blender::Span corner_verts; blender::Span corner_edges; BMVert *eve_act; @@ -253,10 +253,7 @@ using ExtractPolyBMeshFn = void(const MeshRenderData *mr, const BMFace *f, int f_index, void *data); -using ExtractPolyMeshFn = void(const MeshRenderData *mr, - const MPoly *poly, - int poly_index, - void *data); +using ExtractPolyMeshFn = void(const MeshRenderData *mr, int poly_index, void *data); using ExtractLEdgeBMeshFn = void(const MeshRenderData *mr, const BMEdge *eed, int ledge_index, @@ -298,7 +295,7 @@ using ExtractIterSubdivMeshFn = void(const DRWSubdivCache *subdiv_cache, const MeshRenderData *mr, void *data, uint subdiv_quad_index, - const MPoly *coarse_quad); + int coarse_quad_index); using ExtractFinishSubdivFn = void(const DRWSubdivCache *subdiv_cache, const MeshRenderData *mr, MeshBatchCache *cache, 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 3d3d6ed908e..dbb2d2a63ca 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 @@ -118,12 +118,12 @@ static void extract_edituv_tris_iter_subdiv_mesh(const DRWSubdivCache * /*subdiv const MeshRenderData *mr, void *_data, uint subdiv_quad_index, - const MPoly *coarse_quad) + const int coarse_quad_index) { MeshExtract_EditUvElem_Data *data = static_cast(_data); const uint loop_idx = subdiv_quad_index * 4; - const BMFace *efa = bm_original_face_get(mr, coarse_quad - mr->polys.data()); + const BMFace *efa = bm_original_face_get(mr, coarse_quad_index); 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; @@ -204,12 +204,11 @@ static void extract_edituv_lines_iter_poly_bm(const MeshRenderData * /*mr*/, } static void extract_edituv_lines_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *poly, const int poly_index, void *_data) { MeshExtract_EditUvElem_Data *data = static_cast(_data); - const int ml_index_end = poly->loopstart + poly->totloop; + const IndexRange poly = mr->polys[poly_index]; bool mp_hidden, mp_select; if (mr->bm) { @@ -222,11 +221,11 @@ static void extract_edituv_lines_iter_poly_mesh(const MeshRenderData *mr, mp_select = mr->select_poly && mr->select_poly[poly_index]; } - for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { + for (const int ml_index : poly) { const int edge = mr->corner_edges[ml_index]; - const int ml_index_last = poly->totloop + poly->loopstart - 1; - const int ml_index_next = (ml_index == ml_index_last) ? poly->loopstart : (ml_index + 1); + const int ml_index_last = poly.last(); + const int ml_index_next = (ml_index == ml_index_last) ? poly.start() : (ml_index + 1); const bool real_edge = (mr->e_origindex == nullptr || mr->e_origindex[edge] != ORIGINDEX_NONE); edituv_edge_add(data, mp_hidden || !real_edge, mp_select, ml_index, ml_index_next); } @@ -285,11 +284,10 @@ static void extract_edituv_lines_iter_subdiv_mesh(const DRWSubdivCache *subdiv_c const MeshRenderData *mr, void *_data, uint subdiv_quad_index, - const MPoly *coarse_poly) + const int coarse_poly_index) { MeshExtract_EditUvElem_Data *data = static_cast(_data); int *subdiv_loop_edge_index = (int *)GPU_vertbuf_get_data(subdiv_cache->edges_orig_index); - const int coarse_poly_index = coarse_poly - mr->polys.data(); bool mp_hidden, mp_select; if (mr->bm) { const BMFace *efa = bm_original_face_get(mr, coarse_poly_index); @@ -388,7 +386,6 @@ static void extract_edituv_points_iter_poly_bm(const MeshRenderData * /*mr*/, } static void extract_edituv_points_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *poly, const int poly_index, void *_data) { @@ -398,8 +395,7 @@ static void extract_edituv_points_iter_poly_mesh(const MeshRenderData *mr, 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; - const int ml_index_end = poly->loopstart + poly->totloop; - for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { + for (const int ml_index : mr->polys[poly_index]) { const int vert = mr->corner_verts[ml_index]; const bool real_vert = !mr->v_origindex || mr->v_origindex[vert] != ORIGINDEX_NONE; @@ -453,12 +449,12 @@ static void extract_edituv_points_iter_subdiv_mesh(const DRWSubdivCache *subdiv_ const MeshRenderData *mr, void *_data, uint subdiv_quad_index, - const MPoly *coarse_quad) + const int coarse_quad_index) { MeshExtract_EditUvElem_Data *data = static_cast(_data); int *subdiv_loop_vert_index = (int *)GPU_vertbuf_get_data(subdiv_cache->verts_orig_index); - const BMFace *efa = bm_original_face_get(mr, coarse_quad - mr->polys.data()); + const BMFace *efa = bm_original_face_get(mr, coarse_quad_index); 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; @@ -543,7 +539,6 @@ static void extract_edituv_fdots_iter_poly_bm(const MeshRenderData * /*mr*/, } static void extract_edituv_fdots_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *poly, const int poly_index, void *_data) { @@ -556,8 +551,7 @@ static void extract_edituv_fdots_iter_poly_mesh(const MeshRenderData *mr, if (mr->use_subsurf_fdots) { const BitSpan facedot_tags = mr->me->runtime->subsurf_face_dot_tags; - const int ml_index_end = poly->loopstart + poly->totloop; - for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { + for (const int ml_index : mr->polys[poly_index]) { const int vert = mr->corner_verts[ml_index]; const bool real_fdot = !mr->p_origindex || (mr->p_origindex[poly_index] != ORIGINDEX_NONE); diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_fdots.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_fdots.cc index 9b90f6e5d64..f9ea366bcdb 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_fdots.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_fdots.cc @@ -38,7 +38,6 @@ static void extract_fdots_iter_poly_bm(const MeshRenderData * /*mr*/, } static void extract_fdots_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *poly, const int poly_index, void *_userdata) { @@ -48,8 +47,7 @@ static void extract_fdots_iter_poly_mesh(const MeshRenderData *mr, if (mr->use_subsurf_fdots) { const BitSpan facedot_tags = mr->me->runtime->subsurf_face_dot_tags; - const int ml_index_end = poly->loopstart + poly->totloop; - for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { + for (const int ml_index : mr->polys[poly_index]) { const int vert = mr->corner_verts[ml_index]; if (facedot_tags[vert] && !hidden) { GPU_indexbuf_set_point_vert(elb, poly_index, poly_index); diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc index b6671048b92..f5d1dbb2451 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc @@ -85,16 +85,18 @@ static void extract_lines_iter_poly_bm(const MeshRenderData * /*mr*/, } static void extract_lines_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *poly, - const int /*poly_index*/, + const int poly_index, void *tls_data) { MeshExtract_LinesData *data = static_cast(tls_data); GPUIndexBufBuilder *elb = &data->elb; + + const IndexRange poly = mr->polys[poly_index]; + /* Using poly & loop iterator would complicate accessing the adjacent loop. */ if (data->test_visibility) { - const int ml_index_last = poly->loopstart + (poly->totloop - 1); - int ml_index = ml_index_last, ml_index_next = poly->loopstart; + const int ml_index_last = poly.last(); + int ml_index = ml_index_last, ml_index_next = poly.start(); do { const int edge = mr->corner_edges[ml_index]; if (is_edge_visible(data, edge)) { @@ -106,8 +108,8 @@ static void extract_lines_iter_poly_mesh(const MeshRenderData *mr, } while ((ml_index = ml_index_next++) != ml_index_last); } else { - const int ml_index_last = poly->loopstart + (poly->totloop - 1); - int ml_index = ml_index_last, ml_index_next = poly->loopstart; + const int ml_index_last = poly.last(); + int ml_index = ml_index_last, ml_index_next = poly.start(); do { const int edge = mr->corner_edges[ml_index]; GPU_indexbuf_set_line_verts(elb, edge, ml_index, ml_index_next); 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 63402834bc0..a9800acd669 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 @@ -216,7 +216,7 @@ static void extract_lines_adjacency_iter_subdiv_mesh(const DRWSubdivCache *subdi const MeshRenderData *mr, void *_data, uint subdiv_quad_index, - const MPoly * /*coarse_quad*/) + const int /*coarse_quad_index*/) { extract_lines_adjacency_iter_subdiv(subdiv_cache, mr, _data, subdiv_quad_index); } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc index e2fdf3e91ec..6b487b85e0f 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc @@ -36,20 +36,21 @@ static void extract_lines_paint_mask_init(const MeshRenderData *mr, } static void extract_lines_paint_mask_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *poly, const int poly_index, void *_data) { MeshExtract_LinePaintMask_Data *data = static_cast(_data); - const int ml_index_end = poly->loopstart + poly->totloop; - for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { + const IndexRange poly = mr->polys[poly_index]; + + const int ml_index_end = poly.start() + poly.size(); + for (int ml_index = poly.start(); ml_index < ml_index_end; ml_index += 1) { const int e_index = mr->corner_edges[ml_index]; if (!((mr->use_hide && mr->hide_edge && mr->hide_edge[e_index]) || ((mr->e_origindex) && (mr->e_origindex[e_index] == ORIGINDEX_NONE)))) { - const int ml_index_last = poly->totloop + poly->loopstart - 1; - const int ml_index_other = (ml_index == ml_index_last) ? poly->loopstart : (ml_index + 1); + const int ml_index_last = poly.size() + poly.start() - 1; + const int ml_index_other = (ml_index == ml_index_last) ? poly.start() : (ml_index + 1); if (mr->select_poly && mr->select_poly[poly_index]) { if (BLI_BITMAP_TEST_AND_SET_ATOMIC(data->select_map, e_index)) { /* Hide edge as it has more than 2 selected loop. */ @@ -102,14 +103,12 @@ static void extract_lines_paint_mask_iter_subdiv_mesh(const DRWSubdivCache *subd const MeshRenderData *mr, void *_data, uint subdiv_quad_index, - const MPoly *coarse_quad) + const int coarse_quad_index) { MeshExtract_LinePaintMask_Data *data = static_cast(_data); int *subdiv_loop_edge_index = (int *)GPU_vertbuf_get_data(subdiv_cache->edges_orig_index); int *subdiv_loop_subdiv_edge_index = subdiv_cache->subdiv_loop_subdiv_edge_index; - const int coarse_quad_index = coarse_quad - mr->polys.data(); - uint start_loop_idx = subdiv_quad_index * 4; uint end_loop_idx = (subdiv_quad_index + 1) * 4; for (uint loop_idx = start_loop_idx; loop_idx < end_loop_idx; loop_idx++) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc index 382809216dc..bee908d1194 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc @@ -69,13 +69,11 @@ static void extract_points_iter_poly_bm(const MeshRenderData * /*mr*/, } static void extract_points_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *poly, - const int /*poly_index*/, + const int poly_index, void *_userdata) { GPUIndexBufBuilder *elb = static_cast(_userdata); - const int ml_index_end = poly->loopstart + poly->totloop; - for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { + for (const int ml_index : mr->polys[poly_index]) { vert_set_mesh(elb, mr, mr->corner_verts[ml_index], ml_index); } } @@ -201,7 +199,7 @@ static void extract_points_iter_subdiv_mesh(const DRWSubdivCache *subdiv_cache, const MeshRenderData *mr, void *_data, uint subdiv_quad_index, - const MPoly * /*coarse_quad*/) + const int /*coarse_quad_index*/) { GPUIndexBufBuilder *elb = static_cast(_data); extract_points_iter_subdiv_common(elb, mr, subdiv_cache, subdiv_quad_index, false); 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 a5c37d6ce4c..bb04552d3df 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 @@ -60,7 +60,6 @@ static void extract_tris_iter_poly_bm(const MeshRenderData *mr, } static void extract_tris_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *poly, const int poly_index, void *_data) { @@ -69,10 +68,12 @@ static void extract_tris_iter_poly_mesh(const MeshRenderData *mr, return; } - GPUIndexBufBuilder *elb = static_cast(_data); - int tri_first_index_real = poly_to_tri_count(poly_index, poly->loopstart); + const IndexRange poly = mr->polys[poly_index]; - int tri_len = poly->totloop - 2; + GPUIndexBufBuilder *elb = static_cast(_data); + int tri_first_index_real = poly_to_tri_count(poly_index, poly.start()); + + int tri_len = poly.size() - 2; for (int offs = 0; offs < tri_len; offs++) { const MLoopTri *mlt = &mr->looptris[tri_first_index_real + offs]; int tri_index = tri_first_index + offs; diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc index 1d486e2e069..62c4273afc5 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc @@ -211,9 +211,9 @@ static void fill_vertbuf_with_attribute(const MeshRenderData *mr, break; case ATTR_DOMAIN_FACE: for (int poly_index = 0; poly_index < mr->poly_len; poly_index++) { - const MPoly &poly = mr->polys[poly_index]; + const IndexRange poly = mr->polys[poly_index]; const VBOType value = Converter::convert_value(attr_data[poly_index]); - for (int l = 0; l < poly.totloop; l++) { + for (int l = 0; l < poly.size(); l++) { *vbo_data++ = value; } } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc index 7c732ffba11..73853bda4d6 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc @@ -109,15 +109,14 @@ static void extract_edge_fac_iter_poly_bm(const MeshRenderData *mr, } static void extract_edge_fac_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *poly, const int poly_index, void *_data) { MeshExtract_EdgeFac_Data *data = static_cast(_data); + const IndexRange poly = mr->polys[poly_index]; const BitSpan optimal_display_edges = mr->me->runtime->subsurf_optimal_display_edges; - const int ml_index_end = poly->loopstart + poly->totloop; - for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { + for (const int ml_index : poly) { const int edge = mr->corner_edges[ml_index]; if (data->use_edge_render && !optimal_display_edges[edge]) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc index cf8b812e2a2..730acc2ffe8 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc @@ -145,14 +145,12 @@ static void extract_edit_data_iter_poly_bm(const MeshRenderData *mr, } static void extract_edit_data_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *poly, const int poly_index, void *_data) { EditLoopData *vbo_data = *(EditLoopData **)_data; - const int ml_index_end = poly->loopstart + poly->totloop; - for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { + for (const int ml_index : mr->polys[poly_index]) { EditLoopData *data = vbo_data + ml_index; memset(data, 0x0, sizeof(*data)); BMFace *efa = bm_original_face_get(mr, poly_index); @@ -295,9 +293,8 @@ static void extract_edit_data_iter_subdiv_mesh(const DRWSubdivCache *subdiv_cach const MeshRenderData *mr, void *_data, uint subdiv_quad_index, - const MPoly *coarse_quad) + const int coarse_quad_index) { - const int coarse_quad_index = int(coarse_quad - mr->polys.data()); BMFace *coarse_quad_bm = bm_original_face_get(mr, coarse_quad_index); extract_edit_data_iter_subdiv_bm(subdiv_cache, mr, _data, subdiv_quad_index, coarse_quad_bm); } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc index 1939a9fe56a..3fe03ae665c 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc @@ -70,13 +70,13 @@ static void extract_edituv_data_iter_poly_bm(const MeshRenderData *mr, } static void extract_edituv_data_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *poly, const int poly_index, void *_data) { MeshExtract_EditUVData_Data *data = static_cast(_data); - const int ml_index_end = poly->loopstart + poly->totloop; - for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { + const IndexRange poly = mr->polys[poly_index]; + const int ml_index_end = poly.start() + poly.size(); + for (int ml_index = poly.start(); ml_index < ml_index_end; ml_index += 1) { EditLoopData *eldata = &data->vbo_data[ml_index]; memset(eldata, 0x0, sizeof(*eldata)); BMFace *efa = bm_original_face_get(mr, poly_index); @@ -93,8 +93,8 @@ static void extract_edituv_data_iter_poly_mesh(const MeshRenderData *mr, if (eed == nullptr) { /* Find if the loop's vert is not part of an edit edge. * For this, we check if the previous loop was on an edge. */ - const int ml_index_last = poly->loopstart + poly->totloop - 1; - const int l_prev = (ml_index == poly->loopstart) ? ml_index_last : (ml_index - 1); + const int ml_index_last = poly.start() + poly.size() - 1; + const int l_prev = (ml_index == poly.start()) ? ml_index_last : (ml_index - 1); eed = bm_original_edge_get(mr, mr->corner_edges[l_prev]); } if (eed) { @@ -167,9 +167,8 @@ static void extract_edituv_data_iter_subdiv_mesh(const DRWSubdivCache *subdiv_ca const MeshRenderData *mr, void *_data, uint subdiv_quad_index, - const MPoly *coarse_quad) + const int coarse_quad_index) { - const int coarse_quad_index = int(coarse_quad - mr->polys.data()); BMFace *coarse_quad_bm = bm_original_face_get(mr, coarse_quad_index); extract_edituv_data_iter_subdiv_bm(subdiv_cache, mr, _data, subdiv_quad_index, coarse_quad_bm); } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc index a0ffa15b914..564e48e06e6 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc @@ -154,21 +154,21 @@ static void extract_edituv_stretch_angle_iter_poly_bm(const MeshRenderData *mr, } static void extract_edituv_stretch_angle_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *poly, - const int /*poly_index*/, + const int poly_index, void *_data) { MeshExtract_StretchAngle_Data *data = static_cast(_data); + const IndexRange poly = mr->polys[poly_index]; - const int ml_index_end = poly->loopstart + poly->totloop; - for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { + const int ml_index_end = poly.start() + poly.size(); + for (int ml_index = poly.start(); ml_index < ml_index_end; ml_index += 1) { float(*auv)[2] = data->auv, *last_auv = data->last_auv; float(*av)[3] = data->av, *last_av = data->last_av; int l_next = ml_index + 1; - if (ml_index == poly->loopstart) { + if (ml_index == poly.start()) { /* First loop in face. */ const int ml_index_last = ml_index_end - 1; - const int l_next_tmp = poly->loopstart; + const int l_next_tmp = poly.start(); compute_normalize_edge_vectors(auv, av, data->uv[ml_index_last], @@ -180,7 +180,7 @@ static void extract_edituv_stretch_angle_iter_poly_mesh(const MeshRenderData *mr copy_v3_v3(last_av, av[1]); } if (l_next == ml_index_end) { - l_next = poly->loopstart; + l_next = poly.start(); /* Move previous edge. */ copy_v2_v2(auv[0], auv[1]); copy_v3_v3(av[0], av[1]); diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc index 637965839ff..cbd6a174b0f 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc @@ -76,11 +76,11 @@ static void compute_area_ratio(const MeshRenderData *mr, BLI_assert(mr->extract_type == MR_EXTRACT_MESH); const float2 *uv_data = (const float2 *)CustomData_get_layer(&mr->me->ldata, CD_PROP_FLOAT2); for (int poly_index = 0; poly_index < mr->poly_len; poly_index++) { - const MPoly &poly = mr->polys[poly_index]; - const float area = bke::mesh::poly_area_calc( - mr->vert_positions, mr->corner_verts.slice(poly.loopstart, poly.totloop)); - float uvarea = area_poly_v2(reinterpret_cast(&uv_data[poly.loopstart]), - poly.totloop); + const IndexRange poly = mr->polys[poly_index]; + const float area = bke::mesh::poly_area_calc(mr->vert_positions, + mr->corner_verts.slice(poly)); + float uvarea = area_poly_v2(reinterpret_cast(&uv_data[poly.start()]), + poly.size()); tot_area += area; tot_uv_area += uvarea; r_area_ratio[poly_index] = area_ratio_get(area, uvarea); @@ -115,10 +115,9 @@ static void extract_edituv_stretch_area_finish(const MeshRenderData *mr, } else { BLI_assert(mr->extract_type == MR_EXTRACT_MESH); - for (const int poly_i : mr->polys.index_range()) { - const MPoly &poly = mr->polys[poly_i]; - for (const int loop_i : IndexRange(poly.loopstart, poly.totloop)) { - loop_stretch[loop_i] = area_ratio[poly_i]; + for (int poly_index = 0; poly_index < mr->poly_len; poly_index++) { + for (const int l_index : mr->polys[poly_index]) { + loop_stretch[l_index] = area_ratio[poly_index]; } } } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_edituv_data.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_edituv_data.cc index f9366965b21..bb5812e264e 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_edituv_data.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_edituv_data.cc @@ -51,7 +51,6 @@ static void extract_fdots_edituv_data_iter_poly_bm(const MeshRenderData *mr, } static void extract_fdots_edituv_data_iter_poly_mesh(const MeshRenderData *mr, - const MPoly * /*poly*/, const int poly_index, void *_data) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc index c79fb037d5a..2b463bd59d1 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc @@ -67,7 +67,6 @@ static void extract_fdots_pos_iter_poly_bm(const MeshRenderData *mr, } static void extract_fdots_pos_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *poly, const int poly_index, void *data) { @@ -77,8 +76,7 @@ static void extract_fdots_pos_iter_poly_mesh(const MeshRenderData *mr, const BitSpan facedot_tags = mr->me->runtime->subsurf_face_dot_tags; - const int ml_index_end = poly->loopstart + poly->totloop; - for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { + for (const int ml_index : mr->polys[poly_index]) { const int vert = mr->corner_verts[ml_index]; if (mr->use_subsurf_fdots) { if (facedot_tags[vert]) { @@ -92,7 +90,7 @@ static void extract_fdots_pos_iter_poly_mesh(const MeshRenderData *mr, } if (!mr->use_subsurf_fdots) { - mul_v3_fl(co, 1.0f / float(poly->totloop)); + mul_v3_fl(co, 1.0f / float(mr->polys[poly_index].size())); } } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_uv.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_uv.cc index a55d7329f18..5f9c4e3da23 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_uv.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_uv.cc @@ -69,15 +69,13 @@ static void extract_fdots_uv_iter_poly_bm(const MeshRenderData * /*mr*/, } static void extract_fdots_uv_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *poly, const int poly_index, void *_data) { MeshExtract_FdotUV_Data *data = static_cast(_data); const BitSpan facedot_tags = mr->me->runtime->subsurf_face_dot_tags; - const int ml_index_end = poly->loopstart + poly->totloop; - for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { + for (const int ml_index : mr->polys[poly_index]) { const int vert = mr->corner_verts[ml_index]; if (mr->use_subsurf_fdots) { if (facedot_tags[vert]) { @@ -85,7 +83,7 @@ static void extract_fdots_uv_iter_poly_mesh(const MeshRenderData *mr, } } else { - float w = 1.0f / float(poly->totloop); + float w = 1.0f / float(mr->polys[poly_index].size()); madd_v2_v2fl(data->vbo_data[poly_index], data->uv_data[ml_index], w); } } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc index 6aaef8d7d5f..bd1e91bd4a7 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc @@ -57,15 +57,11 @@ static void extract_lnor_iter_poly_bm(const MeshRenderData *mr, } while ((l_iter = l_iter->next) != l_first); } -static void extract_lnor_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *poly, - const int poly_index, - void *data) +static void extract_lnor_iter_poly_mesh(const MeshRenderData *mr, const int poly_index, void *data) { const bool hidden = mr->hide_poly && mr->hide_poly[poly_index]; - const int ml_index_end = poly->loopstart + poly->totloop; - for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { + for (const int ml_index : mr->polys[poly_index]) { const int vert = mr->corner_verts[ml_index]; GPUPackedNormal *lnor_data = &(*(GPUPackedNormal **)data)[ml_index]; if (!mr->loop_normals.is_empty()) { @@ -182,14 +178,12 @@ static void extract_lnor_hq_iter_poly_bm(const MeshRenderData *mr, } static void extract_lnor_hq_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *poly, const int poly_index, void *data) { const bool hidden = mr->hide_poly && mr->hide_poly[poly_index]; - const int ml_index_end = poly->loopstart + poly->totloop; - for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { + for (const int ml_index : mr->polys[poly_index]) { const int vert = mr->corner_verts[ml_index]; gpuHQNor *lnor_data = &(*(gpuHQNor **)data)[ml_index]; if (!mr->loop_normals.is_empty()) { 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 e9873379d61..52ad80baf1a 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 @@ -97,10 +97,9 @@ static void statvis_calc_overhang(const MeshRenderData *mr, float *r_overhang) } else { for (const int poly_i : mr->polys.index_range()) { - const MPoly &poly = mr->polys[poly_i]; float fac = angle_normalized_v3v3(mr->poly_normals[poly_i], dir) / float(M_PI); fac = overhang_remap(fac, min, max, minmax_irange); - for (const int loop_i : IndexRange(poly.loopstart, poly.totloop)) { + for (const int loop_i : mr->polys[poly_i]) { r_overhang[loop_i] = fac; } } @@ -248,10 +247,9 @@ static void statvis_calc_thickness(const MeshRenderData *mr, float *r_thickness) } for (const int poly_i : mr->polys.index_range()) { - const MPoly &poly = mr->polys[poly_i]; float fac = face_dists[poly_i]; fac = thickness_remap(fac, min, max, minmax_irange); - for (const int loop_i : IndexRange(poly.loopstart, poly.totloop)) { + for (const int loop_i : mr->polys[poly_i]) { r_thickness[loop_i] = fac; } } @@ -350,14 +348,11 @@ static void statvis_calc_intersect(const MeshRenderData *mr, float *r_intersect) BVHTreeOverlap *overlap = BLI_bvhtree_overlap_self(tree, &overlap_len, bvh_overlap_cb, &data); if (overlap) { for (int i = 0; i < overlap_len; i++) { - const MPoly *f_hit_pair[2] = { - &mr->polys[mr->looptris[overlap[i].indexA].poly], - &mr->polys[mr->looptris[overlap[i].indexB].poly], - }; - for (int j = 0; j < 2; j++) { - const MPoly *f_hit = f_hit_pair[j]; - int l_index = f_hit->loopstart; - for (int k = 0; k < f_hit->totloop; k++, l_index++) { + + for (const IndexRange f_hit : {mr->polys[mr->looptris[overlap[i].indexA].poly], + mr->polys[mr->looptris[overlap[i].indexB].poly]}) { + int l_index = f_hit.start(); + for (int k = 0; k < f_hit.size(); k++, l_index++) { r_intersect[l_index] = 1.0f; } } @@ -440,19 +435,18 @@ static void statvis_calc_distort(const MeshRenderData *mr, float *r_distort) } } else { - int l_index = 0; for (const int poly_index : mr->polys.index_range()) { - const MPoly &poly = mr->polys[poly_index]; + const IndexRange poly = mr->polys[poly_index]; float fac = -1.0f; - if (poly.totloop > 3) { + if (poly.size() > 3) { const float *f_no = mr->poly_normals[poly_index]; fac = 0.0f; - for (int i = 1; i <= poly.totloop; i++) { - const int corner_prev = poly.loopstart + (i - 1) % poly.totloop; - const int corner_curr = poly.loopstart + (i + 0) % poly.totloop; - const int corner_next = poly.loopstart + (i + 1) % poly.totloop; + for (int i = 1; i <= poly.size(); i++) { + const int corner_prev = poly.start() + (i - 1) % poly.size(); + const int corner_curr = poly.start() + (i + 0) % poly.size(); + const int corner_next = poly.start() + (i + 1) % poly.size(); float no_corner[3]; normal_tri_v3(no_corner, mr->vert_positions[mr->corner_verts[corner_prev]], @@ -468,8 +462,8 @@ static void statvis_calc_distort(const MeshRenderData *mr, float *r_distort) } fac = distort_remap(fac, min, max, minmax_irange); - for (int i = 0; i < poly.totloop; i++, l_index++) { - r_distort[l_index] = fac; + for (const int corner : poly) { + r_distort[corner] = fac; } } } @@ -530,11 +524,11 @@ static void statvis_calc_sharp(const MeshRenderData *mr, float *r_sharp) EdgeHash *eh = BLI_edgehash_new_ex(__func__, mr->edge_len); - for (const int poly_index : mr->polys.index_range()) { - const MPoly &poly = mr->polys[poly_index]; - for (int i = 0; i < poly.totloop; i++) { - const int vert_curr = mr->corner_verts[poly.loopstart + (i + 0) % poly.totloop]; - const int vert_next = mr->corner_verts[poly.loopstart + (i + 1) % poly.totloop]; + for (int poly_index = 0; poly_index < mr->poly_len; poly_index++) { + const IndexRange poly = mr->polys[poly_index]; + for (int i = 0; i < poly.size(); i++) { + const int vert_curr = mr->corner_verts[poly.start() + (i + 0) % poly.size()]; + const int vert_next = mr->corner_verts[poly.start() + (i + 1) % poly.size()]; float angle; void **pval; bool value_is_init = BLI_edgehash_ensure_p(eh, vert_curr, vert_next, &pval); diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc index b46e834e37e..c721cdc78b4 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc @@ -61,13 +61,9 @@ static void extract_orco_iter_poly_bm(const MeshRenderData * /*mr*/, } while ((l_iter = l_iter->next) != l_first); } -static void extract_orco_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *poly, - const int /*poly_index*/, - void *data) +static void extract_orco_iter_poly_mesh(const MeshRenderData *mr, const int poly_index, void *data) { - const int ml_index_end = poly->loopstart + poly->totloop; - for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { + for (const int ml_index : mr->polys[poly_index]) { const int vert = mr->corner_verts[ml_index]; MeshExtract_Orco_Data *orco_data = (MeshExtract_Orco_Data *)data; float *loop_orco = orco_data->vbo_data[ml_index]; diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc index e92c2fac1d8..39f11721674 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc @@ -82,17 +82,14 @@ static void extract_pos_nor_iter_poly_bm(const MeshRenderData *mr, } static void extract_pos_nor_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *poly, const int poly_index, void *_data) { MeshExtract_PosNor_Data *data = static_cast(_data); const bool poly_hidden = mr->hide_poly && mr->hide_poly[poly_index]; - const int ml_index_end = poly->loopstart + poly->totloop; - for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { + for (const int ml_index : mr->polys[poly_index]) { const int vert_i = mr->corner_verts[ml_index]; - PosNorLoop *vert = &data->vbo_data[ml_index]; const bool vert_hidden = mr->hide_vert && mr->hide_vert[vert_i]; copy_v3_v3(vert->pos, mr->vert_positions[vert_i]); @@ -457,15 +454,13 @@ static void extract_pos_nor_hq_iter_poly_bm(const MeshRenderData *mr, } static void extract_pos_nor_hq_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *poly, - const int /*poly_index*/, + const int poly_index, void *_data) { MeshExtract_PosNorHQ_Data *data = static_cast(_data); - const bool poly_hidden = mr->hide_poly && mr->hide_poly[poly - mr->polys.data()]; + const bool poly_hidden = mr->hide_poly && mr->hide_poly[poly_index]; - const int ml_index_end = poly->loopstart + poly->totloop; - for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { + for (const int ml_index : mr->polys[poly_index]) { const int vert_i = mr->corner_verts[ml_index]; const bool vert_hidden = mr->hide_vert && mr->hide_vert[vert_i]; diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_sculpt_data.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_sculpt_data.cc index c82dbcb865d..985b2170214 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_sculpt_data.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_sculpt_data.cc @@ -84,13 +84,11 @@ static void extract_sculpt_data_init(const MeshRenderData *mr, } } else { - int mp_loop = 0; for (int poly_index = 0; poly_index < mr->poly_len; poly_index++) { - const MPoly &poly = mr->polys[poly_index]; - for (int l = 0; l < poly.totloop; l++) { + for (const int corner : mr->polys[poly_index]) { float v_mask = 0.0f; if (cd_mask) { - v_mask = cd_mask[mr->corner_verts[mp_loop]]; + v_mask = cd_mask[mr->corner_verts[corner]]; } vbo_data->mask = v_mask; @@ -104,7 +102,6 @@ static void extract_sculpt_data_init(const MeshRenderData *mr, } } copy_v3_v3_uchar(vbo_data->face_set_color, face_set_color); - mp_loop++; vbo_data++; } } @@ -128,7 +125,7 @@ static void extract_sculpt_data_init_subdiv(const DRWSubdivCache *subdiv_cache, GPUVertBuf *subdiv_mask_vbo = nullptr; const float *cd_mask = (const float *)CustomData_get_layer(cd_vdata, CD_PAINT_MASK); - const Span coarse_polys = coarse_mesh->polys(); + const OffsetIndices coarse_polys = coarse_mesh->polys(); const Span coarse_corner_verts = coarse_mesh->corner_verts(); if (cd_mask) { @@ -141,11 +138,8 @@ static void extract_sculpt_data_init_subdiv(const DRWSubdivCache *subdiv_cache, float *v_mask = static_cast(GPU_vertbuf_get_data(mask_vbo)); for (int i = 0; i < coarse_mesh->totpoly; i++) { - const MPoly &poly = coarse_polys[i]; - - for (int loop_index = poly.loopstart; loop_index < poly.loopstart + poly.totloop; - loop_index++) { - *v_mask++ = cd_mask[coarse_corner_verts[loop_index]]; + for (const int vert : coarse_corner_verts.slice(coarse_polys[i])) { + *v_mask++ = cd_mask[vert]; } } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc index 303239a0840..183c2d0323b 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc @@ -110,35 +110,29 @@ static void extract_vert_idx_iter_loose_vert_bm(const MeshRenderData *mr, } static void extract_poly_idx_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *poly, const int poly_index, void *data) { - const int ml_index_end = poly->loopstart + poly->totloop; - for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { + for (const int ml_index : mr->polys[poly_index]) { (*(int32_t **)data)[ml_index] = (mr->p_origindex) ? mr->p_origindex[poly_index] : poly_index; } } static void extract_edge_idx_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *poly, - const int /*poly_index*/, + const int poly_index, void *data) { - const int ml_index_end = poly->loopstart + poly->totloop; - for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { + for (const int ml_index : mr->polys[poly_index]) { const int edge = mr->corner_edges[ml_index]; (*(int32_t **)data)[ml_index] = (mr->e_origindex) ? mr->e_origindex[edge] : edge; } } static void extract_vert_idx_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *poly, - const int /*poly_index*/, + const int poly_index, void *data) { - const int ml_index_end = poly->loopstart + poly->totloop; - for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { + for (const int ml_index : mr->polys[poly_index]) { const int vert = mr->corner_verts[ml_index]; (*(int32_t **)data)[ml_index] = (mr->v_origindex) ? mr->v_origindex[vert] : vert; } @@ -379,7 +373,6 @@ static void extract_fdot_idx_iter_poly_bm(const MeshRenderData * /*mr*/, } static void extract_fdot_idx_iter_poly_mesh(const MeshRenderData *mr, - const MPoly * /*poly*/, const int poly_index, void *data) { 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 50a486f29b3..c6361345b10 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 @@ -115,8 +115,7 @@ static void extract_tan_init_common(const MeshRenderData *mr, } else { BKE_mesh_calc_loop_tangent_ex(reinterpret_cast(mr->vert_positions.data()), - mr->polys.data(), - mr->polys.size(), + mr->polys, mr->corner_verts.data(), mr->looptris.data(), mr->tri_len, diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_weights.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_weights.cc index f08eb2eddd6..ef05e967f12 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_weights.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_weights.cc @@ -133,13 +133,11 @@ static void extract_weights_iter_poly_bm(const MeshRenderData * /*mr*/, } static void extract_weights_iter_poly_mesh(const MeshRenderData *mr, - const MPoly *poly, - const int /*poly_index*/, + const int poly_index, void *_data) { MeshExtract_Weight_Data *data = static_cast(_data); - const int ml_index_end = poly->loopstart + poly->totloop; - for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { + for (const int ml_index : mr->polys[poly_index]) { const int vert = mr->corner_verts[ml_index]; if (data->dvert != nullptr) { const MDeformVert *dvert = &data->dvert[vert]; @@ -171,10 +169,9 @@ static void extract_weights_init_subdiv(const DRWSubdivCache *subdiv_cache, extract_weights_init(mr, cache, coarse_weights, _data); if (mr->extract_type != MR_EXTRACT_BMESH) { - const Span coarse_polys = coarse_mesh->polys(); + const OffsetIndices coarse_polys = coarse_mesh->polys(); for (const int i : coarse_polys.index_range()) { - const MPoly &poly = coarse_polys[i]; - extract_weights_iter_poly_mesh(mr, &poly, i, _data); + extract_weights_iter_poly_mesh(mr, i, _data); } } else { diff --git a/source/blender/editors/armature/meshlaplacian.cc b/source/blender/editors/armature/meshlaplacian.cc index 048ed456d8c..156e7bf597d 100644 --- a/source/blender/editors/armature/meshlaplacian.cc +++ b/source/blender/editors/armature/meshlaplacian.cc @@ -649,7 +649,7 @@ void heat_bone_weighting(Object *ob, bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0; const blender::Span vert_positions = me->vert_positions(); - const blender::Span polys = me->polys(); + const blender::OffsetIndices polys = me->polys(); const blender::Span corner_verts = me->corner_verts(); bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; @@ -669,7 +669,7 @@ void heat_bone_weighting(Object *ob, &me->vdata, CD_PROP_BOOL, ".select_vert"); if (select_vert) { for (const int i : polys.index_range()) { - for (const int vert : corner_verts.slice(polys[i].loopstart, polys[i].totloop)) { + for (const int vert : corner_verts.slice(polys[i])) { mask[vert] = select_vert[vert]; } } @@ -681,7 +681,7 @@ void heat_bone_weighting(Object *ob, if (select_poly) { for (const int i : polys.index_range()) { if (select_poly[i]) { - for (const int vert : corner_verts.slice(polys[i].loopstart, polys[i].totloop)) { + for (const int vert : corner_verts.slice(polys[i])) { mask[vert] = 1; } } @@ -871,11 +871,11 @@ typedef struct MDefBoundIsect { float co[3]; /* non-facing intersections are considered interior */ bool facing; - /* ray-cast index aligned with MPoly (ray-hit-triangle isn't needed) */ + /* ray-cast index aligned with polygons (ray-hit-triangle isn't needed) */ int poly_index; /* distance from 'co' to the ray-cast start (clamped to avoid zero division) */ float len; - /* weights aligned with the MPoly's loop indices */ + /* weights aligned with the polygons's loop indices */ float poly_weights[0]; } MDefBoundIsect; @@ -918,7 +918,7 @@ typedef struct MeshDeformBind { /* avoid DM function calls during intersections */ struct { - blender::Span polys; + blender::OffsetIndices polys; blender::Span corner_verts; blender::Span looptris; blender::Span poly_normals; @@ -1026,16 +1026,16 @@ 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 MPoly &poly = mdb->cagemesh_cache.polys[lt->poly]; + const blender::IndexRange poly = mdb->cagemesh_cache.polys[lt->poly]; const float(*cagecos)[3] = mdb->cagecos; const float len = isect_mdef.lambda; MDefBoundIsect *isect; - blender::Array mp_cagecos(poly.totloop); + blender::Array mp_cagecos(poly.size()); /* create MDefBoundIsect, and extra for 'poly_weights[]' */ isect = static_cast( - BLI_memarena_alloc(mdb->memarena, sizeof(*isect) + (sizeof(float) * poly.totloop))); + BLI_memarena_alloc(mdb->memarena, sizeof(*isect) + (sizeof(float) * poly.size()))); /* compute intersection coordinate */ madd_v3_v3v3fl(isect->co, co1, isect_mdef.vec, len); @@ -1047,13 +1047,13 @@ static MDefBoundIsect *meshdeform_ray_tree_intersect(MeshDeformBind *mdb, isect->len = max_ff(len_v3v3(co1, isect->co), MESHDEFORM_LEN_THRESHOLD); /* compute mean value coordinates for interpolation */ - for (int i = 0; i < poly.totloop; i++) { - copy_v3_v3(mp_cagecos[i], cagecos[corner_verts[poly.loopstart + i]]); + for (int i = 0; i < poly.size(); i++) { + copy_v3_v3(mp_cagecos[i], cagecos[corner_verts[poly[i]]]); } interp_weights_poly_v3(isect->poly_weights, reinterpret_cast(mp_cagecos.data()), - poly.totloop, + poly.size(), isect->co); return isect; @@ -1217,11 +1217,11 @@ static float meshdeform_boundary_phi(const MeshDeformBind *mdb, const MDefBoundIsect *isect, int cagevert) { + const blender::IndexRange poly = mdb->cagemesh_cache.polys[isect->poly_index]; const blender::Span corner_verts = mdb->cagemesh_cache.corner_verts; - const MPoly &poly = mdb->cagemesh_cache.polys[isect->poly_index]; - for (int i = 0; i < poly.totloop; i++) { - if (corner_verts[poly.loopstart + i] == cagevert) { + for (int i = 0; i < poly.size(); i++) { + if (corner_verts[poly[i]] == cagevert) { return isect->poly_weights[i]; } } diff --git a/source/blender/editors/mesh/editface.cc b/source/blender/editors/mesh/editface.cc index 84195619c8b..09f6da88fea 100644 --- a/source/blender/editors/mesh/editface.cc +++ b/source/blender/editors/mesh/editface.cc @@ -224,7 +224,7 @@ static void build_poly_connections(blender::AtomicDisjointSet &islands, const bool skip_seams = true) { using namespace blender; - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_edges = mesh.corner_edges(); const bke::AttributeAccessor attributes = mesh.attributes(); @@ -240,8 +240,7 @@ static void build_poly_connections(blender::AtomicDisjointSet &islands, if (hide_poly[poly_index]) { continue; } - const MPoly &poly = polys[poly_index]; - const Span poly_edges = corner_edges.slice(poly.loopstart, poly.totloop); + const Span poly_edges = corner_edges.slice(polys[poly_index]); for (const int poly_loop_index : poly_edges.index_range()) { const int outer_edge = poly_edges[poly_loop_index]; @@ -274,7 +273,7 @@ static void paintface_select_linked_faces(Mesh &mesh, AtomicDisjointSet islands(mesh.totedge); build_poly_connections(islands, mesh); - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_edges = mesh.corner_edges(); bke::MutableAttributeAccessor attributes = mesh.attributes_for_write(); @@ -285,8 +284,7 @@ static void paintface_select_linked_faces(Mesh &mesh, Set selected_roots; for (const int i : face_indices) { - const MPoly &poly = polys[i]; - for (const int edge : corner_edges.slice(poly.loopstart, poly.totloop)) { + for (const int edge : corner_edges.slice(polys[i])) { if (uv_seams[edge]) { continue; } @@ -297,8 +295,7 @@ static void paintface_select_linked_faces(Mesh &mesh, threading::parallel_for(select_poly.span.index_range(), 1024, [&](const IndexRange range) { for (const int poly_index : range) { - const MPoly &poly = polys[poly_index]; - for (const int edge : corner_edges.slice(poly.loopstart, poly.totloop)) { + for (const int edge : corner_edges.slice(polys[poly_index])) { const int root = islands.find_root(edge); if (selected_roots.contains(root)) { select_poly.span[poly_index] = select; @@ -386,7 +383,7 @@ void paintface_select_more(Mesh *mesh, const bool face_step) const VArray hide_poly = attributes.lookup_or_default( ".hide_poly", ATTR_DOMAIN_FACE, false); - const Span polys = mesh->polys(); + const OffsetIndices polys = mesh->polys(); const Span corner_edges = mesh->corner_edges(); const Span edges = mesh->edges(); @@ -395,11 +392,9 @@ void paintface_select_more(Mesh *mesh, const bool face_step) if (select_poly.span[i] || hide_poly[i]) { continue; } - const MPoly &poly = polys[i]; - if (poly_has_selected_neighbor(corner_edges.slice(poly.loopstart, poly.totloop), - edges, - select_vert.span, - face_step)) { + const IndexRange poly = polys[i]; + if (poly_has_selected_neighbor( + corner_edges.slice(poly), edges, select_vert.span, face_step)) { select_poly.span[i] = true; } } @@ -440,7 +435,7 @@ void paintface_select_less(Mesh *mesh, const bool face_step) const VArray hide_poly = attributes.lookup_or_default( ".hide_poly", ATTR_DOMAIN_FACE, false); - const Span polys = mesh->polys(); + const OffsetIndices polys = mesh->polys(); const Span corner_verts = mesh->corner_verts(); const Span corner_edges = mesh->corner_edges(); const Span edges = mesh->edges(); @@ -452,8 +447,8 @@ void paintface_select_less(Mesh *mesh, const bool face_step) if (select_poly.span[i]) { continue; } - const MPoly &poly = polys[i]; - for (const int vert : corner_verts.slice(poly.loopstart, poly.totloop)) { + const IndexRange poly = polys[i]; + for (const int vert : corner_verts.slice(poly)) { verts_of_unselected_faces[vert].set(true); } } @@ -463,11 +458,9 @@ void paintface_select_less(Mesh *mesh, const bool face_step) if (!select_poly.span[i] || hide_poly[i]) { continue; } - const MPoly &poly = polys[i]; - if (poly_has_unselected_neighbor(corner_edges.slice(poly.loopstart, poly.totloop), - edges, - verts_of_unselected_faces, - face_step)) { + const IndexRange poly = polys[i]; + if (poly_has_unselected_neighbor( + corner_edges.slice(poly), edges, verts_of_unselected_faces, face_step)) { select_poly.span[i] = false; } } @@ -549,7 +542,7 @@ bool paintface_minmax(Object *ob, float r_min[3], float r_max[3]) copy_m3_m4(bmat, ob->object_to_world); const Span positions = me->vert_positions(); - const Span polys = me->polys(); + const OffsetIndices polys = me->polys(); const Span corner_verts = me->corner_verts(); bke::AttributeAccessor attributes = me->attributes(); const VArray hide_poly = attributes.lookup_or_default( @@ -562,10 +555,8 @@ bool paintface_minmax(Object *ob, float r_min[3], float r_max[3]) continue; } - const MPoly &poly = polys[i]; - for (int b = 0; b < poly.totloop; b++) { - const int corner = poly.loopstart + b; - mul_v3_m3v3(vec, bmat, positions[corner_verts[corner]]); + for (const int vert : corner_verts.slice(polys[i])) { + mul_v3_m3v3(vec, bmat, positions[vert]); add_v3_v3v3(vec, vec, ob->object_to_world[3]); minmax_v3v3_v3(r_min, r_max, vec); } @@ -798,7 +789,7 @@ void paintvert_select_more(Mesh *mesh, const bool face_step) const VArray hide_poly = attributes.lookup_or_default( ".hide_poly", ATTR_DOMAIN_FACE, false); - const Span polys = mesh->polys(); + const OffsetIndices polys = mesh->polys(); const Span corner_edges = mesh->corner_edges(); const Span corner_verts = mesh->corner_verts(); const Span edges = mesh->edges(); @@ -832,8 +823,8 @@ void paintvert_select_more(Mesh *mesh, const bool face_step) if (hide_poly[poly_i]) { continue; } - const MPoly &poly = polys[poly_i]; - for (const int vert : corner_verts.slice(poly.loopstart, poly.totloop)) { + const IndexRange poly = polys[poly_i]; + for (const int vert : corner_verts.slice(poly)) { select_vert.span[vert] = true; } } @@ -854,7 +845,7 @@ void paintvert_select_less(Mesh *mesh, const bool face_step) const VArray hide_poly = attributes.lookup_or_default( ".hide_poly", ATTR_DOMAIN_FACE, false); - const Span polys = mesh->polys(); + const OffsetIndices polys = mesh->polys(); const Span corner_edges = mesh->corner_edges(); const Span corner_verts = mesh->corner_verts(); const Span edges = mesh->edges(); @@ -865,8 +856,7 @@ void paintvert_select_less(Mesh *mesh, const bool face_step) BKE_mesh_edge_poly_map_create(&edge_poly_map, &edge_poly_mem, edges.size(), - polys.data(), - polys.size(), + polys, corner_edges.data(), corner_edges.size()); } @@ -893,8 +883,8 @@ void paintvert_select_less(Mesh *mesh, const bool face_step) if (hide_poly[poly_i]) { continue; } - const MPoly &poly = polys[poly_i]; - for (const int vert : corner_verts.slice(poly.loopstart, poly.totloop)) { + const IndexRange poly = polys[poly_i]; + for (const int vert : corner_verts.slice(poly)) { select_vert.span[vert] = false; } } diff --git a/source/blender/editors/mesh/editmesh_undo.cc b/source/blender/editors/mesh/editmesh_undo.cc index d9aedb82878..b36768d8c39 100644 --- a/source/blender/editors/mesh/editmesh_undo.cc +++ b/source/blender/editors/mesh/editmesh_undo.cc @@ -120,6 +120,7 @@ struct UndoMesh { /* Null arrays are considered empty. */ struct { /* most data is stored as 'custom' data */ BArrayCustomData *vdata, *edata, *ldata, *pdata; + BArrayState *poly_offset_indices; BArrayState **keyblocks; BArrayState *mselect; } store; @@ -143,6 +144,7 @@ enum { ARRAY_STORE_INDEX_EDGE, ARRAY_STORE_INDEX_LOOP, ARRAY_STORE_INDEX_POLY, + ARRAY_STORE_INDEX_POLY_OFFSETS, ARRAY_STORE_INDEX_SHAPE, ARRAY_STORE_INDEX_MSEL, }; @@ -382,6 +384,23 @@ static void um_arraystore_compact_ex(UndoMesh *um, const UndoMesh *um_ref, bool um_ref ? um_ref->store.pdata : nullptr, &um->store.pdata); }, + [&]() { + if (me->poly_offset_indices) { + BLI_assert(create == (um->store.poly_offset_indices == nullptr)); + if (create) { + BArrayState *state_reference = um_ref ? um_ref->store.poly_offset_indices : nullptr; + const size_t stride = sizeof(*me->poly_offset_indices); + BArrayStore *bs = BLI_array_store_at_size_ensure( + &um_arraystore.bs_stride[ARRAY_STORE_INDEX_POLY_OFFSETS], + stride, + array_chunk_size_calc(stride)); + um->store.poly_offset_indices = BLI_array_store_state_add( + bs, me->poly_offset_indices, size_t(me->totpoly + 1) * stride, state_reference); + } + + MEM_SAFE_FREE(me->poly_offset_indices); + } + }, [&]() { if (me->key && me->key->totkey) { const size_t stride = me->key->elemsize; @@ -541,6 +560,15 @@ static void um_arraystore_expand(UndoMesh *um) } } + if (um->store.poly_offset_indices) { + const size_t stride = sizeof(*me->poly_offset_indices); + BArrayState *state = um->store.poly_offset_indices; + size_t state_len; + me->poly_offset_indices = static_cast( + BLI_array_store_state_data_get_alloc(state, &state_len)); + BLI_assert((me->totpoly + 1) == (state_len / stride)); + UNUSED_VARS_NDEBUG(stride); + } if (um->store.mselect) { const size_t stride = sizeof(*me->mselect); BArrayState *state = um->store.mselect; @@ -572,6 +600,14 @@ static void um_arraystore_free(UndoMesh *um) um->store.keyblocks = nullptr; } + if (um->store.poly_offset_indices) { + const size_t stride = sizeof(*me->poly_offset_indices); + BArrayStore *bs = BLI_array_store_at_size_get( + &um_arraystore.bs_stride[ARRAY_STORE_INDEX_POLY_OFFSETS], stride); + BArrayState *state = um->store.poly_offset_indices; + BLI_array_store_state_remove(bs, state); + um->store.poly_offset_indices = nullptr; + } if (um->store.mselect) { const size_t stride = sizeof(*me->mselect); BArrayStore *bs = BLI_array_store_at_size_get(&um_arraystore.bs_stride[ARRAY_STORE_INDEX_MSEL], diff --git a/source/blender/editors/mesh/mesh_data.cc b/source/blender/editors/mesh/mesh_data.cc index 47a5eba178d..4bc023ee10e 100644 --- a/source/blender/editors/mesh/mesh_data.cc +++ b/source/blender/editors/mesh/mesh_data.cc @@ -169,15 +169,15 @@ static void mesh_uv_reset_bmface(BMFace *f, const int cd_loop_uv_offset) mesh_uv_reset_array(fuv.data(), f->len); } -static void mesh_uv_reset_mface(const MPoly *poly, float2 *mloopuv) +static void mesh_uv_reset_mface(const blender::IndexRange poly, float2 *mloopuv) { - Array fuv(poly->totloop); + Array fuv(poly.size()); - for (int i = 0; i < poly->totloop; i++) { - fuv[i] = mloopuv[poly->loopstart + i]; + for (int i = 0; i < poly.size(); i++) { + fuv[i] = mloopuv[poly[i]]; } - mesh_uv_reset_array(fuv.data(), poly->totloop); + mesh_uv_reset_array(fuv.data(), poly.size()); } void ED_mesh_uv_loop_reset_ex(Mesh *me, const int layernum) @@ -208,9 +208,9 @@ void ED_mesh_uv_loop_reset_ex(Mesh *me, const int layernum) float2 *mloopuv = static_cast( CustomData_get_layer_n_for_write(&me->ldata, CD_PROP_FLOAT2, layernum, me->totloop)); - const blender::Span polys = me->polys(); + const blender::OffsetIndices polys = me->polys(); for (const int i : polys.index_range()) { - mesh_uv_reset_mface(&polys[i], mloopuv); + mesh_uv_reset_mface(polys[i], mloopuv); } } @@ -1226,6 +1226,12 @@ static void mesh_add_loops(Mesh *mesh, int len) mesh->ldata = ldata; mesh->totloop = totloop; + + /* Keep the last poly offset up to date with the corner total (they must be the same). We have + * to be careful here though, since the mesh may not be in a valid state at this point. */ + if (mesh->poly_offset_indices) { + mesh->poly_offsets_for_write().last() = mesh->totloop; + } } static void mesh_add_polys(Mesh *mesh, int len) @@ -1244,9 +1250,8 @@ static void mesh_add_polys(Mesh *mesh, int len) CustomData_copy(&mesh->pdata, &pdata, CD_MASK_MESH.pmask, CD_SET_DEFAULT, totpoly); CustomData_copy_data(&mesh->pdata, &pdata, 0, 0, mesh->totpoly); - if (!CustomData_has_layer(&pdata, CD_MPOLY)) { - CustomData_add_layer(&pdata, CD_MPOLY, CD_SET_DEFAULT, totpoly); - } + mesh->poly_offset_indices = static_cast( + MEM_reallocN(mesh->poly_offset_indices, sizeof(int) * (totpoly + 1))); CustomData_free(&mesh->pdata, mesh->totpoly); mesh->pdata = pdata; @@ -1254,6 +1259,9 @@ static void mesh_add_polys(Mesh *mesh, int len) BKE_mesh_runtime_clear_cache(mesh); mesh->totpoly = totpoly; + /* Update the last offset, which may not be set elsewhere and must be the same as the number of + * face corners. */ + mesh->poly_offsets_for_write().last() = mesh->totloop; bke::MutableAttributeAccessor attributes = mesh->attributes_for_write(); bke::SpanAttributeWriter select_poly = attributes.lookup_or_add_for_write_span( @@ -1465,7 +1473,7 @@ Mesh *ED_mesh_context(bContext *C) void ED_mesh_split_faces(Mesh *mesh) { using namespace blender; - const Span polys = mesh->polys(); + const OffsetIndices polys = mesh->polys(); const Span corner_verts = mesh->corner_verts(); const Span corner_edges = mesh->corner_edges(); const float split_angle = (mesh->flag & ME_AUTOSMOOTH) != 0 ? mesh->smoothresh : float(M_PI); @@ -1488,9 +1496,8 @@ void ED_mesh_split_faces(Mesh *mesh) threading::parallel_for(polys.index_range(), 1024, [&](const IndexRange range) { for (const int poly_i : range) { - const MPoly &poly = polys[poly_i]; if (sharp_faces && sharp_faces[poly_i]) { - for (const int edge : corner_edges.slice(poly.loopstart, poly.totloop)) { + for (const int edge : corner_edges.slice(polys[poly_i])) { sharp_edges[edge] = true; } } diff --git a/source/blender/editors/mesh/meshtools.cc b/source/blender/editors/mesh/meshtools.cc index 8dd8762dfb7..95b443d8a6c 100644 --- a/source/blender/editors/mesh/meshtools.cc +++ b/source/blender/editors/mesh/meshtools.cc @@ -76,7 +76,7 @@ static void join_mesh_single(Depsgraph *depsgraph, MEdge **medge_pp, int **corner_verts_pp, int **corner_edges_pp, - MPoly **mpoly_pp, + int *all_poly_offsets, CustomData *vdata, CustomData *edata, CustomData *ldata, @@ -267,8 +267,10 @@ static void join_mesh_single(Depsgraph *depsgraph, } } + const Span src_poly_offsets = me->poly_offsets(); + int *poly_offsets = all_poly_offsets + *polyofs; for (const int i : blender::IndexRange(me->totpoly)) { - (*mpoly_pp)[i].loopstart += *loopofs; + poly_offsets[i] = src_poly_offsets[i] + *loopofs; } /* Face maps. */ @@ -298,7 +300,6 @@ static void join_mesh_single(Depsgraph *depsgraph, *corner_verts_pp += me->totloop; *corner_edges_pp += me->totloop; *polyofs += me->totpoly; - *mpoly_pp += me->totpoly; } /* Face Sets IDs are a sparse sequence, so this function offsets all the IDs by face_set_offset and @@ -336,7 +337,6 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op) Material **matar = nullptr, *ma; Mesh *me; MEdge *edge = nullptr; - MPoly *polys = nullptr; Key *key, *nkey = nullptr; float imat[4][4]; int a, b, totcol, totmat = 0, totedge = 0, totvert = 0; @@ -591,7 +591,8 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op) &ldata, CD_PROP_INT32, CD_CONSTRUCT, totloop, ".corner_vert"); int *corner_edges = (int *)CustomData_add_layer_named( &ldata, CD_PROP_INT32, CD_CONSTRUCT, totloop, ".corner_edge"); - polys = (MPoly *)CustomData_add_layer(&pdata, CD_MPOLY, CD_SET_DEFAULT, totpoly); + int *poly_offsets = static_cast(MEM_malloc_arrayN(totpoly + 1, sizeof(int), __func__)); + poly_offsets[totpoly] = totloop; vertofs = 0; edgeofs = 0; @@ -617,7 +618,7 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op) &edge, &corner_verts, &corner_edges, - &polys, + poly_offsets, &vdata, &edata, &ldata, @@ -652,7 +653,7 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op) &edge, &corner_verts, &corner_edges, - &polys, + poly_offsets, &vdata, &edata, &ldata, @@ -686,6 +687,8 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op) CustomData_free(&me->edata, me->totedge); CustomData_free(&me->ldata, me->totloop); CustomData_free(&me->pdata, me->totpoly); + MEM_SAFE_FREE(me->poly_offset_indices); + me->poly_offset_indices = poly_offsets; me->totvert = totvert; me->totedge = totedge; @@ -1230,16 +1233,16 @@ static void ed_mesh_pick_face_vert__mpoly_find( ARegion *region, const float mval[2], /* mesh data (evaluated) */ - const MPoly *poly, + const blender::IndexRange poly, const Span vert_positions, const int *corner_verts, /* return values */ float *r_len_best, int *r_v_idx_best) { - for (int j = poly->totloop; j--;) { + for (int j = poly.size(); j--;) { float sco[2]; - const int v_idx = corner_verts[poly->loopstart + j]; + const int v_idx = corner_verts[poly[j]]; if (ED_view3d_project_float_object(region, vert_positions[v_idx], sco, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { const float len_test = len_manhattan_v2v2(mval, sco); @@ -1275,7 +1278,7 @@ bool ED_mesh_pick_face_vert( float len_best = FLT_MAX; const Span vert_positions = me_eval->vert_positions(); - const Span polys = me_eval->polys(); + const blender::OffsetIndices polys = me_eval->polys(); const Span corner_verts = me_eval->corner_verts(); const int *index_mp_to_orig = (const int *)CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX); @@ -1286,7 +1289,7 @@ bool ED_mesh_pick_face_vert( if (index_mp_to_orig[i] == poly_index) { ed_mesh_pick_face_vert__mpoly_find(region, mval_f, - &polys[i], + polys[i], vert_positions, corner_verts.data(), &len_best, @@ -1298,7 +1301,7 @@ bool ED_mesh_pick_face_vert( if (poly_index < polys.size()) { ed_mesh_pick_face_vert__mpoly_find(region, mval_f, - &polys[poly_index], + polys[poly_index], vert_positions, corner_verts.data(), &len_best, diff --git a/source/blender/editors/object/object_bake_api.cc b/source/blender/editors/object/object_bake_api.cc index 15ca66c8b46..49cc126c6a6 100644 --- a/source/blender/editors/object/object_bake_api.cc +++ b/source/blender/editors/object/object_bake_api.cc @@ -978,7 +978,7 @@ static bool bake_targets_init_vertex_colors(Main *bmain, return true; } -static int find_original_loop(const blender::Span orig_polys, +static int find_original_loop(const blender::OffsetIndices orig_polys, const blender::Span orig_corner_verts, const int *vert_origindex, const int *poly_origindex, @@ -988,18 +988,18 @@ static int find_original_loop(const blender::Span orig_polys, /* Get original vertex and polygon index. There is currently no loop mapping * in modifier stack evaluation. */ const int vert_orig = vert_origindex[vert_eval]; - const int poly_orig_i = poly_origindex[poly_eval]; + const int poly_orig_index = poly_origindex[poly_eval]; - if (vert_orig == ORIGINDEX_NONE || poly_orig_i == ORIGINDEX_NONE) { + if (vert_orig == ORIGINDEX_NONE || poly_orig_index == ORIGINDEX_NONE) { return ORIGINDEX_NONE; } /* Find matching loop with original vertex in original polygon. */ - const MPoly &poly_orig = orig_polys[poly_orig_i]; - const int *poly_verts_orig = &orig_corner_verts[poly_orig.loopstart]; - for (int j = 0; j < poly_orig.totloop; ++j) { + const blender::IndexRange orig_poly = orig_polys[poly_orig_index]; + const int *poly_verts_orig = &orig_corner_verts[orig_poly.start()]; + for (int j = 0; j < orig_poly.size(); ++j) { if (poly_verts_orig[j] == vert_orig) { - return poly_orig.loopstart + j; + return orig_poly.start() + j; } } @@ -1042,7 +1042,7 @@ static void bake_targets_populate_pixels_color_attributes(BakeTargets *targets, CustomData_get_layer(&me_eval->vdata, CD_ORIGINDEX)); const int *poly_origindex = static_cast( CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX)); - const blender::Span orig_polys = me->polys(); + const blender::OffsetIndices orig_polys = me->polys(); const blender::Span orig_corner_verts = me->corner_verts(); for (int i = 0; i < tottri; i++) { diff --git a/source/blender/editors/sculpt_paint/paint_hide.cc b/source/blender/editors/sculpt_paint/paint_hide.cc index 67f9b71c79d..a2e0f7b5054 100644 --- a/source/blender/editors/sculpt_paint/paint_hide.cc +++ b/source/blender/editors/sculpt_paint/paint_hide.cc @@ -343,7 +343,7 @@ static int hide_show_exec(bContext *C, wmOperator *op) clip_planes_from_rect(C, depsgraph, clip_planes, &rect); pbvh = BKE_sculpt_object_pbvh_ensure(depsgraph, ob); - BLI_assert(ob->sculpt->pbvh == pbvh); + BLI_assert(BKE_object_sculpt_pbvh_get(ob) == pbvh); get_pbvh_nodes(pbvh, &nodes, &totnode, clip_planes, area); pbvh_type = BKE_pbvh_type(pbvh); diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.cc b/source/blender/editors/sculpt_paint/paint_image_proj.cc index 62b21e90fa4..1fa193096ff 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.cc +++ b/source/blender/editors/sculpt_paint/paint_image_proj.cc @@ -413,7 +413,7 @@ struct ProjPaintState { const float (*vert_positions_eval)[3]; blender::Span vert_normals; blender::Span edges_eval; - blender::Span polys_eval; + blender::OffsetIndices polys_eval; blender::Span corner_verts_eval; const bool *select_poly_eval; const int *material_indices; @@ -4389,14 +4389,11 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps, if (ps->do_backfacecull) { if (ps->do_mask_normal) { if (prev_poly != looptris[tri_index].poly) { - int iloop; bool culled = true; - const MPoly &poly = ps->polys_eval[looptris[tri_index].poly]; - int poly_loops = poly.totloop; + const blender::IndexRange poly = ps->polys_eval[looptris[tri_index].poly]; prev_poly = looptris[tri_index].poly; - for (iloop = 0; iloop < poly_loops; iloop++) { - if (!(ps->vertFlags[ps->corner_verts_eval[poly.loopstart + iloop]] & - PROJ_VERT_CULL)) { + for (const int corner : poly) { + if (!(ps->vertFlags[ps->corner_verts_eval[corner]] & PROJ_VERT_CULL)) { culled = false; break; } @@ -4405,7 +4402,7 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps, if (culled) { /* poly loops - 2 is number of triangles for poly, * but counter gets incremented when continuing, so decrease by 3 */ - int poly_tri = poly_loops - 3; + int poly_tri = poly.size() - 3; tri_index += poly_tri; continue; } diff --git a/source/blender/editors/sculpt_paint/paint_mask.cc b/source/blender/editors/sculpt_paint/paint_mask.cc index 64aa82cb20a..95576ba0027 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.cc +++ b/source/blender/editors/sculpt_paint/paint_mask.cc @@ -1242,13 +1242,12 @@ static void sculpt_gesture_trim_geometry_generate(SculptGestureContext *sgcontex BLI_polyfill_calc(screen_points, tot_screen_points, 0, r_tris); /* Write the front face triangle indices. */ - blender::MutableSpan polys = trim_operation->mesh->polys_for_write(); + blender::MutableSpan poly_offsets = trim_operation->mesh->poly_offsets_for_write(); blender::MutableSpan corner_verts = trim_operation->mesh->corner_verts_for_write(); int poly_index = 0; int loop_index = 0; for (int i = 0; i < tot_tris_face; i++) { - polys[poly_index].loopstart = loop_index; - polys[poly_index].totloop = 3; + poly_offsets[poly_index] = loop_index; corner_verts[loop_index + 0] = r_tris[i][0]; corner_verts[loop_index + 1] = r_tris[i][1]; corner_verts[loop_index + 2] = r_tris[i][2]; @@ -1258,8 +1257,7 @@ static void sculpt_gesture_trim_geometry_generate(SculptGestureContext *sgcontex /* Write the back face triangle indices. */ for (int i = 0; i < tot_tris_face; i++) { - polys[poly_index].loopstart = loop_index; - polys[poly_index].totloop = 3; + poly_offsets[poly_index] = loop_index; corner_verts[loop_index + 0] = r_tris[i][0] + tot_screen_points; corner_verts[loop_index + 1] = r_tris[i][1] + tot_screen_points; corner_verts[loop_index + 2] = r_tris[i][2] + tot_screen_points; @@ -1271,8 +1269,7 @@ static void sculpt_gesture_trim_geometry_generate(SculptGestureContext *sgcontex /* Write the indices for the lateral triangles. */ for (int i = 0; i < tot_screen_points; i++) { - polys[poly_index].loopstart = loop_index; - polys[poly_index].totloop = 3; + poly_offsets[poly_index] = loop_index; int current_index = i; int next_index = current_index + 1; if (next_index >= tot_screen_points) { @@ -1286,8 +1283,7 @@ static void sculpt_gesture_trim_geometry_generate(SculptGestureContext *sgcontex } for (int i = 0; i < tot_screen_points; i++) { - polys[poly_index].loopstart = loop_index; - polys[poly_index].totloop = 3; + poly_offsets[poly_index] = loop_index; int current_index = i; int next_index = current_index + 1; if (next_index >= tot_screen_points) { diff --git a/source/blender/editors/sculpt_paint/paint_vertex.cc b/source/blender/editors/sculpt_paint/paint_vertex.cc index 36074b9c0e5..9b6e2465930 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.cc +++ b/source/blender/editors/sculpt_paint/paint_vertex.cc @@ -1240,7 +1240,7 @@ static void vertex_paint_init_session_data(const ToolSettings *ts, Object *ob) } Mesh *me = (Mesh *)ob->data; - const Span polys = me->polys(); + const blender::OffsetIndices polys = me->polys(); const Span corner_verts = me->corner_verts(); if (gmap->vert_to_loop == nullptr) { @@ -1248,20 +1248,10 @@ static void vertex_paint_init_session_data(const ToolSettings *ts, Object *ob) gmap->vert_to_loop = nullptr; gmap->poly_map_mem = nullptr; gmap->vert_to_poly = nullptr; - BKE_mesh_vert_loop_map_create(&gmap->vert_to_loop, - &gmap->vert_map_mem, - polys.data(), - corner_verts.data(), - me->totvert, - me->totpoly, - me->totloop); - BKE_mesh_vert_poly_map_create(&gmap->vert_to_poly, - &gmap->poly_map_mem, - polys.data(), - corner_verts.data(), - me->totvert, - me->totpoly, - me->totloop); + BKE_mesh_vert_loop_map_create( + &gmap->vert_to_loop, &gmap->vert_map_mem, polys, corner_verts.data(), me->totvert); + BKE_mesh_vert_poly_map_create( + &gmap->vert_to_poly, &gmap->poly_map_mem, polys, corner_verts.data(), me->totvert); } /* Create average brush arrays */ @@ -1982,13 +1972,11 @@ static void do_wpaint_brush_blur_task_cb_ex(void *__restrict userdata, float weight_final = 0.0f; for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { const int p_index = gmap->vert_to_poly[v_index].indices[j]; - const MPoly &poly = ss->polys[p_index]; + const blender::IndexRange poly = ss->polys[p_index]; - total_hit_loops += poly.totloop; - for (int k = 0; k < poly.totloop; k++) { - const int l_index = poly.loopstart + k; - const int vert_i = ss->corner_verts[l_index]; - weight_final += data->wpd->precomputed_weight[vert_i]; + total_hit_loops += poly.size(); + for (const int vert : ss->corner_verts.slice(poly)) { + weight_final += data->wpd->precomputed_weight[vert]; } } @@ -2096,10 +2084,7 @@ static void do_wpaint_brush_smear_task_cb_ex(void *__restrict userdata, float weight_final = 0.0; for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { const int p_index = gmap->vert_to_poly[v_index].indices[j]; - const MPoly &poly = ss->polys[p_index]; - for (int k = 0; k < poly.totloop; k++) { - const int other_corner_i = poly.loopstart + k; - const int v_other_index = ss->corner_verts[other_corner_i]; + for (const int v_other_index : ss->corner_verts.slice(ss->polys[p_index])) { if (v_other_index != v_index) { const float3 &mv_other = ss->vert_positions[v_other_index]; @@ -3034,12 +3019,11 @@ static void do_vpaint_brush_blur_loops(bContext *C, for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { int p_index = gmap->vert_to_poly[v_index].indices[j]; - const MPoly &poly = ss->polys[p_index]; if (!use_face_sel || select_poly[p_index]) { - total_hit_loops += poly.totloop; - for (int k = 0; k < poly.totloop; k++) { - const uint l_index = poly.loopstart + k; - Color *col = lcol + l_index; + const blender::IndexRange poly = ss->polys[p_index]; + total_hit_loops += poly.size(); + for (const int corner : poly) { + Color *col = lcol + corner; /* Color is squared to compensate the sqrt color encoding. */ blend[0] += (Blend)col->r * (Blend)col->r; @@ -3179,14 +3163,11 @@ static void do_vpaint_brush_blur_verts(bContext *C, for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { int p_index = gmap->vert_to_poly[v_index].indices[j]; - const MPoly &poly = ss->polys[p_index]; if (!use_face_sel || select_poly[p_index]) { - total_hit_loops += poly.totloop; - for (int k = 0; k < poly.totloop; k++) { - const uint l_index = poly.loopstart + k; - const uint v_index = ss->corner_verts[l_index]; - - Color *col = lcol + v_index; + const blender::IndexRange poly = ss->polys[p_index]; + total_hit_loops += poly.size(); + for (const int vert : ss->corner_verts.slice(poly)) { + Color *col = lcol + vert; /* Color is squared to compensate the sqrt color encoding. */ blend[0] += (Blend)col->r * (Blend)col->r; @@ -3342,11 +3323,9 @@ static void do_vpaint_brush_smear(bContext *C, const int l_index = gmap->vert_to_loop[v_index].indices[j]; BLI_assert(ss->corner_verts[l_index] == v_index); UNUSED_VARS_NDEBUG(l_index); - const MPoly &poly = ss->polys[p_index]; if (!use_face_sel || select_poly[p_index]) { - for (int k = 0; k < poly.totloop; k++) { - const int other_corner_i = poly.loopstart + k; - const int v_other_index = ss->corner_verts[other_corner_i]; + for (const int corner : ss->polys[p_index]) { + const int v_other_index = ss->corner_verts[corner]; if (v_other_index != v_index) { const float3 &mv_other = &ss->vert_positions[v_other_index]; @@ -3365,7 +3344,7 @@ static void do_vpaint_brush_smear(bContext *C, elem_index = v_other_index; } else { - elem_index = poly.loopstart + k; + elem_index = corner; } if (stroke_dot > stroke_dot_max) { @@ -4123,29 +4102,25 @@ static void fill_mesh_face_or_corner_attribute(Mesh &mesh, const VArray select_poly = mesh.attributes().lookup_or_default( ".select_poly", ATTR_DOMAIN_FACE, false); - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_verts = mesh.corner_verts(); for (const int i : polys.index_range()) { if (use_face_sel && !select_poly[i]) { continue; } - const MPoly &poly = polys[i]; - - int j = 0; - do { - const int vidx = corner_verts[poly.loopstart + j]; - - if (!(use_vert_sel && !(select_vert[vidx]))) { - if (domain == ATTR_DOMAIN_CORNER) { - data[poly.loopstart + j] = value; - } - else { - data[vidx] = value; - } + for (const int corner : polys[i]) { + const int vert = corner_verts[corner]; + if (use_vert_sel && !select_vert[vert]) { + continue; } - j++; - } while (j < poly.totloop); + if (domain == ATTR_DOMAIN_CORNER) { + data[corner] = value; + } + else { + data[vert] = value; + } + } } BKE_mesh_tessface_clear(&mesh); diff --git a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.cc b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.cc index 46540486600..10f9cb9a722 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.cc +++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.cc @@ -317,7 +317,7 @@ static const EnumPropertyItem *weight_paint_sample_enum_itemf(bContext *C, ED_view3d_viewcontext_init(C, &vc, depsgraph); me = BKE_mesh_from_object(vc.obact); - const blender::Span polys = me->polys(); + const blender::OffsetIndices polys = me->polys(); const blender::Span corner_verts = me->corner_verts(); const MDeformVert *dverts = BKE_mesh_deform_verts(me); @@ -344,11 +344,11 @@ static const EnumPropertyItem *weight_paint_sample_enum_itemf(bContext *C, } else { if (ED_mesh_pick_face(C, vc.obact, mval, ED_MESH_PICK_DEFAULT_FACE_DIST, &index)) { - const MPoly &poly = polys[index]; - uint fidx = poly.totloop - 1; + const blender::IndexRange poly = polys[index]; + int fidx = poly.size() - 1; do { - const MDeformVert *dvert = &dverts[corner_verts[poly.loopstart + fidx]]; + const MDeformVert *dvert = &dverts[corner_verts[poly[fidx]]]; found |= weight_paint_sample_enum_itemf__helper(dvert, defbase_tot, groups); } while (fidx--); } @@ -445,7 +445,7 @@ static bool weight_paint_set(Object *ob, float paintweight) /* mutually exclusive, could be made into a */ const short paint_selmode = ME_EDIT_PAINT_SEL_MODE(me); - const blender::Span polys = me->polys(); + const blender::OffsetIndices polys = me->polys(); const blender::Span corner_verts = me->corner_verts(); MDeformVert *dvert = BKE_mesh_deform_verts_for_write(me); @@ -469,15 +469,15 @@ static bool weight_paint_set(Object *ob, float paintweight) &me->pdata, CD_PROP_BOOL, ".select_poly"); for (const int i : polys.index_range()) { - const MPoly &poly = polys[i]; - uint fidx = poly.totloop - 1; + const blender::IndexRange poly = polys[i]; + uint fidx = poly.size() - 1; if ((paint_selmode == SCE_SELECT_FACE) && !(select_poly && select_poly[i])) { continue; } do { - const int vidx = corner_verts[poly.loopstart + fidx]; + const int vidx = corner_verts[poly[fidx]]; if (!dvert[vidx].flag) { if ((paint_selmode == SCE_SELECT_VERTEX) && !(select_vert && select_vert[vidx])) { diff --git a/source/blender/editors/sculpt_paint/sculpt.cc b/source/blender/editors/sculpt_paint/sculpt.cc index fbb5caeacd6..ff16258920d 100644 --- a/source/blender/editors/sculpt_paint/sculpt.cc +++ b/source/blender/editors/sculpt_paint/sculpt.cc @@ -725,9 +725,9 @@ static bool sculpt_check_unique_face_set_for_edge_in_base_mesh(SculptSession *ss const MeshElemMap *vert_map = &ss->pmap[v1]; int p1 = -1, p2 = -1; for (int i = 0; i < vert_map->count; i++) { - const MPoly &poly = ss->polys[vert_map->indices[i]]; - for (int l = 0; l < poly.totloop; l++) { - if (ss->corner_verts[poly.loopstart + l] == v2) { + const int poly_i = vert_map->indices[i]; + for (const int corner : ss->polys[poly_i]) { + if (ss->corner_verts[corner] == v2) { if (p1 == -1) { p1 = vert_map->indices[i]; break; @@ -768,13 +768,7 @@ bool SCULPT_vertex_has_unique_face_set(SculptSession *ss, PBVHVertRef vertex) coord.y = vertex_index / key->grid_size; int v1, v2; const SubdivCCGAdjacencyType adjacency = BKE_subdiv_ccg_coarse_mesh_adjacency_info_get( - ss->subdiv_ccg, - &coord, - ss->corner_verts.data(), - ss->corner_verts.size(), - ss->polys.data(), - &v1, - &v2); + ss->subdiv_ccg, &coord, ss->corner_verts, ss->polys, &v1, &v2); switch (adjacency) { case SUBDIV_CCG_ADJACENT_VERTEX: return sculpt_check_unique_face_set_in_base_mesh(ss, v1); @@ -893,7 +887,7 @@ static void sculpt_vertex_neighbors_get_faces(SculptSession *ss, /* Skip connectivity from hidden faces. */ continue; } - const MPoly &poly = ss->polys[vert_map->indices[i]]; + const blender::IndexRange poly = ss->polys[vert_map->indices[i]]; const blender::int2 f_adj_v = blender::bke::mesh::poly_find_adjecent_verts( poly, ss->corner_verts, vertex.i); for (int j = 0; j < 2; j++) { @@ -1008,13 +1002,7 @@ bool SCULPT_vertex_is_boundary(const SculptSession *ss, const PBVHVertRef vertex coord.y = vertex_index / key->grid_size; int v1, v2; const SubdivCCGAdjacencyType adjacency = BKE_subdiv_ccg_coarse_mesh_adjacency_info_get( - ss->subdiv_ccg, - &coord, - ss->corner_verts.data(), - ss->corner_verts.size(), - ss->polys.data(), - &v1, - &v2); + ss->subdiv_ccg, &coord, ss->corner_verts, ss->polys, &v1, &v2); switch (adjacency) { case SUBDIV_CCG_ADJACENT_VERTEX: return sculpt_check_boundary_vertex_in_base_mesh(ss, v1); @@ -6212,18 +6200,16 @@ void SCULPT_boundary_info_ensure(Object *object) Mesh *base_mesh = BKE_mesh_from_object(object); const blender::Span edges = base_mesh->edges(); - const blender::Span polys = base_mesh->polys(); + const OffsetIndices polys = base_mesh->polys(); const Span corner_edges = base_mesh->corner_edges(); ss->vertex_info.boundary = BLI_BITMAP_NEW(base_mesh->totvert, "Boundary info"); int *adjacent_faces_edge_count = static_cast( MEM_calloc_arrayN(base_mesh->totedge, sizeof(int), "Adjacent face edge count")); - for (const int p : polys.index_range()) { - const MPoly &poly = polys[p]; - for (int l = 0; l < poly.totloop; l++) { - const int edge_i = corner_edges[poly.loopstart + l]; - adjacent_faces_edge_count[edge_i]++; + for (const int i : polys.index_range()) { + for (const int edge : corner_edges.slice(polys[i])) { + adjacent_faces_edge_count[edge]++; } } diff --git a/source/blender/editors/sculpt_paint/sculpt_dyntopo.cc b/source/blender/editors/sculpt_paint/sculpt_dyntopo.cc index 19b94ddb933..cffb6636483 100644 --- a/source/blender/editors/sculpt_paint/sculpt_dyntopo.cc +++ b/source/blender/editors/sculpt_paint/sculpt_dyntopo.cc @@ -153,6 +153,7 @@ static void SCULPT_dynamic_topology_disable_ex( CustomData_free(&me->fdata, me->totface); CustomData_free(&me->ldata, me->totloop); CustomData_free(&me->pdata, me->totpoly); + MEM_SAFE_FREE(me->poly_offset_indices); /* Copy over stored custom data. */ SculptUndoNodeGeometry *geometry = &unode->geometry_bmesh_enter; @@ -169,6 +170,7 @@ static void SCULPT_dynamic_topology_disable_ex( &geometry->ldata, &me->ldata, CD_MASK_MESH.lmask, CD_DUPLICATE, geometry->totloop); CustomData_copy( &geometry->pdata, &me->pdata, CD_MASK_MESH.pmask, CD_DUPLICATE, geometry->totpoly); + me->poly_offset_indices = static_cast(MEM_dupallocN(geometry->poly_offset_indices)); } else { BKE_sculptsession_bm_to_me(ob, true); @@ -326,7 +328,7 @@ static bool dyntopo_supports_layer(const CustomDataLayer &layer, const int elem_ return BM_attribute_stored_in_bmesh_builtin(layer.name); } /* Some layers just encode #Mesh topology or are handled as special cases for dyntopo. */ - return ELEM(layer.type, CD_MEDGE, CD_MPOLY, CD_PAINT_MASK, CD_ORIGINDEX); + return ELEM(layer.type, CD_MEDGE, CD_PAINT_MASK, CD_ORIGINDEX); } static bool dyntopo_supports_customdata_layers(const blender::Span layers, diff --git a/source/blender/editors/sculpt_paint/sculpt_expand.cc b/source/blender/editors/sculpt_paint/sculpt_expand.cc index ebb2f938e6c..b22509cf40b 100644 --- a/source/blender/editors/sculpt_paint/sculpt_expand.cc +++ b/source/blender/editors/sculpt_paint/sculpt_expand.cc @@ -148,7 +148,7 @@ static bool sculpt_expand_is_face_in_active_component(SculptSession *ss, ExpandCache *expand_cache, const int f) { - const int vert = ss->corner_verts[ss->polys[f].loopstart]; + const int vert = ss->corner_verts[ss->polys[f].start()]; return sculpt_expand_is_vert_in_active_component(ss, expand_cache, BKE_pbvh_make_vref(vert)); } @@ -712,9 +712,8 @@ static float *sculpt_expand_diagonals_falloff_create(Object *ob, const PBVHVertR int v_next_i = BKE_pbvh_vertex_to_index(ss->pbvh, v_next); for (int j = 0; j < ss->pmap[v_next_i].count; j++) { - const MPoly &poly = ss->polys[ss->pmap[v_next_i].indices[j]]; - for (int l = 0; l < poly.totloop; l++) { - const PBVHVertRef neighbor_v = BKE_pbvh_make_vref(ss->corner_verts[poly.loopstart + l]); + for (const int vert : ss->corner_verts.slice(ss->polys[ss->pmap[v_next_i].indices[j]])) { + const PBVHVertRef neighbor_v = BKE_pbvh_make_vref(vert); if (BLI_BITMAP_TEST(visited_verts, neighbor_v.i)) { continue; } @@ -791,35 +790,32 @@ static void sculpt_expand_grids_to_faces_falloff(SculptSession *ss, Mesh *mesh, ExpandCache *expand_cache) { - const blender::Span polys = mesh->polys(); + const blender::OffsetIndices polys = mesh->polys(); const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh); - for (const int p : polys.index_range()) { - const MPoly &poly = polys[p]; + for (const int i : polys.index_range()) { float accum = 0.0f; - for (int l = 0; l < poly.totloop; l++) { - const int grid_loop_index = (poly.loopstart + l) * key->grid_area; + for (const int corner : polys[i]) { + const int grid_loop_index = corner * key->grid_area; for (int g = 0; g < key->grid_area; g++) { accum += expand_cache->vert_falloff[grid_loop_index + g]; } } - expand_cache->face_falloff[p] = accum / (poly.totloop * key->grid_area); + expand_cache->face_falloff[i] = accum / (polys[i].size() * key->grid_area); } } static void sculpt_expand_vertex_to_faces_falloff(Mesh *mesh, ExpandCache *expand_cache) { - const blender::Span polys = mesh->polys(); + const blender::OffsetIndices polys = mesh->polys(); const blender::Span corner_verts = mesh->corner_verts(); - for (const int p : polys.index_range()) { - const MPoly &poly = polys[p]; + for (const int i : polys.index_range()) { float accum = 0.0f; - for (int l = 0; l < poly.totloop; l++) { - const int vert = corner_verts[poly.loopstart + l]; + for (const int vert : corner_verts.slice(polys[i])) { accum += expand_cache->vert_falloff[vert]; } - expand_cache->face_falloff[p] = accum / poly.totloop; + expand_cache->face_falloff[i] = accum / polys[i].size(); } } @@ -1115,18 +1111,16 @@ static void sculpt_expand_snap_initialize_from_enabled(SculptSession *ss, BLI_gset_add(expand_cache->snap_enabled_face_sets, POINTER_FROM_INT(face_set)); } - for (int p = 0; p < totface; p++) { - const MPoly &poly = ss->polys[p]; + for (const int i : ss->polys.index_range()) { bool any_disabled = false; - for (int l = 0; l < poly.totloop; l++) { - const int vert = ss->corner_verts[l + poly.loopstart]; + for (const int vert : ss->corner_verts.slice(ss->polys[i])) { if (!BLI_BITMAP_TEST(enabled_verts, vert)) { any_disabled = true; break; } } if (any_disabled) { - const int face_set = expand_cache->original_face_sets[p]; + const int face_set = expand_cache->original_face_sets[i]; BLI_gset_remove(expand_cache->snap_enabled_face_sets, POINTER_FROM_INT(face_set), nullptr); } } @@ -1987,7 +1981,7 @@ static void sculpt_expand_delete_face_set_id(int *r_face_sets, { const int totface = ss->totfaces; MeshElemMap *pmap = ss->pmap; - const blender::Span polys = mesh->polys(); + const blender::OffsetIndices polys = mesh->polys(); const blender::Span corner_verts = mesh->corner_verts(); /* Check that all the face sets IDs in the mesh are not equal to `delete_id` @@ -2023,9 +2017,7 @@ static void sculpt_expand_delete_face_set_id(int *r_face_sets, while (BLI_LINKSTACK_SIZE(queue)) { const int f_index = POINTER_AS_INT(BLI_LINKSTACK_POP(queue)); int other_id = delete_id; - const MPoly &c_poly = polys[f_index]; - for (int l = 0; l < c_poly.totloop; l++) { - const int vert = corner_verts[c_poly.loopstart + l]; + for (const int vert : corner_verts.slice(polys[f_index])) { const MeshElemMap *vert_map = &pmap[vert]; for (int i = 0; i < vert_map->count; i++) { diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.cc b/source/blender/editors/sculpt_paint/sculpt_face_set.cc index 7f8e0aa7557..42ce5006dce 100644 --- a/source/blender/editors/sculpt_paint/sculpt_face_set.cc +++ b/source/blender/editors/sculpt_paint/sculpt_face_set.cc @@ -140,10 +140,10 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata, if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) { MeshElemMap *vert_map = &ss->pmap[vd.index]; for (int j = 0; j < ss->pmap[vd.index].count; j++) { - const MPoly &poly = ss->polys[vert_map->indices[j]]; + const blender::IndexRange poly = ss->polys[vert_map->indices[j]]; - const float3 poly_center = bke::mesh::poly_center_calc( - positions, ss->corner_verts.slice(poly.loopstart, poly.totloop)); + const float3 poly_center = bke::mesh::poly_center_calc(positions, + ss->corner_verts.slice(poly)); if (!sculpt_brush_test_sq_fn(&test, poly_center)) { continue; @@ -550,17 +550,12 @@ static void sculpt_face_sets_init_flood_fill(Object *ob, const FaceSetsFloodFill int *face_sets = ss->face_sets; const Span edges = mesh->edges(); - const Span polys = mesh->polys(); + const OffsetIndices polys = mesh->polys(); const Span corner_edges = mesh->corner_edges(); if (!ss->epmap) { - BKE_mesh_edge_poly_map_create(&ss->epmap, - &ss->epmap_mem, - edges.size(), - polys.data(), - polys.size(), - corner_edges.data(), - corner_edges.size()); + BKE_mesh_edge_poly_map_create( + &ss->epmap, &ss->epmap_mem, edges.size(), polys, corner_edges.data(), corner_edges.size()); } int next_face_set = 1; @@ -577,10 +572,9 @@ static void sculpt_face_sets_init_flood_fill(Object *ob, const FaceSetsFloodFill while (!queue.empty()) { const int poly_i = queue.front(); - const MPoly &poly = polys[poly_i]; queue.pop(); - for (const int edge_i : corner_edges.slice(poly.loopstart, poly.totloop)) { + for (const int edge_i : corner_edges.slice(polys[poly_i])) { const Span neighbor_polys(ss->epmap[edge_i].indices, ss->epmap[edge_i].count); for (const int neighbor_i : neighbor_polys) { if (neighbor_i == poly_i) { @@ -1110,15 +1104,14 @@ static void sculpt_face_set_grow(Object *ob, { using namespace blender; Mesh *mesh = BKE_mesh_from_object(ob); - const blender::Span polys = mesh->polys(); + const OffsetIndices polys = mesh->polys(); const Span corner_verts = mesh->corner_verts(); for (const int p : polys.index_range()) { if (!modify_hidden && prev_face_sets[p] <= 0) { continue; } - const MPoly &c_poly = polys[p]; - for (const int vert : corner_verts.slice(c_poly.loopstart, c_poly.totloop)) { + for (const int vert : corner_verts.slice(polys[p])) { const MeshElemMap *vert_map = &ss->pmap[vert]; for (int i = 0; i < vert_map->count; i++) { const int neighbor_face_index = vert_map->indices[i]; @@ -1141,15 +1134,14 @@ static void sculpt_face_set_shrink(Object *ob, { using namespace blender; Mesh *mesh = BKE_mesh_from_object(ob); - const blender::Span polys = mesh->polys(); + const OffsetIndices polys = mesh->polys(); const Span corner_verts = mesh->corner_verts(); for (const int p : polys.index_range()) { if (!modify_hidden && prev_face_sets[p] <= 0) { continue; } if (abs(prev_face_sets[p]) == active_face_set_id) { - const MPoly &c_poly = polys[p]; - for (const int vert_i : corner_verts.slice(c_poly.loopstart, c_poly.totloop)) { + for (const int vert_i : corner_verts.slice(polys[p])) { const MeshElemMap *vert_map = &ss->pmap[vert_i]; for (int i = 0; i < vert_map->count; i++) { const int neighbor_face_index = vert_map->indices[i]; diff --git a/source/blender/editors/sculpt_paint/sculpt_geodesic.cc b/source/blender/editors/sculpt_paint/sculpt_geodesic.cc index b84a18d27a9..65bfed8b916 100644 --- a/source/blender/editors/sculpt_paint/sculpt_geodesic.cc +++ b/source/blender/editors/sculpt_paint/sculpt_geodesic.cc @@ -88,7 +88,7 @@ static float *SCULPT_geodesic_mesh_create(Object *ob, float(*vert_positions)[3] = SCULPT_mesh_deformed_positions_get(ss); const blender::Span edges = mesh->edges(); - const blender::Span polys = mesh->polys(); + const blender::OffsetIndices polys = mesh->polys(); const blender::Span corner_verts = mesh->corner_verts(); const blender::Span corner_edges = mesh->corner_edges(); @@ -96,13 +96,8 @@ static float *SCULPT_geodesic_mesh_create(Object *ob, BLI_bitmap *edge_tag = BLI_BITMAP_NEW(totedge, "edge tag"); if (!ss->epmap) { - BKE_mesh_edge_poly_map_create(&ss->epmap, - &ss->epmap_mem, - edges.size(), - polys.data(), - polys.size(), - corner_edges.data(), - corner_edges.size()); + BKE_mesh_edge_poly_map_create( + &ss->epmap, &ss->epmap_mem, edges.size(), polys, corner_edges.data(), corner_edges.size()); } if (!ss->vemap) { BKE_mesh_vert_edge_map_create( @@ -182,9 +177,7 @@ static float *SCULPT_geodesic_mesh_create(Object *ob, if (ss->hide_poly && ss->hide_poly[poly]) { continue; } - - for (int loop_index = 0; loop_index < polys[poly].totloop; loop_index++) { - const int v_other = corner_verts[loop_index + polys[poly].loopstart]; + for (const int v_other : corner_verts.slice(polys[poly])) { if (ELEM(v_other, v1, v2)) { continue; } diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.hh b/source/blender/editors/sculpt_paint/sculpt_intern.hh index fae073233a6..1966aef1027 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.hh +++ b/source/blender/editors/sculpt_paint/sculpt_intern.hh @@ -146,6 +146,7 @@ struct SculptUndoNodeGeometry { CustomData edata; CustomData ldata; CustomData pdata; + int *poly_offset_indices; int totvert; int totedge; int totloop; diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.cc b/source/blender/editors/sculpt_paint/sculpt_undo.cc index aed43dea458..f2815ff8c39 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.cc +++ b/source/blender/editors/sculpt_paint/sculpt_undo.cc @@ -749,6 +749,7 @@ static void sculpt_undo_geometry_store_data(SculptUndoNodeGeometry *geometry, Ob CustomData_copy(&mesh->edata, &geometry->edata, CD_MASK_MESH.emask, CD_DUPLICATE, mesh->totedge); CustomData_copy(&mesh->ldata, &geometry->ldata, CD_MASK_MESH.lmask, CD_DUPLICATE, mesh->totloop); CustomData_copy(&mesh->pdata, &geometry->pdata, CD_MASK_MESH.pmask, CD_DUPLICATE, mesh->totpoly); + geometry->poly_offset_indices = static_cast(MEM_dupallocN(mesh->poly_offset_indices)); geometry->totvert = mesh->totvert; geometry->totedge = mesh->totedge; @@ -767,6 +768,7 @@ static void sculpt_undo_geometry_restore_data(SculptUndoNodeGeometry *geometry, CustomData_free(&mesh->fdata, mesh->totface); CustomData_free(&mesh->ldata, mesh->totloop); CustomData_free(&mesh->pdata, mesh->totpoly); + MEM_SAFE_FREE(mesh->poly_offset_indices); mesh->totvert = geometry->totvert; mesh->totedge = geometry->totedge; @@ -782,6 +784,7 @@ static void sculpt_undo_geometry_restore_data(SculptUndoNodeGeometry *geometry, &geometry->ldata, &mesh->ldata, CD_MASK_MESH.lmask, CD_DUPLICATE, geometry->totloop); CustomData_copy( &geometry->pdata, &mesh->pdata, CD_MASK_MESH.pmask, CD_DUPLICATE, geometry->totpoly); + mesh->poly_offset_indices = static_cast(geometry->poly_offset_indices); BKE_mesh_runtime_clear_cache(mesh); } @@ -800,6 +803,7 @@ static void sculpt_undo_geometry_free_data(SculptUndoNodeGeometry *geometry) if (geometry->totpoly) { CustomData_free(&geometry->pdata, geometry->totpoly); } + MEM_SAFE_FREE(geometry->poly_offset_indices); } static void sculpt_undo_geometry_restore(SculptUndoNode *unode, Object *object) diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc index 0673a5acced..ba4505f5c98 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc @@ -142,7 +142,6 @@ static std::unique_ptr build_mesh_debug_columns(const Mesh &mesh, return {}; } case ATTR_DOMAIN_FACE: { - const Span polys = mesh.polys(); if (name == "Original Index") { const int *data = static_cast( CustomData_get_layer(&mesh.pdata, CD_ORIGINDEX)); @@ -152,14 +151,13 @@ static std::unique_ptr build_mesh_debug_columns(const Mesh &mesh, } if (name == "Corner Start") { return std::make_unique( - name, VArray::ForFunc(polys.size(), [polys](int64_t index) { - return polys[index].loopstart; - })); + name, VArray::ForSpan(mesh.poly_offsets().drop_back(1))); } if (name == "Corner Size") { + const OffsetIndices polys = mesh.polys(); return std::make_unique( name, VArray::ForFunc(polys.size(), [polys](int64_t index) { - return polys[index].totloop; + return polys[index].size(); })); } return {}; diff --git a/source/blender/editors/space_view3d/drawobject.cc b/source/blender/editors/space_view3d/drawobject.cc index 2754ffa7651..5ead0c8356b 100644 --- a/source/blender/editors/space_view3d/drawobject.cc +++ b/source/blender/editors/space_view3d/drawobject.cc @@ -70,7 +70,7 @@ void ED_draw_object_facemap(Depsgraph *depsgraph, GPU_blend(GPU_BLEND_ALPHA); const float(*positions)[3] = BKE_mesh_vert_positions(me); - const blender::Span polys = me->polys(); + const blender::OffsetIndices polys = me->polys(); const blender::Span corner_verts = me->corner_verts(); const blender::Span looptris = me->looptris(); @@ -93,9 +93,8 @@ void ED_draw_object_facemap(Depsgraph *depsgraph, int tri_index = 0; for (const int i : polys.index_range()) { - const MPoly &poly = polys[i]; if (facemap_data[i] == facemap) { - for (int j = 2; j < poly.totloop; j++) { + for (int j = 2; j < polys[i].size(); j++) { copy_v3_v3(static_cast(GPU_vertbuf_raw_step(&pos_step)), positions[corner_verts[looptris[tri_index].tri[0]]]); copy_v3_v3(static_cast(GPU_vertbuf_raw_step(&pos_step)), @@ -107,7 +106,7 @@ void ED_draw_object_facemap(Depsgraph *depsgraph, } } else { - tri_index += poly.totloop - 2; + tri_index += polys[i].size() - 2; } } diff --git a/source/blender/editors/transform/transform_snap_object.cc b/source/blender/editors/transform/transform_snap_object.cc index 5f423d0eb22..a6b2eadc4d2 100644 --- a/source/blender/editors/transform/transform_snap_object.cc +++ b/source/blender/editors/transform/transform_snap_object.cc @@ -242,7 +242,7 @@ static void snap_object_data_mesh_get(SnapObjectContext *sctx, BVHTreeFromMesh *r_treedata) { const Span vert_positions = me_eval->vert_positions(); - const Span polys = me_eval->polys(); + const blender::OffsetIndices polys = me_eval->polys(); const Span corner_verts = me_eval->corner_verts(); if (ob_eval->type == OB_MESH) { @@ -1785,13 +1785,13 @@ static eSnapMode snap_mesh_polygon(SnapObjectContext *sctx, params->use_backface_culling, &nearest2d); - const MPoly &poly = mesh->polys()[sctx->ret.index]; + const blender::IndexRange poly = mesh->polys()[sctx->ret.index]; if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_EDGE) { elem = SCE_SNAP_MODE_EDGE; BLI_assert(nearest2d.edges != nullptr); - const int *poly_edges = &nearest2d.corner_edges[poly.loopstart]; - for (int i = poly.totloop; i--;) { + const int *poly_edges = &nearest2d.corner_edges[poly.start()]; + for (int i = poly.size(); i--;) { cb_snap_edge(&nearest2d, poly_edges[i], &neasrest_precalc, @@ -1802,8 +1802,8 @@ static eSnapMode snap_mesh_polygon(SnapObjectContext *sctx, } else { elem = SCE_SNAP_MODE_VERTEX; - const int *poly_verts = &nearest2d.corner_verts[poly.loopstart]; - for (int i = poly.totloop; i--;) { + const int *poly_verts = &nearest2d.corner_verts[poly.start()]; + for (int i = poly.size(); i--;) { cb_snap_vert(&nearest2d, poly_verts[i], &neasrest_precalc, diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.cc b/source/blender/editors/uvedit/uvedit_unwrap_ops.cc index 4f2b8c5c6a9..3da6f711b2e 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.cc +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.cc @@ -621,7 +621,7 @@ static ParamHandle *construct_param_handle_subsurfed(const Scene *scene, const float(*subsurfedPositions)[3] = BKE_mesh_vert_positions(subdiv_mesh); const blender::Span subsurf_edges = subdiv_mesh->edges(); - const blender::Span subsurf_polys = subdiv_mesh->polys(); + const blender::OffsetIndices subsurf_polys = subdiv_mesh->polys(); const blender::Span subsurf_corner_verts = subdiv_mesh->corner_verts(); const int *origVertIndices = static_cast( @@ -654,8 +654,7 @@ static ParamHandle *construct_param_handle_subsurfed(const Scene *scene, } /* Prepare and feed faces to the solver. */ - for (const int64_t i : subsurf_polys.index_range()) { - const MPoly &poly = subsurf_polys[i]; + for (const int i : subsurf_polys.index_range()) { ParamKey key, vkeys[4]; bool pin[4], select[4]; const float *co[4]; @@ -674,10 +673,10 @@ static ParamHandle *construct_param_handle_subsurfed(const Scene *scene, } } - const int *poly_corner_verts = &subsurf_corner_verts[poly.loopstart]; + const blender::Span poly_corner_verts = subsurf_corner_verts.slice(subsurf_polys[i]); /* We will not check for v4 here. Sub-surface faces always have 4 vertices. */ - BLI_assert(poly.totloop == 4); + BLI_assert(poly_corner_verts.size() == 4); key = (ParamKey)i; vkeys[0] = (ParamKey)poly_corner_verts[0]; vkeys[1] = (ParamKey)poly_corner_verts[1]; diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp index c9c65150a13..ca917bbcc79 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp @@ -406,7 +406,7 @@ void BlenderFileLoader::insertShapeNode(Object *ob, Mesh *me, int id) char *name = ob->id.name + 2; const Span vert_positions = me->vert_positions(); - const Span mesh_polys = me->polys(); + const OffsetIndices mesh_polys = me->polys(); const Span corner_verts = me->corner_verts(); // Compute loop triangles diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp index 5c3d527d2bc..8905ddb81a0 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp @@ -580,13 +580,13 @@ void BlenderStrokeRenderer::GenerateStrokeMesh(StrokeGroup *group, bool hasTex) mesh->totpoly = group->totpoly; mesh->totloop = group->totloop; mesh->totcol = group->materials.size(); + BKE_mesh_poly_offsets_ensure_alloc(mesh); float3 *vert_positions = (float3 *)CustomData_add_layer_named( &mesh->vdata, CD_PROP_FLOAT3, CD_SET_DEFAULT, mesh->totvert, "position"); MEdge *edges = (MEdge *)CustomData_add_layer( &mesh->edata, CD_MEDGE, CD_SET_DEFAULT, mesh->totedge); - MPoly *polys = (MPoly *)CustomData_add_layer( - &mesh->pdata, CD_MPOLY, CD_SET_DEFAULT, mesh->totpoly); + blender::MutableSpan poly_offsets = mesh->poly_offsets_for_write(); int *corner_verts = (int *)CustomData_add_layer_named( &mesh->ldata, CD_PROP_INT32, CD_SET_DEFAULT, mesh->totloop, ".corner_vert"); int *corner_edges = (int *)CustomData_add_layer_named( @@ -629,7 +629,7 @@ void BlenderStrokeRenderer::GenerateStrokeMesh(StrokeGroup *group, bool hasTex) // Data copy //////////////////// - int vertex_index = 0, edge_index = 0, loop_index = 0; + int vertex_index = 0, edge_index = 0, loop_index = 0, poly_index = 0; int visible_faces, visible_segments; bool visible; Strip::vertex_container::iterator v[3]; @@ -710,11 +710,10 @@ void BlenderStrokeRenderer::GenerateStrokeMesh(StrokeGroup *group, bool hasTex) ++edge_index; // poly - polys->loopstart = loop_index; - polys->totloop = 3; + poly_offsets[poly_index] = loop_index; *material_indices = matnr; ++material_indices; - ++polys; + ++poly_index; // Even and odd loops connect triangles vertices differently bool is_odd = n % 2; diff --git a/source/blender/geometry/intern/mesh_flip_faces.cc b/source/blender/geometry/intern/mesh_flip_faces.cc index 6fd809ad4ca..4380dc4e763 100644 --- a/source/blender/geometry/intern/mesh_flip_faces.cc +++ b/source/blender/geometry/intern/mesh_flip_faces.cc @@ -18,13 +18,13 @@ void flip_faces(Mesh &mesh, const IndexMask &selection) return; } - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); MutableSpan corner_verts = mesh.corner_verts_for_write(); MutableSpan corner_edges = mesh.corner_edges_for_write(); threading::parallel_for(selection.index_range(), 1024, [&](const IndexRange range) { for (const int i : selection.slice(range)) { - const IndexRange poly(polys[i].loopstart, polys[i].totloop); + const IndexRange poly = polys[i]; for (const int j : IndexRange(poly.size() / 2)) { const int a = poly[j + 1]; const int b = poly.last(j); @@ -52,8 +52,7 @@ void flip_faces(Mesh &mesh, const IndexMask &selection) MutableSpan dst_span = attribute.span.typed(); threading::parallel_for(selection.index_range(), 1024, [&](const IndexRange range) { for (const int i : selection.slice(range)) { - const IndexRange poly(polys[i].loopstart, polys[i].totloop); - dst_span.slice(poly.drop_front(1)).reverse(); + dst_span.slice(polys[i].drop_front(1)).reverse(); } }); }); diff --git a/source/blender/geometry/intern/mesh_merge_by_distance.cc b/source/blender/geometry/intern/mesh_merge_by_distance.cc index 03402aacbc4..9b4a01415b9 100644 --- a/source/blender/geometry/intern/mesh_merge_by_distance.cc +++ b/source/blender/geometry/intern/mesh_merge_by_distance.cc @@ -163,14 +163,13 @@ static void weld_assert_edge_kill_len(Span wedge, const int supposed_k static void weld_assert_poly_and_loop_kill_len(WeldMesh *weld_mesh, const Span corner_verts, const Span corner_edges, - Span polys, + const OffsetIndices polys, const int supposed_poly_kill_len, const int supposed_loop_kill_len) { int poly_kills = 0; int loop_kills = corner_verts.size(); for (const int i : polys.index_range()) { - const MPoly &poly = polys[i]; int poly_ctx = weld_mesh->poly_map[i]; if (poly_ctx != OUT_OF_CONTEXT) { const WeldPoly *wp = &weld_mesh->wpoly[poly_ctx]; @@ -214,7 +213,7 @@ static void weld_assert_poly_and_loop_kill_len(WeldMesh *weld_mesh, } } else { - loop_kills -= poly.totloop; + loop_kills -= polys[i].size(); } } @@ -790,7 +789,7 @@ static bool weld_iter_loop_of_poly_next(WeldLoopOfPolyIter &iter) * * \return r_weld_mesh: Loop and poly members will be allocated here. */ -static void weld_poly_loop_ctx_alloc(Span polys, +static void weld_poly_loop_ctx_alloc(const OffsetIndices polys, const Span corner_verts, const Span corner_edges, Span vert_dest_map, @@ -813,12 +812,11 @@ static void weld_poly_loop_ctx_alloc(Span polys, int maybe_new_poly = 0; for (const int i : polys.index_range()) { - const MPoly &poly = polys[i]; - const int loopstart = poly.loopstart; - const int totloop = poly.totloop; + const int loopstart = polys[i].start(); + const int totloop = polys[i].size(); int prev_wloop_len = wloop_len; - for (const int i_loop : IndexRange(loopstart, totloop)) { + for (const int i_loop : polys[i]) { int v = corner_verts[i_loop]; int e = corner_edges[i_loop]; int v_dest = vert_dest_map[v]; @@ -1035,7 +1033,7 @@ static void weld_poly_loop_ctx_setup_collapsed_and_split( #ifdef USE_WELD_DEBUG const Span corner_verts, const Span corner_edges, - Span polys, + const OffsetIndices polys, #endif Span vert_dest_map, const int remain_edge_ctx_len, @@ -1290,7 +1288,7 @@ static int poly_find_doubles(const OffsetIndices poly_corners_offsets, static void weld_poly_find_doubles(const Span corner_verts, const Span corner_edges, #ifdef USE_WELD_DEBUG - const Span polys, + const OffsetIndices polys, #endif const int medge_len, WeldMesh *r_weld_mesh) @@ -1378,7 +1376,7 @@ static void weld_mesh_context_create(const Mesh &mesh, WeldMesh *r_weld_mesh) { const Span edges = mesh.edges(); - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_verts = mesh.corner_verts(); const Span corner_edges = mesh.corner_edges(); @@ -1533,7 +1531,7 @@ static Mesh *create_merged_mesh(const Mesh &mesh, MutableSpan vert_dest_map, const int removed_vertex_count) { - const Span src_polys = mesh.polys(); + const OffsetIndices src_polys = mesh.polys(); const Span src_corner_verts = mesh.corner_verts(); const Span src_corner_edges = mesh.corner_edges(); const int totvert = mesh.totvert; @@ -1554,7 +1552,7 @@ static Mesh *create_merged_mesh(const Mesh &mesh, Mesh *result = BKE_mesh_new_nomain_from_template( &mesh, result_nverts, result_nedges, result_nloops, result_npolys); MutableSpan dst_edges = result->edges_for_write(); - MutableSpan dst_polys = result->polys_for_write(); + MutableSpan dst_poly_offsets = result->poly_offsets_for_write(); MutableSpan dst_corner_verts = result->corner_verts_for_write(); MutableSpan dst_corner_edges = result->corner_edges_for_write(); @@ -1648,12 +1646,12 @@ static Mesh *create_merged_mesh(const Mesh &mesh, int loop_cur = 0; Array group_buffer(weld_mesh.max_poly_len); for (const int i : src_polys.index_range()) { - const MPoly &poly = src_polys[i]; const int loop_start = loop_cur; const int poly_ctx = weld_mesh.poly_map[i]; if (poly_ctx == OUT_OF_CONTEXT) { - int mp_loop_len = poly.totloop; - CustomData_copy_data(&mesh.ldata, &result->ldata, poly.loopstart, loop_cur, mp_loop_len); + int mp_loop_len = src_polys[i].size(); + CustomData_copy_data( + &mesh.ldata, &result->ldata, src_polys[i].start(), loop_cur, src_polys[i].size()); for (; mp_loop_len--; loop_cur++) { dst_corner_verts[loop_cur] = vert_final_map[dst_corner_verts[loop_cur]]; dst_corner_edges[loop_cur] = edge_final_map[dst_corner_edges[loop_cur]]; @@ -1685,8 +1683,7 @@ static Mesh *create_merged_mesh(const Mesh &mesh, } CustomData_copy_data(&mesh.pdata, &result->pdata, i, r_i, 1); - dst_polys[r_i].loopstart = loop_start; - dst_polys[r_i].totloop = loop_cur - loop_start; + dst_poly_offsets[r_i] = loop_start; r_i++; } @@ -1715,8 +1712,7 @@ static Mesh *create_merged_mesh(const Mesh &mesh, loop_cur++; } - dst_polys[r_i].loopstart = loop_start; - dst_polys[r_i].totloop = loop_cur - loop_start; + dst_poly_offsets[r_i] = loop_start; r_i++; } diff --git a/source/blender/geometry/intern/mesh_primitive_cuboid.cc b/source/blender/geometry/intern/mesh_primitive_cuboid.cc index cf87607338f..778096e4d5a 100644 --- a/source/blender/geometry/intern/mesh_primitive_cuboid.cc +++ b/source/blender/geometry/intern/mesh_primitive_cuboid.cc @@ -108,7 +108,7 @@ static void calculate_positions(const CuboidConfig &config, MutableSpan * Hence they are passed as 1,4,3,2 when calculating polys clockwise, and 1,2,3,4 for * anti-clockwise. */ -static void define_quad(MutableSpan polys, +static void define_quad(MutableSpan poly_offsets, MutableSpan corner_verts, const int poly_index, const int loop_index, @@ -117,9 +117,7 @@ static void define_quad(MutableSpan polys, const int vert_3, const int vert_4) { - MPoly &poly = polys[poly_index]; - poly.loopstart = loop_index; - poly.totloop = 4; + poly_offsets[poly_index] = loop_index; corner_verts[loop_index] = vert_1; corner_verts[loop_index + 1] = vert_2; @@ -128,7 +126,7 @@ static void define_quad(MutableSpan polys, } static void calculate_polys(const CuboidConfig &config, - MutableSpan polys, + MutableSpan poly_offsets, MutableSpan corner_verts) { int loop_index = 0; @@ -148,7 +146,7 @@ static void calculate_polys(const CuboidConfig &config, const int vert_3 = vert_2 + 1; const int vert_4 = vert_1 + 1; - define_quad(polys, corner_verts, poly_index, loop_index, vert_1, vert_2, vert_3, vert_4); + define_quad(poly_offsets, corner_verts, poly_index, loop_index, vert_1, vert_2, vert_3, vert_4); loop_index += 4; poly_index++; } @@ -161,7 +159,7 @@ static void calculate_polys(const CuboidConfig &config, for ([[maybe_unused]] const int z : IndexRange(config.edges_z)) { for (const int x : IndexRange(config.edges_x)) { - define_quad(polys, + define_quad(poly_offsets, corner_verts, poly_index, loop_index, @@ -184,7 +182,7 @@ static void calculate_polys(const CuboidConfig &config, for ([[maybe_unused]] const int y : IndexRange(config.edges_y)) { for (const int x : IndexRange(config.edges_x)) { - define_quad(polys, + define_quad(poly_offsets, corner_verts, poly_index, loop_index, @@ -208,7 +206,7 @@ static void calculate_polys(const CuboidConfig &config, vert_2_start += (config.verts_x - 2) * (config.verts_y - 2); } for (const int x : IndexRange(config.edges_x)) { - define_quad(polys, + define_quad(poly_offsets, corner_verts, poly_index, loop_index, @@ -254,7 +252,7 @@ static void calculate_polys(const CuboidConfig &config, vert_3 = vert_2 + 2; } - define_quad(polys, corner_verts, poly_index, loop_index, vert_1, vert_2, vert_3, vert_4); + define_quad(poly_offsets, corner_verts, poly_index, loop_index, vert_1, vert_2, vert_3, vert_4); loop_index += 4; poly_index++; } @@ -301,7 +299,7 @@ static void calculate_polys(const CuboidConfig &config, vert_4 = vert_1 + config.verts_x; } - define_quad(polys, corner_verts, poly_index, loop_index, vert_1, vert_4, vert_3, vert_2); + define_quad(poly_offsets, corner_verts, poly_index, loop_index, vert_1, vert_4, vert_3, vert_2); loop_index += 4; poly_index++; } @@ -401,13 +399,13 @@ Mesh *create_cuboid_mesh(const float3 &size, Mesh *mesh = BKE_mesh_new_nomain(config.vertex_count, 0, config.loop_count, config.poly_count); MutableSpan positions = mesh->vert_positions_for_write(); - MutableSpan polys = mesh->polys_for_write(); + MutableSpan poly_offsets = mesh->poly_offsets_for_write(); MutableSpan corner_verts = mesh->corner_verts_for_write(); BKE_mesh_smooth_flag_set(mesh, false); calculate_positions(config, positions); - calculate_polys(config, polys, corner_verts); + calculate_polys(config, poly_offsets, corner_verts); BKE_mesh_calc_edges(mesh, false, false); if (uv_id) { diff --git a/source/blender/geometry/intern/mesh_split_edges.cc b/source/blender/geometry/intern/mesh_split_edges.cc index 00cfa5eb756..b1693369546 100644 --- a/source/blender/geometry/intern/mesh_split_edges.cc +++ b/source/blender/geometry/intern/mesh_split_edges.cc @@ -246,7 +246,7 @@ static void split_vertex_per_fan(const int vertex, static int adjacent_edge(const Span corner_verts, const Span corner_edges, const int loop_i, - const MPoly &poly, + const IndexRange poly, const int vertex) { const int adjacent_loop_i = (corner_verts[loop_i] == vertex) ? @@ -264,7 +264,7 @@ static int adjacent_edge(const Span corner_verts, static void calc_vertex_fans(const int vertex, const Span new_corner_verts, const Span new_corner_edges, - const Span polys, + const OffsetIndices polys, const Span> edge_to_loop_map, const Span loop_to_poly_map, MutableSpan connected_edges, @@ -373,8 +373,7 @@ void split_edges(Mesh &mesh, mesh.totvert); Vector> edge_to_loop_map = bke::mesh_topology::build_edge_to_loop_map_resizable( mesh.corner_edges(), mesh.totedge); - Array loop_to_poly_map = bke::mesh_topology::build_loop_to_poly_map(mesh.polys(), - mesh.totloop); + Array loop_to_poly_map = bke::mesh_topology::build_loop_to_poly_map(mesh.polys()); /* Store offsets, so we can split edges in parallel. */ Array edge_offsets(edges.size()); @@ -389,7 +388,7 @@ void split_edges(Mesh &mesh, num_edge_duplicates[edge] = num_duplicates; } - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); MutableSpan corner_verts = mesh.corner_verts_for_write(); MutableSpan corner_edges = mesh.corner_edges_for_write(); diff --git a/source/blender/geometry/intern/realize_instances.cc b/source/blender/geometry/intern/realize_instances.cc index 0a51ffe6def..cca5b8cd346 100644 --- a/source/blender/geometry/intern/realize_instances.cc +++ b/source/blender/geometry/intern/realize_instances.cc @@ -101,7 +101,7 @@ struct MeshRealizeInfo { const Mesh *mesh = nullptr; Span positions; Span edges; - Span polys; + OffsetIndices polys; Span corner_verts; Span corner_edges; @@ -956,7 +956,7 @@ static void execute_realize_mesh_task(const RealizeInstancesOptions &options, MutableSpan dst_attribute_writers, MutableSpan all_dst_positions, MutableSpan all_dst_edges, - MutableSpan all_dst_polys, + MutableSpan all_dst_poly_offsets, MutableSpan all_dst_corner_verts, MutableSpan all_dst_corner_edges, MutableSpan all_dst_vertex_ids, @@ -967,7 +967,7 @@ static void execute_realize_mesh_task(const RealizeInstancesOptions &options, const Span src_positions = mesh_info.positions; const Span src_edges = mesh_info.edges; - const Span src_polys = mesh_info.polys; + const OffsetIndices src_polys = mesh_info.polys; const Span src_corner_verts = mesh_info.corner_verts; const Span src_corner_edges = mesh_info.corner_edges; @@ -978,7 +978,7 @@ static void execute_realize_mesh_task(const RealizeInstancesOptions &options, MutableSpan dst_positions = all_dst_positions.slice(dst_vert_range); MutableSpan dst_edges = all_dst_edges.slice(dst_edge_range); - MutableSpan dst_polys = all_dst_polys.slice(dst_poly_range); + MutableSpan dst_poly_offsets = all_dst_poly_offsets.slice(dst_poly_range); MutableSpan dst_corner_verts = all_dst_corner_verts.slice(dst_loop_range); MutableSpan dst_corner_edges = all_dst_corner_edges.slice(dst_loop_range); @@ -1008,10 +1008,7 @@ static void execute_realize_mesh_task(const RealizeInstancesOptions &options, }); threading::parallel_for(src_polys.index_range(), 1024, [&](const IndexRange poly_range) { for (const int i : poly_range) { - const MPoly &src_poly = src_polys[i]; - MPoly &dst_poly = dst_polys[i]; - dst_poly = src_poly; - dst_poly.loopstart += task.start_indices.loop; + dst_poly_offsets[i] = src_polys[i].start() + task.start_indices.loop; } }); if (!all_dst_material_indices.is_empty()) { @@ -1093,7 +1090,7 @@ static void execute_realize_mesh_tasks(const RealizeInstancesOptions &options, bke::MutableAttributeAccessor dst_attributes = dst_mesh->attributes_for_write(); MutableSpan dst_positions = dst_mesh->vert_positions_for_write(); MutableSpan dst_edges = dst_mesh->edges_for_write(); - MutableSpan dst_polys = dst_mesh->polys_for_write(); + MutableSpan dst_poly_offsets = dst_mesh->poly_offsets_for_write(); MutableSpan dst_corner_verts = dst_mesh->corner_verts_for_write(); MutableSpan dst_corner_edges = dst_mesh->corner_edges_for_write(); @@ -1143,7 +1140,7 @@ static void execute_realize_mesh_tasks(const RealizeInstancesOptions &options, dst_attribute_writers, dst_positions, dst_edges, - dst_polys, + dst_poly_offsets, dst_corner_verts, dst_corner_edges, vertex_ids.span, diff --git a/source/blender/io/alembic/exporter/abc_writer_mesh.cc b/source/blender/io/alembic/exporter/abc_writer_mesh.cc index e46d45c50ae..95782023b7b 100644 --- a/source/blender/io/alembic/exporter/abc_writer_mesh.cc +++ b/source/blender/io/alembic/exporter/abc_writer_mesh.cc @@ -176,7 +176,7 @@ void ABCGenericMeshWriter::do_write(HierarchyContext &context) m_custom_data_config.pack_uvs = args_.export_params->packuv; m_custom_data_config.mesh = mesh; - m_custom_data_config.polys = mesh->polys_for_write().data(); + m_custom_data_config.poly_offsets = mesh->poly_offsets_for_write().data(); m_custom_data_config.corner_verts = mesh->corner_verts_for_write().data(); m_custom_data_config.totpoly = mesh->totpoly; m_custom_data_config.totloop = mesh->totloop; @@ -449,7 +449,7 @@ static void get_topology(struct Mesh *mesh, std::vector &loop_counts, bool &r_has_flat_shaded_poly) { - const Span polys = mesh->polys(); + const OffsetIndices polys = mesh->polys(); const Span corner_verts = mesh->corner_verts(); const bke::AttributeAccessor attributes = mesh->attributes(); const VArray sharp_faces = attributes.lookup_or_default( @@ -468,11 +468,11 @@ static void get_topology(struct Mesh *mesh, /* NOTE: data needs to be written in the reverse order. */ for (const int i : polys.index_range()) { - const MPoly &poly = polys[i]; - loop_counts.push_back(poly.totloop); + const IndexRange poly = polys[i]; + loop_counts.push_back(poly.size()); - int corner = poly.loopstart + (poly.totloop - 1); - for (int j = 0; j < poly.totloop; j++, corner--) { + int corner = poly.start() + (poly.size() - 1); + for (int j = 0; j < poly.size(); j++, corner--) { poly_verts.push_back(corner_verts[corner]); } } @@ -550,12 +550,12 @@ static void get_loop_normals(struct Mesh *mesh, /* NOTE: data needs to be written in the reverse order. */ int abc_index = 0; - const Span polys = mesh->polys(); + const OffsetIndices polys = mesh->polys(); for (const int i : polys.index_range()) { - const MPoly &poly = polys[i]; - for (int j = poly.totloop - 1; j >= 0; j--, abc_index++) { - int blender_index = poly.loopstart + j; + const IndexRange poly = polys[i]; + for (int j = poly.size() - 1; j >= 0; j--, abc_index++) { + int blender_index = poly[j]; copy_yup_from_zup(normals[abc_index].getValue(), lnors[blender_index]); } } diff --git a/source/blender/io/alembic/intern/abc_customdata.cc b/source/blender/io/alembic/intern/abc_customdata.cc index f9ae257e1ff..96714330fb9 100644 --- a/source/blender/io/alembic/intern/abc_customdata.cc +++ b/source/blender/io/alembic/intern/abc_customdata.cc @@ -56,8 +56,7 @@ static void get_uvs(const CDStreamConfig &config, return; } - const int num_poly = config.totpoly; - MPoly *polys = config.polys; + const OffsetIndices polys = config.mesh->polys(); int *corner_verts = config.corner_verts; if (!config.pack_uvs) { @@ -66,11 +65,11 @@ static void get_uvs(const CDStreamConfig &config, uvs.resize(config.totloop); /* Iterate in reverse order to match exported polygons. */ - for (int i = 0; i < num_poly; i++) { - MPoly ¤t_poly = polys[i]; - const float2 *loopuv = mloopuv_array + current_poly.loopstart + current_poly.totloop; + for (const int i : polys.index_range()) { + const IndexRange poly = polys[i]; + const float2 *loopuv = mloopuv_array + poly.start() + poly.size(); - for (int j = 0; j < current_poly.totloop; j++, count++) { + for (int j = 0; j < poly.size(); j++, count++) { loopuv--; uvidx[count] = count; @@ -84,12 +83,12 @@ static void get_uvs(const CDStreamConfig &config, std::vector> idx_map(config.totvert); int idx_count = 0; - for (int i = 0; i < num_poly; i++) { - MPoly ¤t_poly = polys[i]; - int *poly_verts = corner_verts + current_poly.loopstart + current_poly.totloop; - const float2 *loopuv = mloopuv_array + current_poly.loopstart + current_poly.totloop; + for (const int i : polys.index_range()) { + const IndexRange poly = polys[i]; + int *poly_verts = corner_verts + poly.start() + poly.size(); + const float2 *loopuv = mloopuv_array + poly.start() + poly.size(); - for (int j = 0; j < current_poly.totloop; j++) { + for (int j = 0; j < poly.size(); j++) { poly_verts--; loopuv--; @@ -172,7 +171,7 @@ static void get_cols(const CDStreamConfig &config, const void *cd_data) { const float cscale = 1.0f / 255.0f; - const MPoly *polys = config.polys; + const OffsetIndices polys = config.mesh->polys(); const MCol *cfaces = static_cast(cd_data); buffer.reserve(config.totvert); @@ -180,11 +179,11 @@ static void get_cols(const CDStreamConfig &config, Imath::C4f col; - for (int i = 0; i < config.totpoly; i++) { - const MPoly &poly = polys[i]; - const MCol *cface = &cfaces[poly.loopstart + poly.totloop]; + for (const int i : polys.index_range()) { + const IndexRange poly = polys[i]; + const MCol *cface = &cfaces[poly.start() + poly.size()]; - for (int j = 0; j < poly.totloop; j++) { + for (int j = 0; j < poly.size(); j++) { cface--; col[0] = cface->a * cscale; @@ -315,7 +314,7 @@ static void read_uvs(const CDStreamConfig &config, const Alembic::AbcGeom::V2fArraySamplePtr &uvs, const UInt32ArraySamplePtr &indices) { - MPoly *polys = config.polys; + const OffsetIndices polys = config.mesh->polys(); const int *corner_verts = config.corner_verts; float2 *mloopuvs = static_cast(data); @@ -324,13 +323,13 @@ static void read_uvs(const CDStreamConfig &config, BLI_assert(uv_scope != ABC_UV_SCOPE_NONE); const bool do_uvs_per_loop = (uv_scope == ABC_UV_SCOPE_LOOP); - for (int i = 0; i < config.totpoly; i++) { - MPoly &poly = polys[i]; - uint rev_loop_offset = poly.loopstart + poly.totloop - 1; + for (const int i : polys.index_range()) { + const IndexRange poly = polys[i]; + uint rev_loop_offset = poly.start() + poly.size() - 1; - for (int f = 0; f < poly.totloop; f++) { + for (int f = 0; f < poly.size(); f++) { rev_loop_index = rev_loop_offset - f; - loop_index = do_uvs_per_loop ? poly.loopstart + f : corner_verts[rev_loop_index]; + loop_index = do_uvs_per_loop ? poly.start() + f : corner_verts[rev_loop_index]; uv_index = (*indices)[loop_index]; const Imath::V2f &uv = (*uvs)[uv_index]; @@ -411,7 +410,7 @@ static void read_custom_data_mcols(const std::string &iobject_full_name, void *cd_data = config.add_customdata_cb( config.mesh, prop_header.getName().c_str(), CD_PROP_BYTE_COLOR); MCol *cfaces = static_cast(cd_data); - const MPoly *polys = config.polys; + const OffsetIndices polys = config.mesh->polys(); const int *corner_verts = config.corner_verts; size_t face_index = 0; @@ -424,12 +423,12 @@ static void read_custom_data_mcols(const std::string &iobject_full_name, * is why we have to check for indices->size() > 0 */ bool use_dual_indexing = is_facevarying && indices->size() > 0; - for (int i = 0; i < config.totpoly; i++) { - const MPoly &poly = polys[i]; - MCol *cface = &cfaces[poly.loopstart + poly.totloop]; - const int *poly_verts = &corner_verts[poly.loopstart + poly.totloop]; + for (const int i : polys.index_range()) { + const IndexRange poly = polys[i]; + MCol *cface = &cfaces[poly.start() + poly.size()]; + const int *poly_verts = &corner_verts[poly.start() + poly.size()]; - for (int j = 0; j < poly.totloop; j++, face_index++) { + for (int j = 0; j < poly.size(); j++, face_index++) { cface--; poly_verts--; diff --git a/source/blender/io/alembic/intern/abc_customdata.h b/source/blender/io/alembic/intern/abc_customdata.h index 4e011393e36..6891dd42237 100644 --- a/source/blender/io/alembic/intern/abc_customdata.h +++ b/source/blender/io/alembic/intern/abc_customdata.h @@ -16,7 +16,6 @@ #include "BLI_math_vector_types.hh" struct CustomData; -struct MPoly; struct Mesh; using Alembic::Abc::ICompoundProperty; @@ -32,7 +31,7 @@ struct CDStreamConfig { int *corner_verts; int totloop; - MPoly *polys; + int *poly_offsets; int totpoly; float3 *positions; @@ -74,7 +73,7 @@ struct CDStreamConfig { CDStreamConfig() : corner_verts(NULL), totloop(0), - polys(NULL), + poly_offsets(NULL), totpoly(0), totvert(0), pack_uvs(false), diff --git a/source/blender/io/alembic/intern/abc_reader_mesh.cc b/source/blender/io/alembic/intern/abc_reader_mesh.cc index f4190f3d40e..5ff83d25690 100644 --- a/source/blender/io/alembic/intern/abc_reader_mesh.cc +++ b/source/blender/io/alembic/intern/abc_reader_mesh.cc @@ -175,7 +175,7 @@ void read_mverts(Mesh &mesh, const P3fArraySamplePtr positions, const N3fArraySa static void read_mpolys(CDStreamConfig &config, const AbcMeshData &mesh_data) { - MPoly *polys = config.polys; + int *poly_offsets = config.poly_offsets; int *corner_verts = config.corner_verts; float2 *mloopuvs = config.mloopuv; @@ -197,9 +197,7 @@ static void read_mpolys(CDStreamConfig &config, const AbcMeshData &mesh_data) for (int i = 0; i < face_counts->size(); i++) { const int face_size = (*face_counts)[i]; - MPoly &poly = polys[i]; - poly.loopstart = loop_index; - poly.totloop = face_size; + poly_offsets[i] = loop_index; /* Polygons are always assumed to be smooth-shaded. If the Alembic mesh should be flat-shaded, * this is encoded in custom loop normals. See #71246. */ @@ -269,14 +267,14 @@ static void process_loop_normals(CDStreamConfig &config, const N3fArraySamplePtr float(*lnors)[3] = static_cast( MEM_malloc_arrayN(loop_count, sizeof(float[3]), "ABC::FaceNormals")); - const Span polys = mesh->polys(); + const OffsetIndices polys = mesh->polys(); const N3fArraySample &loop_normals = *loop_normals_ptr; int abc_index = 0; - for (const int i : polys.index_range()) { - const MPoly &poly = polys[i]; + for (int i = 0, e = mesh->totpoly; i < e; i++) { + const IndexRange poly = polys[i]; /* As usual, ABC orders the loops in reverse. */ - for (int j = poly.totloop - 1; j >= 0; j--, abc_index++) { - int blender_index = poly.loopstart + j; + for (int j = poly.size() - 1; j >= 0; j--, abc_index++) { + int blender_index = poly[j]; copy_zup_from_yup(lnors[blender_index], loop_normals[abc_index].getValue()); } } @@ -518,7 +516,7 @@ CDStreamConfig get_config(Mesh *mesh, const bool use_vertex_interpolation) config.mesh = mesh; config.positions = mesh->vert_positions_for_write().data(); config.corner_verts = mesh->corner_verts_for_write().data(); - config.polys = mesh->polys_for_write().data(); + config.poly_offsets = mesh->poly_offsets_for_write().data(); config.totvert = mesh->totvert; config.totloop = mesh->totloop; config.totpoly = mesh->totpoly; diff --git a/source/blender/io/collada/GeometryExporter.cpp b/source/blender/io/collada/GeometryExporter.cpp index 04340a04f93..6c69324dae6 100644 --- a/source/blender/io/collada/GeometryExporter.cpp +++ b/source/blender/io/collada/GeometryExporter.cpp @@ -292,7 +292,7 @@ static bool collect_vertex_counts_per_poly(Mesh *me, int material_index, std::vector &vcount_list) { - const Span polys = me->polys(); + const blender::OffsetIndices polys = me->polys(); const blender::bke::AttributeAccessor attributes = me->attributes(); const blender::VArray material_indices = attributes.lookup_or_default( "material_index", ATTR_DOMAIN_FACE, 0); @@ -301,8 +301,7 @@ static bool collect_vertex_counts_per_poly(Mesh *me, /* Expecting that the material index is always 0 if the mesh has no materials assigned */ for (const int i : polys.index_range()) { if (material_indices[i] == material_index) { - const MPoly &poly = polys[i]; - const int vertex_count = poly.totloop; + const int vertex_count = polys[i].size(); vcount_list.push_back(vertex_count); if (vertex_count != 3) { is_triangulated = false; @@ -327,7 +326,7 @@ void GeometryExporter::create_mesh_primitive_list(short material_index, std::string &geom_id, std::vector &norind) { - const Span polys = me->polys(); + const blender::OffsetIndices polys = me->polys(); const Span corner_verts = me->corner_verts(); std::vector vcount_list; @@ -411,14 +410,14 @@ void GeometryExporter::create_mesh_primitive_list(short material_index, /*

*/ int texindex = 0; for (const int i : polys.index_range()) { - const MPoly *poly = &polys[i]; - int loop_count = poly->totloop; + const blender::IndexRange poly = polys[i]; + int loop_count = poly.size(); if (material_indices[i] == material_index) { BCPolygonNormalsIndices normal_indices = norind[i]; for (int j = 0; j < loop_count; j++) { - const int vert = corner_verts[poly->loopstart + j]; + const int vert = corner_verts[poly[j]]; primitive_list->appendValues(vert); primitive_list->appendValues(normal_indices[j]); if (has_uvs) { @@ -507,11 +506,10 @@ void GeometryExporter::createVertexColorSource(std::string geom_id, Mesh *me) source.prepareToAppendValues(); - const Span polys = me->polys(); + const blender::OffsetIndices polys = me->polys(); for (const int i : polys.index_range()) { - const MPoly &poly = polys[i]; - const MLoopCol *mlc = mloopcol + poly.loopstart; - for (int j = 0; j < poly.totloop; j++, mlc++) { + for (const int corner : polys[i]) { + const MLoopCol *mlc = &mloopcol[corner]; source.appendValues(mlc->r / 255.0f, mlc->g / 255.0f, mlc->b / 255.0f, mlc->a / 255.0f); } } @@ -537,7 +535,7 @@ std::string GeometryExporter::makeTexcoordSourceId(std::string &geom_id, void GeometryExporter::createTexcoordsSource(std::string geom_id, Mesh *me) { int totuv = me->totloop; - const Span polys = me->polys(); + const blender::OffsetIndices polys = me->polys(); int num_layers = CustomData_number_of_layers(&me->ldata, CD_PROP_FLOAT2); @@ -565,10 +563,8 @@ void GeometryExporter::createTexcoordsSource(std::string geom_id, Mesh *me) source.prepareToAppendValues(); for (const int i : polys.index_range()) { - const MPoly *poly = &polys[i]; - const blender::float2 *mloop = uv_map + poly->loopstart; - for (int j = 0; j < poly->totloop; j++) { - source.appendValues(mloop[j][0], mloop[j][1]); + for (const int corner : polys[i]) { + source.appendValues(uv_map[corner][0], uv_map[corner][1]); } } @@ -621,7 +617,7 @@ void GeometryExporter::create_normals(std::vector &normals, const Span positions = me->vert_positions(); const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(me); - const Span polys = me->polys(); + const blender::OffsetIndices polys = me->polys(); const Span corner_verts = me->corner_verts(); const float(*lnors)[3] = nullptr; bool use_custom_normals = false; @@ -637,14 +633,14 @@ void GeometryExporter::create_normals(std::vector &normals, } for (const int poly_index : polys.index_range()) { - const MPoly *poly = &polys[poly_index]; + const IndexRange poly = polys[poly_index]; bool use_vert_normals = use_custom_normals || !sharp_faces[poly_index]; if (!use_vert_normals) { /* For flat faces use face normal as vertex normal: */ - const float3 vector = blender::bke::mesh::poly_normal_calc( - positions, corner_verts.slice(poly->loopstart, poly->totloop)); + const float3 vector = blender::bke::mesh::poly_normal_calc(positions, + corner_verts.slice(poly)); Normal n = {vector[0], vector[1], vector[2]}; normals.push_back(n); @@ -652,16 +648,15 @@ void GeometryExporter::create_normals(std::vector &normals, } BCPolygonNormalsIndices poly_indices; - for (int loop_index = 0; loop_index < poly->totloop; loop_index++) { - uint loop_idx = poly->loopstart + loop_index; + for (const int corner : poly) { if (use_vert_normals) { float normalized[3]; if (use_custom_normals) { - normalize_v3_v3(normalized, lnors[loop_idx]); + normalize_v3_v3(normalized, lnors[corner]); } else { - copy_v3_v3(normalized, vert_normals[corner_verts[loop_index]]); + copy_v3_v3(normalized, vert_normals[corner_verts[corner]]); normalize_v3(normalized); } Normal n = {normalized[0], normalized[1], normalized[2]}; diff --git a/source/blender/io/collada/MeshImporter.cpp b/source/blender/io/collada/MeshImporter.cpp index 6ccad864790..e0a205f9162 100644 --- a/source/blender/io/collada/MeshImporter.cpp +++ b/source/blender/io/collada/MeshImporter.cpp @@ -205,11 +205,11 @@ MeshImporter::MeshImporter(UnitConverter *unitconv, /* pass */ } -bool MeshImporter::set_poly_indices( - MPoly *poly, int *poly_verts, int loop_index, const uint *indices, int loop_count) +bool MeshImporter::set_poly_indices(int *poly_verts, + int loop_index, + const uint *indices, + int loop_count) { - poly->loopstart = loop_index; - poly->totloop = loop_count; bool broken_loop = false; for (int index = 0; index < loop_count; index++) { @@ -451,7 +451,7 @@ void MeshImporter::allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me) if (total_poly_count > 0) { me->totpoly = total_poly_count; me->totloop = total_loop_count; - CustomData_add_layer(&me->pdata, CD_MPOLY, CD_SET_DEFAULT, me->totpoly); + BKE_mesh_poly_offsets_ensure_alloc(me); CustomData_add_layer_named( &me->ldata, CD_PROP_INT32, CD_SET_DEFAULT, me->totloop, ".corner_vert"); @@ -604,7 +604,7 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, UVDataWrapper uvs(collada_mesh->getUVCoords()); VCOLDataWrapper vcol(collada_mesh->getColors()); - MutableSpan polys = me->polys_for_write(); + MutableSpan poly_offsets = me->poly_offsets_for_write(); MutableSpan corner_verts = me->corner_verts_for_write(); int poly_index = 0; int loop_index = 0; @@ -655,11 +655,8 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, /* For each triangle store indices of its 3 vertices */ uint triangle_vertex_indices[3] = { first_vertex, position_indices[1], position_indices[2]}; - set_poly_indices(&polys[poly_index], - &corner_verts[loop_index], - loop_index, - triangle_vertex_indices, - 3); + poly_offsets[poly_index] = loop_index; + set_poly_indices(&corner_verts[loop_index], loop_index, triangle_vertex_indices, 3); if (mp_has_normals) { /* vertex normals, same implementation as for the triangles */ /* The same for vertices normals. */ @@ -701,8 +698,9 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, continue; /* TODO: add support for holes */ } + poly_offsets[poly_index] = loop_index; bool broken_loop = set_poly_indices( - &polys[poly_index], &corner_verts[loop_index], loop_index, position_indices, vcount); + &corner_verts[loop_index], loop_index, position_indices, vcount); if (broken_loop) { invalid_loop_holes += 1; } @@ -729,7 +727,7 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, } if (mp_has_normals) { - /* If it turns out that we have complete custom normals for each MPoly + /* If it turns out that we have complete custom normals for each poly * and we want to use custom normals, this will be overridden. */ sharp_faces[poly_index] = is_flat_face(normal_indices, nor, vcount); diff --git a/source/blender/io/collada/MeshImporter.h b/source/blender/io/collada/MeshImporter.h index e34a9e322fb..eab9ef7cb8f 100644 --- a/source/blender/io/collada/MeshImporter.h +++ b/source/blender/io/collada/MeshImporter.h @@ -92,8 +92,10 @@ class MeshImporter : public MeshImporterBase { * A pair/of geom UID and mat UID, one geometry can have several materials. */ std::multimap materials_mapped_to_geom; - bool set_poly_indices( - MPoly *poly, int *poly_verts, int loop_index, const unsigned int *indices, int loop_count); + bool set_poly_indices(int *poly_verts, + int loop_index, + const unsigned int *indices, + int loop_count); void set_face_uv(blender::float2 *mloopuv, UVDataWrapper &uvs, diff --git a/source/blender/io/ply/exporter/ply_export_load_plydata.cc b/source/blender/io/ply/exporter/ply_export_load_plydata.cc index adadf102837..b88c5070553 100644 --- a/source/blender/io/ply/exporter/ply_export_load_plydata.cc +++ b/source/blender/io/ply/exporter/ply_export_load_plydata.cc @@ -168,8 +168,9 @@ void load_plydata(PlyData &plyData, Depsgraph *depsgraph, const PLYExportParams BKE_object_get_pre_modified_mesh(&export_object_eval_); bool force_triangulation = false; - for (const MPoly poly : mesh->polys()) { - if (poly.totloop > 255) { + const OffsetIndices polys = mesh->polys(); + for (const int i : polys.index_range()) { + if (polys[i].size() > 255) { force_triangulation = true; break; } @@ -197,15 +198,14 @@ void load_plydata(PlyData &plyData, Depsgraph *depsgraph, const PLYExportParams /* Face data. */ plyData.face_vertices.reserve(mesh->totloop); plyData.face_sizes.reserve(mesh->totpoly); - int loop_offset = 0; - for (const MPoly &poly : mesh->polys()) { - for (int i = 0; i < poly.totloop; ++i) { - int ply_index = loop_to_ply[i + loop_offset]; + for (const int i : polys.index_range()) { + const IndexRange poly = polys[i]; + for (const int corner : poly) { + int ply_index = loop_to_ply[corner]; BLI_assert(ply_index >= 0 && ply_index < ply_to_vertex.size()); plyData.face_vertices.append(ply_index + vertex_offset); } - loop_offset += poly.totloop; - plyData.face_sizes.append(poly.totloop); + plyData.face_sizes.append(poly.size()); } /* Vertices */ diff --git a/source/blender/io/ply/importer/ply_import_mesh.cc b/source/blender/io/ply/importer/ply_import_mesh.cc index 541796ed83b..9efb2af4aea 100644 --- a/source/blender/io/ply/importer/ply_import_mesh.cc +++ b/source/blender/io/ply/importer/ply_import_mesh.cc @@ -53,18 +53,17 @@ Mesh *convert_ply_to_mesh(PlyData &data, Mesh *mesh, const PLYImportParams ¶ /* Create poly and loop layers. */ mesh->totpoly = int(data.face_sizes.size()); mesh->totloop = int(data.face_vertices.size()); - CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_SET_DEFAULT, mesh->totpoly); + BKE_mesh_poly_offsets_ensure_alloc(mesh); CustomData_add_layer_named( &mesh->ldata, CD_PROP_INT32, CD_CONSTRUCT, mesh->totloop, ".corner_vert"); - MutableSpan polys = mesh->polys_for_write(); + MutableSpan poly_offsets = mesh->poly_offsets_for_write(); MutableSpan corner_verts = mesh->corner_verts_for_write(); /* Fill in face data. */ uint32_t offset = 0; for (int i = 0; i < mesh->totpoly; i++) { uint32_t size = data.face_sizes[i]; - polys[i].loopstart = offset; - polys[i].totloop = size; + poly_offsets[i] = offset; for (int j = 0; j < size; j++) { uint32_t v = data.face_vertices[offset + j]; if (v >= mesh->totvert) { diff --git a/source/blender/io/stl/importer/stl_import_mesh.cc b/source/blender/io/stl/importer/stl_import_mesh.cc index 39a24c2c13a..1c19a96cc0d 100644 --- a/source/blender/io/stl/importer/stl_import_mesh.cc +++ b/source/blender/io/stl/importer/stl_import_mesh.cc @@ -82,16 +82,20 @@ Mesh *STLMeshHelper::to_mesh(Main *bmain, char *mesh_name) mesh->totpoly = tris_.size(); mesh->totloop = tris_.size() * 3; - CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_SET_DEFAULT, mesh->totpoly); + BKE_mesh_poly_offsets_ensure_alloc(mesh); CustomData_add_layer_named( &mesh->ldata, CD_PROP_INT32, CD_SET_DEFAULT, mesh->totloop, ".corner_vert"); - MutableSpan polys = mesh->polys_for_write(); + + MutableSpan poly_offsets = mesh->poly_offsets_for_write(); + threading::parallel_for(poly_offsets.index_range(), 4096, [&](const IndexRange range) { + for (const int i : range) { + poly_offsets[i] = i * 3; + } + }); + MutableSpan corner_verts = mesh->corner_verts_for_write(); threading::parallel_for(tris_.index_range(), 2048, [&](IndexRange tris_range) { for (const int i : tris_range) { - polys[i].loopstart = 3 * i; - polys[i].totloop = 3; - corner_verts[3 * i] = tris_[i].v1; corner_verts[3 * i + 1] = tris_[i].v2; corner_verts[3 * i + 2] = tris_[i].v3; diff --git a/source/blender/io/usd/intern/usd_reader_mesh.cc b/source/blender/io/usd/intern/usd_reader_mesh.cc index 62add35ea5e..4df4f7d566a 100644 --- a/source/blender/io/usd/intern/usd_reader_mesh.cc +++ b/source/blender/io/usd/intern/usd_reader_mesh.cc @@ -262,7 +262,7 @@ bool USDMeshReader::topology_changed(const Mesh *existing_mesh, const double mot void USDMeshReader::read_mpolys(Mesh *mesh) { - MutableSpan polys = mesh->polys_for_write(); + MutableSpan poly_offsets = mesh->poly_offsets_for_write(); MutableSpan corner_verts = mesh->corner_verts_for_write(); int loop_index = 0; @@ -270,9 +270,7 @@ void USDMeshReader::read_mpolys(Mesh *mesh) for (int i = 0; i < face_counts_.size(); i++) { const int face_size = face_counts_[i]; - MPoly &poly = polys[i]; - poly.loopstart = loop_index; - poly.totloop = face_size; + poly_offsets[i] = loop_index; /* Polygons are always assumed to be smooth-shaded. If the mesh should be flat-shaded, * this is encoded in custom loop normals. */ @@ -467,12 +465,12 @@ void USDMeshReader::read_colors(Mesh *mesh, const double motionSampleTime) MLoopCol *colors = static_cast(cd_ptr); - const Span polys = mesh->polys(); + const OffsetIndices polys = mesh->polys(); const Span corner_verts = mesh->corner_verts(); for (const int i : polys.index_range()) { - const MPoly &poly = polys[i]; - for (int j = 0; j < poly.totloop; ++j) { - int loop_index = poly.loopstart + j; + const IndexRange poly = polys[i]; + for (int j = 0; j < poly.size(); ++j) { + int loop_index = poly[j]; /* Default for constant varying interpolation. */ int usd_index = 0; @@ -481,9 +479,9 @@ void USDMeshReader::read_colors(Mesh *mesh, const double motionSampleTime) usd_index = corner_verts[loop_index]; } else if (interp == pxr::UsdGeomTokens->faceVarying) { - usd_index = poly.loopstart; + usd_index = poly.start(); if (is_left_handed_) { - usd_index += poly.totloop - 1 - j; + usd_index += poly.size() - 1 - j; } else { usd_index += j; @@ -581,15 +579,15 @@ void USDMeshReader::process_normals_face_varying(Mesh *mesh) float(*lnors)[3] = static_cast( MEM_malloc_arrayN(loop_count, sizeof(float[3]), "USD::FaceNormals")); - const Span polys = mesh->polys(); + const OffsetIndices polys = mesh->polys(); for (const int i : polys.index_range()) { - const MPoly &poly = polys[i]; - for (int j = 0; j < poly.totloop; j++) { - int blender_index = poly.loopstart + j; + const IndexRange poly = polys[i]; + for (int j = 0; j < poly.size(); j++) { + int blender_index = poly.start() + j; - int usd_index = poly.loopstart; + int usd_index = poly.start(); if (is_left_handed_) { - usd_index += poly.totloop - 1 - j; + usd_index += poly.size() - 1 - j; } else { usd_index += j; @@ -620,14 +618,12 @@ void USDMeshReader::process_normals_uniform(Mesh *mesh) float(*lnors)[3] = static_cast( MEM_malloc_arrayN(mesh->totloop, sizeof(float[3]), "USD::FaceNormals")); - const Span polys = mesh->polys(); + const OffsetIndices polys = mesh->polys(); for (const int i : polys.index_range()) { - const MPoly &poly = polys[i]; - for (int j = 0; j < poly.totloop; j++) { - int loop_index = poly.loopstart + j; - lnors[loop_index][0] = normals_[i][0]; - lnors[loop_index][1] = normals_[i][1]; - lnors[loop_index][2] = normals_[i][2]; + for (const int corner : polys[i]) { + lnors[corner][0] = normals_[i][0]; + lnors[corner][1] = normals_[i][1]; + lnors[corner][2] = normals_[i][2]; } } @@ -858,8 +854,7 @@ Mesh *USDMeshReader::read_mesh(Mesh *existing_mesh, /* Here we assume that the number of materials doesn't change, i.e. that * the material slots that were created when the object was loaded from * USD are still valid now. */ - MutableSpan polys = active_mesh->polys_for_write(); - if (!polys.is_empty() && import_params_.import_materials) { + if (active_mesh->totpoly != 0 && import_params_.import_materials) { std::map mat_map; bke::MutableAttributeAccessor attributes = active_mesh->attributes_for_write(); bke::SpanAttributeWriter material_indices = diff --git a/source/blender/io/usd/intern/usd_reader_shape.cc b/source/blender/io/usd/intern/usd_reader_shape.cc index fe661b5acab..d1352c3006a 100644 --- a/source/blender/io/usd/intern/usd_reader_shape.cc +++ b/source/blender/io/usd/intern/usd_reader_shape.cc @@ -142,23 +142,18 @@ Mesh *USDShapeReader::read_mesh(struct Mesh *existing_mesh, return existing_mesh; } - MutableSpan polys = active_mesh->polys_for_write(); - MutableSpan corner_verts = active_mesh->corner_verts_for_write(); + MutableSpan poly_offsets = active_mesh->poly_offsets_for_write(); + for (const int i : IndexRange(active_mesh->totpoly)) { + poly_offsets[i] = face_counts[i]; + } + offset_indices::accumulate_counts_to_offsets(poly_offsets); /* Don't smooth-shade cubes; we're not worrying about sharpness for Gprims. */ BKE_mesh_smooth_flag_set(active_mesh, !prim_.IsA()); - int loop_index = 0; - for (int i = 0; i < face_counts.size(); i++) { - const int face_size = face_counts[i]; - - MPoly &poly = polys[i]; - poly.loopstart = loop_index; - poly.totloop = face_size; - - for (int f = 0; f < face_size; ++f, ++loop_index) { - corner_verts[loop_index] = face_indices[loop_index]; - } + MutableSpan corner_verts = active_mesh->corner_verts_for_write(); + for (const int i : corner_verts.index_range()) { + corner_verts[i] = face_indices[i]; } BKE_mesh_calc_edges(active_mesh, false, false); diff --git a/source/blender/io/usd/intern/usd_writer_mesh.cc b/source/blender/io/usd/intern/usd_writer_mesh.cc index 670ce5567ab..885b34eb5ba 100644 --- a/source/blender/io/usd/intern/usd_writer_mesh.cc +++ b/source/blender/io/usd/intern/usd_writer_mesh.cc @@ -287,13 +287,13 @@ static void get_loops_polys(const Mesh *mesh, USDMeshData &usd_mesh_data) usd_mesh_data.face_vertex_counts.reserve(mesh->totpoly); usd_mesh_data.face_indices.reserve(mesh->totloop); - const Span polys = mesh->polys(); + const OffsetIndices polys = mesh->polys(); const Span corner_verts = mesh->corner_verts(); for (const int i : polys.index_range()) { - const MPoly &poly = polys[i]; - usd_mesh_data.face_vertex_counts.push_back(poly.totloop); - for (const int vert : corner_verts.slice(poly.loopstart, poly.totloop)) { + const IndexRange poly = polys[i]; + usd_mesh_data.face_vertex_counts.push_back(poly.size()); + for (const int vert : corner_verts.slice(poly)) { usd_mesh_data.face_indices.push_back(vert); } } @@ -426,7 +426,7 @@ void USDGenericMeshWriter::write_normals(const Mesh *mesh, pxr::UsdGeomMesh usd_ pxr::UsdTimeCode timecode = get_export_time_code(); const float(*lnors)[3] = static_cast( CustomData_get_layer(&mesh->ldata, CD_NORMAL)); - const Span polys = mesh->polys(); + const OffsetIndices polys = mesh->polys(); const Span corner_verts = mesh->corner_verts(); pxr::VtVec3fArray loop_normals; @@ -446,18 +446,17 @@ void USDGenericMeshWriter::write_normals(const Mesh *mesh, pxr::UsdGeomMesh usd_ const VArray sharp_faces = attributes.lookup_or_default( "sharp_face", ATTR_DOMAIN_FACE, false); for (const int i : polys.index_range()) { - const MPoly &poly = polys[i]; - + const IndexRange poly = polys[i]; if (sharp_faces[i]) { /* Flat shaded, use common normal for all verts. */ pxr::GfVec3f pxr_normal(&poly_normals[i].x); - for (int loop_idx = 0; loop_idx < poly.totloop; ++loop_idx) { + for (int loop_idx = 0; loop_idx < poly.size(); ++loop_idx) { loop_normals.push_back(pxr_normal); } } else { /* Smooth shaded, use individual vert normals. */ - for (const int vert : corner_verts.slice(poly.loopstart, poly.totloop)) { + for (const int vert : corner_verts.slice(poly)) { loop_normals.push_back(pxr::GfVec3f(&vert_normals[vert].x)); } } diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc index 3fed4547cf2..066d960a78d 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc +++ b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc @@ -284,8 +284,7 @@ float3 OBJMesh::calc_vertex_coords(const int vert_index, const float global_scal Span OBJMesh::calc_poly_vertex_indices(const int poly_index) const { - const MPoly &poly = mesh_polys_[poly_index]; - return mesh_corner_verts_.slice(poly.loopstart, poly.totloop); + return mesh_corner_verts_.slice(mesh_polys_[poly_index]); } void OBJMesh::store_uv_coords_and_indices() @@ -329,15 +328,13 @@ Span OBJMesh::calc_poly_uv_indices(const int poly_index) const return {}; } BLI_assert(poly_index < export_mesh_->totpoly); - const MPoly &poly = mesh_polys_[poly_index]; - return loop_to_uv_index_.as_span().slice(poly.loopstart, poly.totloop); + return loop_to_uv_index_.as_span().slice(mesh_polys_[poly_index]); } float3 OBJMesh::calc_poly_normal(const int poly_index) const { - const MPoly &poly = mesh_polys_[poly_index]; float3 r_poly_normal = bke::mesh::poly_normal_calc( - mesh_positions_, mesh_corner_verts_.slice(poly.loopstart, poly.totloop)); + mesh_positions_, mesh_corner_verts_.slice(mesh_polys_[poly_index])); mul_m3_v3(world_and_axes_normal_transform_, r_poly_normal); normalize_v3(r_poly_normal); return r_poly_normal; @@ -376,14 +373,13 @@ void OBJMesh::store_normal_coords_and_indices() const float(*lnors)[3] = static_cast( CustomData_get_layer(&export_mesh_->ldata, CD_NORMAL)); for (int poly_index = 0; poly_index < export_mesh_->totpoly; ++poly_index) { - const MPoly &poly = mesh_polys_[poly_index]; + const IndexRange poly = mesh_polys_[poly_index]; bool need_per_loop_normals = lnors != nullptr || !(sharp_faces_[poly_index]); if (need_per_loop_normals) { - for (int loop_of_poly = 0; loop_of_poly < poly.totloop; ++loop_of_poly) { + for (const int corner : poly) { float3 loop_normal; - int loop_index = poly.loopstart + loop_of_poly; - BLI_assert(loop_index < export_mesh_->totloop); - copy_v3_v3(loop_normal, lnors[loop_index]); + BLI_assert(corner < export_mesh_->totloop); + copy_v3_v3(loop_normal, lnors[corner]); mul_m3_v3(world_and_axes_normal_transform_, loop_normal); normalize_v3(loop_normal); float3 rounded_loop_normal = round_float3_to_n_digits(loop_normal, round_digits); @@ -393,7 +389,7 @@ void OBJMesh::store_normal_coords_and_indices() normal_to_index.add(rounded_loop_normal, loop_norm_index); normal_coords_.append(rounded_loop_normal); } - loop_to_normal_index_[loop_index] = loop_norm_index; + loop_to_normal_index_[corner] = loop_norm_index; } } else { @@ -405,10 +401,9 @@ void OBJMesh::store_normal_coords_and_indices() normal_to_index.add(rounded_poly_normal, poly_norm_index); normal_coords_.append(rounded_poly_normal); } - for (int i = 0; i < poly.totloop; ++i) { - int loop_index = poly.loopstart + i; - BLI_assert(loop_index < export_mesh_->totloop); - loop_to_normal_index_[loop_index] = poly_norm_index; + for (const int corner : poly) { + BLI_assert(corner < export_mesh_->totloop); + loop_to_normal_index_[corner] = poly_norm_index; } } } @@ -420,12 +415,10 @@ Vector OBJMesh::calc_poly_normal_indices(const int poly_index) const if (loop_to_normal_index_.is_empty()) { return {}; } - const MPoly &poly = mesh_polys_[poly_index]; - const int totloop = poly.totloop; - Vector r_poly_normal_indices(totloop); - for (int poly_loop_index = 0; poly_loop_index < totloop; poly_loop_index++) { - int loop_index = poly.loopstart + poly_loop_index; - r_poly_normal_indices[poly_loop_index] = loop_to_normal_index_[loop_index]; + const IndexRange poly = mesh_polys_[poly_index]; + Vector r_poly_normal_indices(poly.size()); + for (const int i : IndexRange(poly.size())) { + r_poly_normal_indices[i] = loop_to_normal_index_[poly[i]]; } return r_poly_normal_indices; } @@ -450,8 +443,7 @@ int16_t OBJMesh::get_poly_deform_group_index(const int poly_index, group_weights.fill(0); bool found_any_group = false; - const MPoly &poly = mesh_polys_[poly_index]; - for (const int vert : mesh_corner_verts_.slice(poly.loopstart, poly.totloop)) { + for (const int vert : mesh_corner_verts_.slice(mesh_polys_[poly_index])) { const MDeformVert &dv = dverts[vert]; for (int weight_i = 0; weight_i < dv.totweight; ++weight_i) { const auto group = dv.dw[weight_i].def_nr; diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh index b19c5df740f..90932cbbb06 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh +++ b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh @@ -39,7 +39,7 @@ class OBJMesh : NonCopyable { Mesh *owned_export_mesh_ = nullptr; Span mesh_positions_; Span mesh_edges_; - Span mesh_polys_; + OffsetIndices mesh_polys_; Span mesh_corner_verts_; VArray sharp_faces_; diff --git a/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc b/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc index ee53dc32bf6..851c8c1b6fa 100644 --- a/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc +++ b/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc @@ -183,7 +183,7 @@ void MeshFromGeometry::create_polys_loops(Mesh *mesh, bool use_vertex_groups) dverts = mesh->deform_verts_for_write(); } - MutableSpan polys = mesh->polys_for_write(); + MutableSpan poly_offsets = mesh->poly_offsets_for_write(); MutableSpan corner_verts = mesh->corner_verts_for_write(); bke::MutableAttributeAccessor attributes = mesh->attributes_for_write(); bke::SpanAttributeWriter material_indices = @@ -202,9 +202,7 @@ void MeshFromGeometry::create_polys_loops(Mesh *mesh, bool use_vertex_groups) continue; } - MPoly &poly = polys[poly_idx]; - poly.totloop = curr_face.corner_count_; - poly.loopstart = tot_loop_idx; + poly_offsets[poly_idx] = tot_loop_idx; sharp_faces.span[poly_idx] = !curr_face.shaded_smooth; material_indices.span[poly_idx] = curr_face.material_index; /* Importing obj files without any materials would result in negative indices, which is not diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h index 95f89462cfb..74b76f42ea8 100644 --- a/source/blender/makesdna/DNA_customdata_types.h +++ b/source/blender/makesdna/DNA_customdata_types.h @@ -190,7 +190,6 @@ typedef enum eCustomDataType { #define CD_MASK_CLOTH_ORCO (1 << CD_CLOTH_ORCO) // #define CD_MASK_RECAST (1 << CD_RECAST) /* DEPRECATED */ -#define CD_MASK_MPOLY (1 << CD_MPOLY) #define CD_MASK_SHAPE_KEYINDEX (1 << CD_SHAPE_KEYINDEX) #define CD_MASK_SHAPEKEY (1 << CD_SHAPEKEY) #define CD_MASK_BWEIGHT (1 << CD_BWEIGHT) diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index 67c1606be94..50323233917 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -18,6 +18,7 @@ # include "BLI_bounds_types.hh" # include "BLI_math_vector_types.hh" +# include "BLI_offset_indices.hh" namespace blender { template class Span; @@ -69,11 +70,17 @@ typedef struct Mesh { int totvert; /** The number of edges (#MEdge) in the mesh, and the size of #edata. */ int totedge; - /** The number of polygons/faces (#MPoly) in the mesh, and the size of #pdata. */ + /** The number of polygons/faces in the mesh, and the size of #pdata. */ int totpoly; /** The number of face corners in the mesh, and the size of #ldata. */ int totloop; + /** + * Array owned by mesh. May be null of there are no polygons. Index of the first corner of each + * polygon, with the total number of corners at the end. See #Mesh::polys() and #OffsetIndices. + */ + int *poly_offset_indices; + CustomData vdata, edata, pdata, ldata; /** @@ -226,7 +233,7 @@ typedef struct Mesh { blender::MutableSpan vert_positions_for_write(); /** * Array of edges, containing vertex indices. For simple triangle or quad meshes, edges could be - * calculated from the #MPoly and "corner edge" arrays, however, edges need to be stored + * calculated from the polygon and "corner edge" arrays, however, edges need to be stored * explicitly to edge domain attributes and to support loose edges that aren't connected to * faces. */ @@ -234,11 +241,15 @@ typedef struct Mesh { /** Write access to edge data. */ blender::MutableSpan edges_for_write(); /** - * Face topology storage of the size and offset of each face's section of the face corners. + * Face topology storage of the offset of each face's section of the face corners. The size of + * each polygon is encoded using the next offset value. Can be used to slice the #corner_verts or + * #corner_edges arrays to find the vertices or edges that make up each face. */ - blender::Span polys() const; - /** Write access to polygon data. */ - blender::MutableSpan polys_for_write(); + blender::OffsetIndices polys() const; + /** The first corner index of every polygon. */ + blender::Span poly_offsets() const; + /** Write access to #poly_offsets data. */ + blender::MutableSpan poly_offsets_for_write(); /** * Array of vertices for every face corner, stored in the ".corner_vert" integer attribute. diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index c4bd8559bac..0525a440ae7 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -50,35 +50,6 @@ enum { }; #endif -/** - * Mesh Faces. - * This only stores the polygon size & flags, the vertex & edge indices are stored in the "corner - * edges" array. - * - * Typically accessed with #Mesh.polys(). - */ -typedef struct MPoly { - /** Offset into loop array and number of loops in the face. */ - int loopstart; - /** Keep signed since we need to subtract when getting the previous loop. */ - int totloop; - /** Deprecated material index. Now stored in the "material_index" attribute, but kept for IO. */ - short mat_nr_legacy; - char flag_legacy, _pad; -} MPoly; - -/** #MPoly.flag */ -#ifdef DNA_DEPRECATED_ALLOW -enum { - /** Deprecated smooth shading status. Now stored reversed in "sharp_face" attribute. */ - ME_SMOOTH = (1 << 0), - /** Deprecated selection status. Now stored in ".select_poly" attribute. */ - ME_FACE_SEL = (1 << 1), - /** Deprecated hide status. Now stored in ".hide_poly" attribute. */ - /* ME_HIDE = (1 << 4), */ -}; -#endif - /** \} */ /* -------------------------------------------------------------------- */ @@ -113,8 +84,8 @@ enum { /** * #MLoopTri's are lightweight triangulation data, - * for functionality that doesn't support ngons (#MPoly). - * This is cache data created from (#MPoly, corner vert & position arrays). + * for functionality that doesn't support ngons. + * This is cache data created from (polygons, corner vert, and position arrays). * There is no attempt to maintain this data's validity over time, * any changes to the underlying mesh invalidate the #MLoopTri array, * which will need to be re-calculated. @@ -155,16 +126,16 @@ enum { * \endcode * * #MLoopTri's are allocated in an array, where each polygon's #MLoopTri's are stored contiguously, - * the number of triangles for each polygon is guaranteed to be (#MPoly.totloop - 2), + * the number of triangles for each polygon is guaranteed to be the corner count - 2, * even for degenerate geometry. See #ME_POLY_TRI_TOT macro. * - * It's also possible to perform a reverse lookup (find all #MLoopTri's for any given #MPoly). + * It's also possible to perform a reverse lookup (find all #MLoopTri's for any given poly). * * \code{.c} * // loop over all looptri's for a given polygon: i - * MPoly *poly = &polys[i]; - * MLoopTri *lt = &looptri[poly_to_tri_count(i, poly->loopstart)]; - * int j, lt_tot = ME_POLY_TRI_TOT(poly); + * const IndexRange poly = polys[i]; + * MLoopTri *lt = &looptri[poly_to_tri_count(i, poly.start())]; + * int j, lt_tot = ME_POLY_TRI_TOT(poly.size()); * * for (j = 0; j < lt_tot; j++, lt++) { * int vtri[3] = { @@ -399,7 +370,7 @@ enum { * \{ */ /** Number of tri's that make up this polygon once tessellated. */ -#define ME_POLY_TRI_TOT(poly) ((poly)->totloop - 2) +#define ME_POLY_TRI_TOT(size) (size - 2) /** * Check out-of-bounds material, note that this is nearly always prevented, @@ -419,6 +390,35 @@ enum { #ifdef DNA_DEPRECATED_ALLOW +/** + * Mesh Faces. + * This only stores the polygon size & flags, the vertex & edge indices are stored in the "corner + * edges" array. + * + * Typically accessed with #Mesh.polys(). + */ +typedef struct MPoly { + /** Offset into loop array and number of loops in the face. */ + int loopstart; + /** Keep signed since we need to subtract when getting the previous loop. */ + int totloop; + /** Deprecated material index. Now stored in the "material_index" attribute, but kept for IO. */ + short mat_nr_legacy; + char flag_legacy, _pad; +} MPoly; + +/** #MPoly.flag */ +# ifdef DNA_DEPRECATED_ALLOW +enum { + /** Deprecated smooth shading status. Now stored reversed in "sharp_face" attribute. */ + ME_SMOOTH = (1 << 0), + /** Deprecated selection status. Now stored in ".select_poly" attribute. */ + ME_FACE_SEL = (1 << 1), + /** Deprecated hide status. Now stored in ".hide_poly" attribute. */ + /* ME_HIDE = (1 << 4), */ +}; +# endif + /** * UV coordinate for a polygon face & flag for selection & other options. * Deprecated, but kept to read old files. UV coordinates are now stored as #CD_PROP_FLOAT2 layers. @@ -475,8 +475,9 @@ typedef struct MLoop { #endif /** - * Used in Blender pre 2.63, See #Mesh::corner_verts(), #MPoly for face data stored in the blend - * file. Use for reading old files and in a handful of cases which should be removed eventually. + * Used in Blender pre 2.63, See #Mesh::corner_verts(), #Mesh::polys() for face data stored in the + * blend file. Use for reading old files and in a handful of cases which should be removed + * eventually. */ typedef struct MFace { unsigned int v1, v2, v3, v4; diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index b334b91c7ca..8cd076be1ee 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -385,8 +385,8 @@ static int rna_MeshEdge_index_get(PointerRNA *ptr) static int rna_MeshPolygon_index_get(PointerRNA *ptr) { const Mesh *mesh = rna_mesh(ptr); - const MPoly *poly = (MPoly *)ptr->data; - const int index = (int)(poly - BKE_mesh_polys(mesh)); + const int *poly_offset = (const int *)ptr->data; + const int index = (int)(poly_offset - BKE_mesh_poly_offsets(mesh)); BLI_assert(index >= 0); BLI_assert(index < mesh->totpoly); return index; @@ -651,11 +651,11 @@ static void rna_MeshLoop_bitangent_get(PointerRNA *ptr, float *values) static void rna_MeshPolygon_normal_get(PointerRNA *ptr, float *values) { Mesh *me = rna_mesh(ptr); - MPoly *poly = (MPoly *)ptr->data; + const int poly_start = *((const int *)ptr->data); + const int poly_size = *(((const int *)ptr->data) + 1) - poly_start; const float(*positions)[3] = BKE_mesh_vert_positions(me); const int *corner_verts = BKE_mesh_corner_verts(me); - BKE_mesh_calc_poly_normal( - &corner_verts[poly->loopstart], poly->totloop, positions, me->totvert, values); + BKE_mesh_calc_poly_normal(&corner_verts[poly_start], poly_size, positions, me->totvert, values); } static bool rna_MeshPolygon_hide_get(PointerRNA *ptr) @@ -755,29 +755,32 @@ static void rna_MeshPolygon_material_index_set(PointerRNA *ptr, int value) static void rna_MeshPolygon_center_get(PointerRNA *ptr, float *values) { Mesh *me = rna_mesh(ptr); - MPoly *poly = (MPoly *)ptr->data; + const int poly_start = *((const int *)ptr->data); + const int poly_size = *(((const int *)ptr->data) + 1) - poly_start; const float(*positions)[3] = BKE_mesh_vert_positions(me); const int *corner_verts = BKE_mesh_corner_verts(me); - BKE_mesh_calc_poly_center( - &corner_verts[poly->loopstart], poly->totloop, positions, me->totvert, values); + BKE_mesh_calc_poly_center(&corner_verts[poly_start], poly_size, positions, me->totvert, values); } static float rna_MeshPolygon_area_get(PointerRNA *ptr) { Mesh *me = (Mesh *)ptr->owner_id; - MPoly *poly = (MPoly *)ptr->data; + const int poly_start = *((const int *)ptr->data); + const int poly_size = *(((const int *)ptr->data) + 1) - poly_start; const float(*positions)[3] = BKE_mesh_vert_positions(me); const int *corner_verts = BKE_mesh_corner_verts(me); - return BKE_mesh_calc_poly_area( - &corner_verts[poly->loopstart], poly->totloop, positions, me->totvert); + return BKE_mesh_calc_poly_area(&corner_verts[poly_start], poly_size, positions, me->totvert); } -static void rna_MeshPolygon_flip(ID *id, MPoly *poly) +static void rna_MeshPolygon_flip(ID *id, MIntProperty *poly_offset_p) { Mesh *me = (Mesh *)id; + const int poly_start = *((const int *)poly_offset_p); + const int poly_size = *(((const int *)poly_offset_p) + 1) - poly_start; int *corner_verts = BKE_mesh_corner_verts_for_write(me); int *corner_edges = BKE_mesh_corner_edges_for_write(me); - BKE_mesh_polygon_flip(poly, corner_verts, corner_edges, &me->ldata, me->totloop); + BKE_mesh_polygon_flip( + poly_start, poly_size, corner_verts, corner_edges, &me->ldata, me->totloop); BKE_mesh_tessface_clear(me); BKE_mesh_runtime_clear_geometry(me); } @@ -1661,25 +1664,46 @@ static void rna_Mesh_face_map_remove(struct Mesh *me, static int rna_MeshPoly_vertices_get_length(const PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION]) { - const MPoly *poly = (MPoly *)ptr->data; + const int *poly_offset_p = (const int *)ptr->data; + const int poly_start = *poly_offset_p; + const int poly_size = *(poly_offset_p + 1) - poly_start; /* NOTE: raw access uses dummy item, this _could_ crash, * watch out for this, #MFace uses it but it can't work here. */ - return (length[0] = poly->totloop); + return (length[0] = poly_size); } static void rna_MeshPoly_vertices_get(PointerRNA *ptr, int *values) { const Mesh *me = rna_mesh(ptr); - const MPoly *poly = (const MPoly *)ptr->data; - memcpy(values, BKE_mesh_corner_verts(me) + poly->loopstart, sizeof(int) * poly->totloop); + const int *poly_offset_p = (const int *)ptr->data; + const int poly_start = *poly_offset_p; + const int poly_size = *(poly_offset_p + 1) - poly_start; + memcpy(values, BKE_mesh_corner_verts(me) + poly_start, sizeof(int) * poly_size); +} + +static int rna_MeshPolygon_loop_start_get(PointerRNA *ptr) +{ + return *(const int *)ptr->data; +} + +static void rna_MeshPolygon_loop_start_set(PointerRNA *ptr, int value) +{ + *(int *)ptr->data = value; +} + +static int rna_MeshPolygon_loop_total_get(PointerRNA *ptr) +{ + const int *data = (const int *)ptr->data; + return *(data + 1) - *data; } static void rna_MeshPoly_vertices_set(PointerRNA *ptr, const int *values) { Mesh *me = rna_mesh(ptr); - const MPoly *poly = (const MPoly *)ptr->data; - memcpy( - BKE_mesh_corner_verts_for_write(me) + poly->loopstart, values, sizeof(int) * poly->totloop); + const int *poly_offset_p = (const int *)ptr->data; + const int poly_start = *poly_offset_p; + const int poly_size = *(poly_offset_p + 1) - poly_start; + memcpy(BKE_mesh_corner_verts_for_write(me) + poly_start, values, sizeof(int) * poly_size); } /* disabling, some importers don't know the total material count when assigning materials */ @@ -2002,7 +2026,7 @@ static void rna_Mesh_polygons_begin(CollectionPropertyIterator *iter, PointerRNA { Mesh *mesh = rna_mesh(ptr); rna_iterator_array_begin( - iter, BKE_mesh_polys_for_write(mesh), sizeof(MPoly), mesh->totpoly, false, NULL); + iter, BKE_mesh_poly_offsets_for_write(mesh), sizeof(int), mesh->totpoly, false, NULL); } static int rna_Mesh_polygons_length(PointerRNA *ptr) { @@ -2017,7 +2041,7 @@ int rna_Mesh_polygons_lookup_int(PointerRNA *ptr, int index, PointerRNA *r_ptr) } r_ptr->owner_id = &mesh->id; r_ptr->type = &RNA_MeshPolygon; - r_ptr->data = &BKE_mesh_polys_for_write(mesh)[index]; + r_ptr->data = &BKE_mesh_poly_offsets_for_write(mesh)[index]; return true; } @@ -2975,7 +2999,7 @@ static void rna_def_mpolygon(BlenderRNA *brna) FunctionRNA *func; srna = RNA_def_struct(brna, "MeshPolygon", NULL); - RNA_def_struct_sdna(srna, "MPoly"); + RNA_def_struct_sdna(srna, "MIntProperty"); RNA_def_struct_ui_text(srna, "Mesh Polygon", "Polygon in a Mesh data-block"); RNA_def_struct_path_func(srna, "rna_MeshPolygon_path"); RNA_def_struct_ui_icon(srna, ICON_FACESEL); @@ -2994,11 +3018,13 @@ static void rna_def_mpolygon(BlenderRNA *brna) /* these are both very low level access */ prop = RNA_def_property(srna, "loop_start", PROP_INT, PROP_UNSIGNED); - RNA_def_property_int_sdna(prop, NULL, "loopstart"); + RNA_def_property_int_funcs( + prop, "rna_MeshPolygon_loop_start_get", "rna_MeshPolygon_loop_start_set", NULL); RNA_def_property_ui_text(prop, "Loop Start", "Index of the first loop of this polygon"); /* also low level */ prop = RNA_def_property(srna, "loop_total", PROP_INT, PROP_UNSIGNED); - RNA_def_property_int_sdna(prop, NULL, "totloop"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_int_funcs(prop, "rna_MeshPolygon_loop_total_get", NULL, NULL); RNA_def_property_ui_text(prop, "Loop Total", "Number of loops used by this polygon"); prop = RNA_def_property(srna, "material_index", PROP_INT, PROP_UNSIGNED); diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c index f6e82c31e32..b59a8e9a094 100644 --- a/source/blender/makesrna/intern/rna_mesh_api.c +++ b/source/blender/makesrna/intern/rna_mesh_api.c @@ -96,7 +96,7 @@ static void rna_Mesh_calc_smooth_groups( const bool *sharp_faces = (const bool *)CustomData_get_layer_named( &mesh->pdata, CD_PROP_BOOL, "sharp_face"); *r_poly_group = BKE_mesh_calc_smoothgroups(mesh->totedge, - BKE_mesh_polys(mesh), + BKE_mesh_poly_offsets(mesh), mesh->totpoly, BKE_mesh_corner_edges(mesh), mesh->totloop, @@ -171,7 +171,7 @@ static void rna_Mesh_transform(Mesh *mesh, float mat[16], bool shape_keys) static void rna_Mesh_flip_normals(Mesh *mesh) { - BKE_mesh_polys_flip(BKE_mesh_polys(mesh), + BKE_mesh_polys_flip(BKE_mesh_poly_offsets(mesh), BKE_mesh_corner_verts_for_write(mesh), BKE_mesh_corner_edges_for_write(mesh), &mesh->ldata, diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index f33c0c443c2..aa186aa4750 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -386,7 +386,7 @@ static void rna_Particle_uv_on_emitter(ParticleData *particle, BKE_report(reports, RPT_ERROR, "Mesh has no UV data"); return; } - BKE_mesh_tessface_ensure(modifier->mesh_final); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */ + BKE_mesh_tessface_ensure(modifier->mesh_final); /* BMESH - UNTIL MODIFIER IS UPDATED FOR POLYS */ if (ELEM(num, DMCACHE_NOTFOUND, DMCACHE_ISCHILD)) { if (particle->num < modifier->mesh_final->totface) { @@ -526,7 +526,7 @@ static int rna_ParticleSystem_tessfaceidx_on_emitter(ParticleSystem *particlesys int totvert; int num = -1; - BKE_mesh_tessface_ensure(modifier->mesh_final); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */ + BKE_mesh_tessface_ensure(modifier->mesh_final); /* BMESH - UNTIL MODIFIER IS UPDATED FOR POLYS */ totface = modifier->mesh_final->totface; totvert = modifier->mesh_final->totvert; diff --git a/source/blender/modifiers/intern/MOD_array.cc b/source/blender/modifiers/intern/MOD_array.cc index 017eeb1eb0a..59c6b964260 100644 --- a/source/blender/modifiers/intern/MOD_array.cc +++ b/source/blender/modifiers/intern/MOD_array.cc @@ -284,9 +284,10 @@ static void mesh_merge_transform(Mesh *result, int *index_orig; int i; MEdge *edge; + const blender::Span cap_poly_offsets = cap_mesh->poly_offsets(); float(*result_positions)[3] = BKE_mesh_vert_positions_for_write(result); blender::MutableSpan result_edges = result->edges_for_write(); - blender::MutableSpan result_polys = result->polys_for_write(); + blender::MutableSpan result_poly_offsets = result->poly_offsets_for_write(); blender::MutableSpan result_corner_verts = result->corner_verts_for_write(); blender::MutableSpan result_corner_edges = result->corner_edges_for_write(); @@ -322,8 +323,8 @@ static void mesh_merge_transform(Mesh *result, } /* adjust cap poly loopstart indices */ - for (const int i : blender::IndexRange(cap_polys_index, cap_npolys)) { - result_polys[i].loopstart += cap_loops_index; + for (i = 0; i < cap_npolys; i++) { + result_poly_offsets[cap_polys_index + i] = cap_poly_offsets[i] + cap_loops_index; } /* adjust cap loop vertex and edge indices */ @@ -554,7 +555,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, mesh, result_nverts, result_nedges, result_nloops, result_npolys); float(*result_positions)[3] = BKE_mesh_vert_positions_for_write(result); blender::MutableSpan result_edges = result->edges_for_write(); - blender::MutableSpan result_polys = result->polys_for_write(); + blender::MutableSpan result_poly_offsets = result->poly_offsets_for_write(); blender::MutableSpan result_corner_verts = result->corner_verts_for_write(); blender::MutableSpan result_corner_edges = result->corner_edges_for_write(); @@ -570,6 +571,8 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, CustomData_copy_data(&mesh->ldata, &result->ldata, 0, 0, chunk_nloops); CustomData_copy_data(&mesh->pdata, &result->pdata, 0, 0, chunk_npolys); + result_poly_offsets.take_front(mesh->totpoly).copy_from(mesh->poly_offsets().drop_back(1)); + /* Remember first chunk, in case of cap merge */ first_chunk_start = 0; first_chunk_nverts = chunk_nverts; @@ -615,8 +618,8 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, edge->v2 += c * chunk_nverts; } - for (const int i : blender::IndexRange(c * chunk_npolys, chunk_npolys)) { - result_polys[i].loopstart += c * chunk_nloops; + for (i = 0; i < chunk_npolys; i++) { + result_poly_offsets[c * chunk_npolys + i] = result_poly_offsets[i] + c * chunk_nloops; } /* adjust loop vertex and edge indices */ diff --git a/source/blender/modifiers/intern/MOD_build.cc b/source/blender/modifiers/intern/MOD_build.cc index 1a9341a6c8f..7d78aef53f2 100644 --- a/source/blender/modifiers/intern/MOD_build.cc +++ b/source/blender/modifiers/intern/MOD_build.cc @@ -60,7 +60,6 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * int i, j, k; int faces_dst_num, edges_dst_num, loops_dst_num = 0; float frac; - MPoly *mpoly_dst; GHashIterator gh_iter; /* maps vert indices in old mesh to indices in new mesh */ GHash *vertHash = BLI_ghash_int_new("build ve apply gh"); @@ -71,7 +70,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * const int vert_src_num = mesh->totvert; const blender::Span edges_src = mesh->edges(); - const blender::Span polys_src = mesh->polys(); + const blender::OffsetIndices polys_src = mesh->polys(); const blender::Span corner_verts_src = mesh->corner_verts(); const blender::Span corner_edges_src = mesh->corner_edges(); @@ -95,7 +94,6 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* if there's at least one face, build based on faces */ if (faces_dst_num) { - const MPoly *polys, *poly; uintptr_t hash_num, hash_num_alt; if (bmd->flag & MOD_BUILD_FLAG_RANDOMIZE) { @@ -105,12 +103,11 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* get the set of all vert indices that will be in the final mesh, * mapped to the new indices */ - polys = polys_src.data(); hash_num = 0; for (i = 0; i < faces_dst_num; i++) { - poly = polys + faceMap[i]; - for (j = 0; j < poly->totloop; j++) { - const int vert_i = corner_verts_src[poly->loopstart + j]; + const blender::IndexRange poly = polys_src[faceMap[i]]; + for (j = 0; j < poly.size(); j++) { + const int vert_i = corner_verts_src[poly[j]]; void **val_p; if (!BLI_ghash_ensure_p(vertHash, POINTER_FROM_INT(vert_i), &val_p)) { *val_p = (void *)hash_num; @@ -118,7 +115,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * } } - loops_dst_num += poly->totloop; + loops_dst_num += poly.size(); } BLI_assert(hash_num == BLI_ghash_len(vertHash)); @@ -195,7 +192,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * result = BKE_mesh_new_nomain_from_template( mesh, BLI_ghash_len(vertHash), BLI_ghash_len(edgeHash), loops_dst_num, faces_dst_num); blender::MutableSpan result_edges = result->edges_for_write(); - blender::MutableSpan result_polys = result->polys_for_write(); + blender::MutableSpan result_poly_offsets = result->poly_offsets_for_write(); blender::MutableSpan result_corner_verts = result->corner_verts_for_write(); blender::MutableSpan result_corner_edges = result->corner_edges_for_write(); @@ -222,29 +219,22 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * *dest = source; } - mpoly_dst = result_polys.data(); - /* copy the faces across, remapping indices */ k = 0; for (i = 0; i < faces_dst_num; i++) { - const MPoly *source; - MPoly *dest; + const blender::IndexRange src_poly = polys_src[faceMap[i]]; + result_poly_offsets[i] = k; - source = &polys_src[faceMap[i]]; - dest = mpoly_dst + i; CustomData_copy_data(&mesh->pdata, &result->pdata, faceMap[i], i, 1); - *dest = *source; - dest->loopstart = k; - CustomData_copy_data( - &mesh->ldata, &result->ldata, source->loopstart, dest->loopstart, dest->totloop); + CustomData_copy_data(&mesh->ldata, &result->ldata, src_poly.start(), k, src_poly.size()); - for (j = 0; j < source->totloop; j++, k++) { - const int vert_src = corner_verts_src[source->loopstart + j]; - const int edge_src = corner_edges_src[source->loopstart + j]; - result_corner_verts[dest->loopstart + j] = POINTER_AS_INT( + for (j = 0; j < src_poly.size(); j++, k++) { + const int vert_src = corner_verts_src[src_poly[j]]; + const int edge_src = corner_edges_src[src_poly[j]]; + result_corner_verts[k] = POINTER_AS_INT( BLI_ghash_lookup(vertHash, POINTER_FROM_INT(vert_src))); - result_corner_edges[dest->loopstart + j] = POINTER_AS_INT( + result_corner_edges[k] = POINTER_AS_INT( BLI_ghash_lookup(edgeHash2, POINTER_FROM_INT(edge_src))); } } diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.cc b/source/blender/modifiers/intern/MOD_correctivesmooth.cc index 903b154f9b5..ca3d42579e4 100644 --- a/source/blender/modifiers/intern/MOD_correctivesmooth.cc +++ b/source/blender/modifiers/intern/MOD_correctivesmooth.cc @@ -128,7 +128,7 @@ static void mesh_get_weights(const MDeformVert *dvert, static void mesh_get_boundaries(Mesh *mesh, float *smooth_weights) { const blender::Span edges = mesh->edges(); - const blender::Span polys = mesh->polys(); + const blender::OffsetIndices polys = mesh->polys(); const blender::Span corner_edges = mesh->corner_edges(); /* Flag boundary edges so only boundaries are set to 1. */ @@ -136,10 +136,8 @@ static void mesh_get_boundaries(Mesh *mesh, float *smooth_weights) MEM_calloc_arrayN(size_t(edges.size()), sizeof(*boundaries), __func__)); for (const int64_t i : polys.index_range()) { - const int totloop = polys[i].totloop; - int j; - for (j = 0; j < totloop; j++) { - uint8_t *e_value = &boundaries[corner_edges[polys[i].loopstart + j]]; + for (const int edge : corner_edges.slice(polys[i])) { + uint8_t *e_value = &boundaries[edge]; *e_value |= uint8_t((*e_value) + 1); } } @@ -434,7 +432,7 @@ static void calc_tangent_spaces(const Mesh *mesh, float *r_tangent_weights_per_vertex) { const uint mvert_num = uint(mesh->totvert); - const blender::Span polys = mesh->polys(); + const blender::OffsetIndices polys = mesh->polys(); blender::Span corner_verts = mesh->corner_verts(); if (r_tangent_weights_per_vertex != nullptr) { @@ -442,9 +440,9 @@ static void calc_tangent_spaces(const Mesh *mesh, } for (const int64_t i : polys.index_range()) { - const MPoly &poly = polys[i]; - int next_corner = poly.loopstart; - int term_corner = next_corner + poly.totloop; + const blender::IndexRange poly = polys[i]; + int next_corner = int(poly.start()); + int term_corner = next_corner + int(poly.size()); int prev_corner = term_corner - 2; int curr_corner = term_corner - 1; diff --git a/source/blender/modifiers/intern/MOD_explode.cc b/source/blender/modifiers/intern/MOD_explode.cc index 762d2aeaecd..ced5e46a438 100644 --- a/source/blender/modifiers/intern/MOD_explode.cc +++ b/source/blender/modifiers/intern/MOD_explode.cc @@ -898,6 +898,7 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh) BKE_mesh_calc_edges_tessface(split_m); BKE_mesh_convert_mfaces_to_mpolys(split_m); + BKE_mesh_legacy_convert_polys_to_offsets(split_m); return split_m; } @@ -1118,6 +1119,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd, /* finalization */ BKE_mesh_calc_edges_tessface(explode); BKE_mesh_convert_mfaces_to_mpolys(explode); + BKE_mesh_legacy_convert_polys_to_offsets(explode); psys_sim_data_free(&sim); @@ -1154,7 +1156,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * return mesh; } - BKE_mesh_tessface_ensure(mesh); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */ + BKE_mesh_tessface_ensure(mesh); /* BMESH - UNTIL MODIFIER IS UPDATED FOR POLYGONS */ /* 1. find faces to be exploded if needed */ if (emd->facepa == nullptr || psmd->flag & eParticleSystemFlag_Pars || diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.cc b/source/blender/modifiers/intern/MOD_laplaciansmooth.cc index cd711362cd1..174c856aaf3 100644 --- a/source/blender/modifiers/intern/MOD_laplaciansmooth.cc +++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.cc @@ -53,7 +53,7 @@ struct LaplacianSystem { /* Pointers to data. */ float (*vertexCos)[3]; blender::Span edges; - blender::Span polys; + blender::OffsetIndices polys; blender::Span corner_verts; LinearSolver *context; @@ -112,17 +112,17 @@ static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numLoops, in static float compute_volume(const float center[3], float (*vertexCos)[3], - const blender::Span polys, + const blender::OffsetIndices polys, const blender::Span corner_verts) { float vol = 0.0f; for (const int i : polys.index_range()) { - const MPoly &poly = polys[i]; - int corner_first = poly.loopstart; + const blender::IndexRange poly = polys[i]; + int corner_first = poly.start(); int corner_prev = corner_first + 1; int corner_curr = corner_first + 2; - int corner_term = corner_first + poly.totloop; + int corner_term = corner_first + poly.size(); for (; corner_curr != corner_term; corner_prev = corner_curr, corner_curr++) { vol += volume_tetrahedron_signed_v3(center, @@ -191,9 +191,9 @@ static void init_laplacian_matrix(LaplacianSystem *sys) const blender::Span corner_verts = sys->corner_verts; for (const int i : sys->polys.index_range()) { - const MPoly &poly = sys->polys[i]; - int corner_next = poly.loopstart; - int corner_term = corner_next + poly.totloop; + const blender::IndexRange poly = sys->polys[i]; + int corner_next = poly.start(); + int corner_term = corner_next + poly.size(); int corner_prev = corner_term - 2; int corner_curr = corner_term - 1; @@ -248,9 +248,9 @@ static void fill_laplacian_matrix(LaplacianSystem *sys) const blender::Span corner_verts = sys->corner_verts; for (const int i : sys->polys.index_range()) { - const MPoly &poly = sys->polys[i]; - int corner_next = poly.loopstart; - int corner_term = corner_next + poly.totloop; + const blender::IndexRange poly = sys->polys[i]; + int corner_next = poly.start(); + int corner_term = corner_next + poly.size(); int corner_prev = corner_term - 2; int corner_curr = corner_term - 1; diff --git a/source/blender/modifiers/intern/MOD_mask.cc b/source/blender/modifiers/intern/MOD_mask.cc index 1a0d9506201..6350b060d08 100644 --- a/source/blender/modifiers/intern/MOD_mask.cc +++ b/source/blender/modifiers/intern/MOD_mask.cc @@ -224,7 +224,7 @@ static void computed_masked_polys(const Mesh *mesh, uint *r_loops_masked_num) { BLI_assert(mesh->totvert == vertex_mask.size()); - const Span polys = mesh->polys(); + const blender::OffsetIndices polys = mesh->polys(); const Span corner_verts = mesh->corner_verts(); r_masked_poly_indices.reserve(mesh->totpoly); @@ -232,10 +232,10 @@ static void computed_masked_polys(const Mesh *mesh, uint loops_masked_num = 0; for (int i : IndexRange(mesh->totpoly)) { - const MPoly &poly_src = polys[i]; + const blender::IndexRange poly = polys[i]; bool all_verts_in_mask = true; - for (const int vert_i : corner_verts.slice(poly_src.loopstart, poly_src.totloop)) { + for (const int vert_i : corner_verts.slice(poly)) { if (!vertex_mask[vert_i]) { all_verts_in_mask = false; break; @@ -245,7 +245,7 @@ static void computed_masked_polys(const Mesh *mesh, if (all_verts_in_mask) { r_masked_poly_indices.append_unchecked(i); r_loop_starts.append_unchecked(loops_masked_num); - loops_masked_num += poly_src.totloop; + loops_masked_num += poly.size(); } } @@ -269,19 +269,19 @@ static void compute_interpolated_polys(const Mesh *mesh, /* NOTE: this reserve can only lift the capacity if there are ngons, which get split. */ r_masked_poly_indices.reserve(r_masked_poly_indices.size() + verts_add_num); r_loop_starts.reserve(r_loop_starts.size() + verts_add_num); - const Span polys = mesh->polys(); + const blender::OffsetIndices polys = mesh->polys(); const Span corner_verts = mesh->corner_verts(); uint edges_add_num = 0; uint polys_add_num = 0; uint loops_add_num = 0; for (int i : IndexRange(mesh->totpoly)) { - const MPoly &poly_src = polys[i]; + const blender::IndexRange poly_src = polys[i]; int in_count = 0; int start = -1; int dst_totloop = -1; - const Span poly_verts_src = corner_verts.slice(poly_src.loopstart, poly_src.totloop); + const Span poly_verts_src = corner_verts.slice(poly_src); for (const int j : poly_verts_src.index_range()) { const int vert_i = poly_verts_src[j]; if (vertex_mask[vert_i]) { @@ -291,12 +291,12 @@ static void compute_interpolated_polys(const Mesh *mesh, start = j; } } - if (0 < in_count && in_count < poly_src.totloop) { + if (0 < in_count && in_count < poly_src.size()) { /* Ring search starting at a vertex which is not included in the mask. */ int last_corner_vert = corner_verts[start]; bool v_loop_in_mask_last = vertex_mask[last_corner_vert]; for (const int j : poly_verts_src.index_range()) { - const int corner_vert = corner_verts[(start + 1 + j) % poly_src.totloop]; + const int corner_vert = corner_verts[(start + 1 + j) % poly_src.size()]; const bool v_loop_in_mask = vertex_mask[corner_vert]; if (v_loop_in_mask && !v_loop_in_mask_last) { dst_totloop = 3; @@ -444,8 +444,8 @@ static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh, Span new_loop_starts, int polys_masked_num) { - const Span src_polys = src_mesh.polys(); - MutableSpan dst_polys = dst_mesh.polys_for_write(); + const blender::OffsetIndices src_polys = src_mesh.polys(); + MutableSpan dst_poly_offsets = dst_mesh.poly_offsets_for_write(); const Span src_corner_verts = src_mesh.corner_verts(); const Span src_corner_edges = src_mesh.corner_edges(); MutableSpan dst_corner_verts = dst_mesh.corner_verts_for_write(); @@ -453,20 +453,20 @@ static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh, for (const int i_dst : IndexRange(polys_masked_num)) { const int i_src = masked_poly_indices[i_dst]; + const blender::IndexRange src_poly = src_polys[i_src]; - const MPoly &mp_src = src_polys[i_src]; - MPoly &mp_dst = dst_polys[i_dst]; - const int i_ml_src = mp_src.loopstart; - const int i_ml_dst = new_loop_starts[i_dst]; + dst_poly_offsets[i_dst] = new_loop_starts[i_dst]; CustomData_copy_data(&src_mesh.pdata, &dst_mesh.pdata, i_src, i_dst, 1); - CustomData_copy_data(&src_mesh.ldata, &dst_mesh.ldata, i_ml_src, i_ml_dst, mp_src.totloop); + CustomData_copy_data(&src_mesh.ldata, + &dst_mesh.ldata, + src_poly.start(), + dst_poly_offsets[i_dst], + src_poly.size()); - mp_dst = mp_src; - mp_dst.loopstart = i_ml_dst; - for (int i : IndexRange(mp_src.totloop)) { - dst_corner_verts[i_ml_dst + i] = vertex_map[src_corner_verts[i_ml_src + i]]; - dst_corner_edges[i_ml_dst + i] = edge_map[src_corner_edges[i_ml_src + i]]; + for (int i : IndexRange(src_poly.size())) { + dst_corner_verts[new_loop_starts[i_dst] + i] = vertex_map[src_corner_verts[src_poly[i]]]; + dst_corner_edges[new_loop_starts[i_dst] + i] = edge_map[src_corner_edges[src_poly[i]]]; } } } @@ -484,8 +484,8 @@ static void add_interpolated_polys_to_new_mesh(const Mesh &src_mesh, int polys_masked_num, int edges_add_num) { - const Span src_polys = src_mesh.polys(); - MutableSpan dst_polys = dst_mesh.polys_for_write(); + const blender::OffsetIndices src_polys = src_mesh.polys(); + MutableSpan dst_poly_offsets = dst_mesh.poly_offsets_for_write(); MutableSpan dst_edges = dst_mesh.edges_for_write(); const Span src_corner_verts = src_mesh.corner_verts(); const Span src_corner_edges = src_mesh.corner_edges(); @@ -506,24 +506,17 @@ static void add_interpolated_polys_to_new_mesh(const Mesh &src_mesh, last_i_src = i_src; } - const MPoly &mp_src = src_polys[i_src]; - MPoly &mp_dst = dst_polys[i_dst]; - const int i_ml_src = mp_src.loopstart; + const blender::IndexRange src_poly = src_polys[i_src]; + const int i_ml_src = src_poly.start(); int i_ml_dst = new_loop_starts[i_dst]; - const int mp_totloop = (i_dst + 1 < new_loop_starts.size() ? new_loop_starts[i_dst + 1] : - dst_mesh.totloop) - - i_ml_dst; - CustomData_copy_data(&src_mesh.pdata, &dst_mesh.pdata, i_src, i_dst, 1); - mp_dst = mp_src; - mp_dst.loopstart = i_ml_dst; - mp_dst.totloop = mp_totloop; + dst_poly_offsets[i_dst] = i_ml_dst; /* Ring search starting at a vertex which is not included in the mask. */ int start = -sub_poly_index - 1; bool skip = false; - Span corner_verts_src(&src_corner_verts[i_ml_src], mp_src.totloop); + Span corner_verts_src(&src_corner_verts[i_ml_src], src_poly.size()); for (const int j : corner_verts_src.index_range()) { if (!vertex_mask[corner_verts_src[j]]) { if (start == -1) { @@ -547,7 +540,7 @@ static void add_interpolated_polys_to_new_mesh(const Mesh &src_mesh, bool v_loop_in_mask_last = vertex_mask[src_corner_verts[last_corner_i]]; int last_index = start; for (const int j : corner_verts_src.index_range()) { - const int index = (start + 1 + j) % mp_src.totloop; + const int index = (start + 1 + j) % src_poly.size(); const bool v_loop_in_mask = vertex_mask[src_corner_verts[index]]; if (v_loop_in_mask && !v_loop_in_mask_last) { /* Start new cut. */ @@ -570,7 +563,7 @@ static void add_interpolated_polys_to_new_mesh(const Mesh &src_mesh, i_ml_dst++; } else if (!v_loop_in_mask && v_loop_in_mask_last) { - BLI_assert(i_ml_dst != mp_dst.loopstart); + BLI_assert(i_ml_dst != dst_poly_offsets[i_dst]); /* End active cut. */ float fac = get_interp_factor_from_vgroup(dvert, defgrp_index, @@ -587,7 +580,7 @@ static void add_interpolated_polys_to_new_mesh(const Mesh &src_mesh, /* Create closing edge. */ MEdge &cut_edge = dst_edges[edge_index]; - cut_edge.v1 = dst_corner_verts[mp_dst.loopstart]; + cut_edge.v1 = dst_corner_verts[dst_poly_offsets[i_dst]]; cut_edge.v2 = dst_corner_verts[i_ml_dst]; BLI_assert(cut_edge.v1 != cut_edge.v2); edge_index++; @@ -596,7 +589,7 @@ static void add_interpolated_polys_to_new_mesh(const Mesh &src_mesh, break; } else if (v_loop_in_mask && v_loop_in_mask_last) { - BLI_assert(i_ml_dst != mp_dst.loopstart); + BLI_assert(i_ml_dst != dst_poly_offsets[i_dst]); /* Extend active poly. */ CustomData_copy_data(&src_mesh.ldata, &dst_mesh.ldata, i_ml_src + index, i_ml_dst, 1); dst_corner_verts[i_ml_dst] = vertex_map[src_corner_verts[index]]; @@ -607,7 +600,6 @@ static void add_interpolated_polys_to_new_mesh(const Mesh &src_mesh, last_index = index; v_loop_in_mask_last = v_loop_in_mask; } - BLI_assert(mp_dst.loopstart + mp_dst.totloop == i_ml_dst); } BLI_assert(edge_index == dst_mesh.totedge); } diff --git a/source/blender/modifiers/intern/MOD_meshcache.c b/source/blender/modifiers/intern/MOD_meshcache.c index 0fd1e7bebda..c7da6711138 100644 --- a/source/blender/modifiers/intern/MOD_meshcache.c +++ b/source/blender/modifiers/intern/MOD_meshcache.c @@ -179,7 +179,7 @@ static void meshcache_do(MeshCacheModifierData *mcmd, float(*vertexCos_New)[3] = MEM_malloc_arrayN(verts_num, sizeof(*vertexCos_New), __func__); BKE_mesh_calc_relative_deform( - BKE_mesh_polys(me), + BKE_mesh_poly_offsets(me), me->totpoly, BKE_mesh_corner_verts(me), me->totvert, diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.cc b/source/blender/modifiers/intern/MOD_meshsequencecache.cc index 1a9ab043d43..b0e87d7c574 100644 --- a/source/blender/modifiers/intern/MOD_meshsequencecache.cc +++ b/source/blender/modifiers/intern/MOD_meshsequencecache.cc @@ -207,10 +207,10 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * if (me != nullptr) { const Span mesh_positions = mesh->vert_positions(); const Span mesh_edges = mesh->edges(); - const Span mesh_polys = mesh->polys(); + const blender::OffsetIndices mesh_polys = mesh->polys(); const Span me_positions = me->vert_positions(); const Span me_edges = me->edges(); - const Span me_polys = me->polys(); + const blender::OffsetIndices me_polys = me->polys(); /* TODO(sybren+bastien): possibly check relevant custom data layers (UV/color depending on * flags) and duplicate those too. diff --git a/source/blender/modifiers/intern/MOD_normal_edit.cc b/source/blender/modifiers/intern/MOD_normal_edit.cc index 0bbd7fa12fd..1f460218994 100644 --- a/source/blender/modifiers/intern/MOD_normal_edit.cc +++ b/source/blender/modifiers/intern/MOD_normal_edit.cc @@ -183,7 +183,7 @@ static bool polygons_check_flip(blender::MutableSpan corner_verts, blender::MutableSpan corner_edges, blender::float3 *nos, CustomData *ldata, - const blender::Span polys, + const blender::OffsetIndices polys, const blender::Span poly_normals) { MDisps *mdisp = static_cast( @@ -191,20 +191,20 @@ static bool polygons_check_flip(blender::MutableSpan corner_verts, bool flipped = false; for (const int i : polys.index_range()) { - const MPoly &poly = polys[i]; + const blender::IndexRange poly = polys[i]; float norsum[3] = {0.0f}; - for (const int64_t j : blender::IndexRange(poly.loopstart, poly.totloop)) { + for (const int64_t j : poly) { add_v3_v3(norsum, nos[j]); } - if (!normalize_v3(norsum)) { continue; } /* If average of new loop normals is opposed to polygon normal, flip polygon. */ if (dot_v3v3(poly_normals[i], norsum) < 0.0f) { - BKE_mesh_polygon_flip_ex(&poly, + BKE_mesh_polygon_flip_ex(poly.start(), + poly.size(), corner_verts.data(), corner_edges.data(), ldata, @@ -235,7 +235,7 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd, blender::MutableSpan sharp_edges, blender::MutableSpan corner_verts, blender::MutableSpan corner_edges, - const blender::Span polys) + const blender::OffsetIndices polys) { Object *ob_target = enmd->target; @@ -363,7 +363,7 @@ static void normalEditModifier_do_directional(NormalEditModifierData *enmd, blender::MutableSpan sharp_edges, blender::MutableSpan corner_verts, blender::MutableSpan corner_edges, - const blender::Span polys) + const blender::OffsetIndices polys) { Object *ob_target = enmd->target; @@ -515,7 +515,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, const blender::Span positions = result->vert_positions(); const blender::Span edges = result->edges(); - const blender::Span polys = result->polys(); + const OffsetIndices polys = result->polys(); blender::MutableSpan corner_verts = result->corner_verts_for_write(); blender::MutableSpan corner_edges = result->corner_edges_for_write(); diff --git a/source/blender/modifiers/intern/MOD_ocean.cc b/source/blender/modifiers/intern/MOD_ocean.cc index cceb840cf17..19bb166a2c3 100644 --- a/source/blender/modifiers/intern/MOD_ocean.cc +++ b/source/blender/modifiers/intern/MOD_ocean.cc @@ -152,7 +152,7 @@ static bool dependsOnNormals(ModifierData *md) struct GenerateOceanGeometryData { float (*vert_positions)[3]; - blender::MutableSpan polys; + blender::MutableSpan poly_offsets; blender::MutableSpan corner_verts; float (*mloopuvs)[2]; @@ -195,8 +195,7 @@ static void generate_ocean_geometry_polys(void *__restrict userdata, gogd->corner_verts[fi * 4 + 2] = vi + 1 + gogd->res_x + 1; gogd->corner_verts[fi * 4 + 3] = vi + gogd->res_x + 1; - gogd->polys[fi].loopstart = fi * 4; - gogd->polys[fi].totloop = 4; + gogd->poly_offsets[fi] = fi * 4; } } @@ -260,7 +259,7 @@ static Mesh *generate_ocean_geometry(OceanModifierData *omd, Mesh *mesh_orig, co BKE_mesh_copy_parameters_for_eval(result, mesh_orig); gogd.vert_positions = BKE_mesh_vert_positions_for_write(result); - gogd.polys = result->polys_for_write(); + gogd.poly_offsets = result->poly_offsets_for_write(); gogd.corner_verts = result->corner_verts_for_write(); TaskParallelSettings settings; @@ -353,7 +352,7 @@ static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mes cfra_for_cache -= omd->bakestart; /* shift to 0 based */ float(*positions)[3] = BKE_mesh_vert_positions_for_write(result); - const blender::Span polys = mesh->polys(); + const blender::OffsetIndices polys = result->polys(); /* Add vertex-colors before displacement: allows lookup based on position. */ @@ -377,15 +376,16 @@ static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mes if (mloopcols) { /* unlikely to fail */ for (const int i : polys.index_range()) { - const int *corner_vert = &corner_verts[polys[i].loopstart]; - MLoopCol *mlcol = &mloopcols[polys[i].loopstart]; + const blender::IndexRange poly = polys[i]; + const int *corner_vert = &corner_verts[poly.start()]; + MLoopCol *mlcol = &mloopcols[poly.start()]; MLoopCol *mlcolspray = nullptr; if (omd->flag & MOD_OCEAN_GENERATE_SPRAY) { - mlcolspray = &mloopcols_spray[polys[i].loopstart]; + mlcolspray = &mloopcols_spray[poly.start()]; } - for (j = polys[i].totloop; j--; corner_vert++, mlcol++) { + for (j = poly.size(); j--; corner_vert++, mlcol++) { const float *vco = positions[*corner_vert]; const float u = OCEAN_CO(size_co_inv, vco[0]); const float v = OCEAN_CO(size_co_inv, vco[1]); diff --git a/source/blender/modifiers/intern/MOD_particleinstance.cc b/source/blender/modifiers/intern/MOD_particleinstance.cc index 2807b909c9e..73ac223531a 100644 --- a/source/blender/modifiers/intern/MOD_particleinstance.cc +++ b/source/blender/modifiers/intern/MOD_particleinstance.cc @@ -314,12 +314,12 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * result = BKE_mesh_new_nomain_from_template(mesh, maxvert, maxedge, maxloop, maxpoly); - const blender::Span orig_polys = mesh->polys(); + const blender::OffsetIndices orig_polys = mesh->polys(); const blender::Span orig_corner_verts = mesh->corner_verts(); const blender::Span orig_corner_edges = mesh->corner_edges(); float(*positions)[3] = BKE_mesh_vert_positions_for_write(result); blender::MutableSpan edges = result->edges_for_write(); - blender::MutableSpan polys = result->polys_for_write(); + blender::MutableSpan poly_offsets = result->poly_offsets_for_write(); blender::MutableSpan corner_verts = result->corner_verts_for_write(); blender::MutableSpan corner_edges = result->corner_edges_for_write(); @@ -478,20 +478,18 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* create polys and loops */ for (k = 0; k < totpoly; k++) { - - const MPoly &in_poly = orig_polys[k]; - MPoly &poly = polys[p_skip * totpoly + k]; + const blender::IndexRange in_poly = orig_polys[k]; CustomData_copy_data(&mesh->pdata, &result->pdata, k, p_skip * totpoly + k, 1); - poly = in_poly; - poly.loopstart += p_skip * totloop; + const int dst_poly_start = in_poly.start() + p_skip * totloop; + poly_offsets[p_skip * totpoly + k] = dst_poly_start; { - int orig_corner_i = in_poly.loopstart; - int dst_corner_i = poly.loopstart; - int j = poly.totloop; + int orig_corner_i = in_poly.start(); + int dst_corner_i = dst_poly_start; + int j = in_poly.size(); - CustomData_copy_data(&mesh->ldata, &result->ldata, in_poly.loopstart, poly.loopstart, j); + CustomData_copy_data(&mesh->ldata, &result->ldata, in_poly.start(), dst_poly_start, j); for (; j; j--, orig_corner_i++, dst_corner_i++) { corner_verts[dst_corner_i] = orig_corner_verts[orig_corner_i] + (p_skip * totvert); corner_edges[dst_corner_i] = orig_corner_edges[orig_corner_i] + (p_skip * totedge); diff --git a/source/blender/modifiers/intern/MOD_remesh.cc b/source/blender/modifiers/intern/MOD_remesh.cc index 119c14d824a..a867db11127 100644 --- a/source/blender/modifiers/intern/MOD_remesh.cc +++ b/source/blender/modifiers/intern/MOD_remesh.cc @@ -79,7 +79,7 @@ static void init_dualcon_mesh(DualConInput *input, Mesh *mesh) typedef struct { Mesh *mesh; float (*vert_positions)[3]; - MPoly *polys; + int *poly_offsets; int *corner_verts; int curvert, curface; } DualConOutput; @@ -95,7 +95,7 @@ static void *dualcon_alloc_output(int totvert, int totquad) output->mesh = BKE_mesh_new_nomain(totvert, 0, 4 * totquad, totquad); output->vert_positions = BKE_mesh_vert_positions_for_write(output->mesh); - output->polys = output->mesh->polys_for_write().data(); + output->poly_offsets = output->mesh->poly_offsets_for_write().data(); output->corner_verts = output->mesh->corner_verts_for_write().data(); return output; @@ -120,9 +120,7 @@ static void dualcon_add_quad(void *output_v, const int vert_indices[4]) BLI_assert(output->curface < mesh->totpoly); UNUSED_VARS_NDEBUG(mesh); - output->polys[output->curface].loopstart = output->curface * 4; - output->polys[output->curface].totloop = 4; - + output->poly_offsets[output->curface] = output->curface * 4; for (i = 0; i < 4; i++) { output->corner_verts[output->curface * 4 + i] = vert_indices[i]; } @@ -190,7 +188,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext * /*ctx*/, M rmd->scale, rmd->depth)); BLI_mutex_unlock(&dualcon_mutex); - + output->mesh->poly_offsets_for_write().last() = output->mesh->totloop; result = output->mesh; MEM_freeN(output); } diff --git a/source/blender/modifiers/intern/MOD_screw.cc b/source/blender/modifiers/intern/MOD_screw.cc index be42917d27c..c922e9d1f37 100644 --- a/source/blender/modifiers/intern/MOD_screw.cc +++ b/source/blender/modifiers/intern/MOD_screw.cc @@ -252,7 +252,6 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * uint edge_offset; - MPoly *mp_new; MEdge *edge_new, *med_new_firstloop; Object *ob_axis = ltmd->ob_axis; @@ -399,13 +398,13 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * const float(*vert_positions_orig)[3] = BKE_mesh_vert_positions(mesh); const blender::Span edges_orig = mesh->edges(); - const blender::Span polys_orig = mesh->polys(); + const OffsetIndices polys_orig = mesh->polys(); const blender::Span corner_verts_orig = mesh->corner_verts(); const blender::Span corner_edges_orig = mesh->corner_edges(); float(*vert_positions_new)[3] = BKE_mesh_vert_positions_for_write(result); blender::MutableSpan edges_new = result->edges_for_write(); - blender::MutableSpan polys_new = result->polys_for_write(); + MutableSpan poly_offests_new = result->poly_offsets_for_write(); blender::MutableSpan corner_verts_new = result->corner_verts_for_write(); blender::MutableSpan corner_edges_new = result->corner_edges_for_write(); bke::MutableAttributeAccessor attributes = result->attributes_for_write(); @@ -459,7 +458,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* build polygon -> edge map */ if (totpoly) { - + edge_poly_map = static_cast( MEM_malloc_arrayN(totedge, sizeof(*edge_poly_map), __func__)); memset(edge_poly_map, 0xff, sizeof(*edge_poly_map) * totedge); @@ -469,14 +468,11 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * memset(vert_loop_map, 0xff, sizeof(*vert_loop_map) * totvert); for (const int64_t i : polys_orig.index_range()) { - uint loopstart = uint(polys_orig[i].loopstart); - uint loopend = loopstart + uint(polys_orig[i].totloop); - - for (uint k = loopstart; k < loopend; k++) { - const uint vert_i = uint(corner_verts_orig[k]); - const uint edge_i = uint(corner_edges_orig[k]); + for (const int64_t corner : polys_orig[i]) { + const uint vert_i = uint(corner_verts_orig[corner]); + const uint edge_i = uint(corner_edges_orig[corner]); edge_poly_map[edge_i] = uint(i); - vert_loop_map[vert_i] = k; + vert_loop_map[vert_i] = uint(corner); /* also order edges based on faces */ if (edges_new[edge_i].v1 != vert_i) { @@ -827,7 +823,6 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * } } - mp_new = polys_new.data(); int new_loop_index = 0; med_new_firstloop = edges_new.data(); @@ -885,8 +880,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * dst_material_index[mpoly_index] = mat_nr; sharp_faces.span[i] = use_flat_shading; } - mp_new->loopstart = mpoly_index * 4; - mp_new->totloop = 4; + poly_offests_new[mpoly_index] = mpoly_index * 4; /* Loop-Custom-Data */ if (has_mloop_orig) { @@ -968,7 +962,6 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * corner_edges_new[new_loop_index + quad_ord_ofs[3]] = int(totedge + i1); } - mp_new++; new_loop_index += 4; mpoly_index++; } @@ -987,19 +980,19 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * for (; i < maxPolys * 4; i += 4) { uint ii; ml_new = mloop_new + i; - ii = findEd(medge_new, maxEdges, ml_new[0].v, ml_new[1].v); + ii = findEd(edges_new, maxEdges, ml_new[0].v, ml_new[1].v); printf("%d %d -- ", ii, ml_new[0].e); ml_new[0].e = ii; - ii = findEd(medge_new, maxEdges, ml_new[1].v, ml_new[2].v); + ii = findEd(edges_new, maxEdges, ml_new[1].v, ml_new[2].v); printf("%d %d -- ", ii, ml_new[1].e); ml_new[1].e = ii; - ii = findEd(medge_new, maxEdges, ml_new[2].v, ml_new[3].v); + ii = findEd(edges_new, maxEdges, ml_new[2].v, ml_new[3].v); printf("%d %d -- ", ii, ml_new[2].e); ml_new[2].e = ii; - ii = findEd(medge_new, maxEdges, ml_new[3].v, ml_new[0].v); + ii = findEd(edges_new, maxEdges, ml_new[3].v, ml_new[0].v); printf("%d %d\n", ii, ml_new[3].e); ml_new[3].e = ii; } diff --git a/source/blender/modifiers/intern/MOD_solidify_extrude.cc b/source/blender/modifiers/intern/MOD_solidify_extrude.cc index 59dba0536ce..4ce7df075ba 100644 --- a/source/blender/modifiers/intern/MOD_solidify_extrude.cc +++ b/source/blender/modifiers/intern/MOD_solidify_extrude.cc @@ -59,7 +59,7 @@ static void mesh_calc_hq_normal(Mesh *mesh, { const int verts_num = mesh->totvert; const blender::Span edges = mesh->edges(); - const blender::Span polys = mesh->polys(); + const blender::OffsetIndices polys = mesh->polys(); const blender::Span corner_edges = mesh->corner_edges(); { @@ -69,11 +69,7 @@ static void mesh_calc_hq_normal(Mesh *mesh, /* Add an edge reference if it's not there, pointing back to the face index. */ for (const int i : polys.index_range()) { - int j; - - for (j = 0; j < polys[i].totloop; j++) { - const int edge_i = corner_edges[polys[i].loopstart + j]; - + for (const int edge_i : corner_edges.slice(polys[i])) { /* --- add edge ref to face --- */ edge_ref = &edge_ref_array[edge_i]; if (!edgeref_is_init(edge_ref)) { @@ -207,7 +203,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex const float(*orig_vert_positions)[3] = BKE_mesh_vert_positions(mesh); const blender::Span orig_edges = mesh->edges(); - const blender::Span orig_polys = mesh->polys(); + const blender::OffsetIndices orig_polys = mesh->polys(); const blender::Span orig_corner_verts = mesh->corner_verts(); const blender::Span orig_corner_edges = mesh->corner_edges(); @@ -246,13 +242,13 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex } for (const int64_t i : orig_polys.index_range()) { - const MPoly &poly = orig_polys[i]; + const blender::IndexRange poly = orig_polys[i]; int j; - int corner_i_prev = poly.loopstart + (poly.totloop - 1); + int corner_i_prev = poly.last(); - for (j = 0; j < poly.totloop; j++) { - const int corner_i = poly.loopstart + j; + for (j = 0; j < poly.size(); j++) { + const int corner_i = poly[j]; const int vert_i = orig_corner_verts[corner_i]; const int prev_vert_i = orig_corner_verts[corner_i_prev]; /* add edge user */ @@ -332,7 +328,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex float(*vert_positions)[3] = BKE_mesh_vert_positions_for_write(result); blender::MutableSpan edges = result->edges_for_write(); - blender::MutableSpan polys = result->polys_for_write(); + blender::MutableSpan poly_offsets = result->poly_offsets_for_write(); blender::MutableSpan corner_verts = result->corner_verts_for_write(); blender::MutableSpan corner_edges = result->corner_edges_for_write(); @@ -352,6 +348,10 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex CustomData_copy_data(&mesh->pdata, &result->pdata, 0, 0, int(polys_num)); CustomData_copy_data(&mesh->pdata, &result->pdata, 0, int(polys_num), int(polys_num)); + poly_offsets.take_front(polys_num).copy_from(mesh->poly_offsets().drop_back(1)); + for (const int i : orig_polys.index_range()) { + poly_offsets[polys_num + i] = orig_polys[i].start() + mesh->totloop; + } } else { int i, j; @@ -381,6 +381,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex /* will be created later */ CustomData_copy_data(&mesh->ldata, &result->ldata, 0, 0, int(loops_num)); CustomData_copy_data(&mesh->pdata, &result->pdata, 0, 0, int(polys_num)); + poly_offsets.take_front(polys_num).copy_from(mesh->poly_offsets().drop_back(1)); } float *result_edge_bweight = nullptr; @@ -415,39 +416,38 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex if (do_shell) { for (const int64_t i : blender::IndexRange(mesh->totpoly)) { - const int64_t poly_i = polys_num + i; - MPoly &poly = polys[poly_i]; - const int loop_end = poly.totloop - 1; + const blender::IndexRange poly = orig_polys[i]; + const int loop_end = poly.size() - 1; int e; int j; /* reverses the loop direction (corner verts as well as custom-data) * Corner edges also need to be corrected too, done in a separate loop below. */ - const int corner_2 = poly.loopstart + mesh->totloop; + const int corner_2 = poly.start() + mesh->totloop; #if 0 - for (j = 0; j < poly.totloop; j++) { + for (j = 0; j < poly.size(); j++) { CustomData_copy_data(&mesh->ldata, &result->ldata, - poly.loopstart + j, - poly.loopstart + (loop_end - j) + mesh->totloop, + poly.start() + j, + poly.start() + (loop_end - j) + mesh->totloop, 1); } #else /* slightly more involved, keep the first vertex the same for the copy, * ensures the diagonals in the new face match the original. */ j = 0; - for (int j_prev = loop_end; j < poly.totloop; j_prev = j++) { + for (int j_prev = loop_end; j < poly.size(); j_prev = j++) { CustomData_copy_data(&mesh->ldata, &result->ldata, - poly.loopstart + j, - poly.loopstart + (loop_end - j_prev) + mesh->totloop, + poly.start() + j, + poly.start() + (loop_end - j_prev) + mesh->totloop, 1); } #endif if (mat_ofs) { - dst_material_index[poly_i] += mat_ofs; - CLAMP(dst_material_index[poly_i], 0, mat_nr_max); + dst_material_index[polys_num + i] += mat_ofs; + CLAMP(dst_material_index[polys_num + i], 0, mat_nr_max); } e = corner_edges[corner_2 + 0]; @@ -456,9 +456,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex } corner_edges[corner_2 + loop_end] = e; - poly.loopstart += mesh->totloop; - - for (j = 0; j < poly.totloop; j++) { + for (j = 0; j < poly.size(); j++) { corner_verts[corner_2 + j] += verts_num; corner_edges[corner_2 + j] += edges_num; } @@ -515,10 +513,9 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex edge_user_pairs[eidx][1] = INVALID_UNUSED; } for (const int64_t i : orig_polys.index_range()) { - const MPoly &poly = orig_polys[i]; - int prev_corner_i = poly.loopstart + poly.totloop - 1; - for (int j = 0; j < poly.totloop; j++) { - const int corner_i = poly.loopstart + j; + const blender::IndexRange poly = orig_polys[i]; + int prev_corner_i = poly.last(); + for (const int corner_i : poly) { const int vert_i = orig_corner_verts[corner_i]; const int prev_vert_i = orig_corner_verts[prev_corner_i]; /* add edge user */ @@ -716,21 +713,22 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex } for (const int64_t i : blender::IndexRange(polys_num)) { + const blender::IndexRange poly = orig_polys[i]; /* #bke::mesh::poly_angles_calc logic is inlined here */ float nor_prev[3]; float nor_next[3]; - int i_curr = polys[i].totloop - 1; + int i_curr = poly.size() - 1; int i_next = 0; - const int *poly_verts = &corner_verts[polys[i].loopstart]; - const int *poly_edges = &corner_edges[polys[i].loopstart]; + const int *poly_verts = &corner_verts[poly.start()]; + const int *poly_edges = &corner_edges[poly.start()]; sub_v3_v3v3( nor_prev, vert_positions[poly_verts[i_curr - 1]], vert_positions[poly_verts[i_curr]]); normalize_v3(nor_prev); - while (i_next < polys[i].totloop) { + while (i_next < poly.size()) { float angle; sub_v3_v3v3( nor_next, vert_positions[poly_verts[i_curr]], vert_positions[poly_verts[i_next]]); @@ -817,10 +815,10 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex edge_user_pairs[eidx][1] = INVALID_UNUSED; } for (const int i : orig_polys.index_range()) { - const MPoly &poly = orig_polys[i]; - int prev_corner_i = poly.loopstart + poly.totloop - 1; - for (int j = 0; j < poly.totloop; j++) { - const int corner_i = poly.loopstart + j; + const blender::IndexRange poly = orig_polys[i]; + int prev_corner_i = poly.start() + poly.size() - 1; + for (int j = 0; j < poly.size(); j++) { + const int corner_i = poly.start() + j; const int vert_i = orig_corner_verts[corner_i]; const int prev_vert_i = orig_corner_verts[prev_corner_i]; @@ -1092,19 +1090,14 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex /* copy most of the face settings */ CustomData_copy_data( &mesh->pdata, &result->pdata, int(pidx), int((polys_num * stride) + i), 1); - polys[new_poly_index].loopstart = int(j + (loops_num * stride)); - /* notice we use 'polys[new_poly_index].totloop' which is later overwritten, - * we could lookup the original face but there's no point since this is a copy - * and will have the same value, just take care when changing order of assignment */ + const int old_poly_size = orig_polys[pidx].size(); + poly_offsets[new_poly_index] = int(j + (loops_num * stride)); /* prev loop */ - k1 = polys[pidx].loopstart + (((edge_order[eidx] - 1) + polys[new_poly_index].totloop) % - polys[new_poly_index].totloop); + k1 = poly_offsets[pidx] + (((edge_order[eidx] - 1) + old_poly_size) % old_poly_size); - k2 = polys[pidx].loopstart + (edge_order[eidx]); - - polys[new_poly_index].totloop = 4; + k2 = poly_offsets[pidx] + (edge_order[eidx]); CustomData_copy_data(&mesh->ldata, &result->ldata, k2, int((loops_num * stride) + j + 0), 1); CustomData_copy_data(&mesh->ldata, &result->ldata, k1, int((loops_num * stride) + j + 1), 1); diff --git a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.cc b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.cc index 3af2a85ca8f..d1ed55e13ed 100644 --- a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.cc +++ b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.cc @@ -74,7 +74,7 @@ static float clamp_nonzero(const float value, const float epsilon) struct NewEdgeRef; struct NewFaceRef { - const MPoly *face; + blender::IndexRange face; uint index; bool reversed; NewEdgeRef **link_edges; @@ -184,7 +184,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, const float(*orig_vert_positions)[3] = BKE_mesh_vert_positions(mesh); const blender::Span orig_edges = mesh->edges(); - const blender::Span orig_polys = mesh->polys(); + const blender::OffsetIndices orig_polys = mesh->polys(); const blender::Span orig_corner_verts = mesh->corner_verts(); const blender::Span orig_corner_edges = mesh->corner_edges(); @@ -216,10 +216,10 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, /* Calculate face to #NewFaceRef map. */ { for (const int i : orig_polys.index_range()) { - const MPoly &poly = orig_polys[i]; + const blender::IndexRange &poly = orig_polys[i]; /* Make normals for faces without area (should really be avoided though). */ if (len_squared_v3(poly_nors[i]) < 0.5f) { - const MEdge *edge = &orig_edges[orig_corner_edges[poly.loopstart]]; + const MEdge *edge = &orig_edges[orig_corner_edges[poly.start()]]; float edgedir[3]; sub_v3_v3v3(edgedir, orig_vert_positions[edge->v2], orig_vert_positions[edge->v1]); if (fabsf(edgedir[2]) < fabsf(edgedir[1])) { @@ -234,32 +234,32 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, } NewEdgeRef **link_edges = static_cast( - MEM_calloc_arrayN(uint(poly.totloop), sizeof(*link_edges), __func__)); + MEM_calloc_arrayN(uint(poly.size()), sizeof(*link_edges), __func__)); NewFaceRef new_face_ref_a{}; - new_face_ref_a.face = &poly; + new_face_ref_a.face = poly; new_face_ref_a.index = uint(i); new_face_ref_a.reversed = false; new_face_ref_a.link_edges = link_edges; face_sides_arr[i * 2] = new_face_ref_a; link_edges = static_cast( - MEM_calloc_arrayN(uint(poly.totloop), sizeof(*link_edges), __func__)); + MEM_calloc_arrayN(uint(poly.size()), sizeof(*link_edges), __func__)); NewFaceRef new_face_ref_b{}; - new_face_ref_b.face = &poly; + new_face_ref_b.face = poly; new_face_ref_b.index = uint(i); new_face_ref_b.reversed = true; new_face_ref_b.link_edges = link_edges; face_sides_arr[i * 2 + 1] = new_face_ref_b; - if (poly.totloop > largest_ngon) { - largest_ngon = uint(poly.totloop); + if (poly.size() > largest_ngon) { + largest_ngon = uint(poly.size()); } /* add to final mesh face count */ if (do_shell) { new_polys_num += 2; - new_loops_num += uint(poly.totloop * 2); + new_loops_num += uint(poly.size() * 2); } } } @@ -269,9 +269,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, /* Count for each edge how many faces it has adjacent. */ { for (const int64_t i : orig_polys.index_range()) { - const MPoly &poly = orig_polys[i]; - for (uint j = 0; j < poly.totloop; j++) { - edge_adj_faces_len[orig_corner_edges[poly.loopstart + j]]++; + for (const int64_t edge : orig_corner_edges.slice(orig_polys[i])) { + edge_adj_faces_len[edge]++; } } } @@ -318,10 +317,9 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, /* Create link_faces for edges. */ { for (const int64_t i : orig_polys.index_range()) { - const MPoly &poly = orig_polys[i]; - for (uint j = 0; j < poly.totloop; j++) { - const int vert = orig_corner_verts[poly.loopstart + j]; - const int edge = orig_corner_edges[poly.loopstart + j]; + for (const int64_t corner : orig_polys[i]) { + const int vert = orig_corner_verts[corner]; + const int edge = orig_corner_edges[corner]; const bool reversed = orig_edges[edge].v2 != vert; OldEdgeFaceRef *old_face_edge_ref = edge_adj_faces[edge]; if (old_face_edge_ref == nullptr) { @@ -391,12 +389,12 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, if (k != i && edge_adj_faces_len[k] > 0 && (ELEM(vm[orig_edges[k].v1], v1, v2) != ELEM(vm[orig_edges[k].v2], v1, v2))) { for (uint j = 0; j < edge_adj_faces[k]->faces_len && can_merge; j++) { - const MPoly &poly = orig_polys[edge_adj_faces[k]->faces[j]]; + const blender::IndexRange poly = orig_polys[edge_adj_faces[k]->faces[j]]; uint changes = 0; - int cur = poly.totloop - 1; - for (int next = 0; next < poly.totloop && changes <= 2; next++) { - uint cur_v = vm[orig_corner_verts[poly.loopstart + cur]]; - uint next_v = vm[orig_corner_verts[poly.loopstart + next]]; + int cur = poly.size() - 1; + for (int next = 0; next < poly.size() && changes <= 2; next++) { + uint cur_v = vm[orig_corner_verts[poly[cur]]]; + uint next_v = vm[orig_corner_verts[poly[next]]]; changes += (ELEM(cur_v, v1, v2) != ELEM(next_v, v1, v2)); cur = next; } @@ -453,8 +451,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, const uint face = edge_adj_faces[i]->faces[j]; if (!face_singularity[face]) { bool is_singularity = true; - for (uint k = 0; k < orig_polys[face].totloop; k++) { - if (vm[orig_corner_verts[uint(orig_polys[face].loopstart) + k]] != v1) { + for (const int vert : orig_corner_verts.slice(orig_polys[face])) { + if (vm[vert] != v1) { is_singularity = false; break; } @@ -620,15 +618,15 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, /* For each face pair check if they have equal verts. */ for (uint j = 0; j < adj_len; j++) { const uint face = adj_faces->faces[j]; - const int j_loopstart = orig_polys[face].loopstart; - const int totloop = orig_polys[face].totloop; + const int j_loopstart = orig_polys[face].start(); + const int totloop = orig_polys[face].size(); const uint j_first_v = vm[orig_corner_verts[j_loopstart]]; for (uint k = j + 1; k < adj_len; k++) { - if (orig_polys[adj_faces->faces[k]].totloop != totloop) { + if (orig_polys[adj_faces->faces[k]].size() != totloop) { continue; } /* Find first face first loop vert in second face loops. */ - const int k_loopstart = orig_polys[adj_faces->faces[k]].loopstart; + const int k_loopstart = orig_polys[adj_faces->faces[k]].start(); int l; { const int *corner_vert = &orig_corner_verts[k_loopstart]; @@ -790,7 +788,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, copy_v3_v3(nor, poly_nors[face_i]); } float d = 1; - if (orig_polys[face_i].totloop > 3) { + if (orig_polys[face_i].size() > 3) { d = project_v3_v3(nor, edgedir); if (LIKELY(d != 0)) { d = normalize_v3(nor); @@ -871,8 +869,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, new_edges[j] = edge_data; for (uint k = 0; k < 2; k++) { if (faces[k] != nullptr) { - for (int l = 0; l < faces[k]->face->totloop; l++) { - const int edge = orig_corner_edges[faces[k]->face->loopstart + l]; + for (int l = 0; l < faces[k]->face.size(); l++) { + const int edge = orig_corner_edges[faces[k]->face.start() + l]; if (edge_adj_faces[edge] == edge_adj_faces[i]) { if (edge != i && orig_edge_data_arr[edge] == nullptr) { orig_edge_data_arr[edge] = new_edges; @@ -1408,11 +1406,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, MEM_malloc_arrayN(polys_num, sizeof(*face_weight), __func__)); for (const int i : orig_polys.index_range()) { - const MPoly &poly = orig_polys[i]; float scalar_vgroup = 1.0f; - int loopend = poly.loopstart + poly.totloop; - for (int j = poly.loopstart; j < loopend; j++) { - const int vert = orig_corner_verts[poly.loopstart + j]; + for (const int vert : orig_corner_verts.slice(orig_polys[i])) { const MDeformVert *dv = &dvert[vert]; if (defgrp_invert) { scalar_vgroup = min_ff(1.0f - BKE_defvert_find_weight(dv, defgrp_index), @@ -1683,12 +1678,12 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, if (smd->nonmanifold_offset_mode == MOD_SOLIDIFY_NONMANIFOLD_OFFSET_MODE_EVEN) { - int corner_next = face->face->loopstart; - int corner = corner_next + (face->face->totloop - 1); + int corner_next = face->face.start(); + int corner = corner_next + (face->face.size() - 1); int corner_prev = corner - 1; for (int m = 0; - m < face->face->totloop && vm[orig_corner_verts[corner]] != i; + m < face->face.size() && vm[orig_corner_verts[corner]] != i; m++, corner_next++) { corner_prev = corner; corner = corner_next; @@ -1990,7 +1985,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, float(*vert_positions)[3] = BKE_mesh_vert_positions_for_write(result); blender::MutableSpan edges = result->edges_for_write(); - blender::MutableSpan polys = result->polys_for_write(); + blender::MutableSpan poly_offsets = result->poly_offsets_for_write(); blender::MutableSpan corner_verts = result->corner_verts_for_write(); blender::MutableSpan corner_edges = result->corner_edges_for_write(); @@ -2313,8 +2308,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, if (origindex_poly) { origindex_poly[poly_index] = ORIGINDEX_NONE; } - polys[poly_index].loopstart = int(loop_index); - polys[poly_index].totloop = int(j); + poly_offsets[poly_index] = int(loop_index); dst_material_index[poly_index] = most_mat_nr + (g->is_orig_closed || !do_rim ? 0 : mat_ofs_rim); CLAMP(dst_material_index[poly_index], 0, mat_nr_max); @@ -2322,11 +2316,11 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, for (uint k = 0; g2->valid && k < j; g2++) { if ((do_rim && !g2->is_orig_closed) || (do_shell && g2->split)) { - const MPoly *face = g2->edges[0]->faces[0]->face; - for (int l = 0; l < face->totloop; l++) { - const int vert = orig_corner_verts[face->loopstart + l]; + const blender::IndexRange face = g2->edges[0]->faces[0]->face; + for (int l = 0; l < face.size(); l++) { + const int vert = orig_corner_verts[face[l]]; if (vm[vert] == i) { - loops_data[k] = face->loopstart + l; + loops_data[k] = face[l]; break; } } @@ -2384,11 +2378,10 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, } const uint orig_face_index = (*new_edges)->faces[0]->index; - const MPoly *face = (*new_edges)->faces[0]->face; + const blender::IndexRange face = (*new_edges)->faces[0]->face; CustomData_copy_data( &mesh->pdata, &result->pdata, int((*new_edges)->faces[0]->index), int(poly_index), 1); - polys[poly_index].loopstart = int(loop_index); - polys[poly_index].totloop = 4 - int(v1_singularity || v2_singularity); + poly_offsets[poly_index] = int(loop_index); dst_material_index[poly_index] = (src_material_index ? src_material_index[orig_face_index] : 0) + mat_ofs_rim; CLAMP(dst_material_index[poly_index], 0, mat_nr_max); @@ -2398,13 +2391,13 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, int loop2 = -1; const uint old_v1 = vm[orig_edges[edge1->old_edge].v1]; const uint old_v2 = vm[orig_edges[edge1->old_edge].v2]; - for (uint j = 0; j < face->totloop; j++) { - const int vert = orig_corner_verts[face->loopstart + j]; + for (uint j = 0; j < face.size(); j++) { + const int vert = orig_corner_verts[face.start() + j]; if (vm[vert] == old_v1) { - loop1 = face->loopstart + int(j); + loop1 = face.start() + int(j); } else if (vm[vert] == old_v2) { - loop2 = face->loopstart + int(j); + loop2 = face.start() + int(j); } } BLI_assert(loop1 != -1 && loop2 != -1); @@ -2526,8 +2519,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, uint *face_edges = static_cast( MEM_malloc_arrayN(largest_ngon * 2, sizeof(*face_edges), __func__)); for (uint i = 0; i < polys_num * 2; i++, fr++) { - const uint loopstart = uint(fr->face->loopstart); - uint totloop = uint(fr->face->totloop); + const uint loopstart = uint(fr->face.start()); + uint totloop = uint(fr->face.size()); uint valid_edges = 0; uint k = 0; while (totloop > 0 && (!fr->link_edges[totloop - 1] || @@ -2578,8 +2571,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, } if (k > 2 && valid_edges > 2) { CustomData_copy_data(&mesh->pdata, &result->pdata, int(i / 2), int(poly_index), 1); - polys[poly_index].loopstart = int(loop_index); - polys[poly_index].totloop = int(k); + poly_offsets[poly_index] = int(loop_index); dst_material_index[poly_index] = (src_material_index ? src_material_index[fr->index] : 0) + (fr->reversed != do_flip ? mat_ofs : 0); diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.cc b/source/blender/modifiers/intern/MOD_surfacedeform.cc index c1ce4e14242..911098d8da2 100644 --- a/source/blender/modifiers/intern/MOD_surfacedeform.cc +++ b/source/blender/modifiers/intern/MOD_surfacedeform.cc @@ -69,7 +69,7 @@ struct SDefBindCalcData { const SDefEdgePolys *edge_polys; SDefVert *bind_verts; blender::Span edges; - blender::Span polys; + blender::OffsetIndices polys; blender::Span corner_verts; blender::Span corner_edges; blender::Span looptris; @@ -289,7 +289,7 @@ static void freeAdjacencyMap(SDefAdjacencyArray *const vert_edges, MEM_freeN(vert_edges); } -static int buildAdjacencyMap(const blender::Span polys, +static int buildAdjacencyMap(const blender::OffsetIndices polys, const blender::Span edges, const blender::Span corner_edges, SDefAdjacencyArray *const vert_edges, @@ -298,9 +298,7 @@ static int buildAdjacencyMap(const blender::Span polys, { /* Find polygons adjacent to edges. */ for (const int i : polys.index_range()) { - const MPoly &poly = polys[i]; - for (int j = 0; j < poly.totloop; j++) { - const int edge_i = corner_edges[poly.loopstart + j]; + for (const int edge_i : corner_edges.slice(polys[i])) { if (edge_polys[edge_i].num == 0) { edge_polys[edge_i].polys[0] = i; edge_polys[edge_i].polys[1] = -1; @@ -393,10 +391,10 @@ 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 MPoly &poly = data->polys[data->looptris[nearest.index].poly]; + const blender::IndexRange poly = data->polys[data->looptris[nearest.index].poly]; - for (int i = 0; i < poly.totloop; i++) { - const int edge_i = data->corner_edges[poly.loopstart + i]; + for (int i = 0; i < poly.size(); i++) { + const int edge_i = data->corner_edges[poly.start() + i]; edge = &data->edges[edge_i]; dist = dist_squared_to_line_segment_v3( point_co, data->targetCos[edge->v1], data->targetCos[edge->v2]); @@ -542,13 +540,13 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, bpoly->coords_v2 = nullptr; /* Copy poly data */ - const MPoly &poly = data->polys[bpoly->index]; + const blender::IndexRange poly = data->polys[bpoly->index]; - bpoly->verts_num = poly.totloop; - bpoly->loopstart = poly.loopstart; + bpoly->verts_num = poly.size(); + bpoly->loopstart = poly.start(); bpoly->coords = static_cast( - MEM_malloc_arrayN(poly.totloop, sizeof(*bpoly->coords), "SDefBindPolyCoords")); + MEM_malloc_arrayN(poly.size(), sizeof(*bpoly->coords), "SDefBindPolyCoords")); if (bpoly->coords == nullptr) { freeBindData(bwdata); data->success = MOD_SDEF_BIND_RESULT_MEM_ERR; @@ -556,32 +554,32 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, } bpoly->coords_v2 = static_cast( - MEM_malloc_arrayN(poly.totloop, sizeof(*bpoly->coords_v2), "SDefBindPolyCoords_v2")); + MEM_malloc_arrayN(poly.size(), sizeof(*bpoly->coords_v2), "SDefBindPolyCoords_v2")); if (bpoly->coords_v2 == nullptr) { freeBindData(bwdata); data->success = MOD_SDEF_BIND_RESULT_MEM_ERR; return nullptr; } - for (int j = 0; j < poly.totloop; j++) { - const int vert_i = data->corner_verts[poly.loopstart + j]; - const int edge_i = data->corner_edges[poly.loopstart + j]; + for (int j = 0; j < poly.size(); j++) { + const int vert_i = data->corner_verts[poly.start() + j]; + const int edge_i = data->corner_edges[poly.start() + j]; copy_v3_v3(bpoly->coords[j], data->targetCos[vert_i]); /* Find corner and edge indices within poly loop array */ if (vert_i == nearest) { bpoly->corner_ind = j; - bpoly->edge_vert_inds[0] = (j == 0) ? (poly.totloop - 1) : (j - 1); - bpoly->edge_vert_inds[1] = (j == poly.totloop - 1) ? (0) : (j + 1); + bpoly->edge_vert_inds[0] = (j == 0) ? (poly.size() - 1) : (j - 1); + bpoly->edge_vert_inds[1] = (j == poly.size() - 1) ? (0) : (j + 1); - bpoly->edge_inds[0] = data->corner_edges[poly.loopstart + bpoly->edge_vert_inds[0]]; + bpoly->edge_inds[0] = data->corner_edges[poly.start() + bpoly->edge_vert_inds[0]]; bpoly->edge_inds[1] = edge_i; } } /* Compute polygons parametric data. */ - mid_v3_v3_array(bpoly->centroid, bpoly->coords, poly.totloop); - normal_poly_v3(bpoly->normal, bpoly->coords, poly.totloop); + mid_v3_v3_array(bpoly->centroid, bpoly->coords, poly.size()); + normal_poly_v3(bpoly->normal, bpoly->coords, poly.size()); /* Compute poly skew angle and axis */ angle = angle_normalized_v3v3(bpoly->normal, world); @@ -593,12 +591,12 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, map_to_plane_axis_angle_v2_v3v3fl(bpoly->point_v2, point_co, axis, angle); zero_v2(bpoly->centroid_v2); - for (int j = 0; j < poly.totloop; j++) { + for (int j = 0; j < poly.size(); j++) { map_to_plane_axis_angle_v2_v3v3fl(bpoly->coords_v2[j], bpoly->coords[j], axis, angle); - madd_v2_v2fl(bpoly->centroid_v2, bpoly->coords_v2[j], 1.0f / poly.totloop); + madd_v2_v2fl(bpoly->centroid_v2, bpoly->coords_v2[j], 1.0f / poly.size()); } - is_poly_valid = isPolyValid(bpoly->coords_v2, poly.totloop); + is_poly_valid = isPolyValid(bpoly->coords_v2, poly.size()); if (is_poly_valid != MOD_SDEF_BIND_RESULT_SUCCESS) { freeBindData(bwdata); @@ -606,8 +604,7 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, return nullptr; } - bpoly->inside = isect_point_poly_v2( - bpoly->point_v2, bpoly->coords_v2, poly.totloop, false); + bpoly->inside = isect_point_poly_v2(bpoly->point_v2, bpoly->coords_v2, poly.size(), false); /* Initialize weight components */ bpoly->weight_angular = 1.0f; @@ -1180,7 +1177,7 @@ static bool surfacedeformBind(Object *ob, BVHTreeFromMesh treeData = {nullptr}; const float(*positions)[3] = BKE_mesh_vert_positions(target); const blender::Span edges = target->edges(); - const blender::Span polys = target->polys(); + const blender::OffsetIndices polys = target->polys(); const blender::Span corner_verts = target->corner_verts(); const blender::Span corner_edges = target->corner_edges(); uint tedges_num = target->totedge; diff --git a/source/blender/modifiers/intern/MOD_util.cc b/source/blender/modifiers/intern/MOD_util.cc index 0e2340b1e9c..f1080f76d47 100644 --- a/source/blender/modifiers/intern/MOD_util.cc +++ b/source/blender/modifiers/intern/MOD_util.cc @@ -94,7 +94,7 @@ void MOD_get_texture_coords(MappingInfoModifierData *dmd, /* UVs need special handling, since they come from faces */ if (texmapping == MOD_DISP_MAP_UV) { if (CustomData_has_layer(&mesh->ldata, CD_PROP_FLOAT2)) { - const blender::Span polys = mesh->polys(); + const OffsetIndices polys = mesh->polys(); const Span corner_verts = mesh->corner_verts(); BLI_bitmap *done = BLI_BITMAP_NEW(verts_num, __func__); char uvname[MAX_CUSTOMDATA_LAYER_NAME]; @@ -104,11 +104,11 @@ void MOD_get_texture_coords(MappingInfoModifierData *dmd, /* verts are given the UV from the first face that uses them */ for (const int i : polys.index_range()) { - const MPoly &poly = polys[i]; - uint fidx = poly.totloop - 1; + const IndexRange poly = polys[i]; + uint fidx = poly.size() - 1; do { - uint lidx = poly.loopstart + fidx; + uint lidx = poly.start() + fidx; const int vidx = corner_verts[lidx]; if (!BLI_BITMAP_TEST(done, vidx)) { diff --git a/source/blender/modifiers/intern/MOD_uvproject.cc b/source/blender/modifiers/intern/MOD_uvproject.cc index 984ebb9fcfc..4cee9d70a4e 100644 --- a/source/blender/modifiers/intern/MOD_uvproject.cc +++ b/source/blender/modifiers/intern/MOD_uvproject.cc @@ -182,7 +182,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, } const blender::Span positions = mesh->vert_positions(); - const blender::Span polys = mesh->polys(); + const blender::OffsetIndices polys = mesh->polys(); const Span corner_verts = mesh->corner_verts(); float(*mloop_uv)[2] = static_cast(CustomData_get_layer_named_for_write( @@ -204,12 +204,12 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, /* apply coords as UVs */ for (const int i : polys.index_range()) { - const MPoly &poly = polys[i]; + const blender::IndexRange poly = polys[i]; if (projectors_num == 1) { if (projectors[0].uci) { - uint fidx = poly.totloop - 1; + uint fidx = poly.size() - 1; do { - uint lidx = poly.loopstart + fidx; + uint lidx = poly.start() + fidx; const int vidx = corner_verts[lidx]; BLI_uvproject_from_camera( mloop_uv[lidx], coords[vidx], static_cast(projectors[0].uci)); @@ -217,9 +217,9 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, } else { /* apply transformed coords as UVs */ - uint fidx = poly.totloop - 1; + uint fidx = poly.size() - 1; do { - uint lidx = poly.loopstart + fidx; + uint lidx = poly.start() + fidx; const int vidx = corner_verts[lidx]; copy_v2_v2(mloop_uv[lidx], coords[vidx]); } while (fidx--); @@ -233,7 +233,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, /* get the untransformed face normal */ const blender::float3 face_no = blender::bke::mesh::poly_normal_calc( - positions, corner_verts.slice(poly.loopstart, poly.totloop)); + positions, corner_verts.slice(poly)); /* find the projector which the face points at most directly * (projector normal with largest dot product is best) @@ -250,18 +250,18 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, } if (best_projector->uci) { - uint fidx = poly.totloop - 1; + uint fidx = poly.size() - 1; do { - uint lidx = poly.loopstart + fidx; + uint lidx = poly.start() + fidx; const int vidx = corner_verts[lidx]; BLI_uvproject_from_camera( mloop_uv[lidx], coords[vidx], static_cast(best_projector->uci)); } while (fidx--); } else { - uint fidx = poly.totloop - 1; + uint fidx = poly.size() - 1; do { - uint lidx = poly.loopstart + fidx; + uint lidx = poly.start() + fidx; const int vidx = corner_verts[lidx]; mul_v2_project_m4_v3(mloop_uv[lidx], best_projector->projmat, coords[vidx]); } while (fidx--); diff --git a/source/blender/modifiers/intern/MOD_uvwarp.cc b/source/blender/modifiers/intern/MOD_uvwarp.cc index 562ff538654..a1333ee013d 100644 --- a/source/blender/modifiers/intern/MOD_uvwarp.cc +++ b/source/blender/modifiers/intern/MOD_uvwarp.cc @@ -80,7 +80,7 @@ static void matrix_from_obj_pchan(float mat[4][4], Object *ob, const char *bonen } struct UVWarpData { - blender::Span polys; + blender::OffsetIndices polys; blender::Span corner_verts; float (*mloopuv)[2]; @@ -96,10 +96,10 @@ static void uv_warp_compute(void *__restrict userdata, const TaskParallelTLS *__restrict /*tls*/) { const UVWarpData *data = static_cast(userdata); + const blender::IndexRange poly = data->polys[i]; + const blender::Span poly_verts = data->corner_verts.slice(poly); - const MPoly &poly = data->polys[i]; - const int *poly_verts = &data->corner_verts[poly.loopstart]; - float(*mluv)[2] = &data->mloopuv[poly.loopstart]; + float(*mluv)[2] = &data->mloopuv[poly.start()]; const MDeformVert *dvert = data->dvert; const int defgrp_index = data->defgrp_index; @@ -109,7 +109,7 @@ static void uv_warp_compute(void *__restrict userdata, int l; if (dvert) { - for (l = 0; l < poly.totloop; l++, mluv++) { + for (l = 0; l < poly.size(); l++, mluv++) { const int vert_i = poly_verts[l]; float uv[2]; const float weight = data->invert_vgroup ? @@ -121,7 +121,7 @@ static void uv_warp_compute(void *__restrict userdata, } } else { - for (l = 0; l < poly.totloop; l++, mluv++) { + for (l = 0; l < poly.size(); l++, mluv++) { uv_warp_from_mat4_pair(*mluv, *mluv, warp_mat); } } @@ -192,7 +192,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* make sure we're using an existing layer */ CustomData_validate_layer_name(&mesh->ldata, CD_PROP_FLOAT2, umd->uvlayer_name, uvname); - const blender::Span polys = mesh->polys(); + const blender::OffsetIndices polys = mesh->polys(); const blender::Span corner_verts = mesh->corner_verts(); float(*mloopuv)[2] = static_cast(CustomData_get_layer_named_for_write( diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.cc b/source/blender/modifiers/intern/MOD_weighted_normal.cc index fa2147f6615..40ef86b7488 100644 --- a/source/blender/modifiers/intern/MOD_weighted_normal.cc +++ b/source/blender/modifiers/intern/MOD_weighted_normal.cc @@ -82,7 +82,7 @@ struct WeightedNormalData { bool has_clnors; /* True if clnors already existed, false if we had to create them. */ float split_angle; - blender::Span polys; + blender::OffsetIndices polys; blender::Span poly_normals; const bool *sharp_faces; const int *poly_strength; @@ -187,7 +187,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, const blender::Span positions = wn_data->vert_positions; const blender::Span edges = wn_data->edges; - const blender::Span polys = wn_data->polys; + const blender::OffsetIndices polys = wn_data->polys; const blender::Span corner_verts = wn_data->corner_verts; const blender::Span corner_edges = wn_data->corner_edges; @@ -245,12 +245,11 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, * to its smooth fan of loops (aka lnor space). */ int item_index = 0; for (const int i : polys.index_range()) { - for (const int ml_index : blender::IndexRange(polys[i].loopstart, polys[i].totloop)) { + for (const int ml_index : polys[i]) { if (BLI_BITMAP_TEST(done_loops, ml_index)) { /* Smooth fan of this loop has already been processed, skip it. */ continue; } - BLI_assert(item_index < items_num); WeightedNormalDataAggregateItem *itdt = &items_data[item_index]; itdt->curr_strength = FACE_STRENGTH_WEAK; @@ -292,9 +291,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, const int poly_index = mode_pair[i].index; const float mp_val = mode_pair[i].val; - int ml_index = polys[poly_index].loopstart; - const int ml_index_end = ml_index + polys[poly_index].totloop; - for (; ml_index < ml_index_end; ml_index++) { + for (const int ml_index : polys[poly_index]) { const int mv_index = corner_verts[ml_index]; WeightedNormalDataAggregateItem *item_data = keep_sharp ? static_cast( @@ -434,16 +431,15 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, static void wn_face_area(WeightedNormalModifierData *wnmd, WeightedNormalData *wn_data) { const blender::Span positions = wn_data->vert_positions; - const blender::Span polys = wn_data->polys; + const blender::OffsetIndices polys = wn_data->polys; const blender::Span corner_verts = wn_data->corner_verts; ModePair *face_area = static_cast( - MEM_malloc_arrayN(size_t(polys.size()), sizeof(*face_area), __func__)); + MEM_malloc_arrayN(polys.size(), sizeof(*face_area), __func__)); ModePair *f_area = face_area; for (const int i : polys.index_range()) { - f_area[i].val = blender::bke::mesh::poly_area_calc( - positions, corner_verts.slice(polys[i].loopstart, polys[i].totloop)); + f_area[i].val = blender::bke::mesh::poly_area_calc(positions, corner_verts.slice(polys[i])); f_area[i].index = i; } @@ -456,22 +452,22 @@ static void wn_face_area(WeightedNormalModifierData *wnmd, WeightedNormalData *w static void wn_corner_angle(WeightedNormalModifierData *wnmd, WeightedNormalData *wn_data) { const blender::Span positions = wn_data->vert_positions; - const blender::Span polys = wn_data->polys; + const blender::OffsetIndices polys = wn_data->polys; const blender::Span corner_verts = wn_data->corner_verts; ModePair *corner_angle = static_cast( MEM_malloc_arrayN(corner_verts.size(), sizeof(*corner_angle), __func__)); for (const int i : polys.index_range()) { - const MPoly &poly = polys[i]; + const blender::IndexRange poly = polys[i]; float *index_angle = static_cast( - MEM_malloc_arrayN(poly.totloop, sizeof(*index_angle), __func__)); + MEM_malloc_arrayN(poly.size(), sizeof(*index_angle), __func__)); blender::bke::mesh::poly_angles_calc( - positions, corner_verts.slice(poly.loopstart, poly.totloop), {index_angle, poly.totloop}); + positions, corner_verts.slice(poly), {index_angle, poly.size()}); - ModePair *c_angl = &corner_angle[poly.loopstart]; + ModePair *c_angl = &corner_angle[poly.start()]; float *angl = index_angle; - for (int ml_index = poly.loopstart; ml_index < poly.loopstart + poly.totloop; + for (int ml_index = poly.start(); ml_index < poly.start() + poly.size(); ml_index++, c_angl++, angl++) { c_angl->val = float(M_PI) - *angl; c_angl->index = ml_index; @@ -488,23 +484,23 @@ static void wn_corner_angle(WeightedNormalModifierData *wnmd, WeightedNormalData static void wn_face_with_angle(WeightedNormalModifierData *wnmd, WeightedNormalData *wn_data) { const blender::Span positions = wn_data->vert_positions; - const blender::Span polys = wn_data->polys; + const blender::OffsetIndices polys = wn_data->polys; const blender::Span corner_verts = wn_data->corner_verts; ModePair *combined = static_cast( MEM_malloc_arrayN(corner_verts.size(), sizeof(*combined), __func__)); for (const int i : polys.index_range()) { - const MPoly &poly = polys[i]; - const blender::Span poly_verts = corner_verts.slice(poly.loopstart, poly.totloop); + const blender::IndexRange poly = polys[i]; + const blender::Span poly_verts = corner_verts.slice(poly); const float face_area = blender::bke::mesh::poly_area_calc(positions, poly_verts); float *index_angle = static_cast( - MEM_malloc_arrayN(size_t(poly.totloop), sizeof(*index_angle), __func__)); - blender::bke::mesh::poly_angles_calc(positions, poly_verts, {index_angle, poly.totloop}); + MEM_malloc_arrayN(size_t(poly.size()), sizeof(*index_angle), __func__)); + blender::bke::mesh::poly_angles_calc(positions, poly_verts, {index_angle, poly.size()}); - ModePair *cmbnd = &combined[poly.loopstart]; + ModePair *cmbnd = &combined[poly.start()]; float *angl = index_angle; - for (int ml_index = poly.loopstart; ml_index < poly.loopstart + poly.totloop; + for (int ml_index = poly.start(); ml_index < poly.start() + poly.size(); ml_index++, cmbnd++, angl++) { /* In this case val is product of corner angle and face area. */ cmbnd->val = (float(M_PI) - *angl) * face_area; @@ -547,7 +543,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * const int verts_num = result->totvert; const blender::Span positions = mesh->vert_positions(); const blender::Span edges = mesh->edges(); - const blender::Span polys = mesh->polys(); + const OffsetIndices polys = result->polys(); const blender::Span corner_verts = mesh->corner_verts(); const blender::Span corner_edges = mesh->corner_edges(); @@ -584,8 +580,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * int defgrp_index; MOD_get_vgroup(ctx->object, mesh, wnmd->defgrp_name, &dvert, &defgrp_index); - const Array loop_to_poly_map = bke::mesh_topology::build_loop_to_poly_map(result->polys(), - result->totloop); + const Array loop_to_poly_map = bke::mesh_topology::build_loop_to_poly_map(result->polys()); bke::MutableAttributeAccessor attributes = result->attributes_for_write(); bke::SpanAttributeWriter sharp_edges = attributes.lookup_or_add_for_write_span( diff --git a/source/blender/nodes/geometry/nodes/node_geo_blur_attribute.cc b/source/blender/nodes/geometry/nodes/node_geo_blur_attribute.cc index 10cc6137926..7adbdce52cb 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_blur_attribute.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_blur_attribute.cc @@ -178,21 +178,20 @@ static Array> build_edge_to_edge_by_vert_map(const Span edges return map; } -static Array> build_face_to_edge_by_loop_map(const Span polys, +static Array> build_face_to_edge_by_loop_map(const OffsetIndices polys, const Span corner_edges, const int edges_num) { Array> map(edges_num); for (const int i : polys.index_range()) { - const MPoly &poly = polys[i]; - for (const int edge : corner_edges.slice(poly.loopstart, poly.totloop)) { + for (const int edge : corner_edges.slice(polys[i])) { map[edge].append(i); } } return map; } -static Array> build_face_to_face_by_edge_map(const Span polys, +static Array> build_face_to_face_by_edge_map(const OffsetIndices polys, const Span corner_edges, const int edges_num, const IndexMask poly_mask) @@ -203,8 +202,7 @@ static Array> build_face_to_face_by_edge_map(const Span polys threading::parallel_for(poly_mask.index_range(), 1024, [&](IndexRange range) { for (const int poly_i : poly_mask.slice(range)) { - const MPoly &poly = polys[poly_i]; - for (const int edge : corner_edges.slice(poly.loopstart, poly.totloop)) { + for (const int edge : corner_edges.slice(polys[poly_i])) { if (faces_by_edge[edge].size() > 1) { for (const int neighbor : faces_by_edge[edge]) { if (neighbor != poly_i) { @@ -234,7 +232,7 @@ static Array> create_mesh_map(const Mesh &mesh, return build_edge_to_edge_by_vert_map(edges, verts_num, mask); } case ATTR_DOMAIN_FACE: { - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const int edges_num = mesh.totedge; return build_face_to_face_by_edge_map(polys, mesh.corner_edges(), edges_num, mask); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc b/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc index 89d19905e74..201ce4beaaf 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc @@ -105,7 +105,7 @@ static Mesh *hull_from_bullet(const Mesh *mesh, Span coords) /* Copy faces. */ Array loops; int j = 0; - MutableSpan polys = result->polys_for_write(); + MutableSpan poly_offsets = result->poly_offsets_for_write(); MutableSpan mesh_corner_verts = result->corner_verts_for_write(); MutableSpan mesh_corner_edges = result->corner_edges_for_write(); int dst_corner = 0; @@ -119,9 +119,7 @@ static Mesh *hull_from_bullet(const Mesh *mesh, Span coords) loops.reinitialize(len); plConvexHullGetFaceLoops(hull, i, loops.data()); - MPoly &face = polys[i]; - face.loopstart = j; - face.totloop = len; + poly_offsets[i] = j; for (const int k : IndexRange(len)) { mesh_corner_verts[dst_corner] = corner_verts[loops[k]]; mesh_corner_edges[dst_corner] = corner_edges[loops[k]]; diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc index f0e6eafd662..9cdfba0f8cc 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc @@ -82,7 +82,7 @@ static Mesh *cdt_to_mesh(const meshintersect::CDT_result &result) Mesh *mesh = BKE_mesh_new_nomain(vert_len, edge_len, loop_len, poly_len); MutableSpan positions = mesh->vert_positions_for_write(); MutableSpan edges = mesh->edges_for_write(); - MutableSpan polys = mesh->polys_for_write(); + MutableSpan poly_offsets = mesh->poly_offsets_for_write(); MutableSpan corner_verts = mesh->corner_verts_for_write(); for (const int i : IndexRange(result.vert.size())) { @@ -94,8 +94,7 @@ static Mesh *cdt_to_mesh(const meshintersect::CDT_result &result) } int i_loop = 0; for (const int i : IndexRange(result.face.size())) { - polys[i].loopstart = i_loop; - polys[i].totloop = result.face[i].size(); + poly_offsets[i] = i_loop; for (const int j : result.face[i].index_range()) { corner_verts[i_loop] = result.face[i][j]; i_loop++; diff --git a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc index a4db785c644..e40597a2dfc 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc @@ -140,15 +140,12 @@ static void copy_face_corner_attributes(const Map const Span selected_poly_indices, const Mesh &mesh_in) { - const Span polys = mesh_in.polys(); + const OffsetIndices polys = mesh_in.polys(); Vector indices; indices.reserve(selected_loops_num); for (const int src_poly_index : selected_poly_indices) { - const MPoly &src_poly = polys[src_poly_index]; - const int src_loop_start = src_poly.loopstart; - const int tot_loop = src_poly.totloop; - for (const int i : IndexRange(tot_loop)) { - indices.append_unchecked(src_loop_start + i); + for (const int corner : polys[src_poly_index]) { + indices.append_unchecked(corner); } } copy_attributes_based_on_mask( @@ -205,30 +202,29 @@ static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh, Span masked_poly_indices, Span new_loop_starts) { - const Span src_polys = src_mesh.polys(); + const OffsetIndices src_polys = src_mesh.polys(); const Span src_corner_verts = src_mesh.corner_verts(); const Span src_corner_edges = src_mesh.corner_edges(); - MutableSpan dst_polys = dst_mesh.polys_for_write(); + MutableSpan dst_poly_offsets = dst_mesh.poly_offsets_for_write(); MutableSpan dst_corner_verts = dst_mesh.corner_verts_for_write(); MutableSpan dst_corner_edges = dst_mesh.corner_edges_for_write(); threading::parallel_for(masked_poly_indices.index_range(), 512, [&](const IndexRange range) { for (const int i_dst : range) { const int i_src = masked_poly_indices[i_dst]; - const MPoly &mp_src = src_polys[i_src]; - const int size = mp_src.totloop; - const Span src_poly_verts = src_corner_verts.slice(mp_src.loopstart, size); - const Span src_poly_edges = src_corner_edges.slice(mp_src.loopstart, size); + const IndexRange poly_src = src_polys[i_src]; + const Span src_poly_verts = src_corner_verts.slice(poly_src); + const Span src_poly_edges = src_corner_edges.slice(poly_src); - MPoly &mp_dst = dst_polys[i_dst]; - mp_dst = mp_src; - mp_dst.loopstart = new_loop_starts[i_dst]; - MutableSpan dst_poly_verts = dst_corner_verts.slice(mp_dst.loopstart, size); - MutableSpan dst_poly_edges = dst_corner_edges.slice(mp_dst.loopstart, size); + dst_poly_offsets[i_dst] = new_loop_starts[i_dst]; + MutableSpan dst_poly_verts = dst_corner_verts.slice(dst_poly_offsets[i_dst], + poly_src.size()); + MutableSpan dst_poly_edges = dst_corner_edges.slice(dst_poly_offsets[i_dst], + poly_src.size()); dst_poly_verts.copy_from(src_poly_verts); - for (const int i : IndexRange(size)) { + for (const int i : IndexRange(poly_src.size())) { dst_poly_edges[i] = edge_map[src_poly_edges[i]]; } } @@ -241,26 +237,25 @@ static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh, Span masked_poly_indices, Span new_loop_starts) { - const Span src_polys = src_mesh.polys(); + const OffsetIndices src_polys = src_mesh.polys(); const Span src_corner_verts = src_mesh.corner_verts(); const Span src_corner_edges = src_mesh.corner_edges(); - MutableSpan dst_polys = dst_mesh.polys_for_write(); + MutableSpan dst_poly_offsets = dst_mesh.poly_offsets_for_write(); MutableSpan dst_corner_verts = dst_mesh.corner_verts_for_write(); MutableSpan dst_corner_edges = dst_mesh.corner_edges_for_write(); threading::parallel_for(masked_poly_indices.index_range(), 512, [&](const IndexRange range) { for (const int i_dst : range) { const int i_src = masked_poly_indices[i_dst]; - const MPoly &mp_src = src_polys[i_src]; - const int size = mp_src.totloop; - const Span src_poly_verts = src_corner_verts.slice(mp_src.loopstart, size); - const Span src_poly_edges = src_corner_edges.slice(mp_src.loopstart, size); + const IndexRange poly_src = src_polys[i_src]; + const Span src_poly_verts = src_corner_verts.slice(poly_src); + const Span src_poly_edges = src_corner_edges.slice(poly_src); - MPoly &mp_dst = dst_polys[i_dst]; - mp_dst = mp_src; - mp_dst.loopstart = new_loop_starts[i_dst]; - MutableSpan dst_poly_verts = dst_corner_verts.slice(mp_dst.loopstart, size); - MutableSpan dst_poly_edges = dst_corner_edges.slice(mp_dst.loopstart, size); + dst_poly_offsets[i_dst] = new_loop_starts[i_dst]; + MutableSpan dst_poly_verts = dst_corner_verts.slice(dst_poly_offsets[i_dst], + poly_src.size()); + MutableSpan dst_poly_edges = dst_corner_edges.slice(dst_poly_offsets[i_dst], + poly_src.size()); dst_poly_verts.copy_from(src_poly_verts); dst_poly_edges.copy_from(src_poly_edges); @@ -275,31 +270,30 @@ static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh, Span masked_poly_indices, Span new_loop_starts) { - const Span src_polys = src_mesh.polys(); + const OffsetIndices src_polys = src_mesh.polys(); const Span src_corner_verts = src_mesh.corner_verts(); const Span src_corner_edges = src_mesh.corner_edges(); - MutableSpan dst_polys = dst_mesh.polys_for_write(); + MutableSpan dst_poly_offsets = dst_mesh.poly_offsets_for_write(); MutableSpan dst_corner_verts = dst_mesh.corner_verts_for_write(); MutableSpan dst_corner_edges = dst_mesh.corner_edges_for_write(); threading::parallel_for(masked_poly_indices.index_range(), 512, [&](const IndexRange range) { for (const int i_dst : range) { const int i_src = masked_poly_indices[i_dst]; - const MPoly &mp_src = src_polys[i_src]; - const int size = mp_src.totloop; - const Span src_poly_verts = src_corner_verts.slice(mp_src.loopstart, size); - const Span src_poly_edges = src_corner_edges.slice(mp_src.loopstart, size); + const IndexRange poly_src = src_polys[i_src]; + const Span src_poly_verts = src_corner_verts.slice(poly_src); + const Span src_poly_edges = src_corner_edges.slice(poly_src); - MPoly &mp_dst = dst_polys[i_dst]; - mp_dst = mp_src; - mp_dst.loopstart = new_loop_starts[i_dst]; - MutableSpan dst_poly_verts = dst_corner_verts.slice(mp_dst.loopstart, size); - MutableSpan dst_poly_edges = dst_corner_edges.slice(mp_dst.loopstart, size); + dst_poly_offsets[i_dst] = new_loop_starts[i_dst]; + MutableSpan dst_poly_verts = dst_corner_verts.slice(dst_poly_offsets[i_dst], + poly_src.size()); + MutableSpan dst_poly_edges = dst_corner_edges.slice(dst_poly_offsets[i_dst], + poly_src.size()); - for (const int i : IndexRange(size)) { + for (const int i : IndexRange(poly_src.size())) { dst_poly_verts[i] = vertex_map[src_poly_verts[i]]; } - for (const int i : IndexRange(size)) { + for (const int i : IndexRange(poly_src.size())) { dst_poly_edges[i] = edge_map[src_poly_edges[i]]; } } @@ -446,7 +440,7 @@ static void compute_selected_polys_from_vertex_selection(const Mesh &mesh, int *r_selected_loops_num) { BLI_assert(mesh.totvert == vertex_selection.size()); - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_verts = mesh.corner_verts(); r_selected_poly_indices.reserve(mesh.totpoly); @@ -454,10 +448,10 @@ static void compute_selected_polys_from_vertex_selection(const Mesh &mesh, int selected_loops_num = 0; for (const int i : polys.index_range()) { - const MPoly &poly_src = polys[i]; + const IndexRange poly_src = polys[i]; bool all_verts_in_selection = true; - for (const int vert : corner_verts.slice(poly_src.loopstart, poly_src.totloop)) { + for (const int vert : corner_verts.slice(poly_src)) { if (!vertex_selection[vert]) { all_verts_in_selection = false; break; @@ -467,7 +461,7 @@ static void compute_selected_polys_from_vertex_selection(const Mesh &mesh, if (all_verts_in_selection) { r_selected_poly_indices.append_unchecked(i); r_loop_starts.append_unchecked(selected_loops_num); - selected_loops_num += poly_src.totloop; + selected_loops_num += poly_src.size(); } } @@ -549,7 +543,7 @@ static void compute_selected_polys_from_edge_selection(const Mesh &mesh, int *r_selected_polys_num, int *r_selected_loops_num) { - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_edges = mesh.corner_edges(); r_selected_poly_indices.reserve(mesh.totpoly); @@ -557,10 +551,10 @@ static void compute_selected_polys_from_edge_selection(const Mesh &mesh, int selected_loops_num = 0; for (const int i : polys.index_range()) { - const MPoly &poly_src = polys[i]; + const IndexRange poly_src = polys[i]; bool all_edges_in_selection = true; - for (const int edge : corner_edges.slice(poly_src.loopstart, poly_src.totloop)) { + for (const int edge : corner_edges.slice(poly_src)) { if (!edge_selection[edge]) { all_edges_in_selection = false; break; @@ -570,7 +564,7 @@ static void compute_selected_polys_from_edge_selection(const Mesh &mesh, if (all_edges_in_selection) { r_selected_poly_indices.append_unchecked(i); r_loop_starts.append_unchecked(selected_loops_num); - selected_loops_num += poly_src.totloop; + selected_loops_num += poly_src.size(); } } @@ -719,19 +713,19 @@ static void compute_selected_polys_from_poly_selection(const Mesh &mesh, int *r_selected_loops_num) { BLI_assert(mesh.totpoly == poly_selection.size()); - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); r_selected_poly_indices.reserve(mesh.totpoly); r_loop_starts.reserve(mesh.totloop); int selected_loops_num = 0; for (const int i : polys.index_range()) { - const MPoly &poly_src = polys[i]; + const IndexRange poly_src = polys[i]; /* We keep this one. */ if (poly_selection[i]) { r_selected_poly_indices.append_unchecked(i); r_loop_starts.append_unchecked(selected_loops_num); - selected_loops_num += poly_src.totloop; + selected_loops_num += poly_src.size(); } } *r_selected_polys_num = r_selected_poly_indices.size(); @@ -753,7 +747,7 @@ static void compute_selected_mesh_data_from_poly_selection_edge_face( { BLI_assert(mesh.totpoly == poly_selection.size()); BLI_assert(mesh.totedge == r_edge_map.size()); - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_edges = mesh.corner_edges(); r_edge_map.fill(-1); @@ -764,15 +758,15 @@ static void compute_selected_mesh_data_from_poly_selection_edge_face( int selected_loops_num = 0; int selected_edges_num = 0; for (const int i : polys.index_range()) { - const MPoly &poly_src = polys[i]; + const IndexRange poly_src = polys[i]; /* We keep this one. */ if (poly_selection[i]) { r_selected_poly_indices.append_unchecked(i); r_loop_starts.append_unchecked(selected_loops_num); - selected_loops_num += poly_src.totloop; + selected_loops_num += poly_src.size(); /* Add the vertices and the edges. */ - for (const int edge : corner_edges.slice(poly_src.loopstart, poly_src.totloop)) { + for (const int edge : corner_edges.slice(poly_src)) { /* Check first if it has not yet been added. */ if (r_edge_map[edge] == -1) { r_edge_map[edge] = selected_edges_num; @@ -803,7 +797,7 @@ static void compute_selected_mesh_data_from_poly_selection(const Mesh &mesh, { BLI_assert(mesh.totpoly == poly_selection.size()); BLI_assert(mesh.totedge == r_edge_map.size()); - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_verts = mesh.corner_verts(); const Span corner_edges = mesh.corner_edges(); @@ -817,15 +811,15 @@ static void compute_selected_mesh_data_from_poly_selection(const Mesh &mesh, int selected_verts_num = 0; int selected_edges_num = 0; for (const int i : polys.index_range()) { - const MPoly &poly_src = polys[i]; + const IndexRange poly_src = polys[i]; /* We keep this one. */ if (poly_selection[i]) { r_selected_poly_indices.append_unchecked(i); r_loop_starts.append_unchecked(selected_loops_num); - selected_loops_num += poly_src.totloop; + selected_loops_num += poly_src.size(); /* Add the vertices and the edges. */ - for (const int corner : IndexRange(poly_src.loopstart, poly_src.totloop)) { + for (const int corner : poly_src) { const int vert = corner_verts[corner]; const int edge = corner_edges[corner]; /* Check first if it has not yet been added. */ diff --git a/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc index 44f20cbe2be..1ae7524f90d 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc @@ -210,7 +210,7 @@ static void calc_boundaries(const Mesh &mesh, BLI_assert(r_vertex_types.size() == mesh.totvert); BLI_assert(r_edge_types.size() == mesh.totedge); const Span edges = mesh.edges(); - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_edges = mesh.corner_edges(); r_vertex_types.fill(VertexType::Loose); @@ -218,8 +218,7 @@ static void calc_boundaries(const Mesh &mesh, /* Add up the number of polys connected to each edge. */ for (const int i : IndexRange(mesh.totpoly)) { - const MPoly &poly = polys[i]; - for (const int edge_i : corner_edges.slice(poly.loopstart, poly.totloop)) { + for (const int edge_i : corner_edges.slice(polys[i])) { r_edge_types[edge_i] = get_edge_type_with_added_neighbor(r_edge_types[edge_i]); } } @@ -312,7 +311,7 @@ static void calc_boundaries(const Mesh &mesh, * loop. */ static bool sort_vertex_polys(const Span edges, - const Span polys, + const OffsetIndices polys, const Span corner_verts, const Span corner_edges, const int vertex_index, @@ -329,9 +328,8 @@ static bool sort_vertex_polys(const Span edges, /* For each polygon store the two corners whose edge contains the vertex. */ Array> poly_vertex_corners(connected_polys.size()); for (const int i : connected_polys.index_range()) { - const MPoly &poly = polys[connected_polys[i]]; bool first_edge_done = false; - for (const int corner : IndexRange(poly.loopstart, poly.totloop)) { + for (const int corner : polys[connected_polys[i]]) { const int edge = corner_edges[corner]; if (edges[edge].v1 == vertex_index || edges[edge].v2 == vertex_index) { if (!first_edge_done) { @@ -450,14 +448,13 @@ static bool sort_vertex_polys(const Span edges, /** * Get the edge on the poly that contains the given vertex and is a boundary edge. */ -static void boundary_edge_on_poly(const MPoly &poly, - const Span edges, - const Span corner_edges, +static void boundary_edge_on_poly(const Span edges, + const Span poly_edges, const int vertex_index, const Span edge_types, int &r_edge) { - for (const int edge_i : corner_edges.slice(poly.loopstart, poly.totloop)) { + for (const int edge_i : poly_edges) { if (edge_types[edge_i] == EdgeType::Boundary) { const MEdge &edge = edges[edge_i]; if (edge.v1 == vertex_index || edge.v2 == vertex_index) { @@ -472,7 +469,7 @@ static void boundary_edge_on_poly(const MPoly &poly, * Get the two edges on the poly that contain the given vertex and are boundary edges. The * orientation of the poly is taken into account. */ -static void boundary_edges_on_poly(const MPoly &poly, +static void boundary_edges_on_poly(const IndexRange poly, const Span edges, const Span corner_verts, const Span corner_edges, @@ -485,7 +482,7 @@ static void boundary_edges_on_poly(const MPoly &poly, /* This is set to true if the order in which we encounter the two edges is inconsistent with the * orientation of the polygon. */ bool needs_swap = false; - for (const int corner : IndexRange(poly.loopstart, poly.totloop)) { + for (const int corner : poly) { const int edge_i = corner_edges[corner]; if (edge_types[edge_i] == EdgeType::Boundary) { const MEdge &edge = edges[edge_i]; @@ -549,7 +546,7 @@ static bool vertex_needs_dissolving(const int vertex, * edges being created. (See #94144) */ static void dissolve_redundant_verts(const Span edges, - const Span polys, + const OffsetIndices polys, const Span corner_edges, const Span> vert_to_poly_map, MutableSpan vertex_types, @@ -566,8 +563,7 @@ static void dissolve_redundant_verts(const Span edges, const int second_poly_index = vert_to_poly_map[vert_i][1]; const int new_edge_index = new_edges.size(); bool edge_created = false; - const MPoly &poly = polys[first_poly_index]; - for (const int edge_i : corner_edges.slice(poly.loopstart, poly.totloop)) { + for (const int edge_i : corner_edges.slice(polys[first_poly_index])) { const MEdge &edge = edges[edge_i]; const int v1 = edge.v1; const int v2 = edge.v2; @@ -620,7 +616,7 @@ static Mesh *calc_dual_mesh(const Mesh &src_mesh, { const Span src_positions = src_mesh.vert_positions(); const Span src_edges = src_mesh.edges(); - const Span src_polys = src_mesh.polys(); + const OffsetIndices src_polys = src_mesh.polys(); const Span src_corner_verts = src_mesh.corner_verts(); const Span src_corner_edges = src_mesh.corner_edges(); @@ -684,9 +680,8 @@ static Mesh *calc_dual_mesh(const Mesh &src_mesh, Vector vert_positions(src_mesh.totpoly); for (const int i : src_polys.index_range()) { - const MPoly &poly = src_polys[i]; - vert_positions[i] = bke::mesh::poly_center_calc( - src_positions, src_corner_verts.slice(poly.loopstart, poly.totloop)); + const IndexRange poly = src_polys[i]; + vert_positions[i] = bke::mesh::poly_center_calc(src_positions, src_corner_verts.slice(poly)); } Array boundary_edge_midpoint_index; @@ -814,10 +809,16 @@ static Mesh *calc_dual_mesh(const Mesh &src_mesh, int edge2; if (loop_indices.size() >= 2) { /* The first boundary edge is at the end of the chain of polygons. */ - boundary_edge_on_poly( - src_polys[loop_indices.last()], src_edges, src_corner_edges, i, edge_types, edge1); - boundary_edge_on_poly( - src_polys[loop_indices.first()], src_edges, src_corner_edges, i, edge_types, edge2); + boundary_edge_on_poly(src_edges, + src_corner_edges.slice(src_polys[loop_indices.last()]), + i, + edge_types, + edge1); + boundary_edge_on_poly(src_edges, + src_corner_edges.slice(src_polys[loop_indices.first()]), + i, + edge_types, + edge2); } else { /* If there is only one polygon both edges are in that polygon. */ @@ -911,19 +912,16 @@ static Mesh *calc_dual_mesh(const Mesh &src_mesh, mesh_out->attributes_for_write()); mesh_out->vert_positions_for_write().copy_from(vert_positions); - MutableSpan dst_edges = mesh_out->edges_for_write(); - MutableSpan dst_polys = mesh_out->polys_for_write(); + mesh_out->edges_for_write().copy_from(new_edges); - int loop_start = 0; - for (const int i : IndexRange(mesh_out->totpoly)) { - dst_polys[i].loopstart = loop_start; - dst_polys[i].totloop = loop_lengths[i]; - loop_start += loop_lengths[i]; + if (mesh_out->totpoly > 0) { + MutableSpan dst_poly_offsets = mesh_out->poly_offsets_for_write(); + dst_poly_offsets.drop_back(1).copy_from(loop_lengths); + offset_indices::accumulate_counts_to_offsets(dst_poly_offsets); } mesh_out->corner_verts_for_write().copy_from(loops); mesh_out->corner_edges_for_write().copy_from(loop_edges); - dst_edges.copy_from(new_edges); return mesh_out; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc index 476a81a58dc..de8dc3a510f 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc @@ -449,16 +449,16 @@ static void copy_stable_id_faces(const Mesh &mesh, VArraySpan src{src_attribute.varray.typed()}; MutableSpan dst = dst_attribute.span.typed(); - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); int loop_index = 0; for (const int i_poly : selection.index_range()) { const IndexRange range = poly_offsets[i_poly]; if (range.size() == 0) { continue; } - const MPoly &source = polys[i_poly]; + const IndexRange source = polys[i_poly]; for ([[maybe_unused]] const int i_duplicate : IndexRange(range.size())) { - for ([[maybe_unused]] const int i_loops : IndexRange(source.totloop)) { + for ([[maybe_unused]] const int i_loops : IndexRange(source.size())) { if (i_duplicate == 0) { dst[loop_index] = src[vert_mapping[loop_index]]; } @@ -487,7 +487,7 @@ static void duplicate_faces(GeometrySet &geometry_set, const Mesh &mesh = *geometry_set.get_mesh_for_read(); const Span edges = mesh.edges(); - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_verts = mesh.corner_verts(); const Span corner_edges = mesh.corner_edges(); @@ -506,7 +506,7 @@ static void duplicate_faces(GeometrySet &geometry_set, const int count = counts[selection[i_selection]]; offset_data[i_selection] = total_polys; total_polys += count; - total_loops += count * polys[selection[i_selection]].totloop; + total_loops += count * polys[selection[i_selection]].size(); } offset_data[selection.size()] = total_polys; @@ -514,7 +514,7 @@ static void duplicate_faces(GeometrySet &geometry_set, Mesh *new_mesh = BKE_mesh_new_nomain(total_loops, total_loops, total_loops, total_polys); MutableSpan new_edges = new_mesh->edges_for_write(); - MutableSpan new_polys = new_mesh->polys_for_write(); + MutableSpan new_poly_offsets = new_mesh->poly_offsets_for_write(); MutableSpan new_corner_verts = new_mesh->corner_verts_for_write(); MutableSpan new_corner_edges = new_mesh->corner_edges_for_write(); @@ -527,22 +527,21 @@ static void duplicate_faces(GeometrySet &geometry_set, for (const int i_selection : selection.index_range()) { const IndexRange poly_range = duplicates[i_selection]; - const MPoly &source = polys[selection[i_selection]]; + const IndexRange source = polys[selection[i_selection]]; for ([[maybe_unused]] const int i_duplicate : IndexRange(poly_range.size())) { - new_polys[poly_index] = source; - new_polys[poly_index].loopstart = loop_index; - for (const int i_loops : IndexRange(source.totloop)) { - const int src_corner = source.loopstart + i_loops; + new_poly_offsets[poly_index] = loop_index; + for (const int i_loops : IndexRange(source.size())) { + const int src_corner = source[i_loops]; loop_mapping[loop_index] = src_corner; vert_mapping[loop_index] = corner_verts[src_corner]; new_edges[loop_index] = edges[corner_edges[src_corner]]; edge_mapping[loop_index] = corner_edges[src_corner]; new_edges[loop_index].v1 = loop_index; - if (i_loops + 1 != source.totloop) { + if (i_loops + 1 != source.size()) { new_edges[loop_index].v2 = loop_index + 1; } else { - new_edges[loop_index].v2 = new_polys[poly_index].loopstart; + new_edges[loop_index].v2 = new_poly_offsets[poly_index]; } new_corner_verts[loop_index] = loop_index; new_corner_edges[loop_index] = loop_index; diff --git a/source/blender/nodes/geometry/nodes/node_geo_edges_to_face_groups.cc b/source/blender/nodes/geometry/nodes/node_geo_edges_to_face_groups.cc index 7d6b55a3085..cf3309aa7db 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_edges_to_face_groups.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_edges_to_face_groups.cc @@ -52,7 +52,7 @@ class FaceSetFromBoundariesInput final : public bke::MeshFieldInput { evaluator.evaluate(); const IndexMask non_boundary_edges = evaluator.get_evaluated_as_mask(0); - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Array> edge_to_face_map = bke::mesh_topology::build_edge_to_poly_map( polys, mesh.corner_edges(), mesh.totedge); diff --git a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc index 71c3ecbee37..dbdc28d8d16 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc @@ -108,6 +108,9 @@ static void expand_mesh(Mesh &mesh, const int old_polys_num = mesh.totpoly; mesh.totpoly += poly_expand; CustomData_realloc(&mesh.pdata, old_polys_num, mesh.totpoly); + mesh.poly_offset_indices = static_cast( + MEM_reallocN(mesh.poly_offset_indices, sizeof(int) * (mesh.totpoly + 1))); + mesh.poly_offsets_for_write().last() = mesh.totloop + loop_expand; } if (loop_expand != 0) { const int old_loops_num = mesh.totloop; @@ -155,14 +158,6 @@ static MEdge new_edge(const int v1, const int v2) return edge; } -static MPoly new_poly(const int loopstart, const int totloop) -{ - MPoly poly; - poly.loopstart = loopstart; - poly.totloop = totloop; - return poly; -} - /** * \param get_mix_indices_fn: Returns a Span of indices of the source points to mix for every * result point. @@ -356,7 +351,7 @@ static void extrude_mesh_edges(Mesh &mesh, { const int orig_vert_size = mesh.totvert; const Span orig_edges = mesh.edges(); - const Span orig_polys = mesh.polys(); + const OffsetIndices orig_polys = mesh.polys(); const int orig_loop_size = mesh.totloop; const bke::MeshFieldContext edge_context{mesh, ATTR_DOMAIN_EDGE}; @@ -409,13 +404,17 @@ static void extrude_mesh_edges(Mesh &mesh, MutableSpan edges = mesh.edges_for_write(); MutableSpan connect_edges = edges.slice(connect_edge_range); MutableSpan duplicate_edges = edges.slice(duplicate_edge_range); - MutableSpan polys = mesh.polys_for_write(); - MutableSpan new_polys = polys.slice(new_poly_range); + MutableSpan poly_offsets = mesh.poly_offsets_for_write(); + MutableSpan new_poly_offsets = poly_offsets.slice(new_poly_range); MutableSpan corner_verts = mesh.corner_verts_for_write(); MutableSpan new_corner_verts = corner_verts.slice(new_loop_range); MutableSpan corner_edges = mesh.corner_edges_for_write(); MutableSpan new_corner_edges = corner_edges.slice(new_loop_range); + new_poly_offsets.fill(4); + offset_indices::accumulate_counts_to_offsets(new_poly_offsets, orig_loop_size); + const OffsetIndices polys = mesh.polys(); + for (const int i : connect_edges.index_range()) { connect_edges[i] = new_edge(new_vert_indices[i], new_vert_range[i]); } @@ -427,10 +426,6 @@ static void extrude_mesh_edges(Mesh &mesh, duplicate_edges[i] = new_edge(new_vert_range[i_new_vert_1], new_vert_range[i_new_vert_2]); } - for (const int i : new_polys.index_range()) { - new_polys[i] = new_poly(new_loop_range[i * 4], 4); - } - for (const int i : edge_selection.index_range()) { const int orig_edge_index = edge_selection[i]; @@ -448,9 +443,9 @@ static void extrude_mesh_edges(Mesh &mesh, Span connected_poly_verts = {}; Span connected_poly_edges = {}; if (connected_polys.size() == 1) { - const MPoly &connected_poly = polys[connected_polys.first()]; - connected_poly_verts = corner_verts.slice(connected_poly.loopstart, connected_poly.totloop); - connected_poly_edges = corner_edges.slice(connected_poly.loopstart, connected_poly.totloop); + const IndexRange connected_poly = polys[connected_polys.first()]; + connected_poly_verts = corner_verts.slice(connected_poly); + connected_poly_edges = corner_edges.slice(connected_poly); } fill_quad_consistent_direction(connected_poly_verts, connected_poly_edges, @@ -545,9 +540,8 @@ static void extrude_mesh_edges(Mesh &mesh, /* Average the corner data from the corners that share a vertex from the * polygons that share an edge with the extruded edge. */ for (const int i_connected_poly : connected_polys.index_range()) { - const MPoly &connected_poly = polys[connected_polys[i_connected_poly]]; - for (const int i_loop : - IndexRange(connected_poly.loopstart, connected_poly.totloop)) { + const IndexRange connected_poly = polys[connected_polys[i_connected_poly]]; + for (const int i_loop : IndexRange(connected_poly)) { if (corner_verts[i_loop] == orig_vert_1) { mixer.mix_in(0, data[i_loop]); } @@ -641,8 +635,9 @@ static void extrude_mesh_face_regions(Mesh &mesh, { const int orig_vert_size = mesh.totvert; const Span orig_edges = mesh.edges(); - const Span orig_polys = mesh.polys(); + const OffsetIndices orig_polys = mesh.polys(); const Span orig_corner_verts = mesh.corner_verts(); + const int orig_loop_size = orig_corner_verts.size(); const bke::MeshFieldContext poly_context{mesh, ATTR_DOMAIN_FACE}; FieldEvaluator poly_evaluator{poly_context, mesh.totpoly}; @@ -650,7 +645,7 @@ static void extrude_mesh_face_regions(Mesh &mesh, poly_evaluator.add(offset_field); poly_evaluator.evaluate(); const IndexMask poly_selection = poly_evaluator.get_evaluated_selection_as_mask(); - const VArray poly_offsets = poly_evaluator.get_evaluated(0); + const VArray poly_position_offsets = poly_evaluator.get_evaluated(0); if (poly_selection.is_empty()) { return; } @@ -664,13 +659,12 @@ static void extrude_mesh_face_regions(Mesh &mesh, * in order to be consistent with the selection, and to use the face normals rather than vertex * normals as an offset, for example. */ Array vert_offsets; - if (!poly_offsets.is_single()) { + if (!poly_position_offsets.is_single()) { vert_offsets.reinitialize(orig_vert_size); attribute_math::DefaultPropagationMixer mixer(vert_offsets); for (const int i_poly : poly_selection) { - const MPoly &poly = orig_polys[i_poly]; - const float3 offset = poly_offsets[i_poly]; - for (const int vert : orig_corner_verts.slice(poly.loopstart, poly.totloop)) { + const float3 offset = poly_position_offsets[i_poly]; + for (const int vert : orig_corner_verts.slice(orig_polys[i_poly])) { mixer.mix_in(vert, offset); } } @@ -686,8 +680,7 @@ static void extrude_mesh_face_regions(Mesh &mesh, VectorSet all_selected_verts; all_selected_verts.reserve(orig_polys.size()); for (const int i_poly : poly_selection) { - const MPoly &poly = orig_polys[i_poly]; - for (const int vert : orig_corner_verts.slice(poly.loopstart, poly.totloop)) { + for (const int vert : orig_corner_verts.slice(orig_polys[i_poly])) { all_selected_verts.add(vert); } } @@ -774,13 +767,18 @@ static void extrude_mesh_face_regions(Mesh &mesh, MutableSpan connect_edges = edges.slice(connect_edge_range); MutableSpan boundary_edges = edges.slice(boundary_edge_range); MutableSpan new_inner_edges = edges.slice(new_inner_edge_range); - MutableSpan polys = mesh.polys_for_write(); - MutableSpan new_polys = polys.slice(side_poly_range); + MutableSpan poly_offsets = mesh.poly_offsets_for_write(); + MutableSpan new_poly_offsets = poly_offsets.slice(side_poly_range); MutableSpan corner_verts = mesh.corner_verts_for_write(); MutableSpan new_corner_verts = corner_verts.slice(side_loop_range); MutableSpan corner_edges = mesh.corner_edges_for_write(); MutableSpan new_corner_edges = corner_edges.slice(side_loop_range); + /* Initialize the new side polygons. */ + new_poly_offsets.fill(4); + offset_indices::accumulate_counts_to_offsets(new_poly_offsets, orig_loop_size); + const OffsetIndices polys = mesh.polys(); + /* Initialize the edges that form the sides of the extrusion. */ for (const int i : connect_edges.index_range()) { connect_edges[i] = new_edge(new_vert_indices[i], new_vert_range[i]); @@ -802,11 +800,6 @@ static void extrude_mesh_face_regions(Mesh &mesh, new_inner_edges[i] = new_edge(new_vert_range[i_new_vert_1], new_vert_range[i_new_vert_2]); } - /* Initialize the new side polygons. */ - for (const int i : new_polys.index_range()) { - new_polys[i] = new_poly(side_loop_range[i * 4], 4); - } - /* Connect original edges inside face regions to any new vertices, if necessary. */ for (const int i : inner_edge_indices) { MEdge &edge = edges[i]; @@ -822,8 +815,7 @@ static void extrude_mesh_face_regions(Mesh &mesh, /* Connect the selected faces to the extruded or duplicated edges and the new vertices. */ for (const int i_poly : poly_selection) { - const MPoly &poly = polys[i_poly]; - for (const int corner : IndexRange(poly.loopstart, poly.totloop)) { + for (const int corner : polys[i_poly]) { const int i_new_vert = new_vert_indices.index_of_try(corner_verts[corner]); if (i_new_vert != -1) { corner_verts[corner] = new_vert_range[i_new_vert]; @@ -849,21 +841,20 @@ static void extrude_mesh_face_regions(Mesh &mesh, const int extrude_index_1 = new_vert_1 - orig_vert_size; const int extrude_index_2 = new_vert_2 - orig_vert_size; - const MPoly &extrude_poly = polys[edge_extruded_face_indices[i]]; + const IndexRange extrude_poly = polys[edge_extruded_face_indices[i]]; - fill_quad_consistent_direction( - corner_verts.slice(extrude_poly.loopstart, extrude_poly.totloop), - corner_edges.slice(extrude_poly.loopstart, extrude_poly.totloop), - new_corner_verts.slice(4 * i, 4), - new_corner_edges.slice(4 * i, 4), - new_vert_1, - new_vert_2, - new_vert_indices[extrude_index_1], - new_vert_indices[extrude_index_2], - boundary_edge_range[i], - connect_edge_range[extrude_index_1], - boundary_edge_indices[i], - connect_edge_range[extrude_index_2]); + fill_quad_consistent_direction(corner_verts.slice(extrude_poly), + corner_edges.slice(extrude_poly), + new_corner_verts.slice(4 * i, 4), + new_corner_edges.slice(4 * i, 4), + new_vert_1, + new_vert_2, + new_vert_indices[extrude_index_1], + new_vert_indices[extrude_index_2], + boundary_edge_range[i], + connect_edge_range[extrude_index_1], + boundary_edge_indices[i], + connect_edge_range[extrude_index_2]); } /* Create a map of indices in the extruded vertices array to all of the indices of edges @@ -923,8 +914,6 @@ static void extrude_mesh_face_regions(Mesh &mesh, threading::parallel_for( boundary_edge_indices.index_range(), 256, [&](const IndexRange range) { for (const int i_boundary_edge : range) { - const MPoly &poly = polys[edge_extruded_face_indices[i_boundary_edge]]; - const MEdge &boundary_edge = boundary_edges[i_boundary_edge]; const int new_vert_1 = boundary_edge.v1; const int new_vert_2 = boundary_edge.v2; @@ -938,7 +927,7 @@ static void extrude_mesh_face_regions(Mesh &mesh, * face). */ T data_1; T data_2; - for (const int i_loop : IndexRange(poly.loopstart, poly.totloop)) { + for (const int i_loop : polys[edge_extruded_face_indices[i_boundary_edge]]) { if (corner_verts[i_loop] == new_vert_1) { data_1 = data[i_loop]; } @@ -975,8 +964,8 @@ static void extrude_mesh_face_regions(Mesh &mesh, * have been duplicated and only the new vertex should use the offset. Otherwise the vertex might * still need an offset, but it was reused on the inside of a region of extruded faces. */ MutableSpan positions = mesh.vert_positions_for_write(); - if (poly_offsets.is_single()) { - const float3 offset = poly_offsets.get_internal_single(); + if (poly_position_offsets.is_single()) { + const float3 offset = poly_position_offsets.get_internal_single(); threading::parallel_for( IndexRange(all_selected_verts.size()), 1024, [&](const IndexRange range) { for (const int i_orig : all_selected_verts.as_span().slice(range)) { @@ -1058,8 +1047,9 @@ static void extrude_individual_mesh_faces(Mesh &mesh, { const int orig_vert_size = mesh.totvert; const int orig_edge_size = mesh.totedge; - const Span orig_polys = mesh.polys(); + const OffsetIndices orig_polys = mesh.polys(); const Span orig_corner_verts = mesh.corner_verts(); + const int orig_loop_size = orig_corner_verts.size(); /* Use a mesh for the result of the evaluation because the mesh is reallocated before * the vertices are moved, and the evaluated result might reference an attribute. */ @@ -1077,9 +1067,8 @@ static void extrude_individual_mesh_faces(Mesh &mesh, int extrude_corner_size = 0; Array index_offsets(poly_selection.size() + 1); for (const int i_selection : poly_selection.index_range()) { - const MPoly &poly = orig_polys[poly_selection[i_selection]]; index_offsets[i_selection] = extrude_corner_size; - extrude_corner_size += poly.totloop; + extrude_corner_size += orig_polys[poly_selection[i_selection]].size(); } index_offsets.last() = extrude_corner_size; @@ -1090,7 +1079,7 @@ static void extrude_individual_mesh_faces(Mesh &mesh, const IndexRange duplicate_edge_range = connect_edge_range.after(extrude_corner_size); /* Each edge selected for extrusion is extruded into a single face. */ const IndexRange side_poly_range{orig_polys.size(), duplicate_edge_range.size()}; - const IndexRange side_loop_range{orig_corner_verts.size(), side_poly_range.size() * 4}; + const IndexRange side_loop_range{orig_loop_size, side_poly_range.size() * 4}; expand_mesh(mesh, new_vert_range.size(), @@ -1102,11 +1091,15 @@ static void extrude_individual_mesh_faces(Mesh &mesh, MutableSpan edges = mesh.edges_for_write(); MutableSpan connect_edges = edges.slice(connect_edge_range); MutableSpan duplicate_edges = edges.slice(duplicate_edge_range); - MutableSpan polys = mesh.polys_for_write(); - MutableSpan new_polys = polys.slice(side_poly_range); + MutableSpan poly_offsets = mesh.poly_offsets_for_write(); + MutableSpan new_poly_offsets = poly_offsets.slice(side_poly_range); MutableSpan corner_verts = mesh.corner_verts_for_write(); MutableSpan corner_edges = mesh.corner_edges_for_write(); + new_poly_offsets.fill(4); + offset_indices::accumulate_counts_to_offsets(new_poly_offsets, orig_loop_size); + const OffsetIndices polys = mesh.polys(); + /* For every selected polygon, change it to use the new extruded vertices and the duplicate * edges, and build the faces that form the sides of the extrusion. Build "original index" * arrays for the new vertices and edges so they can be accessed later. @@ -1119,11 +1112,11 @@ static void extrude_individual_mesh_faces(Mesh &mesh, for (const int i_selection : range) { const IndexRange extrude_range = selected_corner_range(index_offsets, i_selection); - const MPoly &poly = polys[poly_selection[i_selection]]; - MutableSpan poly_verts = corner_verts.slice(poly.loopstart, poly.totloop); - MutableSpan poly_edges = corner_edges.slice(poly.loopstart, poly.totloop); + const IndexRange poly = polys[poly_selection[i_selection]]; + MutableSpan poly_verts = corner_verts.slice(poly); + MutableSpan poly_edges = corner_edges.slice(poly); - for (const int i : IndexRange(poly.totloop)) { + for (const int i : IndexRange(poly.size())) { const int i_extrude = extrude_range[i]; new_vert_indices[i_extrude] = poly_verts[i]; duplicate_edge_indices[i_extrude] = poly_edges[i]; @@ -1132,8 +1125,8 @@ static void extrude_individual_mesh_faces(Mesh &mesh, poly_edges[i] = duplicate_edge_range[i_extrude]; } - for (const int i : IndexRange(poly.totloop)) { - const int i_next = (i == poly.totloop - 1) ? 0 : i + 1; + for (const int i : IndexRange(poly.size())) { + const int i_next = (i == poly.size() - 1) ? 0 : i + 1; const int i_extrude = extrude_range[i]; const int i_extrude_next = extrude_range[i_next]; @@ -1148,8 +1141,6 @@ static void extrude_individual_mesh_faces(Mesh &mesh, duplicate_edges[i_extrude] = new_edge(new_vert, new_vert_next); - new_polys[i_extrude] = new_poly(side_loop_range[i_extrude * 4], 4); - MutableSpan side_poly_verts = corner_verts.slice(side_loop_range[i_extrude * 4], 4); MutableSpan side_poly_edges = corner_edges.slice(side_loop_range[i_extrude * 4], 4); side_poly_verts[0] = new_vert_next; @@ -1196,13 +1187,13 @@ static void extrude_individual_mesh_faces(Mesh &mesh, MutableSpan connect_data = data.slice(connect_edge_range); threading::parallel_for(poly_selection.index_range(), 512, [&](const IndexRange range) { for (const int i_selection : range) { - const MPoly &poly = polys[poly_selection[i_selection]]; + const IndexRange poly = polys[poly_selection[i_selection]]; const IndexRange extrude_range = selected_corner_range(index_offsets, i_selection); /* For the extruded edges, mix the data from the two neighboring original edges of * the extruded polygon. */ - for (const int i : IndexRange(poly.totloop)) { - const int i_prev = (i == 0) ? poly.totloop - 1 : i - 1; + for (const int i : IndexRange(poly.size())) { + const int i_prev = (i == 0) ? poly.size() - 1 : i - 1; const int i_extrude = extrude_range[i]; const int i_extrude_prev = extrude_range[i_prev]; @@ -1239,12 +1230,12 @@ static void extrude_individual_mesh_faces(Mesh &mesh, MutableSpan new_data = data.slice(side_loop_range); threading::parallel_for(poly_selection.index_range(), 256, [&](const IndexRange range) { for (const int i_selection : range) { - const MPoly &poly = polys[poly_selection[i_selection]]; - const Span poly_loop_data = data.slice(poly.loopstart, poly.totloop); + const IndexRange poly = polys[poly_selection[i_selection]]; + const Span poly_loop_data = data.slice(poly); const IndexRange extrude_range = selected_corner_range(index_offsets, i_selection); - for (const int i : IndexRange(poly.totloop)) { - const int i_next = (i == poly.totloop - 1) ? 0 : i + 1; + for (const int i : IndexRange(poly.size())) { + const int i_next = (i == poly.size() - 1) ? 0 : i + 1; const int i_extrude = extrude_range[i]; MutableSpan side_loop_data = new_data.slice(i_extrude * 4, 4); diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_angle.cc b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_angle.cc index 850f9db2101..f1476552be1 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_angle.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_angle.cc @@ -34,15 +34,14 @@ struct EdgeMapEntry { int face_index_2; }; -static Array create_edge_map(const Span polys, +static Array create_edge_map(const OffsetIndices polys, const Span corner_edges, const int total_edges) { Array edge_map(total_edges, {0, 0, 0}); for (const int i_poly : polys.index_range()) { - const MPoly &poly = polys[i_poly]; - for (const int edge : corner_edges.slice(poly.loopstart, poly.totloop)) { + for (const int edge : corner_edges.slice(polys[i_poly])) { EdgeMapEntry &entry = edge_map[edge]; if (entry.face_count == 0) { entry.face_index_1 = i_poly; @@ -68,7 +67,7 @@ class AngleFieldInput final : public bke::MeshFieldInput { const IndexMask /*mask*/) const final { const Span positions = mesh.vert_positions(); - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_verts = mesh.corner_verts(); const Span corner_edges = mesh.corner_edges(); Array edge_map = create_edge_map(polys, corner_edges, mesh.totedge); @@ -78,12 +77,10 @@ class AngleFieldInput final : public bke::MeshFieldInput { if (edge_map[i].face_count != 2) { return 0.0f; } - const MPoly &poly_1 = polys[edge_map[i].face_index_1]; - const MPoly &poly_2 = polys[edge_map[i].face_index_2]; - const float3 normal_1 = bke::mesh::poly_normal_calc( - positions, corner_verts.slice(poly_1.loopstart, poly_1.totloop)); - const float3 normal_2 = bke::mesh::poly_normal_calc( - positions, corner_verts.slice(poly_2.loopstart, poly_2.totloop)); + const IndexRange poly_1 = polys[edge_map[i].face_index_1]; + const IndexRange poly_2 = polys[edge_map[i].face_index_2]; + const float3 normal_1 = bke::mesh::poly_normal_calc(positions, corner_verts.slice(poly_1)); + const float3 normal_2 = bke::mesh::poly_normal_calc(positions, corner_verts.slice(poly_2)); return angle_normalized_v3v3(normal_1, normal_2); }; @@ -121,7 +118,7 @@ class SignedAngleFieldInput final : public bke::MeshFieldInput { { const Span positions = mesh.vert_positions(); const Span edges = mesh.edges(); - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_verts = mesh.corner_verts(); const Span corner_edges = mesh.corner_edges(); Array edge_map = create_edge_map(polys, corner_edges, mesh.totedge); @@ -131,22 +128,22 @@ class SignedAngleFieldInput final : public bke::MeshFieldInput { if (edge_map[i].face_count != 2) { return 0.0f; } - const MPoly &poly_1 = polys[edge_map[i].face_index_1]; - const MPoly &poly_2 = polys[edge_map[i].face_index_2]; + const IndexRange poly_1 = polys[edge_map[i].face_index_1]; + const IndexRange poly_2 = polys[edge_map[i].face_index_2]; /* Find the normals of the 2 polys. */ - const float3 poly_1_normal = bke::mesh::poly_normal_calc( - positions, corner_verts.slice(poly_1.loopstart, poly_1.totloop)); - const float3 poly_2_normal = bke::mesh::poly_normal_calc( - positions, corner_verts.slice(poly_2.loopstart, poly_2.totloop)); + const float3 poly_1_normal = bke::mesh::poly_normal_calc(positions, + corner_verts.slice(poly_1)); + const float3 poly_2_normal = bke::mesh::poly_normal_calc(positions, + corner_verts.slice(poly_2)); /* Find the centerpoint of the axis edge */ const float3 edge_centerpoint = (positions[edges[i].v1] + positions[edges[i].v2]) * 0.5f; /* Get the centerpoint of poly 2 and subtract the edge centerpoint to get a tangent * normal for poly 2. */ - const float3 poly_center_2 = bke::mesh::poly_center_calc( - positions, corner_verts.slice(poly_2.loopstart, poly_2.totloop)); + const float3 poly_center_2 = bke::mesh::poly_center_calc(positions, + corner_verts.slice(poly_2)); const float3 poly_2_tangent = math::normalize(poly_center_2 - edge_centerpoint); const float concavity = math::dot(poly_1_normal, poly_2_tangent); diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_area.cc b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_area.cc index 4dcf63342e8..8c2357b847b 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_area.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_area.cc @@ -19,12 +19,11 @@ static void node_declare(NodeDeclarationBuilder &b) static VArray construct_face_area_varray(const Mesh &mesh, const eAttrDomain domain) { const Span positions = mesh.vert_positions(); - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_verts = mesh.corner_verts(); auto area_fn = [positions, polys, corner_verts](const int i) -> float { - const MPoly &poly = polys[i]; - return bke::mesh::poly_area_calc(positions, corner_verts.slice(poly.loopstart, poly.totloop)); + return bke::mesh::poly_area_calc(positions, corner_verts.slice(polys[i])); }; return mesh.attributes().adapt_domain( diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_is_planar.cc b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_is_planar.cc index d70d0292ae1..57831035856 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_is_planar.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_is_planar.cc @@ -40,7 +40,7 @@ class PlanarFieldInput final : public bke::MeshFieldInput { IndexMask /*mask*/) const final { const Span positions = mesh.vert_positions(); - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_verts = mesh.corner_verts(); const Span poly_normals = mesh.poly_normals(); @@ -52,8 +52,8 @@ class PlanarFieldInput final : public bke::MeshFieldInput { auto planar_fn = [positions, polys, corner_verts, thresholds, poly_normals](const int i) -> bool { - const MPoly &poly = polys[i]; - if (poly.totloop <= 3) { + const IndexRange poly = polys[i]; + if (poly.size() <= 3) { return true; } const float3 &reference_normal = poly_normals[i]; @@ -61,7 +61,7 @@ class PlanarFieldInput final : public bke::MeshFieldInput { float min = FLT_MAX; float max = -FLT_MAX; - for (const int vert : corner_verts.slice(poly.loopstart, poly.totloop)) { + for (const int vert : corner_verts.slice(poly)) { float dot = math::dot(reference_normal, positions[vert]); if (dot > max) { max = dot; diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_neighbors.cc b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_neighbors.cc index e0fa844a2df..f8b8b3d08f1 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_neighbors.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_neighbors.cc @@ -21,7 +21,7 @@ static void node_declare(NodeDeclarationBuilder &b) static VArray construct_neighbor_count_varray(const Mesh &mesh, const eAttrDomain domain) { - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_edges = mesh.corner_edges(); Array edge_count(mesh.totedge, 0); @@ -31,8 +31,7 @@ static VArray construct_neighbor_count_varray(const Mesh &mesh, const eAttr Array poly_count(polys.size(), 0); for (const int poly_index : polys.index_range()) { - const MPoly &poly = polys[poly_index]; - for (const int edge : corner_edges.slice(poly.loopstart, poly.totloop)) { + for (const int edge : corner_edges.slice(polys[poly_index])) { poly_count[poly_index] += edge_count[edge] - 1; } } @@ -75,10 +74,10 @@ class FaceNeighborCountFieldInput final : public bke::MeshFieldInput { static VArray construct_vertex_count_varray(const Mesh &mesh, const eAttrDomain domain) { - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); return mesh.attributes().adapt_domain( VArray::ForFunc(polys.size(), - [polys](const int i) -> float { return polys[i].totloop; }), + [polys](const int i) -> float { return polys[i].size(); }), ATTR_DOMAIN_FACE, domain); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_face_group_boundaries.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_face_group_boundaries.cc index daa7333910e..db4cd400c8a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_face_group_boundaries.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_face_group_boundaries.cc @@ -46,11 +46,10 @@ class BoundaryFieldInput final : public bke::MeshFieldInput { Array boundary(mesh.totedge, false); Array edge_visited(mesh.totedge, false); Array edge_face_set(mesh.totedge, 0); - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_edges = mesh.corner_edges(); for (const int i : polys.index_range()) { - const MPoly &poly = polys[i]; - for (const int edge : corner_edges.slice(poly.loopstart, poly.totloop)) { + for (const int edge : corner_edges.slice(polys[i])) { if (edge_visited[edge]) { if (edge_face_set[edge] != face_set[i]) { /* This edge is connected to two faces on different face sets. */ diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc index 6e8a7a331f3..5825e0add37 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc @@ -115,7 +115,7 @@ static Mesh *create_circle_mesh(const float radius, BKE_id_material_eval_ensure_default_slot(&mesh->id); MutableSpan positions = mesh->vert_positions_for_write(); MutableSpan edges = mesh->edges_for_write(); - MutableSpan polys = mesh->polys_for_write(); + MutableSpan poly_offsets = mesh->poly_offsets_for_write(); MutableSpan corner_verts = mesh->corner_verts_for_write(); MutableSpan corner_edges = mesh->corner_edges_for_write(); BKE_mesh_smooth_flag_set(mesh, false); @@ -148,19 +148,17 @@ static Mesh *create_circle_mesh(const float radius, /* Create corners and faces. */ if (fill_type == GEO_NODE_MESH_CIRCLE_FILL_NGON) { - MPoly &poly = polys[0]; - poly.loopstart = 0; - poly.totloop = corner_verts.size(); + poly_offsets.first() = 0; + poly_offsets.last() = corner_verts.size(); std::iota(corner_verts.begin(), corner_verts.end(), 0); std::iota(corner_edges.begin(), corner_edges.end(), 0); } else if (fill_type == GEO_NODE_MESH_CIRCLE_FILL_TRIANGLE_FAN) { + for (const int i : poly_offsets.index_range()) { + poly_offsets[i] = 3 * i; + } for (const int i : IndexRange(verts_num)) { - MPoly &poly = polys[i]; - poly.loopstart = 3 * i; - poly.totloop = 3; - corner_verts[3 * i] = i; corner_edges[3 * i] = i; diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc index c3f2970dc02..d128aca133a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc @@ -367,12 +367,11 @@ static void calculate_cone_edges(const ConeConfig &config, MutableSpan ed static void calculate_cone_faces(const ConeConfig &config, MutableSpan corner_verts, MutableSpan corner_edges, - MutableSpan polys) + MutableSpan poly_sizes) { - int rings_poly_start = 0; int rings_loop_start = 0; if (config.top_has_center_vert) { - rings_poly_start = config.circle_segments; + poly_sizes.take_front(config.top_faces_len).fill(3); rings_loop_start = config.circle_segments * 3; /* Top cone tip or center triangle fan in the fill. */ @@ -381,9 +380,6 @@ static void calculate_cone_faces(const ConeConfig &config, for (const int i : IndexRange(config.circle_segments)) { const int loop_start = i * 3; - MPoly &poly = polys[i]; - poly.loopstart = loop_start; - poly.totloop = 3; corner_verts[loop_start + 0] = config.first_ring_verts_start + i; corner_edges[loop_start + 0] = config.first_ring_edges_start + i; @@ -397,13 +393,10 @@ static void calculate_cone_faces(const ConeConfig &config, } } else if (config.fill_type == GEO_NODE_MESH_CIRCLE_FILL_NGON) { - rings_poly_start = 1; + /* Center n-gon in the fill. */ + poly_sizes.first() = config.circle_segments; rings_loop_start = config.circle_segments; - /* Center n-gon in the fill. */ - MPoly &poly = polys[0]; - poly.loopstart = 0; - poly.totloop = config.circle_segments; for (const int i : IndexRange(config.circle_segments)) { corner_verts[i] = i; corner_edges[i] = i; @@ -411,8 +404,9 @@ static void calculate_cone_faces(const ConeConfig &config, } /* Quads connect one edge ring to the next one. */ + const int ring_poly_size = (config.top_is_point || config.bottom_is_point) ? 3 : 4; + poly_sizes.slice(config.side_faces_start, config.side_faces_len).fill(ring_poly_size); for (const int i : IndexRange(config.tot_quad_rings)) { - const int this_ring_poly_start = rings_poly_start + i * config.circle_segments; const int this_ring_loop_start = rings_loop_start + i * config.circle_segments * 4; const int this_ring_vert_start = config.first_ring_verts_start + (i * config.circle_segments); const int next_ring_vert_start = this_ring_vert_start + config.circle_segments; @@ -424,9 +418,6 @@ static void calculate_cone_faces(const ConeConfig &config, for (const int j : IndexRange(config.circle_segments)) { const int loop_start = this_ring_loop_start + j * 4; - MPoly &poly = polys[this_ring_poly_start + j]; - poly.loopstart = loop_start; - poly.totloop = 4; corner_verts[loop_start + 0] = this_ring_vert_start + j; corner_edges[loop_start + 0] = ring_connections_start + j; @@ -442,17 +433,15 @@ static void calculate_cone_faces(const ConeConfig &config, } } - const int bottom_poly_start = rings_poly_start + config.tot_quad_rings * config.circle_segments; const int bottom_loop_start = rings_loop_start + config.tot_quad_rings * config.circle_segments * 4; if (config.bottom_has_center_vert) { + poly_sizes.take_front(config.bottom_faces_len).fill(3); + /* Bottom cone tip or center triangle fan in the fill. */ for (const int i : IndexRange(config.circle_segments)) { const int loop_start = bottom_loop_start + i * 3; - MPoly &poly = polys[bottom_poly_start + i]; - poly.loopstart = loop_start; - poly.totloop = 3; corner_verts[loop_start + 0] = config.last_ring_verts_start + i; corner_edges[loop_start + 0] = config.last_fan_edges_start + i; @@ -468,10 +457,7 @@ static void calculate_cone_faces(const ConeConfig &config, } else if (config.fill_type == GEO_NODE_MESH_CIRCLE_FILL_NGON) { /* Center n-gon in the fill. */ - MPoly &poly = polys[bottom_poly_start]; - poly.loopstart = bottom_loop_start; - poly.totloop = config.circle_segments; - + poly_sizes.last() = config.circle_segments; for (const int i : IndexRange(config.circle_segments)) { /* Go backwards to reverse surface normal. */ corner_verts[bottom_loop_start + i] = config.last_vert - i; @@ -719,14 +705,15 @@ Mesh *create_cylinder_or_cone_mesh(const float radius_top, MutableSpan positions = mesh->vert_positions_for_write(); MutableSpan edges = mesh->edges_for_write(); - MutableSpan polys = mesh->polys_for_write(); + MutableSpan poly_offsets = mesh->poly_offsets_for_write(); MutableSpan corner_verts = mesh->corner_verts_for_write(); MutableSpan corner_edges = mesh->corner_edges_for_write(); BKE_mesh_smooth_flag_set(mesh, false); calculate_cone_verts(config, positions); calculate_cone_edges(config, edges); - calculate_cone_faces(config, corner_verts, corner_edges, polys); + calculate_cone_faces(config, corner_verts, corner_edges, poly_offsets.drop_back(1)); + offset_indices::accumulate_counts_to_offsets(poly_offsets); if (attribute_outputs.uv_map_id) { calculate_cone_uvs(config, mesh, attribute_outputs.uv_map_id.get()); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc index 10acbb1e4af..c8c7463532d 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc @@ -55,11 +55,17 @@ Mesh *create_grid_mesh(const int verts_x, edges_x * edges_y); MutableSpan positions = mesh->vert_positions_for_write(); MutableSpan edges = mesh->edges_for_write(); - MutableSpan polys = mesh->polys_for_write(); + MutableSpan poly_offsets = mesh->poly_offsets_for_write(); MutableSpan corner_verts = mesh->corner_verts_for_write(); MutableSpan corner_edges = mesh->corner_edges_for_write(); BKE_mesh_smooth_flag_set(mesh, false); + threading::parallel_for(poly_offsets.index_range(), 4096, [poly_offsets](IndexRange range) { + for (const int i : range) { + poly_offsets[i] = i * 4; + } + }); + { const float dx = edges_x == 0 ? 0.0f : size_x / edges_x; const float dy = edges_y == 0 ? 0.0f : size_y / edges_y; @@ -121,9 +127,6 @@ Mesh *create_grid_mesh(const int verts_x, for (const int y : y_range) { const int poly_index = y_offset + y; const int loop_index = poly_index * 4; - MPoly &poly = polys[poly_index]; - poly.loopstart = loop_index; - poly.totloop = 4; const int vert_index = x * verts_y + y; corner_verts[loop_index] = vert_index; diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc index 7bf05aca760..c09e15ccd3e 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc @@ -151,30 +151,17 @@ BLI_NOINLINE static void calculate_sphere_edge_indices(MutableSpan edges, } } -BLI_NOINLINE static void calculate_sphere_faces(MutableSpan polys, const int segments) +BLI_NOINLINE static void calculate_sphere_faces(MutableSpan poly_offsets, const int segments) { - int loop_index = 0; - + MutableSpan poly_sizes = poly_offsets.drop_back(1); /* Add the triangles connected to the top vertex. */ - for (MPoly &poly : polys.take_front(segments)) { - poly.loopstart = loop_index; - poly.totloop = 3; - loop_index += 3; - } - + poly_sizes.take_front(segments).fill(3); /* Add the middle quads. */ - for (MPoly &poly : polys.drop_front(segments).drop_back(segments)) { - poly.loopstart = loop_index; - poly.totloop = 4; - loop_index += 4; - } - + poly_sizes.drop_front(segments).drop_back(segments).fill(4); /* Add the triangles connected to the bottom vertex. */ - for (MPoly &poly : polys.take_back(segments)) { - poly.loopstart = loop_index; - poly.totloop = 3; - loop_index += 3; - } + poly_sizes.take_back(segments).fill(3); + + offset_indices::accumulate_counts_to_offsets(poly_offsets); } BLI_NOINLINE static void calculate_sphere_corners(MutableSpan corner_verts, @@ -324,7 +311,7 @@ static Mesh *create_uv_sphere_mesh(const float radius, BKE_id_material_eval_ensure_default_slot(&mesh->id); MutableSpan positions = mesh->vert_positions_for_write(); MutableSpan edges = mesh->edges_for_write(); - MutableSpan polys = mesh->polys_for_write(); + MutableSpan poly_offsets = mesh->poly_offsets_for_write(); MutableSpan corner_verts = mesh->corner_verts_for_write(); MutableSpan corner_edges = mesh->corner_edges_for_write(); BKE_mesh_smooth_flag_set(mesh, false); @@ -338,7 +325,7 @@ static Mesh *create_uv_sphere_mesh(const float radius, BKE_mesh_vert_normals_clear_dirty(mesh); }, [&]() { calculate_sphere_edge_indices(edges, segments, rings); }, - [&]() { calculate_sphere_faces(polys, segments); }, + [&]() { calculate_sphere_faces(poly_offsets, segments); }, [&]() { calculate_sphere_corners(corner_verts, corner_edges, segments, rings); }, [&]() { if (uv_map_id) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_corners_of_face.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_corners_of_face.cc index 9d359848bc6..d24fa758d7e 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_corners_of_face.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_corners_of_face.cc @@ -49,7 +49,7 @@ class CornersOfFaceInput final : public bke::MeshFieldInput { const eAttrDomain domain, const IndexMask mask) const final { - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const bke::MeshFieldContext context{mesh, domain}; fn::FieldEvaluator evaluator{context, &mask}; @@ -80,8 +80,7 @@ class CornersOfFaceInput final : public bke::MeshFieldInput { continue; } - const MPoly &poly = polys[poly_i]; - const IndexRange corners(poly.loopstart, poly.totloop); + const IndexRange corners = polys[poly_i]; const int index_in_sort_wrapped = mod_i(index_in_sort, corners.size()); if (use_sorting) { @@ -137,11 +136,6 @@ class CornersOfFaceInput final : public bke::MeshFieldInput { } }; -static int get_poly_totloop(const MPoly &poly) -{ - return poly.totloop; -} - class CornersOfFaceCountInput final : public bke::MeshFieldInput { public: CornersOfFaceCountInput() : bke::MeshFieldInput(CPPType::get(), "Face Corner Count") @@ -156,7 +150,9 @@ class CornersOfFaceCountInput final : public bke::MeshFieldInput { if (domain != ATTR_DOMAIN_FACE) { return {}; } - return VArray::ForDerivedSpan(mesh.polys()); + const OffsetIndices polys = mesh.polys(); + return VArray::ForFunc(mesh.totpoly, + [polys](const int64_t i) { return polys[i].size(); }); } uint64_t hash() const final diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_edges_of_corner.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_edges_of_corner.cc index ba831221995..13ab19b2881 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_edges_of_corner.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_edges_of_corner.cc @@ -75,14 +75,14 @@ class CornerPreviousEdgeFieldInput final : public bke::MeshFieldInput { if (domain != ATTR_DOMAIN_CORNER) { return {}; } - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_edges = mesh.corner_edges(); - Array loop_to_poly_map = bke::mesh_topology::build_loop_to_poly_map(polys, mesh.totloop); + Array loop_to_poly_map = bke::mesh_topology::build_loop_to_poly_map(polys); return VArray::ForFunc( mesh.totloop, [polys, corner_edges, loop_to_poly_map = std::move(loop_to_poly_map)](const int corner_i) { - const MPoly &poly = polys[loop_to_poly_map[corner_i]]; - return corner_edges[bke::mesh::poly_corner_prev(poly, corner_i)]; + return corner_edges[bke::mesh::poly_corner_prev(polys[loop_to_poly_map[corner_i]], + corner_i)]; }); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_face_of_corner.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_face_of_corner.cc index c572a52a93d..c51b44447c9 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_face_of_corner.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_face_of_corner.cc @@ -35,8 +35,7 @@ class CornerFaceIndexInput final : public bke::MeshFieldInput { if (domain != ATTR_DOMAIN_CORNER) { return {}; } - return VArray::ForContainer( - bke::mesh_topology::build_loop_to_poly_map(mesh.polys(), mesh.totloop)); + return VArray::ForContainer(bke::mesh_topology::build_loop_to_poly_map(mesh.polys())); } uint64_t hash() const final @@ -64,12 +63,12 @@ class CornerIndexInFaceInput final : public bke::MeshFieldInput { if (domain != ATTR_DOMAIN_CORNER) { return {}; } - const Span polys = mesh.polys(); - Array loop_to_poly_map = bke::mesh_topology::build_loop_to_poly_map(polys, mesh.totloop); + const OffsetIndices polys = mesh.polys(); + Array loop_to_poly_map = bke::mesh_topology::build_loop_to_poly_map(polys); return VArray::ForFunc( mesh.totloop, [polys, loop_to_poly_map = std::move(loop_to_poly_map)](const int corner_i) { const int poly_i = loop_to_poly_map[corner_i]; - return corner_i - polys[poly_i].loopstart; + return corner_i - polys[poly_i].start(); }); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_offset_corner_in_face.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_offset_corner_in_face.cc index 45b21836acc..a497c612677 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_offset_corner_in_face.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_offset_corner_in_face.cc @@ -42,7 +42,7 @@ class OffsetCornerInFaceFieldInput final : public bke::MeshFieldInput { const IndexMask mask) const final { const IndexRange corner_range(mesh.totloop); - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const bke::MeshFieldContext context{mesh, domain}; fn::FieldEvaluator evaluator{context, &mask}; @@ -52,7 +52,7 @@ class OffsetCornerInFaceFieldInput final : public bke::MeshFieldInput { const VArray corner_indices = evaluator.get_evaluated(0); const VArray offsets = evaluator.get_evaluated(1); - Array loop_to_poly_map = bke::mesh_topology::build_loop_to_poly_map(polys, mesh.totloop); + Array loop_to_poly_map = bke::mesh_topology::build_loop_to_poly_map(polys); Array offset_corners(mask.min_array_size()); threading::parallel_for(mask.index_range(), 2048, [&](const IndexRange range) { @@ -64,9 +64,8 @@ class OffsetCornerInFaceFieldInput final : public bke::MeshFieldInput { continue; } - const int poly_i = loop_to_poly_map[corner_i]; - const IndexRange poly_range(polys[poly_i].loopstart, polys[poly_i].totloop); - offset_corners[selection_i] = apply_offset_in_cyclic_range(poly_range, corner_i, offset); + const IndexRange poly = polys[loop_to_poly_map[corner_i]]; + offset_corners[selection_i] = apply_offset_in_cyclic_range(poly, corner_i, offset); } }); 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 60a12cdde40..53a78778e96 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_sample_nearest.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_sample_nearest.cc @@ -164,7 +164,7 @@ static void get_closest_mesh_corners(const Mesh &mesh, const MutableSpan r_positions) { const Span vert_positions = mesh.vert_positions(); - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_verts = mesh.corner_verts(); BLI_assert(mesh.totloop > 0); @@ -174,13 +174,12 @@ static void get_closest_mesh_corners(const Mesh &mesh, for (const int i : mask) { const float3 position = positions[i]; const int poly_index = poly_indices[i]; - const MPoly &poly = polys[poly_index]; /* Find the closest vertex in the polygon. */ float min_distance_sq = FLT_MAX; int closest_vert_index = 0; int closest_loop_index = 0; - for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) { + for (const int loop_index : polys[poly_index]) { const int vertex_index = corner_verts[loop_index]; const float distance_sq = math::distance_squared(position, vert_positions[vertex_index]); if (distance_sq < min_distance_sq) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_scale_elements.cc b/source/blender/nodes/geometry/nodes/node_geo_scale_elements.cc index 5d3992bcd76..4afb51b2e17 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_scale_elements.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_scale_elements.cc @@ -148,7 +148,7 @@ static float4x4 create_single_axis_transform(const float3 ¢er, } using GetVertexIndicesFn = FunctionRef edges, - Span polys, + OffsetIndices polys, Span corner_verts, int element_index, VectorSet &r_vertex_indices)>; @@ -160,7 +160,7 @@ static void scale_vertex_islands_uniformly(Mesh &mesh, { MutableSpan positions = mesh.vert_positions_for_write(); const Span edges = mesh.edges(); - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_verts = mesh.corner_verts(); threading::parallel_for(islands.index_range(), 256, [&](const IndexRange range) { @@ -198,7 +198,7 @@ static void scale_vertex_islands_on_axis(Mesh &mesh, { MutableSpan positions = mesh.vert_positions_for_write(); const Span edges = mesh.edges(); - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_verts = mesh.corner_verts(); threading::parallel_for(islands.index_range(), 256, [&](const IndexRange range) { @@ -239,15 +239,14 @@ static void scale_vertex_islands_on_axis(Mesh &mesh, static Vector prepare_face_islands(const Mesh &mesh, const IndexMask face_selection) { - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_verts = mesh.corner_verts(); /* Use the disjoint set data structure to determine which vertices have to be scaled together. */ DisjointSet disjoint_set(mesh.totvert); for (const int poly_index : face_selection) { - const MPoly &poly = polys[poly_index]; - const Span poly_verts = corner_verts.slice(poly.loopstart, poly.totloop); - for (const int loop_index : IndexRange(poly.totloop - 1)) { + const Span poly_verts = corner_verts.slice(polys[poly_index]); + for (const int loop_index : poly_verts.index_range().drop_back(1)) { const int v1 = poly_verts[loop_index]; const int v2 = poly_verts[loop_index + 1]; disjoint_set.join(v1, v2); @@ -262,8 +261,7 @@ static Vector prepare_face_islands(const Mesh &mesh, const IndexM /* Gather all of the face indices in each island into separate vectors. */ for (const int poly_index : face_selection) { - const MPoly &poly = polys[poly_index]; - const Span poly_verts = corner_verts.slice(poly.loopstart, poly.totloop); + const Span poly_verts = corner_verts.slice(polys[poly_index]); const int island_id = disjoint_set.find_root(poly_verts[0]); const int island_index = island_ids.index_of_or_add(island_id); if (island_index == islands.size()) { @@ -277,13 +275,12 @@ static Vector prepare_face_islands(const Mesh &mesh, const IndexM } static void get_face_verts(const Span /*edges*/, - const Span polys, + const OffsetIndices polys, const Span corner_verts, int face_index, VectorSet &r_vertex_indices) { - const MPoly &poly = polys[face_index]; - r_vertex_indices.add_multiple(corner_verts.slice(poly.loopstart, poly.totloop)); + r_vertex_indices.add_multiple(corner_verts.slice(polys[face_index])); } static AxisScaleParams evaluate_axis_scale_fields(FieldEvaluator &evaluator, @@ -363,7 +360,7 @@ static Vector prepare_edge_islands(const Mesh &mesh, const IndexM } static void get_edge_verts(const Span edges, - const Span /*polys*/, + const OffsetIndices /*polys*/, const Span /*corner_verts*/, int edge_index, VectorSet &r_vertex_indices) diff --git a/source/blender/nodes/geometry/nodes/node_geo_uv_pack_islands.cc b/source/blender/nodes/geometry/nodes/node_geo_uv_pack_islands.cc index 7f1c7d36a8d..02734b18fb2 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_uv_pack_islands.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_uv_pack_islands.cc @@ -38,7 +38,7 @@ static VArray construct_uv_gvarray(const Mesh &mesh, const eAttrDomain domain) { const Span positions = mesh.vert_positions(); - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_verts = mesh.corner_verts(); bke::MeshFieldContext face_context{mesh, ATTR_DOMAIN_FACE}; @@ -58,14 +58,14 @@ static VArray construct_uv_gvarray(const Mesh &mesh, geometry::ParamHandle *handle = geometry::uv_parametrizer_construct_begin(); for (const int poly_index : selection) { - const MPoly &poly = polys[poly_index]; - Array mp_vkeys(poly.totloop); - Array mp_pin(poly.totloop); - Array mp_select(poly.totloop); - Array mp_co(poly.totloop); - Array mp_uv(poly.totloop); - for (const int i : IndexRange(poly.totloop)) { - const int corner = poly.loopstart + i; + const IndexRange poly = polys[poly_index]; + Array mp_vkeys(poly.size()); + Array mp_pin(poly.size()); + Array mp_select(poly.size()); + Array mp_co(poly.size()); + Array mp_uv(poly.size()); + for (const int i : IndexRange(poly.size())) { + const int corner = poly[i]; const int vert = corner_verts[corner]; mp_vkeys[i] = vert; mp_co[i] = positions[vert]; @@ -75,7 +75,7 @@ static VArray construct_uv_gvarray(const Mesh &mesh, } geometry::uv_parametrizer_face_add(handle, poly_index, - poly.totloop, + poly.size(), mp_vkeys.data(), mp_co.data(), mp_uv.data(), diff --git a/source/blender/nodes/geometry/nodes/node_geo_uv_unwrap.cc b/source/blender/nodes/geometry/nodes/node_geo_uv_unwrap.cc index 98729eb67b6..36d0aea3bab 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_uv_unwrap.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_uv_unwrap.cc @@ -64,7 +64,7 @@ static VArray construct_uv_gvarray(const Mesh &mesh, { const Span positions = mesh.vert_positions(); const Span edges = mesh.edges(); - const Span polys = mesh.polys(); + const OffsetIndices polys = mesh.polys(); const Span corner_verts = mesh.corner_verts(); bke::MeshFieldContext face_context{mesh, ATTR_DOMAIN_FACE}; @@ -86,14 +86,14 @@ static VArray construct_uv_gvarray(const Mesh &mesh, geometry::ParamHandle *handle = geometry::uv_parametrizer_construct_begin(); for (const int poly_index : selection) { - const MPoly &poly = polys[poly_index]; - Array mp_vkeys(poly.totloop); - Array mp_pin(poly.totloop); - Array mp_select(poly.totloop); - Array mp_co(poly.totloop); - Array mp_uv(poly.totloop); - for (const int i : IndexRange(poly.totloop)) { - const int corner = poly.loopstart + i; + const IndexRange poly = polys[poly_index]; + Array mp_vkeys(poly.size()); + Array mp_pin(poly.size()); + Array mp_select(poly.size()); + Array mp_co(poly.size()); + Array mp_uv(poly.size()); + for (const int i : IndexRange(poly.size())) { + const int corner = poly[i]; const int vert = corner_verts[corner]; mp_vkeys[i] = vert; mp_co[i] = positions[vert]; @@ -103,7 +103,7 @@ static VArray construct_uv_gvarray(const Mesh &mesh, } geometry::uv_parametrizer_face_add(handle, poly_index, - poly.totloop, + poly.size(), mp_vkeys.data(), mp_co.data(), mp_uv.data(), diff --git a/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc index 99311bbd003..10c7670140f 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc @@ -124,7 +124,7 @@ static Mesh *create_mesh_from_volume_grids(Span gri Mesh *mesh = BKE_mesh_new_nomain(vert_offset, 0, loop_offset, poly_offset); BKE_id_material_eval_ensure_default_slot(&mesh->id); MutableSpan positions = mesh->vert_positions_for_write(); - MutableSpan polys = mesh->polys_for_write(); + MutableSpan dst_poly_offsets = mesh->poly_offsets_for_write(); MutableSpan corner_verts = mesh->corner_verts_for_write(); for (const int i : grids.index_range()) { @@ -136,7 +136,7 @@ static Mesh *create_mesh_from_volume_grids(Span gri poly_offsets[i], loop_offsets[i], positions, - polys, + dst_poly_offsets, corner_verts); } diff --git a/source/blender/render/intern/bake.cc b/source/blender/render/intern/bake.cc index 474ddf73038..63d3f812882 100644 --- a/source/blender/render/intern/bake.cc +++ b/source/blender/render/intern/bake.cc @@ -463,7 +463,7 @@ static TriTessFace *mesh_calc_tri_tessface(Mesh *me, bool tangent, Mesh *me_eval blender::float3 no; const blender::Span positions = me->vert_positions(); - const blender::Span polys = me->polys(); + const blender::OffsetIndices polys = me->polys(); const blender::Span corner_verts = me->corner_verts(); const bke::AttributeAccessor attributes = me->attributes(); const VArray sharp_faces = attributes.lookup_or_default( @@ -503,7 +503,6 @@ static TriTessFace *mesh_calc_tri_tessface(Mesh *me, bool tangent, Mesh *me_eval const blender::Span vert_normals = me->vert_normals(); for (i = 0; i < tottri; i++) { const MLoopTri *lt = &looptri[i]; - const MPoly &poly = polys[lt->poly]; triangles[i].positions[0] = positions[corner_verts[lt->tri[0]]]; triangles[i].positions[1] = positions[corner_verts[lt->tri[1]]]; @@ -527,8 +526,7 @@ 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(poly.loopstart, poly.totloop)); + no = blender::bke::mesh::poly_normal_calc(positions, corner_verts.slice(polys[lt->poly])); mpoly_prev = lt->poly; } copy_v3_v3(triangles[i].normal, no); diff --git a/source/blender/render/intern/multires_bake.cc b/source/blender/render/intern/multires_bake.cc index 8976c1f26de..7b0b2544526 100644 --- a/source/blender/render/intern/multires_bake.cc +++ b/source/blender/render/intern/multires_bake.cc @@ -42,7 +42,7 @@ using MPassKnownData = void (*)(blender::Span vert_positions, blender::Span vert_normals, - blender::Span polys, + blender::OffsetIndices polys, blender::Span corner_verts, blender::Span looptris, blender::Span uv_map, @@ -67,7 +67,7 @@ struct MultiresBakeResult { struct MResolvePixelData { /* Data from low-resolution mesh. */ blender::Span vert_positions; - blender::Span polys; + blender::OffsetIndices polys; blender::Span corner_verts; blender::Span looptris; blender::Span vert_normals; @@ -496,12 +496,12 @@ static void do_multires_bake(MultiresBakeRender *bkr, temp_mesh->vert_positions_for_write().copy_from( {reinterpret_cast(dm->getVertArray(dm)), temp_mesh->totvert}); temp_mesh->edges_for_write().copy_from({dm->getEdgeArray(dm), temp_mesh->totedge}); - temp_mesh->polys_for_write().copy_from({dm->getPolyArray(dm), temp_mesh->totpoly}); + temp_mesh->poly_offsets_for_write().copy_from({dm->getPolyArray(dm), temp_mesh->totpoly + 1}); temp_mesh->corner_verts_for_write().copy_from({dm->getCornerVertArray(dm), temp_mesh->totloop}); temp_mesh->corner_edges_for_write().copy_from({dm->getCornerEdgeArray(dm), temp_mesh->totloop}); const blender::Span positions = temp_mesh->vert_positions(); - const blender::Span polys = temp_mesh->polys(); + const blender::OffsetIndices polys = temp_mesh->polys(); const blender::Span corner_verts = temp_mesh->corner_verts(); const blender::Span vert_normals = temp_mesh->vert_normals(); const blender::Span poly_normals = temp_mesh->poly_normals(); @@ -511,8 +511,7 @@ static void do_multires_bake(MultiresBakeRender *bkr, if (CustomData_get_layer_index(&dm->loopData, CD_TANGENT) == -1) { BKE_mesh_calc_loop_tangent_ex( reinterpret_cast(positions.data()), - dm->getPolyArray(dm), - dm->getNumPolys(dm), + polys, dm->getCornerVertArray(dm), looptris.data(), looptris.size(), @@ -654,7 +653,7 @@ static void interp_bilinear_grid( interp_bilinear_quad_v3(data, u, v, res); } -static void get_ccgdm_data(const blender::Span lores_polys, +static void get_ccgdm_data(const blender::OffsetIndices lores_polys, DerivedMesh *hidm, const int *index_mp_to_orig, const int lvl, @@ -679,10 +678,13 @@ static void get_ccgdm_data(const blender::Span lores_polys, if (lvl == 0) { face_side = (grid_size << 1) - 1; - const MPoly &poly = lores_polys[poly_index]; g_index = grid_offset[poly_index]; - S = mdisp_rot_face_to_crn( - &poly, face_side, u * (face_side - 1), v * (face_side - 1), &crn_x, &crn_y); + S = mdisp_rot_face_to_crn(lores_polys[poly_index].size(), + face_side, + u * (face_side - 1), + v * (face_side - 1), + &crn_x, + &crn_y); } else { /* number of faces per grid side */ @@ -726,7 +728,7 @@ static void get_ccgdm_data(const blender::Span lores_polys, static void interp_bilinear_mpoly(const blender::Span vert_positions, const blender::Span vert_normals, const blender::Span corner_verts, - const MPoly &poly, + const blender::IndexRange poly, const float u, const float v, const int mode, @@ -735,16 +737,16 @@ static void interp_bilinear_mpoly(const blender::Span vert_posi float data[4][3]; if (mode == 0) { - copy_v3_v3(data[0], vert_normals[corner_verts[poly.loopstart]]); - copy_v3_v3(data[1], vert_normals[corner_verts[poly.loopstart + 1]]); - copy_v3_v3(data[2], vert_normals[corner_verts[poly.loopstart + 2]]); - copy_v3_v3(data[3], vert_normals[corner_verts[poly.loopstart + 3]]); + copy_v3_v3(data[0], vert_normals[corner_verts[poly[0]]]); + copy_v3_v3(data[1], vert_normals[corner_verts[poly[1]]]); + copy_v3_v3(data[2], vert_normals[corner_verts[poly[2]]]); + copy_v3_v3(data[3], vert_normals[corner_verts[poly[3]]]); } else { - copy_v3_v3(data[0], vert_positions[corner_verts[poly.loopstart]]); - copy_v3_v3(data[1], vert_positions[corner_verts[poly.loopstart + 1]]); - copy_v3_v3(data[2], vert_positions[corner_verts[poly.loopstart + 2]]); - copy_v3_v3(data[3], vert_positions[corner_verts[poly.loopstart + 3]]); + copy_v3_v3(data[0], vert_positions[corner_verts[poly[0]]]); + copy_v3_v3(data[1], vert_positions[corner_verts[poly[1]]]); + copy_v3_v3(data[2], vert_positions[corner_verts[poly[2]]]); + copy_v3_v3(data[3], vert_positions[corner_verts[poly[3]]]); } interp_bilinear_quad_v3(data, u, v, res); @@ -834,7 +836,7 @@ static void free_heights_data(void *bake_data) * - height wound be dot(n, p1-p0) */ static void apply_heights_callback(const blender::Span vert_positions, const blender::Span vert_normals, - const blender::Span polys, + const blender::OffsetIndices polys, const blender::Span corner_verts, const blender::Span looptris, const blender::Span uv_map, @@ -850,7 +852,7 @@ static void apply_heights_callback(const blender::Span vert_pos const int y) { const MLoopTri *lt = &looptris[tri_index]; - const MPoly &poly = polys[lt->poly]; + const blender::IndexRange poly = polys[lt->poly]; MHeightBakeData *height_data = (MHeightBakeData *)bake_data; MultiresBakeThread *thread_data = (MultiresBakeThread *)thread_data_v; float uv[2]; @@ -860,11 +862,11 @@ static void apply_heights_callback(const blender::Span vert_pos /* ideally we would work on triangles only, however, we rely on quads to get orthogonal * coordinates for use in grid space (triangle barycentric is not orthogonal) */ - if (poly.totloop == 4) { - st0 = uv_map[poly.loopstart]; - st1 = uv_map[poly.loopstart + 1]; - st2 = uv_map[poly.loopstart + 2]; - st3 = uv_map[poly.loopstart + 3]; + if (poly.size() == 4) { + st0 = uv_map[poly[0]]; + st1 = uv_map[poly[1]]; + st2 = uv_map[poly[2]]; + st3 = uv_map[poly[3]]; resolve_quad_uv_v2(uv, st, st0, st1, st2, st3); } else { @@ -884,7 +886,7 @@ static void apply_heights_callback(const blender::Span vert_pos polys, height_data->ssdm, height_data->orig_index_mp_to_orig, 0, lt, uv[0], uv[1], p0, n); } else { - if (poly.totloop == 4) { + if (poly.size() == 4) { interp_bilinear_mpoly(vert_positions, vert_normals, corner_verts, poly, uv[0], uv[1], 1, p0); interp_bilinear_mpoly(vert_positions, vert_normals, corner_verts, poly, uv[0], uv[1], 0, n); } @@ -948,7 +950,7 @@ static void free_normal_data(void *bake_data) */ static void apply_tangmat_callback(const blender::Span /*vert_positions*/, const blender::Span /*vert_normals*/, - const blender::Span polys, + const blender::OffsetIndices polys, const blender::Span /*corner_verts*/, const blender::Span looptris, const blender::Span uv_map, @@ -964,7 +966,7 @@ static void apply_tangmat_callback(const blender::Span /*vert_p const int y) { const MLoopTri *lt = &looptris[tri_index]; - const MPoly &poly = polys[lt->poly]; + const blender::IndexRange poly = polys[lt->poly]; MNormalBakeData *normal_data = (MNormalBakeData *)bake_data; float uv[2]; const float *st0, *st1, *st2, *st3; @@ -973,11 +975,11 @@ static void apply_tangmat_callback(const blender::Span /*vert_p /* ideally we would work on triangles only, however, we rely on quads to get orthogonal * coordinates for use in grid space (triangle barycentric is not orthogonal) */ - if (poly.totloop == 4) { - st0 = uv_map[poly.loopstart]; - st1 = uv_map[poly.loopstart + 1]; - st2 = uv_map[poly.loopstart + 2]; - st3 = uv_map[poly.loopstart + 3]; + if (poly.size() == 4) { + st0 = uv_map[poly[0]]; + st1 = uv_map[poly[1]]; + st2 = uv_map[poly[2]]; + st3 = uv_map[poly[3]]; resolve_quad_uv_v2(uv, st, st0, st1, st2, st3); } else { @@ -1225,7 +1227,6 @@ static void apply_ao_callback(DerivedMesh *lores_dm, const int y) { const MLoopTri *lt = lores_dm->getLoopTriArray(lores_dm) + tri_index; - const MPoly &poly = lores_dm->getPolyArray(lores_dm) [lt->poly]; float (*mloopuv)[2] = lores_dm->getLoopDataArray(lores_dm, CD_PROP_FLOAT2); MAOBakeData *ao_data = (MAOBakeData *)bake_data; @@ -1240,11 +1241,11 @@ static void apply_ao_callback(DerivedMesh *lores_dm, /* ideally we would work on triangles only, however, we rely on quads to get orthogonal * coordinates for use in grid space (triangle barycentric is not orthogonal) */ - if (poly.totloop == 4) { - st0 = mloopuv[poly.loopstart]; - st1 = mloopuv[poly.loopstart + 1]; - st2 = mloopuv[poly.loopstart + 2]; - st3 = mloopuv[poly.loopstart + 3]; + if (poly.size() == 4) { + st0 = mloopuv[poly[0]]; + st1 = mloopuv[poly[1]]; + st2 = mloopuv[poly[2]]; + st3 = mloopuv[poly[3]]; resolve_quad_uv_v2(uv, st, st0, st1, st2, st3); } else { diff --git a/source/blender/render/intern/texture_margin.cc b/source/blender/render/intern/texture_margin.cc index 41e5214f4bd..8b1175a06c8 100644 --- a/source/blender/render/intern/texture_margin.cc +++ b/source/blender/render/intern/texture_margin.cc @@ -54,7 +54,7 @@ class TextureMarginMap { uint32_t value_to_store_; char *mask_; - Span polys_; + OffsetIndices polys_; Span corner_edges_; Span mloopuv_; int totedge_; @@ -64,7 +64,7 @@ class TextureMarginMap { size_t h, const float uv_offset[2], const int totedge, - const Span polys, + const OffsetIndices polys, const Span corner_edges, const Span mloopuv) : w_(w), @@ -282,8 +282,7 @@ class TextureMarginMap { void build_tables() { - loop_to_poly_map_ = blender::bke::mesh_topology::build_loop_to_poly_map(polys_, - corner_edges_.size()); + loop_to_poly_map_ = blender::bke::mesh_topology::build_loop_to_poly_map(polys_); loop_adjacency_map_.resize(corner_edges_.size(), -1); @@ -318,8 +317,8 @@ class TextureMarginMap { return true; } - int loopstart = polys_[*r_start_poly].loopstart; - int totloop = polys_[*r_start_poly].totloop; + int loopstart = polys_[*r_start_poly].start(); + int totloop = polys_[*r_start_poly].size(); float destx, desty; int foundpoly; @@ -376,11 +375,11 @@ class TextureMarginMap { /* Find the closest edge on which the point x,y can be projected. */ - for (size_t i = 0; i < polys_[src_poly].totloop; i++) { - int l1 = polys_[src_poly].loopstart + i; + for (size_t i = 0; i < polys_[src_poly].size(); i++) { + int l1 = polys_[src_poly].start() + i; int l2 = l1 + 1; - if (l2 >= polys_[src_poly].loopstart + polys_[src_poly].totloop) { - l2 = polys_[src_poly].loopstart; + if (l2 >= polys_[src_poly].start() + polys_[src_poly].size()) { + l2 = polys_[src_poly].start(); } /* edge points */ float2 edgepoint1 = uv_to_xy(mloopuv_[l1]); @@ -415,7 +414,7 @@ class TextureMarginMap { /* Stother_ab the info of the closest edge so far. */ found_dist = reflectLen; found_t = t; - found_edge = i + polys_[src_poly].loopstart; + found_edge = i + polys_[src_poly].start(); } } } @@ -440,8 +439,8 @@ class TextureMarginMap { } int other_edge2 = other_edge + 1; - if (other_edge2 >= polys_[dst_poly].loopstart + polys_[dst_poly].totloop) { - other_edge2 = polys_[dst_poly].loopstart; + if (other_edge2 >= polys_[dst_poly].start() + polys_[dst_poly].size()) { + other_edge2 = polys_[dst_poly].start(); } float2 other_edgepoint1 = uv_to_xy(mloopuv_[other_edge]); @@ -475,7 +474,7 @@ static void generate_margin(ImBuf *ibuf, const int margin, const Span vert_positions, const int edges_num, - const Span polys, + const OffsetIndices polys, const Span corner_edges, const Span mloopuv, const float uv_offset[2]) @@ -580,7 +579,7 @@ void RE_generate_texturemargin_adjacentfaces_dm( margin, {reinterpret_cast(dm->getVertArray(dm)), dm->getNumVerts(dm)}, dm->getNumEdges(dm), - {dm->getPolyArray(dm), dm->getNumPolys(dm)}, + blender::Span(dm->getPolyArray(dm), dm->getNumPolys(dm) + 1), {dm->getCornerEdgeArray(dm), dm->getNumLoops(dm)}, {mloopuv, dm->getNumLoops(dm)}, uv_offset);