diff --git a/source/blender/blenkernel/intern/multires_reshape_smooth.cc b/source/blender/blenkernel/intern/multires_reshape_smooth.cc index 6dff0ff69f2..75aa02a2d8f 100644 --- a/source/blender/blenkernel/intern/multires_reshape_smooth.cc +++ b/source/blender/blenkernel/intern/multires_reshape_smooth.cc @@ -47,12 +47,12 @@ * traversing the final limit surface. */ struct SurfacePoint { - float P[3]; - float tangent_matrix[3][3]; + blender::float3 P; + blender::float3x3 tangent_matrix; }; struct SurfaceGrid { - SurfacePoint *points; + blender::Array points; }; /* Geometry elements which are used to simplify creation of topology refiner at the sculpt level. @@ -62,14 +62,15 @@ struct Vertex { /* All grid coordinates which the vertex corresponding to. * For a vertices which are created from inner points of grids there is always one coordinate. */ int num_grid_coords; - GridCoord *grid_coords; + blender::Vector grid_coords; float sharpness; bool is_infinite_sharp; }; struct Corner { - const Vertex *vertex; + /* Indexes into the geometry.vertices array */ + int vert_index; int grid_index; }; @@ -87,7 +88,8 @@ struct LinearGridElement { }; struct LinearGrid { - LinearGridElement *elements; + /* Span pointing to section of `elements_storage` in `LinearGrids` */ + blender::MutableSpan elements; }; struct LinearGrids { @@ -98,10 +100,10 @@ struct LinearGrids { int grid_size; /* Indexed by grid index. */ - LinearGrid *grids; + blender::Array grids; /* Elements for all grids are allocated in a single array, for the allocation performance. */ - LinearGridElement *elements_storage; + blender::Array elements_storage; }; /* Context which holds all information needed during propagation and smoothing. */ @@ -111,8 +113,7 @@ struct MultiresReshapeSmoothContext { /* Geometry at a reshape multires level. */ struct { - int num_vertices; - Vertex *vertices; + blender::Array vertices; /* Maximum number of edges which might be stored in the edges array. * Is calculated based on the number of edges in the base mesh and the subdivision level. */ @@ -122,10 +123,10 @@ struct MultiresReshapeSmoothContext { * * NOTE: Different type from others to be able to easier use atomic ops. */ size_t num_edges; - Edge *edges; + blender::Array edges; int num_corners; - Corner *corners; + blender::Array corners; int num_faces; /* Face topology of subdivision level. */ @@ -155,7 +156,7 @@ struct MultiresReshapeSmoothContext { * understand what it actually means in a concrete example. This is a generic code which is also * used by Subdivide operation, but the idea is exactly the same as propagation in the sculpt * mode. */ - SurfaceGrid *base_surface_grids; + blender::Array base_surface_grids; /* Defines how displacement is interpolated on the higher levels (for example, whether * displacement is smoothed in Catmull-Clark mode or interpolated linearly preserving sharp edges @@ -176,9 +177,6 @@ static void linear_grids_init(LinearGrids *linear_grids) { linear_grids->num_grids = 0; linear_grids->level = 0; - - linear_grids->grids = nullptr; - linear_grids->elements_storage = nullptr; } static void linear_grids_allocate(LinearGrids *linear_grids, int num_grids, int level) @@ -191,17 +189,17 @@ static void linear_grids_allocate(LinearGrids *linear_grids, int num_grids, int linear_grids->level = level; linear_grids->grid_size = grid_size; - linear_grids->grids = MEM_malloc_arrayN(size_t(num_grids), __func__); - linear_grids->elements_storage = MEM_calloc_arrayN(num_grid_elements, - __func__); + linear_grids->grids.reinitialize(num_grids); + linear_grids->elements_storage.reinitialize(num_grid_elements); for (int i = 0; i < num_grids; ++i) { const size_t element_offset = grid_area * i; - linear_grids->grids[i].elements = &linear_grids->elements_storage[element_offset]; + linear_grids->grids[i].elements = linear_grids->elements_storage.as_mutable_span().slice( + element_offset, grid_area); } } -static LinearGridElement *linear_grid_element_get(const LinearGrids *linear_grids, +static LinearGridElement *linear_grid_element_get(LinearGrids *linear_grids, const GridCoord *grid_coord) { BLI_assert(grid_coord->grid_index >= 0); @@ -217,12 +215,6 @@ static LinearGridElement *linear_grid_element_get(const LinearGrids *linear_grid return &grid->elements[grid_element_index]; } -static void linear_grids_free(LinearGrids *linear_grids) -{ - MEM_SAFE_FREE(linear_grids->grids); - MEM_SAFE_FREE(linear_grids->elements_storage); -} - static void linear_grid_element_init(LinearGridElement *linear_grid_element) { linear_grid_element->mask = 0.0f; @@ -258,32 +250,15 @@ static void base_surface_grids_allocate(MultiresReshapeSmoothContext *reshape_sm const int grid_size = reshape_context->top.grid_size; const int grid_area = grid_size * grid_size; - SurfaceGrid *surface_grid = MEM_malloc_arrayN(size_t(num_grids), __func__); + reshape_smooth_context->base_surface_grids.reinitialize(num_grids); - for (int grid_index = 0; grid_index < num_grids; ++grid_index) { - surface_grid[grid_index].points = MEM_calloc_arrayN(grid_area, __func__); + for (const int i : reshape_smooth_context->base_surface_grids.index_range()) { + reshape_smooth_context->base_surface_grids[i].points.reinitialize(grid_area); } - - reshape_smooth_context->base_surface_grids = surface_grid; } -static void base_surface_grids_free(MultiresReshapeSmoothContext *reshape_smooth_context) -{ - if (reshape_smooth_context->base_surface_grids == nullptr) { - return; - } - - const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context; - - const int num_grids = reshape_context->num_grids; - for (int grid_index = 0; grid_index < num_grids; ++grid_index) { - MEM_freeN(reshape_smooth_context->base_surface_grids[grid_index].points); - } - MEM_freeN(reshape_smooth_context->base_surface_grids); -} - -static SurfacePoint *base_surface_grids_read( - const MultiresReshapeSmoothContext *reshape_smooth_context, const GridCoord *grid_coord) +static SurfacePoint *base_surface_grids_read(MultiresReshapeSmoothContext *reshape_smooth_context, + const GridCoord *grid_coord) { const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context; @@ -297,14 +272,14 @@ static SurfacePoint *base_surface_grids_read( return &surface_grid->points[grid_element_index]; } -static void base_surface_grids_write(const MultiresReshapeSmoothContext *reshape_smooth_context, +static void base_surface_grids_write(MultiresReshapeSmoothContext *reshape_smooth_context, const GridCoord *grid_coord, float P[3], float tangent_matrix[3][3]) { SurfacePoint *point = base_surface_grids_read(reshape_smooth_context, grid_coord); copy_v3_v3(point->P, P); - copy_m3_m3(point->tangent_matrix, tangent_matrix); + copy_m3_m3(point->tangent_matrix.ptr(), tangent_matrix); } /** \} */ @@ -330,9 +305,10 @@ static int get_face_grid_index(const MultiresReshapeSmoothContext *reshape_smoot return grid_index; } -static GridCoord *vertex_grid_coord_with_grid_index(const Vertex *vertex, const int grid_index) +static const GridCoord *vertex_grid_coord_with_grid_index(const Vertex *vertex, + const int grid_index) { - for (int i = 0; i < vertex->num_grid_coords; ++i) { + for (const int i : vertex->grid_coords.index_range()) { if (vertex->grid_coords[i].grid_index == grid_index) { return &vertex->grid_coords[i]; } @@ -342,7 +318,7 @@ static GridCoord *vertex_grid_coord_with_grid_index(const Vertex *vertex, const /* Get grid coordinates which correspond to corners of the given face. * All the grid coordinates will be from the same grid index. */ -static void grid_coords_from_face_verts(const MultiresReshapeSmoothContext *reshape_smooth_context, +static void grid_coords_from_face_verts(MultiresReshapeSmoothContext *reshape_smooth_context, const blender::IndexRange face, const GridCoord *grid_coords[]) { @@ -353,8 +329,9 @@ static void grid_coords_from_face_verts(const MultiresReshapeSmoothContext *resh for (const int i : face.index_range()) { const int corner_index = face[i]; - const Corner *corner = &reshape_smooth_context->geometry.corners[corner_index]; - grid_coords[i] = vertex_grid_coord_with_grid_index(corner->vertex, grid_index); + Corner *corner = &reshape_smooth_context->geometry.corners[corner_index]; + grid_coords[i] = vertex_grid_coord_with_grid_index( + &reshape_smooth_context->geometry.vertices[corner->vert_index], grid_index); BLI_assert(grid_coords[i] != nullptr); } } @@ -397,7 +374,7 @@ static void interpolate_grid_coord(GridCoord *result, } static void foreach_toplevel_grid_coord( - const MultiresReshapeSmoothContext *reshape_smooth_context, + MultiresReshapeSmoothContext *reshape_smooth_context, blender::FunctionRef callback) { using namespace blender; @@ -484,15 +461,8 @@ static void context_init(MultiresReshapeSmoothContext *reshape_smooth_context, { reshape_smooth_context->reshape_context = reshape_context; - reshape_smooth_context->geometry.num_vertices = 0; - reshape_smooth_context->geometry.vertices = nullptr; - reshape_smooth_context->geometry.max_edges = 0; reshape_smooth_context->geometry.num_edges = 0; - reshape_smooth_context->geometry.edges = nullptr; - - reshape_smooth_context->geometry.num_corners = 0; - reshape_smooth_context->geometry.corners = nullptr; reshape_smooth_context->geometry.num_faces = 0; @@ -500,26 +470,10 @@ static void context_init(MultiresReshapeSmoothContext *reshape_smooth_context, reshape_smooth_context->loose_base_edges = {}; reshape_smooth_context->reshape_subdiv = nullptr; - reshape_smooth_context->base_surface_grids = nullptr; reshape_smooth_context->smoothing_type = mode; } -static void context_free_geometry(MultiresReshapeSmoothContext *reshape_smooth_context) -{ - if (reshape_smooth_context->geometry.vertices != nullptr) { - for (int i = 0; i < reshape_smooth_context->geometry.num_vertices; ++i) { - MEM_SAFE_FREE(reshape_smooth_context->geometry.vertices[i].grid_coords); - } - } - MEM_SAFE_FREE(reshape_smooth_context->geometry.vertices); - MEM_SAFE_FREE(reshape_smooth_context->geometry.corners); - reshape_smooth_context->geometry.face_offsets = {}; - MEM_SAFE_FREE(reshape_smooth_context->geometry.edges); - - linear_grids_free(&reshape_smooth_context->linear_delta_grids); -} - static void context_free_subdiv(MultiresReshapeSmoothContext *reshape_smooth_context) { if (reshape_smooth_context->reshape_subdiv == nullptr) { @@ -530,9 +484,7 @@ static void context_free_subdiv(MultiresReshapeSmoothContext *reshape_smooth_con static void context_free(MultiresReshapeSmoothContext *reshape_smooth_context) { - context_free_geometry(reshape_smooth_context); context_free_subdiv(reshape_smooth_context); - base_surface_grids_free(reshape_smooth_context); } static bool foreach_topology_info(const blender::bke::subdiv::ForeachContext *foreach_context, @@ -549,18 +501,12 @@ static bool foreach_topology_info(const blender::bke::subdiv::ForeachContext *fo num_edges : reshape_smooth_context->geometry.max_edges; - /* NOTE: Calloc so the counters are re-set to 0 "for free". */ - reshape_smooth_context->geometry.num_vertices = num_vertices; - reshape_smooth_context->geometry.vertices = MEM_calloc_arrayN(num_vertices, - "smooth vertices"); + reshape_smooth_context->geometry.vertices.reinitialize(num_vertices); reshape_smooth_context->geometry.max_edges = max_edges; - reshape_smooth_context->geometry.edges = MEM_malloc_arrayN(size_t(max_edges), - "smooth edges"); + reshape_smooth_context->geometry.edges.reinitialize(max_edges); - reshape_smooth_context->geometry.num_corners = num_loops; - reshape_smooth_context->geometry.corners = MEM_malloc_arrayN(size_t(num_loops), - "smooth corners"); + reshape_smooth_context->geometry.corners.reinitialize(num_loops); reshape_smooth_context->geometry.num_faces = num_faces; reshape_smooth_context->geometry.face_offsets.reinitialize(num_faces + 1); @@ -574,17 +520,14 @@ static void foreach_single_vertex(const blender::bke::subdiv::ForeachContext *fo const int coarse_vertex_index, const int subdiv_vertex_index) { - const MultiresReshapeSmoothContext *reshape_smooth_context = + MultiresReshapeSmoothContext *reshape_smooth_context = static_cast(foreach_context->user_data); - BLI_assert(subdiv_vertex_index < reshape_smooth_context->geometry.num_vertices); + BLI_assert(subdiv_vertex_index < reshape_smooth_context->geometry.vertices.size()); Vertex *vertex = &reshape_smooth_context->geometry.vertices[subdiv_vertex_index]; - vertex->grid_coords = static_cast( - MEM_reallocN(vertex->grid_coords, sizeof(Vertex) * (vertex->num_grid_coords + 1))); - vertex->grid_coords[vertex->num_grid_coords] = *grid_coord; - ++vertex->num_grid_coords; + vertex->grid_coords.append(*grid_coord); if (coarse_vertex_index == -1) { return; @@ -718,14 +661,14 @@ static void foreach_loop(const blender::bke::subdiv::ForeachContext *foreach_con const int subdiv_vertex_index, const int /*subdiv_edge_index*/) { - const MultiresReshapeSmoothContext *reshape_smooth_context = - static_cast(foreach_context->user_data); + MultiresReshapeSmoothContext *reshape_smooth_context = + static_cast(foreach_context->user_data); const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context; - BLI_assert(subdiv_loop_index < reshape_smooth_context->geometry.num_corners); + BLI_assert(subdiv_loop_index < reshape_smooth_context->geometry.corners.size()); Corner *corner = &reshape_smooth_context->geometry.corners[subdiv_loop_index]; - corner->vertex = &reshape_smooth_context->geometry.vertices[subdiv_vertex_index]; + corner->vert_index = subdiv_vertex_index; const int first_grid_index = reshape_context->face_start_grid_index[coarse_face_index]; corner->grid_index = first_grid_index + coarse_corner; @@ -753,11 +696,11 @@ static void foreach_vertex_of_loose_edge( const float /*u*/, const int vertex_index) { - const MultiresReshapeSmoothContext *reshape_smooth_context = - static_cast(foreach_context->user_data); + MultiresReshapeSmoothContext *reshape_smooth_context = + static_cast(foreach_context->user_data); Vertex *vertex = &reshape_smooth_context->geometry.vertices[vertex_index]; - if (vertex->num_grid_coords != 0) { + if (!vertex->grid_coords.is_empty()) { vertex->is_infinite_sharp = true; } } @@ -911,7 +854,7 @@ static int get_num_vertices(const OpenSubdiv_Converter *converter) const MultiresReshapeSmoothContext *reshape_smooth_context = static_cast(converter->user_data); - return reshape_smooth_context->geometry.num_vertices; + return reshape_smooth_context->geometry.vertices.size(); } static void get_face_vertices(const OpenSubdiv_Converter *converter, @@ -927,7 +870,7 @@ static void get_face_vertices(const OpenSubdiv_Converter *converter, for (const int i : face.index_range()) { const int corner_index = face[i]; const Corner *corner = &reshape_smooth_context->geometry.corners[corner_index]; - face_vertices[i] = corner->vertex - reshape_smooth_context->geometry.vertices; + face_vertices[i] = corner->vert_index; } } @@ -965,7 +908,7 @@ static float get_vertex_sharpness(const OpenSubdiv_Converter *converter, const i { const MultiresReshapeSmoothContext *reshape_smooth_context = static_cast(converter->user_data); - BLI_assert(vertex_index < reshape_smooth_context->geometry.num_vertices); + BLI_assert(vertex_index < reshape_smooth_context->geometry.vertices.size()); const Vertex *vertex = &reshape_smooth_context->geometry.vertices[vertex_index]; return vertex->sharpness; @@ -976,7 +919,7 @@ static bool is_infinite_sharp_vertex(const OpenSubdiv_Converter *converter, int const MultiresReshapeSmoothContext *reshape_smooth_context = static_cast(converter->user_data); - BLI_assert(vertex_index < reshape_smooth_context->geometry.num_vertices); + BLI_assert(vertex_index < reshape_smooth_context->geometry.vertices.size()); const Vertex *vertex = &reshape_smooth_context->geometry.vertices[vertex_index]; return vertex->is_infinite_sharp; @@ -1058,7 +1001,7 @@ static void reshape_subdiv_refine(const MultiresReshapeSmoothContext *reshape_sm /* TODO(sergey): For non-trivial coarse_position_cb we should multi-thread this loop. */ - const int num_vertices = reshape_smooth_context->geometry.num_vertices; + const int num_vertices = reshape_smooth_context->geometry.vertices.size(); for (int i = 0; i < num_vertices; ++i) { const Vertex *vertex = &reshape_smooth_context->geometry.vertices[i]; float P[3]; @@ -1070,7 +1013,7 @@ static void reshape_subdiv_refine(const MultiresReshapeSmoothContext *reshape_sm BLI_INLINE const GridCoord *reshape_subdiv_refine_vertex_grid_coord(const Vertex *vertex) { - if (vertex->num_grid_coords == 0) { + if (vertex->grid_coords.is_empty()) { /* This is a loose vertex, the coordinate is not important. */ /* TODO(sergey): Once the subdiv_foreach() supports properly ignoring loose elements this * should become an assert instead. */ @@ -1266,7 +1209,7 @@ static void evaluate_linear_delta_grids(MultiresReshapeSmoothContext *reshape_sm }); } -static void propagate_linear_data_delta(const MultiresReshapeSmoothContext *reshape_smooth_context, +static void propagate_linear_data_delta(MultiresReshapeSmoothContext *reshape_smooth_context, ReshapeGridElement *final_grid_element, const GridCoord *grid_coord) { @@ -1290,7 +1233,7 @@ static void propagate_linear_data_delta(const MultiresReshapeSmoothContext *resh /** \name Evaluation of base surface * \{ */ -static void evaluate_base_surface_grids(const MultiresReshapeSmoothContext *reshape_smooth_context) +static void evaluate_base_surface_grids(MultiresReshapeSmoothContext *reshape_smooth_context) { foreach_toplevel_grid_coord( reshape_smooth_context, [&](const PTexCoord *ptex_coord, const GridCoord *grid_coord) { @@ -1338,7 +1281,7 @@ static void evaluate_final_original_point( } static void evaluate_higher_grid_positions_with_details( - const MultiresReshapeSmoothContext *reshape_smooth_context) + MultiresReshapeSmoothContext *reshape_smooth_context) { const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context; foreach_toplevel_grid_coord( @@ -1359,7 +1302,7 @@ static void evaluate_higher_grid_positions_with_details( * original sculpt level. */ float original_detail_delta_tangent[3]; float original_sculpt_tangent_matrix_inv[3][3]; - invert_m3_m3(original_sculpt_tangent_matrix_inv, orig_sculpt_point->tangent_matrix); + invert_m3_m3(original_sculpt_tangent_matrix_inv, orig_sculpt_point->tangent_matrix.ptr()); mul_v3_m3v3(original_detail_delta_tangent, original_sculpt_tangent_matrix_inv, original_detail_delta); @@ -1387,8 +1330,7 @@ static void evaluate_higher_grid_positions_with_details( }); } -static void evaluate_higher_grid_positions( - const MultiresReshapeSmoothContext *reshape_smooth_context) +static void evaluate_higher_grid_positions(MultiresReshapeSmoothContext *reshape_smooth_context) { const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context; foreach_toplevel_grid_coord(