From 7966cd16d6dc4e66d01f7bd68a090107c1a7978c Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 4 Apr 2023 20:39:28 +0200 Subject: [PATCH] Mesh: Replace MPoly struct with offset indices Implements #95967. Currently the `MPoly` struct is 12 bytes, and stores the index of a face's first corner and the number of corners/verts/edges. Polygons and corners are always created in order by Blender, meaning each face's corners will be after the previous face's corners. We can take advantage of this fact and eliminate the redundancy in mesh face storage by only storing a single integer corner offset for each face. The size of the face is then encoded by the offset of the next face. The size of a single integer is 4 bytes, so this reduces memory usage by 3 times. The same method is used for `CurvesGeometry`, so Blender already has an abstraction to simplify using these offsets called `OffsetIndices`. This class is used to easily retrieve a range of corner indices for each face. This also gives the opportunity for sharing some logic with curves. Another benefit of the change is that the offsets and sizes stored in `MPoly` can no longer disagree with each other. Storing faces in the order of their corners can simplify some code too. Face/polygon variables now use the `IndexRange` type, which comes with quite a few utilities that can simplify code. Some: - The offset integer array has to be one longer than the face count to avoid a branch for every face, which means the data is no longer part of the mesh's `CustomData`. - We lose the ability to "reference" an original mesh's offset array until more reusable CoW from #104478 is committed. That will be added in a separate commit. - Since they aren't part of `CustomData`, poly offsets often have to be copied manually. - To simplify using `OffsetIndices` in many places, some functions and structs in headers were moved to only compile in C++. - All meshes created by Blender use the same order for faces and face corners, but just in case, meshes with mismatched order are fixed by versioning code. - `MeshPolygon.totloop` is no longer editable in RNA. This API break is necessary here unfortunately. It should be worth it in 3.6, since that's the best way to allow loading meshes from 4.0, which is important for an LTS version. Pull Request: https://projects.blender.org/blender/blender/pulls/105938 --- intern/cycles/blender/mesh.cpp | 42 +-- source/blender/blenkernel/BKE_DerivedMesh.h | 10 +- source/blender/blenkernel/BKE_deform.h | 13 +- source/blender/blenkernel/BKE_mesh.h | 27 +- source/blender/blenkernel/BKE_mesh.hh | 50 ++-- .../blenkernel/BKE_mesh_legacy_convert.h | 31 +- source/blender/blenkernel/BKE_mesh_mapping.h | 62 ++-- source/blender/blenkernel/BKE_mesh_remap.h | 18 +- source/blender/blenkernel/BKE_mesh_tangent.h | 27 +- source/blender/blenkernel/BKE_multires.h | 4 +- source/blender/blenkernel/BKE_paint.h | 2 +- source/blender/blenkernel/BKE_particle.h | 2 +- source/blender/blenkernel/BKE_pbvh.h | 14 +- source/blender/blenkernel/BKE_shrinkwrap.h | 3 +- source/blender/blenkernel/BKE_subdiv_ccg.h | 23 +- .../blender/blenkernel/BKE_volume_to_mesh.hh | 2 +- source/blender/blenkernel/intern/CCGSubSurf.c | 1 + .../blender/blenkernel/intern/DerivedMesh.cc | 40 ++- source/blender/blenkernel/intern/bvhutils.cc | 4 +- .../blenkernel/intern/cdderivedmesh.cc | 9 +- source/blender/blenkernel/intern/cloth.cc | 37 ++- .../blender/blenkernel/intern/crazyspace.cc | 12 +- .../intern/curve_to_mesh_convert.cc | 18 +- .../blender/blenkernel/intern/customdata.cc | 12 +- .../blenkernel/intern/data_transfer.cc | 15 +- source/blender/blenkernel/intern/deform.cc | 15 +- .../blender/blenkernel/intern/dynamicpaint.cc | 14 +- source/blender/blenkernel/intern/fluid.cc | 31 +- .../intern/geometry_component_mesh.cc | 85 +++--- .../blenkernel/intern/gpencil_geom_legacy.cc | 14 +- source/blender/blenkernel/intern/key.cc | 2 +- .../blenkernel/intern/mball_tessellate.cc | 8 +- source/blender/blenkernel/intern/mesh.cc | 71 +++-- .../blenkernel/intern/mesh_boolean_convert.cc | 119 ++++---- .../blenkernel/intern/mesh_calc_edges.cc | 16 +- .../blender/blenkernel/intern/mesh_convert.cc | 46 ++- .../blenkernel/intern/mesh_evaluate.cc | 92 +++--- source/blender/blenkernel/intern/mesh_fair.cc | 16 +- .../blenkernel/intern/mesh_iterators.cc | 18 +- .../blenkernel/intern/mesh_legacy_convert.cc | 150 ++++++++-- .../blender/blenkernel/intern/mesh_mapping.cc | 194 +++++------- .../intern/mesh_merge_customdata.cc | 9 +- .../blender/blenkernel/intern/mesh_mirror.cc | 21 +- .../blender/blenkernel/intern/mesh_normals.cc | 95 +++--- .../blender/blenkernel/intern/mesh_remap.cc | 212 ++++++------- .../blenkernel/intern/mesh_remesh_voxel.cc | 39 +-- .../blender/blenkernel/intern/mesh_runtime.cc | 8 +- .../blender/blenkernel/intern/mesh_tangent.cc | 70 ++--- .../blenkernel/intern/mesh_tessellate.cc | 52 ++-- .../blenkernel/intern/mesh_validate.cc | 99 +++--- .../blender/blenkernel/intern/mesh_wrapper.cc | 2 +- source/blender/blenkernel/intern/multires.cc | 43 ++- .../blenkernel/intern/multires_reshape.hh | 4 +- .../intern/multires_reshape_apply_base.cc | 22 +- .../intern/multires_reshape_smooth.cc | 8 +- .../intern/multires_reshape_subdivide.cc | 15 +- .../intern/multires_reshape_util.cc | 13 +- .../intern/multires_reshape_vertcos.cc | 3 +- .../blenkernel/intern/multires_unsubdivide.cc | 32 +- .../blender/blenkernel/intern/object_dupli.cc | 31 +- source/blender/blenkernel/intern/paint.cc | 23 +- source/blender/blenkernel/intern/pbvh.cc | 34 ++- .../blender/blenkernel/intern/pbvh_colors.cc | 18 +- .../blender/blenkernel/intern/pbvh_intern.hh | 3 +- .../blender/blenkernel/intern/shrinkwrap.cc | 2 +- source/blender/blenkernel/intern/softbody.c | 29 +- .../blender/blenkernel/intern/subdiv_ccg.cc | 23 +- .../blenkernel/intern/subdiv_ccg_mask.cc | 27 +- .../intern/subdiv_converter_mesh.cc | 31 +- .../intern/subdiv_displacement_multires.cc | 55 ++-- .../blender/blenkernel/intern/subdiv_eval.cc | 14 +- .../blenkernel/intern/subdiv_foreach.cc | 281 +++++++++--------- .../blender/blenkernel/intern/subdiv_mesh.cc | 143 +++++---- .../blender/blenkernel/intern/subsurf_ccg.cc | 50 ++-- .../blenkernel/intern/volume_to_mesh.cc | 10 +- source/blender/blenlib/BLI_offset_indices.hh | 11 +- .../blenloader/intern/versioning_290.cc | 9 +- .../blenloader/intern/versioning_400.cc | 1 + .../bmesh/intern/bmesh_mesh_convert.cc | 23 +- source/blender/draw/DRW_pbvh.hh | 4 +- .../draw/intern/draw_cache_extract_mesh.cc | 6 +- .../draw_cache_extract_mesh_render_data.cc | 6 +- .../intern/draw_cache_impl_subdivision.cc | 12 +- source/blender/draw/intern/draw_pbvh.cc | 3 +- .../intern/mesh_extractors/extract_mesh.hh | 9 +- .../extract_mesh_ibo_edituv.cc | 28 +- .../mesh_extractors/extract_mesh_ibo_fdots.cc | 4 +- .../mesh_extractors/extract_mesh_ibo_lines.cc | 14 +- .../extract_mesh_ibo_lines_adjacency.cc | 2 +- .../extract_mesh_ibo_lines_paint_mask.cc | 15 +- .../extract_mesh_ibo_points.cc | 8 +- .../mesh_extractors/extract_mesh_ibo_tris.cc | 9 +- .../extract_mesh_vbo_attributes.cc | 4 +- .../extract_mesh_vbo_edge_fac.cc | 5 +- .../extract_mesh_vbo_edit_data.cc | 7 +- .../extract_mesh_vbo_edituv_data.cc | 13 +- .../extract_mesh_vbo_edituv_stretch_angle.cc | 14 +- .../extract_mesh_vbo_edituv_stretch_area.cc | 17 +- .../extract_mesh_vbo_fdots_edituv_data.cc | 1 - .../extract_mesh_vbo_fdots_pos.cc | 6 +- .../extract_mesh_vbo_fdots_uv.cc | 6 +- .../mesh_extractors/extract_mesh_vbo_lnor.cc | 12 +- .../extract_mesh_vbo_mesh_analysis.cc | 46 ++- .../mesh_extractors/extract_mesh_vbo_orco.cc | 8 +- .../extract_mesh_vbo_pos_nor.cc | 13 +- .../extract_mesh_vbo_sculpt_data.cc | 16 +- .../extract_mesh_vbo_select_idx.cc | 17 +- .../mesh_extractors/extract_mesh_vbo_tan.cc | 3 +- .../extract_mesh_vbo_weights.cc | 11 +- .../blender/editors/armature/meshlaplacian.cc | 30 +- source/blender/editors/mesh/editface.cc | 60 ++-- source/blender/editors/mesh/editmesh_undo.cc | 36 +++ source/blender/editors/mesh/mesh_data.cc | 33 +- source/blender/editors/mesh/meshtools.cc | 29 +- .../blender/editors/object/object_bake_api.cc | 16 +- .../editors/sculpt_paint/paint_hide.cc | 2 +- .../editors/sculpt_paint/paint_image_proj.cc | 13 +- .../editors/sculpt_paint/paint_mask.cc | 14 +- .../editors/sculpt_paint/paint_vertex.cc | 91 ++---- .../sculpt_paint/paint_vertex_weight_ops.cc | 16 +- source/blender/editors/sculpt_paint/sculpt.cc | 34 +-- .../editors/sculpt_paint/sculpt_dyntopo.cc | 4 +- .../editors/sculpt_paint/sculpt_expand.cc | 42 ++- .../editors/sculpt_paint/sculpt_face_set.cc | 30 +- .../editors/sculpt_paint/sculpt_geodesic.cc | 15 +- .../editors/sculpt_paint/sculpt_intern.hh | 1 + .../editors/sculpt_paint/sculpt_undo.cc | 4 + .../spreadsheet_data_source_geometry.cc | 8 +- .../editors/space_view3d/drawobject.cc | 7 +- .../transform/transform_snap_object.cc | 12 +- .../editors/uvedit/uvedit_unwrap_ops.cc | 9 +- .../blender_interface/BlenderFileLoader.cpp | 2 +- .../BlenderStrokeRenderer.cpp | 11 +- .../geometry/intern/mesh_flip_faces.cc | 7 +- .../geometry/intern/mesh_merge_by_distance.cc | 36 +-- .../geometry/intern/mesh_primitive_cuboid.cc | 24 +- .../geometry/intern/mesh_split_edges.cc | 9 +- .../geometry/intern/realize_instances.cc | 17 +- .../io/alembic/exporter/abc_writer_mesh.cc | 20 +- .../io/alembic/intern/abc_customdata.cc | 55 ++-- .../io/alembic/intern/abc_customdata.h | 5 +- .../io/alembic/intern/abc_reader_mesh.cc | 18 +- .../blender/io/collada/GeometryExporter.cpp | 43 ++- source/blender/io/collada/MeshImporter.cpp | 24 +- source/blender/io/collada/MeshImporter.h | 6 +- .../ply/exporter/ply_export_load_plydata.cc | 16 +- .../io/ply/importer/ply_import_mesh.cc | 7 +- .../io/stl/importer/stl_import_mesh.cc | 14 +- .../blender/io/usd/intern/usd_reader_mesh.cc | 45 ++- .../blender/io/usd/intern/usd_reader_shape.cc | 21 +- .../blender/io/usd/intern/usd_writer_mesh.cc | 17 +- .../wavefront_obj/exporter/obj_export_mesh.cc | 40 +-- .../wavefront_obj/exporter/obj_export_mesh.hh | 2 +- .../wavefront_obj/importer/obj_import_mesh.cc | 6 +- .../blender/makesdna/DNA_customdata_types.h | 1 - source/blender/makesdna/DNA_mesh_types.h | 23 +- source/blender/makesdna/DNA_meshdata_types.h | 79 ++--- source/blender/makesrna/intern/rna_mesh.c | 76 +++-- source/blender/makesrna/intern/rna_mesh_api.c | 4 +- source/blender/makesrna/intern/rna_particle.c | 4 +- source/blender/modifiers/intern/MOD_array.cc | 15 +- source/blender/modifiers/intern/MOD_build.cc | 38 +-- .../modifiers/intern/MOD_correctivesmooth.cc | 16 +- .../blender/modifiers/intern/MOD_explode.cc | 4 +- .../modifiers/intern/MOD_laplaciansmooth.cc | 22 +- source/blender/modifiers/intern/MOD_mask.cc | 70 ++--- .../blender/modifiers/intern/MOD_meshcache.c | 2 +- .../modifiers/intern/MOD_meshsequencecache.cc | 4 +- .../modifiers/intern/MOD_normal_edit.cc | 16 +- source/blender/modifiers/intern/MOD_ocean.cc | 18 +- .../modifiers/intern/MOD_particleinstance.cc | 20 +- source/blender/modifiers/intern/MOD_remesh.cc | 10 +- source/blender/modifiers/intern/MOD_screw.cc | 31 +- .../modifiers/intern/MOD_solidify_extrude.cc | 89 +++--- .../intern/MOD_solidify_nonmanifold.cc | 106 +++---- .../modifiers/intern/MOD_surfacedeform.cc | 51 ++-- source/blender/modifiers/intern/MOD_util.cc | 8 +- .../blender/modifiers/intern/MOD_uvproject.cc | 22 +- source/blender/modifiers/intern/MOD_uvwarp.cc | 14 +- .../modifiers/intern/MOD_weighted_normal.cc | 49 ++- .../geometry/nodes/node_geo_blur_attribute.cc | 12 +- .../geometry/nodes/node_geo_convex_hull.cc | 6 +- .../geometry/nodes/node_geo_curve_fill.cc | 5 +- .../nodes/node_geo_delete_geometry.cc | 116 ++++---- .../geometry/nodes/node_geo_dual_mesh.cc | 60 ++-- .../nodes/node_geo_duplicate_elements.cc | 25 +- .../nodes/node_geo_edges_to_face_groups.cc | 2 +- .../geometry/nodes/node_geo_extrude_mesh.cc | 147 +++++---- .../nodes/node_geo_input_mesh_edge_angle.cc | 35 +-- .../nodes/node_geo_input_mesh_face_area.cc | 5 +- .../node_geo_input_mesh_face_is_planar.cc | 8 +- .../node_geo_input_mesh_face_neighbors.cc | 9 +- .../node_geo_mesh_face_group_boundaries.cc | 5 +- .../nodes/node_geo_mesh_primitive_circle.cc | 14 +- .../nodes/node_geo_mesh_primitive_cone.cc | 37 +-- .../nodes/node_geo_mesh_primitive_grid.cc | 11 +- .../node_geo_mesh_primitive_uv_sphere.cc | 31 +- .../node_geo_mesh_topology_corners_of_face.cc | 14 +- .../node_geo_mesh_topology_edges_of_corner.cc | 8 +- .../node_geo_mesh_topology_face_of_corner.cc | 9 +- ...geo_mesh_topology_offset_corner_in_face.cc | 9 +- .../geometry/nodes/node_geo_sample_nearest.cc | 5 +- .../geometry/nodes/node_geo_scale_elements.cc | 23 +- .../nodes/node_geo_uv_pack_islands.cc | 20 +- .../geometry/nodes/node_geo_uv_unwrap.cc | 20 +- .../geometry/nodes/node_geo_volume_to_mesh.cc | 4 +- source/blender/render/intern/bake.cc | 6 +- source/blender/render/intern/multires_bake.cc | 81 ++--- .../blender/render/intern/texture_margin.cc | 29 +- 209 files changed, 2769 insertions(+), 2983 deletions(-) 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);