diff --git a/source/blender/blenkernel/BKE_ccg.hh b/source/blender/blenkernel/BKE_ccg.hh index b62f63979f0..675165eee6f 100644 --- a/source/blender/blenkernel/BKE_ccg.hh +++ b/source/blender/blenkernel/BKE_ccg.hh @@ -104,18 +104,3 @@ inline blender::float3 &CCG_elem_offset_co(const CCGKey &key, CCGElem *elem, int { return CCG_elem_co(key, CCG_elem_offset(key, elem, offset)); } - -inline blender::float3 &CCG_elem_offset_no(const CCGKey &key, CCGElem *elem, int offset) -{ - return CCG_elem_no(key, CCG_elem_offset(key, elem, offset)); -} - -inline float &CCG_elem_offset_mask(const CCGKey &key, CCGElem *elem, int offset) -{ - return CCG_elem_mask(key, CCG_elem_offset(key, elem, offset)); -} - -inline CCGElem *CCG_elem_next(const CCGKey &key, CCGElem *elem) -{ - return CCG_elem_offset(key, elem, 1); -} diff --git a/source/blender/blenkernel/BKE_pbvh_api.hh b/source/blender/blenkernel/BKE_pbvh_api.hh index 2a35b86ed4c..bc8bab90c5a 100644 --- a/source/blender/blenkernel/BKE_pbvh_api.hh +++ b/source/blender/blenkernel/BKE_pbvh_api.hh @@ -37,7 +37,6 @@ struct BMLog; struct BMesh; -struct CCGElem; struct CCGKey; struct Depsgraph; struct IsectRayPrecalc; @@ -449,7 +448,7 @@ namespace blender::bke::pbvh { */ void update_bounds(const Depsgraph &depsgraph, const Object &object, Tree &pbvh); void update_bounds_mesh(Span vert_positions, Tree &pbvh); -void update_bounds_grids(const CCGKey &key, Span elems, Tree &pbvh); +void update_bounds_grids(const CCGKey &key, Span positions, Tree &pbvh); void update_bounds_bmesh(const BMesh &bm, Tree &pbvh); /** @@ -529,7 +528,7 @@ IndexMask node_draw_update_mask(const Tree &pbvh, IndexMaskMemory &memory); void node_update_mask_mesh(Span mask, MeshNode &node); -void node_update_mask_grids(const CCGKey &key, Span grids, GridsNode &node); +void node_update_mask_grids(const CCGKey &key, Span masks, GridsNode &node); void node_update_mask_bmesh(int mask_offset, BMeshNode &node); void node_update_visibility_mesh(Span hide_vert, MeshNode &node); @@ -537,7 +536,7 @@ void node_update_visibility_grids(const BitGroupVector<> &grid_hidden, GridsNode void node_update_visibility_bmesh(BMeshNode &node); void update_node_bounds_mesh(Span positions, MeshNode &node); -void update_node_bounds_grids(const CCGKey &key, Span grids, GridsNode &node); +void update_node_bounds_grids(const CCGKey &key, Span positions, GridsNode &node); void update_node_bounds_bmesh(BMeshNode &node); inline Span MeshNode::faces() const diff --git a/source/blender/blenkernel/BKE_subdiv_ccg.hh b/source/blender/blenkernel/BKE_subdiv_ccg.hh index a186dd4a655..54844a793ba 100644 --- a/source/blender/blenkernel/BKE_subdiv_ccg.hh +++ b/source/blender/blenkernel/BKE_subdiv_ccg.hh @@ -122,37 +122,19 @@ struct SubdivCCG : blender::NonCopyable { /* Resolution of grid. All grids have matching resolution, and resolution * is same as ptex created for non-quad faces. */ int grid_size = -1; - /* Size of a single element of a grid (including coordinate and all the other layers). - * Measured in bytes. */ - int grid_element_size = -1; - /* Grids represent limit surface, with displacement applied. Grids are - * corresponding to face-corners of coarse mesh, each grid has - * grid_size^2 elements. + /** The number of vertices in each grid (grid_size ^2). */ + int grid_area = -1; + /** The number of grids (face corners) in the geometry (#faces.total_size()). */ + int grids_num = -1; + /** + * Positions represent limit surface, with displacement applied. The vertices in each grid are + * stored in contiguous chunks of size #grid_area in the same order. */ - /* Indexed by a grid index, points to a grid data which is stored in - * grids_storage. */ - blender::Array grids; - /* Flat array of all grids' data. */ - blender::Array grids_storage; - /* Loose edges, each array element contains grid_size elements - * corresponding to vertices created by subdividing coarse edges. */ - CCGElem **edges = nullptr; - int num_edges = -1; - /* Loose vertices. Every element corresponds to a loose vertex from a coarse - * mesh, every coarse loose vertex corresponds to a single subdivided - * element. */ - CCGElem *vertices = nullptr; - int num_vertices = -1; - /* Denotes which layers present in the elements. - * - * Grids always has coordinates, followed by extra layers which are set to - * truth here. - */ - bool has_normal = false; - bool has_mask = false; - /* Offsets of corresponding data layers in the elements. */ - int normal_offset = -1; - int mask_offset = -1; + blender::Array positions; + /** Vertex normals with the same indexing as #positions. */ + blender::Array normals; + /** Optional mask values with the same indexing as #positions. */ + blender::Array masks; /* Faces from which grids are emitted. Owned by base mesh. */ blender::OffsetIndices faces; @@ -350,3 +332,30 @@ inline void BKE_subdiv_ccg_foreach_visible_grid_vert(const CCGKey &key, blender::bits::foreach_0_index(grid_hidden[grid], fn); } } + +namespace blender::bke::ccg { + +/** Find the range of vertices in the entire geometry that are part of a single grid. */ +inline IndexRange grid_range(const int grid_area, const int grid) +{ + return IndexRange(grid * grid_area, grid_area); +} +inline IndexRange grid_range(const CCGKey &key, const int grid) +{ + return IndexRange(grid * key.grid_area, key.grid_area); +} + +/** Find the range of vertices in the entire geometry that are part of a single face. */ +inline IndexRange face_range(const OffsetIndices faces, const CCGKey &key, const int face) +{ + const IndexRange corners = faces[face]; + return IndexRange(corners.start() * key.grid_area, corners.size() * key.grid_area); +} + +/** Find the vertex index in the entire geometry at a specific coordinate in a specific grid. */ +inline int grid_xy_to_vert(const CCGKey &key, const int grid, const int x, const int y) +{ + return key.grid_area * grid + CCG_grid_xy_to_index(key.grid_size, x, y); +} + +} // namespace blender::bke::ccg diff --git a/source/blender/blenkernel/intern/multires_reshape_ccg.cc b/source/blender/blenkernel/intern/multires_reshape_ccg.cc index f308e2465b7..f0fa935480d 100644 --- a/source/blender/blenkernel/intern/multires_reshape_ccg.cc +++ b/source/blender/blenkernel/intern/multires_reshape_ccg.cc @@ -18,18 +18,22 @@ bool multires_reshape_assign_final_coords_from_ccg(const MultiresReshapeContext *reshape_context, SubdivCCG *subdiv_ccg) { + using namespace blender; const CCGKey reshape_level_key = BKE_subdiv_ccg_key(*subdiv_ccg, reshape_context->reshape.level); const int reshape_grid_size = reshape_context->reshape.grid_size; const float reshape_grid_size_1_inv = 1.0f / (float(reshape_grid_size) - 1.0f); - int num_grids = subdiv_ccg->grids.size(); + const Span positions = subdiv_ccg->positions; + const Span masks = subdiv_ccg->masks; + + int num_grids = subdiv_ccg->grids_num; for (int grid_index = 0; grid_index < num_grids; ++grid_index) { - CCGElem *ccg_grid = subdiv_ccg->grids[grid_index]; for (int y = 0; y < reshape_grid_size; ++y) { const float v = float(y) * reshape_grid_size_1_inv; for (int x = 0; x < reshape_grid_size; ++x) { const float u = float(x) * reshape_grid_size_1_inv; + const int vert = bke::ccg::grid_xy_to_vert(reshape_level_key, grid_index, x, y); GridCoord grid_coord; grid_coord.grid_index = grid_index; @@ -40,9 +44,7 @@ bool multires_reshape_assign_final_coords_from_ccg(const MultiresReshapeContext reshape_context, &grid_coord); BLI_assert(grid_element.displacement != nullptr); - memcpy(grid_element.displacement, - CCG_grid_elem_co(reshape_level_key, ccg_grid, x, y), - sizeof(float[3])); + memcpy(grid_element.displacement, positions[vert], sizeof(float[3])); /* NOTE: The sculpt mode might have SubdivCCG's data out of sync from what is stored in * the original object. This happens in the following scenario: @@ -66,8 +68,8 @@ bool multires_reshape_assign_final_coords_from_ccg(const MultiresReshapeContext /* NOTE: There is a known bug in Undo code that results in first Sculpt step * after a Memfile one to never be undone (see #83806). This might be the root cause of * this inconsistency. */ - if (reshape_level_key.has_mask && grid_element.mask != nullptr) { - *grid_element.mask = CCG_grid_elem_mask(reshape_level_key, ccg_grid, x, y); + if (!subdiv_ccg->masks.is_empty() && grid_element.mask != nullptr) { + *grid_element.mask = masks[vert]; } } } diff --git a/source/blender/blenkernel/intern/paint.cc b/source/blender/blenkernel/intern/paint.cc index 88f68910823..81dbf9ef4e4 100644 --- a/source/blender/blenkernel/intern/paint.cc +++ b/source/blender/blenkernel/intern/paint.cc @@ -1814,8 +1814,7 @@ blender::float3 SculptSession::active_vert_position(const Depsgraph &depsgraph, if (std::holds_alternative(active_vert_)) { const CCGKey key = BKE_subdiv_ccg_key_top_level(*this->subdiv_ccg); const SubdivCCGCoord coord = std::get(active_vert_); - - return CCG_grid_elem_co(key, this->subdiv_ccg->grids[coord.grid_index], coord.x, coord.y); + return this->subdiv_ccg->positions[coord.to_index(key)]; } if (std::holds_alternative(active_vert_)) { BMVert *bm_vert = std::get(active_vert_); @@ -2519,7 +2518,7 @@ int BKE_sculptsession_vertex_count(const SculptSession *ss) return ss->bm->totvert; } if (ss->subdiv_ccg) { - return ss->subdiv_ccg->grids.size() * BKE_subdiv_ccg_key_top_level(*ss->subdiv_ccg).grid_area; + return ss->subdiv_ccg->positions.size(); } return ss->totvert; } diff --git a/source/blender/blenkernel/intern/pbvh.cc b/source/blender/blenkernel/intern/pbvh.cc index a279e369233..8334b7860d9 100644 --- a/source/blender/blenkernel/intern/pbvh.cc +++ b/source/blender/blenkernel/intern/pbvh.cc @@ -378,17 +378,14 @@ static int sum_group_sizes(const OffsetIndices groups, const Span indi return count; } -static Bounds calc_face_grid_bounds(const CCGKey &key, - const Span elems, - const IndexRange face) +static Bounds calc_face_grid_bounds(const OffsetIndices faces, + const Span positions, + const CCGKey &key, + const int face) { Bounds bounds = negative_bounds(); - for (const int grid : face) { - CCGElem *elem = elems[grid]; - for (const int i : IndexRange(key.grid_area)) { - const float3 &position = CCG_elem_offset_co(key, elem, i); - math::min_max(position, bounds.min, bounds.max); - } + for (const float3 &position : positions.slice(ccg::face_range(faces, key, face))) { + math::min_max(position, bounds.min, bounds.max); } return bounds; } @@ -406,7 +403,10 @@ std::unique_ptr build_grids(const Mesh &base_mesh, const SubdivCCG &subdiv } const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span elems = subdiv_ccg.grids; + const Span positions = subdiv_ccg.positions; + if (positions.is_empty()) { + return pbvh; + } const int leaf_limit = std::max(2500 / key.grid_area, 1); @@ -418,7 +418,7 @@ std::unique_ptr build_grids(const Mesh &base_mesh, const SubdivCCG &subdiv [&](const IndexRange range, const Bounds &init) { Bounds current = init; for (const int face : range) { - const Bounds bounds = calc_face_grid_bounds(key, elems, faces[face]); + const Bounds bounds = calc_face_grid_bounds(faces, positions, key, face); face_centers[face] = bounds.center(); current = bounds::merge(current, bounds); } @@ -470,7 +470,7 @@ std::unique_ptr build_grids(const Mesh &base_mesh, const SubdivCCG &subdiv } }); - update_bounds_grids(key, elems, *pbvh); + update_bounds_grids(key, positions, *pbvh); store_bounds_orig(*pbvh); const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden; @@ -1047,12 +1047,12 @@ void update_node_bounds_mesh(const Span positions, MeshNode &node) node.bounds_ = bounds; } -void update_node_bounds_grids(const CCGKey &key, const Span grids, GridsNode &node) +void update_node_bounds_grids(const CCGKey &key, const Span positions, GridsNode &node) { Bounds bounds = negative_bounds(); for (const int grid : node.grids()) { - for (const int i : IndexRange(key.grid_area)) { - math::min_max(CCG_elem_offset_co(key, grids[grid], i), bounds.min, bounds.max); + for (const float3 &position : positions.slice(bke::ccg::grid_range(key, grid))) { + math::min_max(position, bounds.min, bounds.max); } } node.bounds_ = bounds; @@ -1118,7 +1118,7 @@ void update_bounds_mesh(const Span vert_positions, Tree &pbvh) } } -void update_bounds_grids(const CCGKey &key, const Span elems, Tree &pbvh) +void update_bounds_grids(const CCGKey &key, const Span positions, Tree &pbvh) { IndexMaskMemory memory; const IndexMask nodes_to_update = search_nodes( @@ -1126,7 +1126,7 @@ void update_bounds_grids(const CCGKey &key, const Span elems, Tree &p MutableSpan nodes = pbvh.nodes(); nodes_to_update.foreach_index( - GrainSize(1), [&](const int i) { update_node_bounds_grids(key, elems, nodes[i]); }); + GrainSize(1), [&](const int i) { update_node_bounds_grids(key, positions, nodes[i]); }); if (!nodes.is_empty()) { flush_bounds_to_parents(pbvh); } @@ -1158,8 +1158,7 @@ void update_bounds(const Depsgraph &depsgraph, const Object &object, Tree &pbvh) const SculptSession &ss = *object.sculpt; const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span elems = subdiv_ccg.grids; - update_bounds_grids(key, elems, pbvh); + update_bounds_grids(key, subdiv_ccg.positions, pbvh); break; } case Type::BMesh: { @@ -1214,15 +1213,13 @@ static void update_mask_mesh(const Mesh &mesh, [&](const int i) { node_update_mask_mesh(mask, nodes[i]); }); } -void node_update_mask_grids(const CCGKey &key, const Span grids, GridsNode &node) +void node_update_mask_grids(const CCGKey &key, const Span masks, GridsNode &node) { BLI_assert(key.has_mask); bool fully_masked = true; bool fully_unmasked = true; for (const int grid : node.grids()) { - CCGElem *elem = grids[grid]; - for (const int i : IndexRange(key.grid_area)) { - const float mask = CCG_elem_offset_mask(key, elem, i); + for (const float mask : masks.slice(bke::ccg::grid_range(key, grid))) { fully_masked &= mask == 1.0f; fully_unmasked &= mask <= 0.0f; } @@ -1237,7 +1234,7 @@ static void update_mask_grids(const SubdivCCG &subdiv_ccg, const IndexMask &nodes_to_update) { const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - if (!key.has_mask) { + if (subdiv_ccg.masks.is_empty()) { nodes_to_update.foreach_index([&](const int i) { nodes[i].flag_ &= ~PBVH_FullyMasked; nodes[i].flag_ |= PBVH_FullyUnmasked; @@ -1247,7 +1244,7 @@ static void update_mask_grids(const SubdivCCG &subdiv_ccg, } nodes_to_update.foreach_index( - GrainSize(1), [&](const int i) { node_update_mask_grids(key, subdiv_ccg.grids, nodes[i]); }); + GrainSize(1), [&](const int i) { node_update_mask_grids(key, subdiv_ccg.masks, nodes[i]); }); } void node_update_mask_bmesh(const int mask_offset, BMeshNode &node) @@ -1510,7 +1507,7 @@ int BKE_pbvh_get_grid_num_verts(const Object &object) const SculptSession &ss = *object.sculpt; BLI_assert(blender::bke::object::pbvh_get(object)->type() == blender::bke::pbvh::Type::Grids); const CCGKey key = BKE_subdiv_ccg_key_top_level(*ss.subdiv_ccg); - return ss.subdiv_ccg->grids.size() * key.grid_area; + return ss.subdiv_ccg->grids_num * key.grid_area; } int BKE_pbvh_get_grid_num_faces(const Object &object) @@ -1518,7 +1515,7 @@ int BKE_pbvh_get_grid_num_faces(const Object &object) const SculptSession &ss = *object.sculpt; BLI_assert(blender::bke::object::pbvh_get(object)->type() == blender::bke::pbvh::Type::Grids); const CCGKey key = BKE_subdiv_ccg_key_top_level(*ss.subdiv_ccg); - return ss.subdiv_ccg->grids.size() * square_i(key.grid_size - 1); + return ss.subdiv_ccg->grids_num * square_i(key.grid_size - 1); } /***************************** Node Access ***********************************/ @@ -2027,12 +2024,11 @@ static bool pbvh_grids_node_raycast(const SubdivCCG &subdiv_ccg, const int grid_size = key.grid_size; bool hit = false; const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden; - const Span elems = subdiv_ccg.grids; + const Span positions = subdiv_ccg.positions; if (node_positions.is_empty()) { for (const int grid : grids) { - CCGElem *elem = elems[grid]; - + const Span grid_positions = positions.slice(bke::ccg::grid_range(key, grid)); for (const short y : IndexRange(grid_size - 1)) { for (const short x : IndexRange(grid_size - 1)) { if (!grid_hidden.is_empty()) { @@ -2040,10 +2036,11 @@ static bool pbvh_grids_node_raycast(const SubdivCCG &subdiv_ccg, continue; } } - const std::array co{{CCG_grid_elem_co(key, elem, x, y + 1), - CCG_grid_elem_co(key, elem, x + 1, y + 1), - CCG_grid_elem_co(key, elem, x + 1, y), - CCG_grid_elem_co(key, elem, x, y)}}; + const std::array co{ + {grid_positions[CCG_grid_xy_to_index(grid_size, x, y + 1)], + grid_positions[CCG_grid_xy_to_index(grid_size, x + 1, y + 1)], + grid_positions[CCG_grid_xy_to_index(grid_size, x + 1, y)], + grid_positions[CCG_grid_xy_to_index(grid_size, x, y)]}}; if (ray_face_intersection_quad( ray_start, isect_precalc, co[0], co[1], co[2], co[3], depth)) { @@ -2362,12 +2359,12 @@ static bool pbvh_grids_node_nearest_to_ray(const SubdivCCG &subdiv_ccg, const Span grids = node.grids(); const int grid_size = key.grid_size; const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden; - const Span elems = subdiv_ccg.grids; + const Span positions = subdiv_ccg.positions; bool hit = false; if (node_positions.is_empty()) { for (const int grid : grids) { - CCGElem *elem = elems[grid]; + const Span grid_positions = positions.slice(bke::ccg::grid_range(key, grid)); for (const short y : IndexRange(grid_size - 1)) { for (const short x : IndexRange(grid_size - 1)) { if (!grid_hidden.is_empty()) { @@ -2375,14 +2372,15 @@ static bool pbvh_grids_node_nearest_to_ray(const SubdivCCG &subdiv_ccg, continue; } } - hit |= ray_face_nearest_quad(ray_start, - ray_normal, - CCG_grid_elem_co(key, elem, x, y), - CCG_grid_elem_co(key, elem, x + 1, y), - CCG_grid_elem_co(key, elem, x + 1, y + 1), - CCG_grid_elem_co(key, elem, x, y + 1), - depth, - dist_sq); + hit |= ray_face_nearest_quad( + ray_start, + ray_normal, + grid_positions[CCG_grid_xy_to_index(grid_size, x, y)], + grid_positions[CCG_grid_xy_to_index(grid_size, x + 1, y)], + grid_positions[CCG_grid_xy_to_index(grid_size, x + 1, y + 1)], + grid_positions[CCG_grid_xy_to_index(grid_size, x, y + 1)], + depth, + dist_sq); } } } @@ -2390,7 +2388,7 @@ static bool pbvh_grids_node_nearest_to_ray(const SubdivCCG &subdiv_ccg, else { for (const int i : grids.index_range()) { const int grid = grids[i]; - const Span grid_positions = node_positions.slice(key.grid_area * i, key.grid_area); + const Span grid_positions = node_positions.slice(bke::ccg::grid_range(key, i)); for (const short y : IndexRange(grid_size - 1)) { for (const short x : IndexRange(grid_size - 1)) { if (!grid_hidden.is_empty()) { diff --git a/source/blender/blenkernel/intern/subdiv_ccg.cc b/source/blender/blenkernel/intern/subdiv_ccg.cc index 069aa3b8c80..aa461065f66 100644 --- a/source/blender/blenkernel/intern/subdiv_ccg.cc +++ b/source/blender/blenkernel/intern/subdiv_ccg.cc @@ -38,6 +38,7 @@ using blender::Span; using blender::Vector; using blender::VectorSet; using namespace blender::bke::subdiv; +using namespace blender::bke::ccg; /* -------------------------------------------------------------------- */ /** \name Various forward declarations @@ -55,65 +56,10 @@ void subdiv_ccg_average_faces_boundaries_and_corners(SubdivCCG &subdiv_ccg, /** \} */ -/* -------------------------------------------------------------------- */ -/** \name Generally useful internal helpers - * \{ */ - -/* Number of floats in per-vertex elements. */ -static int num_element_float_get(const SubdivCCG &subdiv_ccg) -{ - /* We always have 3 floats for coordinate. */ - int num_floats = 3; - if (subdiv_ccg.has_normal) { - num_floats += 3; - } - if (subdiv_ccg.has_mask) { - num_floats += 1; - } - return num_floats; -} - -/* Per-vertex element size in bytes. */ -static int element_size_bytes_get(const SubdivCCG &subdiv_ccg) -{ - return sizeof(float) * num_element_float_get(subdiv_ccg); -} - -/** \} */ - /* -------------------------------------------------------------------- */ /** \name Internal helpers for CCG creation * \{ */ -static void subdiv_ccg_init_layers(SubdivCCG &subdiv_ccg, const SubdivToCCGSettings &settings) -{ - /* CCG always contains coordinates. Rest of layers are coming after them. */ - int layer_offset = sizeof(float[3]); - /* Mask. */ - if (settings.need_mask) { - subdiv_ccg.has_mask = true; - subdiv_ccg.mask_offset = layer_offset; - layer_offset += sizeof(float); - } - else { - subdiv_ccg.has_mask = false; - subdiv_ccg.mask_offset = -1; - } - /* Normals. - * - * NOTE: Keep them at the end, matching old CCGDM. Doesn't really matter - * here, but some other area might in theory depend memory layout. */ - if (settings.need_normal) { - subdiv_ccg.has_normal = true; - subdiv_ccg.normal_offset = layer_offset; - layer_offset += sizeof(float[3]); - } - else { - subdiv_ccg.has_normal = false; - subdiv_ccg.normal_offset = -1; - } -} - /* TODO(sergey): Make it more accessible function. */ static int topology_refiner_count_face_corners(const OpenSubdiv_TopologyRefiner *topology_refiner) { @@ -127,21 +73,21 @@ static int topology_refiner_count_face_corners(const OpenSubdiv_TopologyRefiner /* NOTE: Grid size and layer flags are to be filled in before calling this * function. */ -static void subdiv_ccg_alloc_elements(SubdivCCG &subdiv_ccg, Subdiv &subdiv) +static void subdiv_ccg_alloc_elements(SubdivCCG &subdiv_ccg, + Subdiv &subdiv, + const SubdivToCCGSettings &settings) { const OpenSubdiv_TopologyRefiner *topology_refiner = subdiv.topology_refiner; - const int64_t element_size = element_size_bytes_get(subdiv_ccg); /* Allocate memory for surface grids. */ const int64_t num_grids = topology_refiner_count_face_corners(topology_refiner); const int64_t grid_size = grid_size_from_level(subdiv_ccg.level); const int64_t grid_area = grid_size * grid_size; - subdiv_ccg.grid_element_size = element_size; - subdiv_ccg.grids.reinitialize(num_grids); - subdiv_ccg.grids_storage.reinitialize(num_grids * grid_area * element_size); - const size_t grid_size_in_bytes = size_t(grid_area) * element_size; - for (int grid_index = 0; grid_index < num_grids; grid_index++) { - const size_t grid_offset = grid_size_in_bytes * grid_index; - subdiv_ccg.grids[grid_index] = (CCGElem *)&subdiv_ccg.grids_storage[grid_offset]; + subdiv_ccg.positions.reinitialize(num_grids * grid_area); + if (settings.need_normal) { + subdiv_ccg.normals.reinitialize(num_grids * grid_area); + } + if (settings.need_mask) { + subdiv_ccg.masks.reinitialize(num_grids * grid_area); } /* TODO(sergey): Allocate memory for loose elements. */ } @@ -157,21 +103,21 @@ static void subdiv_ccg_eval_grid_element_limit(Subdiv &subdiv, const int ptex_face_index, const float u, const float v, - uchar *element) + const int element) { if (subdiv.displacement_evaluator != nullptr) { - eval_final_point(&subdiv, ptex_face_index, u, v, (float *)element); + eval_final_point(&subdiv, ptex_face_index, u, v, subdiv_ccg.positions[element]); } - else if (subdiv_ccg.has_normal) { + else if (!subdiv_ccg.normals.is_empty()) { eval_limit_point_and_normal(&subdiv, ptex_face_index, u, v, - (float *)element, - (float *)(element + subdiv_ccg.normal_offset)); + subdiv_ccg.positions[element], + subdiv_ccg.normals[element]); } else { - eval_limit_point(&subdiv, ptex_face_index, u, v, (float *)element); + eval_limit_point(&subdiv, ptex_face_index, u, v, subdiv_ccg.positions[element]); } } @@ -180,17 +126,16 @@ static void subdiv_ccg_eval_grid_element_mask(SubdivCCG &subdiv_ccg, const int ptex_face_index, const float u, const float v, - uchar *element) + const int element) { - if (!subdiv_ccg.has_mask) { + if (subdiv_ccg.masks.is_empty()) { return; } - float *mask_value_ptr = (float *)(element + subdiv_ccg.mask_offset); if (mask_evaluator != nullptr) { - *mask_value_ptr = mask_evaluator->eval_mask(mask_evaluator, ptex_face_index, u, v); + subdiv_ccg.masks[element] = mask_evaluator->eval_mask(mask_evaluator, ptex_face_index, u, v); } else { - *mask_value_ptr = 0.0f; + subdiv_ccg.masks[element] = 0.0f; } } @@ -200,7 +145,7 @@ static void subdiv_ccg_eval_grid_element(Subdiv &subdiv, const int ptex_face_index, const float u, const float v, - uchar *element) + const int element) { subdiv_ccg_eval_grid_element_limit(subdiv, subdiv_ccg, ptex_face_index, u, v, element); subdiv_ccg_eval_grid_element_mask(subdiv_ccg, mask_evaluator, ptex_face_index, u, v, element); @@ -214,22 +159,21 @@ static void subdiv_ccg_eval_regular_grid(Subdiv &subdiv, { const int ptex_face_index = face_ptex_offset[face_index]; const int grid_size = subdiv_ccg.grid_size; + const int grid_area = subdiv_ccg.grid_area; const float grid_size_1_inv = 1.0f / (grid_size - 1); - const int element_size = element_size_bytes_get(subdiv_ccg); const IndexRange face = subdiv_ccg.faces[face_index]; for (int corner = 0; corner < face.size(); corner++) { const int grid_index = face.start() + corner; - uchar *grid = (uchar *)subdiv_ccg.grids[grid_index]; + const IndexRange range = grid_range(grid_area, grid_index); for (int y = 0; y < grid_size; y++) { const float grid_v = y * grid_size_1_inv; for (int x = 0; x < grid_size; x++) { const float grid_u = x * grid_size_1_inv; float u, v; rotate_grid_to_quad(corner, grid_u, grid_v, &u, &v); - const size_t grid_element_index = size_t(y) * grid_size + x; - const size_t grid_element_offset = grid_element_index * element_size; + const int element = range[CCG_grid_xy_to_index(grid_size, x, y)]; subdiv_ccg_eval_grid_element( - subdiv, subdiv_ccg, mask_evaluator, ptex_face_index, u, v, &grid[grid_element_offset]); + subdiv, subdiv_ccg, mask_evaluator, ptex_face_index, u, v, element); } } } @@ -242,21 +186,20 @@ static void subdiv_ccg_eval_special_grid(Subdiv &subdiv, const int face_index) { const int grid_size = subdiv_ccg.grid_size; + const int grid_area = subdiv_ccg.grid_area; const float grid_size_1_inv = 1.0f / (grid_size - 1); - const int element_size = element_size_bytes_get(subdiv_ccg); const IndexRange face = subdiv_ccg.faces[face_index]; for (int corner = 0; corner < face.size(); corner++) { const int grid_index = face.start() + corner; const int ptex_face_index = face_ptex_offset[face_index] + corner; - uchar *grid = (uchar *)subdiv_ccg.grids[grid_index]; + const IndexRange range = grid_range(grid_area, grid_index); for (int y = 0; y < grid_size; y++) { const float u = 1.0f - (y * grid_size_1_inv); for (int x = 0; x < grid_size; x++) { const float v = 1.0f - (x * grid_size_1_inv); - const size_t grid_element_index = size_t(y) * grid_size + x; - const size_t grid_element_offset = grid_element_index * element_size; + const int element = range[CCG_grid_xy_to_index(grid_size, x, y)]; subdiv_ccg_eval_grid_element( - subdiv, subdiv_ccg, mask_evaluator, ptex_face_index, u, v, &grid[grid_element_offset]); + subdiv, subdiv_ccg, mask_evaluator, ptex_face_index, u, v, element); } } } @@ -304,13 +247,6 @@ static SubdivCCGCoord subdiv_ccg_coord(int grid_index, int x, int y) return coord; } -static CCGElem *subdiv_ccg_coord_to_elem(const CCGKey &key, - const SubdivCCG &subdiv_ccg, - const SubdivCCGCoord &coord) -{ - return CCG_grid_elem(key, subdiv_ccg.grids[coord.grid_index], coord.x, coord.y); -} - /* Returns storage where boundary elements are to be stored. */ static SubdivCCGCoord *subdiv_ccg_adjacent_edge_add_face(SubdivCCG &subdiv_ccg, SubdivCCGAdjacentEdge &adjacent_edge) @@ -469,10 +405,11 @@ std::unique_ptr BKE_subdiv_to_ccg(Subdiv &subdiv, subdiv_ccg->subdiv = &subdiv; subdiv_ccg->level = bitscan_forward_i(settings.resolution - 1); subdiv_ccg->grid_size = grid_size_from_level(subdiv_ccg->level); - subdiv_ccg_init_layers(*subdiv_ccg, settings); + subdiv_ccg->grid_area = subdiv_ccg->grid_size * subdiv_ccg->grid_size; subdiv_ccg->faces = coarse_mesh.faces(); + subdiv_ccg->grids_num = subdiv_ccg->faces.total_size(); subdiv_ccg->grid_to_face_map = coarse_mesh.corner_to_face_map(); - subdiv_ccg_alloc_elements(*subdiv_ccg, subdiv); + subdiv_ccg_alloc_elements(*subdiv_ccg, subdiv, settings); subdiv_ccg_init_faces_neighborhood(*subdiv_ccg); if (!subdiv_ccg_evaluate_grids(*subdiv_ccg, subdiv, mask_evaluator)) { stats_end(&subdiv.stats, SUBDIV_STATS_SUBDIV_TO_CCG); @@ -533,24 +470,26 @@ SubdivCCG::~SubdivCCG() } } -CCGKey BKE_subdiv_ccg_key(const SubdivCCG &subdiv_ccg, int level) +CCGKey BKE_subdiv_ccg_key(const SubdivCCG & /*subdiv_ccg*/, int level) { #ifdef WITH_OPENSUBDIV + /* Most #CCGKey fields are unused for #SubdivCCG but still used in other areas of Blender. + * Initialize them to invalid values to catch mistaken use more easily. */ CCGKey key; key.level = level; - key.elem_size = element_size_bytes_get(subdiv_ccg); + key.elem_size = -1; key.grid_size = grid_size_from_level(level); key.grid_area = key.grid_size * key.grid_size; - key.grid_bytes = key.elem_size * key.grid_area; + key.grid_bytes = -1; - key.normal_offset = subdiv_ccg.normal_offset; - key.mask_offset = subdiv_ccg.mask_offset; + key.normal_offset = -1; + key.mask_offset = -1; - key.has_normals = subdiv_ccg.has_normal; - key.has_mask = subdiv_ccg.has_mask; + key.has_normals = false; + key.has_mask = false; return key; #else - UNUSED_VARS(subdiv_ccg, level); + UNUSED_VARS(level); return {}; #endif } @@ -574,41 +513,36 @@ CCGKey BKE_subdiv_ccg_key_top_level(const SubdivCCG &subdiv_ccg) * * The result is stored in normals storage from TLS. */ static void subdiv_ccg_recalc_inner_face_normals(const SubdivCCG &subdiv_ccg, - const CCGKey &key, MutableSpan face_normals, const int corner) { const int grid_size = subdiv_ccg.grid_size; + const int grid_area = subdiv_ccg.grid_area; const int grid_size_1 = grid_size - 1; - CCGElem *grid = subdiv_ccg.grids[corner]; + const Span grid_positions = subdiv_ccg.positions.as_span().slice(grid_range(grid_area, corner)); for (int y = 0; y < grid_size - 1; y++) { for (int x = 0; x < grid_size - 1; x++) { - CCGElem *grid_elements[4] = { - CCG_grid_elem(key, grid, x, y + 1), - CCG_grid_elem(key, grid, x + 1, y + 1), - CCG_grid_elem(key, grid, x + 1, y), - CCG_grid_elem(key, grid, x, y), - }; const int face_index = y * grid_size_1 + x; float *face_normal = face_normals[face_index]; normal_quad_v3(face_normal, - CCG_elem_co(key, grid_elements[0]), - CCG_elem_co(key, grid_elements[1]), - CCG_elem_co(key, grid_elements[2]), - CCG_elem_co(key, grid_elements[3])); + grid_positions[CCG_grid_xy_to_index(grid_size, x, y + 1)], + grid_positions[CCG_grid_xy_to_index(grid_size, x + 1, y + 1)], + grid_positions[CCG_grid_xy_to_index(grid_size, x + 1, y)], + grid_positions[CCG_grid_xy_to_index(grid_size, x, y)]); } } } /* Average normals at every grid element, using adjacent faces normals. */ -static void subdiv_ccg_average_inner_face_normals(const SubdivCCG &subdiv_ccg, - const CCGKey &key, +static void subdiv_ccg_average_inner_face_normals(SubdivCCG &subdiv_ccg, const Span face_normals, const int corner) { const int grid_size = subdiv_ccg.grid_size; + const int grid_area = subdiv_ccg.grid_area; const int grid_size_1 = grid_size - 1; - CCGElem *grid = subdiv_ccg.grids[corner]; + MutableSpan grid_normals = subdiv_ccg.normals.as_mutable_span().slice( + grid_range(grid_area, corner)); for (int y = 0; y < grid_size; y++) { for (int x = 0; x < grid_size; x++) { float normal_acc[3] = {0.0f, 0.0f, 0.0f}; @@ -633,7 +567,7 @@ static void subdiv_ccg_average_inner_face_normals(const SubdivCCG &subdiv_ccg, counter++; } /* Normalize and store. */ - mul_v3_v3fl(CCG_grid_elem_no(key, grid, x, y), normal_acc, 1.0f / counter); + mul_v3_v3fl(grid_normals[CCG_grid_xy_to_index(grid_size, x, y)], normal_acc, 1.0f / counter); } } } @@ -654,8 +588,8 @@ static void subdiv_ccg_recalc_inner_grid_normals(SubdivCCG &subdiv_ccg, const In for (const int face_index : segment) { const IndexRange face = faces[face_index]; for (const int grid_index : face) { - subdiv_ccg_recalc_inner_face_normals(subdiv_ccg, key, face_normals, grid_index); - subdiv_ccg_average_inner_face_normals(subdiv_ccg, key, face_normals, grid_index); + subdiv_ccg_recalc_inner_face_normals(subdiv_ccg, face_normals, grid_index); + subdiv_ccg_average_inner_face_normals(subdiv_ccg, face_normals, grid_index); } subdiv_ccg_average_inner_face_grids(subdiv_ccg, key, face); } @@ -667,7 +601,7 @@ static void subdiv_ccg_recalc_inner_grid_normals(SubdivCCG &subdiv_ccg, const In void BKE_subdiv_ccg_recalc_normals(SubdivCCG &subdiv_ccg) { #ifdef WITH_OPENSUBDIV - if (!subdiv_ccg.has_normal) { + if (subdiv_ccg.normals.is_empty()) { /* Grids don't have normals, can do early output. */ return; } @@ -681,7 +615,7 @@ void BKE_subdiv_ccg_recalc_normals(SubdivCCG &subdiv_ccg) void BKE_subdiv_ccg_update_normals(SubdivCCG &subdiv_ccg, const IndexMask &face_mask) { #ifdef WITH_OPENSUBDIV - if (!subdiv_ccg.has_normal) { + if (subdiv_ccg.normals.is_empty()) { /* Grids don't have normals, can do early output. */ return; } @@ -713,21 +647,20 @@ static void average_grid_element_value_v3(float a[3], float b[3]) copy_v3_v3(b, a); } -static void average_grid_element(const SubdivCCG &subdiv_ccg, - const CCGKey &key, - CCGElem *grid_element_a, - CCGElem *grid_element_b) +static void average_grid_element(SubdivCCG &subdiv_ccg, + const int grid_element_a, + const int grid_element_b) { - average_grid_element_value_v3(CCG_elem_co(key, grid_element_a), - CCG_elem_co(key, grid_element_b)); - if (subdiv_ccg.has_normal) { - average_grid_element_value_v3(CCG_elem_no(key, grid_element_a), - CCG_elem_no(key, grid_element_b)); + average_grid_element_value_v3(subdiv_ccg.positions[grid_element_a], + subdiv_ccg.positions[grid_element_b]); + if (!subdiv_ccg.normals.is_empty()) { + average_grid_element_value_v3(subdiv_ccg.normals[grid_element_a], + subdiv_ccg.normals[grid_element_b]); } - if (subdiv_ccg.has_mask) { - float mask = (CCG_elem_mask(key, grid_element_a) + CCG_elem_mask(key, grid_element_b)) * 0.5f; - CCG_elem_mask(key, grid_element_a) = mask; - CCG_elem_mask(key, grid_element_b) = mask; + if (!subdiv_ccg.masks.is_empty()) { + float mask = (subdiv_ccg.masks[grid_element_a] + subdiv_ccg.masks[grid_element_b]) * 0.5f; + subdiv_ccg.masks[grid_element_a] = mask; + subdiv_ccg.masks[grid_element_b] = mask; } } @@ -747,15 +680,14 @@ static void element_accumulator_init(GridElementAccumulator &accumulator) static void element_accumulator_add(GridElementAccumulator &accumulator, const SubdivCCG &subdiv_ccg, - const CCGKey &key, - /*const*/ CCGElem &grid_element) + const int elem) { - accumulator.co += CCG_elem_co(key, &grid_element); - if (subdiv_ccg.has_normal) { - accumulator.no += CCG_elem_no(key, &grid_element); + accumulator.co += subdiv_ccg.positions[elem]; + if (!subdiv_ccg.normals.is_empty()) { + accumulator.no += subdiv_ccg.normals[elem]; } - if (subdiv_ccg.has_mask) { - accumulator.mask += CCG_elem_mask(key, &grid_element); + if (!subdiv_ccg.masks.is_empty()) { + accumulator.mask += subdiv_ccg.masks[elem]; } } @@ -766,17 +698,16 @@ static void element_accumulator_mul_fl(GridElementAccumulator &accumulator, cons accumulator.mask *= f; } -static void element_accumulator_copy(const SubdivCCG &subdiv_ccg, - const CCGKey &key, - CCGElem &destination, +static void element_accumulator_copy(SubdivCCG &subdiv_ccg, + const int destination, const GridElementAccumulator &accumulator) { - CCG_elem_co(key, &destination) = accumulator.co; - if (subdiv_ccg.has_normal) { - CCG_elem_no(key, &destination) = accumulator.no; + subdiv_ccg.positions[destination] = accumulator.co; + if (!subdiv_ccg.normals.is_empty()) { + subdiv_ccg.normals[destination] = accumulator.no; } - if (subdiv_ccg.has_mask) { - CCG_elem_mask(key, &destination) = accumulator.mask; + if (!subdiv_ccg.masks.is_empty()) { + subdiv_ccg.masks[destination] = accumulator.mask; } } @@ -784,17 +715,15 @@ static void subdiv_ccg_average_inner_face_grids(SubdivCCG &subdiv_ccg, const CCGKey &key, const IndexRange face) { - const Span grids = subdiv_ccg.grids; const int num_face_grids = face.size(); const int grid_size = subdiv_ccg.grid_size; - CCGElem *prev_grid = grids[face.start() + num_face_grids - 1]; + int prev_grid = face.start() + num_face_grids - 1; /* Average boundary between neighbor grid. */ - for (int corner = 0; corner < num_face_grids; corner++) { - CCGElem *grid = grids[face.start() + corner]; + for (const int grid : face) { for (int i = 1; i < grid_size; i++) { - CCGElem *prev_grid_element = CCG_grid_elem(key, prev_grid, i, 0); - CCGElem *grid_element = CCG_grid_elem(key, grid, 0, i); - average_grid_element(subdiv_ccg, key, prev_grid_element, grid_element); + const int prev_grid_element = grid_xy_to_vert(key, prev_grid, i, 0); + const int grid_element = grid_xy_to_vert(key, grid, 0, i); + average_grid_element(subdiv_ccg, prev_grid_element, grid_element); } prev_grid = grid; } @@ -802,16 +731,14 @@ static void subdiv_ccg_average_inner_face_grids(SubdivCCG &subdiv_ccg, * Guarantees correct and smooth averaging in the center. */ GridElementAccumulator center_accumulator; element_accumulator_init(center_accumulator); - for (int corner = 0; corner < num_face_grids; corner++) { - CCGElem *grid = grids[face.start() + corner]; - CCGElem *grid_center_element = CCG_grid_elem(key, grid, 0, 0); - element_accumulator_add(center_accumulator, subdiv_ccg, key, *grid_center_element); + for (const int grid : face) { + const int grid_center_element = grid_xy_to_vert(key, grid, 0, 0); + element_accumulator_add(center_accumulator, subdiv_ccg, grid_center_element); } element_accumulator_mul_fl(center_accumulator, 1.0f / num_face_grids); - for (int corner = 0; corner < num_face_grids; corner++) { - CCGElem *grid = grids[face.start() + corner]; - CCGElem *grid_center_element = CCG_grid_elem(key, grid, 0, 0); - element_accumulator_copy(subdiv_ccg, key, *grid_center_element, center_accumulator); + for (const int grid : face) { + const int grid_center_element = grid_xy_to_vert(key, grid, 0, 0); + element_accumulator_copy(subdiv_ccg, grid_center_element, center_accumulator); } } @@ -831,9 +758,8 @@ static void subdiv_ccg_average_grids_boundary(SubdivCCG &subdiv_ccg, } for (int face_index = 0; face_index < num_adjacent_faces; face_index++) { for (int i = 1; i < grid_size2 - 1; i++) { - CCGElem *grid_element = subdiv_ccg_coord_to_elem( - key, subdiv_ccg, adjacent_edge.boundary_coords[face_index][i]); - element_accumulator_add(accumulators[i], subdiv_ccg, key, *grid_element); + const int grid_element = adjacent_edge.boundary_coords[face_index][i].to_index(key); + element_accumulator_add(accumulators[i], subdiv_ccg, grid_element); } } for (int i = 1; i < grid_size2 - 1; i++) { @@ -842,9 +768,8 @@ static void subdiv_ccg_average_grids_boundary(SubdivCCG &subdiv_ccg, /* Copy averaged value to all the other faces. */ for (int face_index = 0; face_index < num_adjacent_faces; face_index++) { for (int i = 1; i < grid_size2 - 1; i++) { - CCGElem *grid_element = subdiv_ccg_coord_to_elem( - key, subdiv_ccg, adjacent_edge.boundary_coords[face_index][i]); - element_accumulator_copy(subdiv_ccg, key, *grid_element, accumulators[i]); + const int grid_element = adjacent_edge.boundary_coords[face_index][i].to_index(key); + element_accumulator_copy(subdiv_ccg, grid_element, accumulators[i]); } } } @@ -869,16 +794,14 @@ static void subdiv_ccg_average_grids_corners(SubdivCCG &subdiv_ccg, GridElementAccumulator accumulator; element_accumulator_init(accumulator); for (int face_index = 0; face_index < num_adjacent_faces; face_index++) { - CCGElem *grid_element = subdiv_ccg_coord_to_elem( - key, subdiv_ccg, adjacent_vertex.corner_coords[face_index]); - element_accumulator_add(accumulator, subdiv_ccg, key, *grid_element); + const int grid_element = adjacent_vertex.corner_coords[face_index].to_index(key); + element_accumulator_add(accumulator, subdiv_ccg, grid_element); } element_accumulator_mul_fl(accumulator, 1.0f / num_adjacent_faces); /* Copy averaged value to all the other faces. */ for (int face_index = 0; face_index < num_adjacent_faces; face_index++) { - CCGElem *grid_element = subdiv_ccg_coord_to_elem( - key, subdiv_ccg, adjacent_vertex.corner_coords[face_index]); - element_accumulator_copy(subdiv_ccg, key, *grid_element, accumulator); + const int grid_element = adjacent_vertex.corner_coords[face_index].to_index(key); + element_accumulator_copy(subdiv_ccg, grid_element, accumulator); } } @@ -999,7 +922,7 @@ void BKE_subdiv_ccg_topology_counters(const SubdivCCG &subdiv_ccg, int &r_num_faces, int &r_num_loops) { - const int num_grids = subdiv_ccg.grids.size(); + const int num_grids = subdiv_ccg.grids_num; const int grid_size = subdiv_ccg.grid_size; const int grid_area = grid_size * grid_size; const int num_edges_per_grid = 2 * (grid_size * (grid_size - 1)); @@ -1022,7 +945,7 @@ void BKE_subdiv_ccg_print_coord(const char *message, const SubdivCCGCoord &coord bool BKE_subdiv_ccg_check_coord_valid(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord) { - if (coord.grid_index < 0 || coord.grid_index >= subdiv_ccg.grids.size()) { + if (coord.grid_index < 0 || coord.grid_index >= subdiv_ccg.grids_num) { return false; } const int grid_size = subdiv_ccg.grid_size; @@ -1536,7 +1459,7 @@ void BKE_subdiv_ccg_neighbor_coords_get(const SubdivCCG &subdiv_ccg, { #ifdef WITH_OPENSUBDIV BLI_assert(coord.grid_index >= 0); - BLI_assert(coord.grid_index < subdiv_ccg.grids.size()); + BLI_assert(coord.grid_index < subdiv_ccg.grids_num); BLI_assert(coord.x >= 0); BLI_assert(coord.x < subdiv_ccg.grid_size); BLI_assert(coord.y >= 0); @@ -1676,8 +1599,8 @@ bool BKE_subdiv_ccg_coord_is_mesh_boundary(const OffsetIndices faces, blender::BitGroupVector<> &BKE_subdiv_ccg_grid_hidden_ensure(SubdivCCG &subdiv_ccg) { if (subdiv_ccg.grid_hidden.is_empty()) { - const int grid_area = subdiv_ccg.grid_size * subdiv_ccg.grid_size; - subdiv_ccg.grid_hidden = blender::BitGroupVector<>(subdiv_ccg.grids.size(), grid_area, false); + const int grid_area = subdiv_ccg.grid_area; + subdiv_ccg.grid_hidden = blender::BitGroupVector<>(subdiv_ccg.grids_num, grid_area, false); } return subdiv_ccg.grid_hidden; } diff --git a/source/blender/draw/engines/overlay/overlay_sculpt.cc b/source/blender/draw/engines/overlay/overlay_sculpt.cc index e1ef3abd327..d7042a452ad 100644 --- a/source/blender/draw/engines/overlay/overlay_sculpt.cc +++ b/source/blender/draw/engines/overlay/overlay_sculpt.cc @@ -74,9 +74,7 @@ void OVERLAY_sculpt_cache_populate(OVERLAY_Data *vedata, Object *ob) case blender::bke::pbvh::Type::Grids: { const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const Mesh &base_mesh = *static_cast(object_orig->data); - if (!BKE_subdiv_ccg_key_top_level(subdiv_ccg).has_mask && - !base_mesh.attributes().contains(".sculpt_face_set")) - { + if (subdiv_ccg.masks.is_empty() && !base_mesh.attributes().contains(".sculpt_face_set")) { return; } break; diff --git a/source/blender/draw/intern/draw_pbvh.cc b/source/blender/draw/intern/draw_pbvh.cc index b928e1fd28d..8e6024f0102 100644 --- a/source/blender/draw/intern/draw_pbvh.cc +++ b/source/blender/draw/intern/draw_pbvh.cc @@ -692,65 +692,64 @@ static void fill_vbo_attribute_mesh(const OffsetIndices faces, } static void fill_vbo_position_grids(const CCGKey &key, - const Span grids, + const Span positions, const bool use_flat_layout, - const Span grid_indices, + const Span grids, gpu::VertBuf &vert_buf) { float3 *data = vert_buf.data().data(); if (use_flat_layout) { const int grid_size_1 = key.grid_size - 1; - for (const int i : grid_indices.index_range()) { - CCGElem *grid = grids[grid_indices[i]]; + for (const int grid : grids) { + const Span grid_positions = positions.slice(bke::ccg::grid_range(key, grid)); for (int y = 0; y < grid_size_1; y++) { for (int x = 0; x < grid_size_1; x++) { - *data = CCG_grid_elem_co(key, grid, x, y); + *data = grid_positions[CCG_grid_xy_to_index(key.grid_size, x, y)]; data++; - *data = CCG_grid_elem_co(key, grid, x + 1, y); + *data = grid_positions[CCG_grid_xy_to_index(key.grid_size, x + 1, y)]; data++; - *data = CCG_grid_elem_co(key, grid, x + 1, y + 1); + *data = grid_positions[CCG_grid_xy_to_index(key.grid_size, x + 1, y + 1)]; data++; - *data = CCG_grid_elem_co(key, grid, x, y + 1); + *data = grid_positions[CCG_grid_xy_to_index(key.grid_size, x, y + 1)]; data++; } } } } else { - for (const int i : grid_indices.index_range()) { - CCGElem *grid = grids[grid_indices[i]]; - for (const int offset : IndexRange(key.grid_area)) { - *data = CCG_elem_offset_co(key, grid, offset); - data++; - } + for (const int grid : grids) { + const Span grid_positions = positions.slice(bke::ccg::grid_range(key, grid)); + std::copy_n(grid_positions.data(), grid_positions.size(), data); + data += grid_positions.size(); } } } static void fill_vbo_normal_grids(const CCGKey &key, - const Span grids, + const Span positions, + const Span normals, const Span grid_to_face_map, const Span sharp_faces, const bool use_flat_layout, - const Span grid_indices, + const Span grids, gpu::VertBuf &vert_buf) { short4 *data = vert_buf.data().data(); if (use_flat_layout) { const int grid_size_1 = key.grid_size - 1; - for (const int i : grid_indices.index_range()) { - const int grid_index = grid_indices[i]; - CCGElem *grid = grids[grid_index]; - if (!sharp_faces.is_empty() && sharp_faces[grid_to_face_map[grid_index]]) { + for (const int grid : grids) { + const Span grid_positions = positions.slice(bke::ccg::grid_range(key, grid)); + const Span grid_normals = normals.slice(bke::ccg::grid_range(key, grid)); + if (!sharp_faces.is_empty() && sharp_faces[grid_to_face_map[grid]]) { for (int y = 0; y < grid_size_1; y++) { for (int x = 0; x < grid_size_1; x++) { float3 no; normal_quad_v3(no, - CCG_grid_elem_co(key, grid, x, y + 1), - CCG_grid_elem_co(key, grid, x + 1, y + 1), - CCG_grid_elem_co(key, grid, x + 1, y), - CCG_grid_elem_co(key, grid, x, y)); + grid_positions[CCG_grid_xy_to_index(key.grid_size, x, y + 1)], + grid_positions[CCG_grid_xy_to_index(key.grid_size, x + 1, y + 1)], + grid_positions[CCG_grid_xy_to_index(key.grid_size, x + 1, y)], + grid_positions[CCG_grid_xy_to_index(key.grid_size, x, y)]); std::fill_n(data, 4, normal_float_to_short(no)); data += 4; } @@ -759,7 +758,10 @@ static void fill_vbo_normal_grids(const CCGKey &key, else { for (int y = 0; y < grid_size_1; y++) { for (int x = 0; x < grid_size_1; x++) { - std::fill_n(data, 4, normal_float_to_short(CCG_grid_elem_no(key, grid, x, y))); + std::fill_n( + data, + 4, + normal_float_to_short(grid_normals[CCG_grid_xy_to_index(key.grid_size, x, y)])); data += 4; } } @@ -768,10 +770,9 @@ static void fill_vbo_normal_grids(const CCGKey &key, } else { /* The non-flat VBO layout does not support sharp faces. */ - for (const int i : grid_indices.index_range()) { - CCGElem *grid = grids[grid_indices[i]]; - for (const int offset : IndexRange(key.grid_area)) { - *data = normal_float_to_short(CCG_elem_offset_no(key, grid, offset)); + for (const int grid : grids) { + for (const float3 &normal : normals.slice(bke::ccg::grid_range(key, grid))) { + *data = normal_float_to_short(normal); data++; } } @@ -779,43 +780,36 @@ static void fill_vbo_normal_grids(const CCGKey &key, } static void fill_vbo_mask_grids(const CCGKey &key, - const Span grids, + const Span masks, const bool use_flat_layout, - const Span grid_indices, + const Span grids, gpu::VertBuf &vert_buf) { - if (key.has_mask) { - float *data = vert_buf.data().data(); - if (use_flat_layout) { - const int grid_size_1 = key.grid_size - 1; - for (const int i : grid_indices.index_range()) { - CCGElem *grid = grids[grid_indices[i]]; - for (int y = 0; y < grid_size_1; y++) { - for (int x = 0; x < grid_size_1; x++) { - *data = CCG_grid_elem_mask(key, grid, x, y); - data++; - *data = CCG_grid_elem_mask(key, grid, x + 1, y); - data++; - *data = CCG_grid_elem_mask(key, grid, x + 1, y + 1); - data++; - *data = CCG_grid_elem_mask(key, grid, x, y + 1); - data++; - } - } - } - } - else { - for (const int i : grid_indices.index_range()) { - CCGElem *grid = grids[grid_indices[i]]; - for (const int offset : IndexRange(key.grid_area)) { - *data = CCG_elem_offset_mask(key, grid, offset); + float *data = vert_buf.data().data(); + if (use_flat_layout) { + const int grid_size_1 = key.grid_size - 1; + for (const int grid : grids) { + const Span grid_masks = masks.slice(bke::ccg::grid_range(key, grid)); + for (int y = 0; y < grid_size_1; y++) { + for (int x = 0; x < grid_size_1; x++) { + *data = grid_masks[CCG_grid_xy_to_index(key.grid_size, x, y)]; + data++; + *data = grid_masks[CCG_grid_xy_to_index(key.grid_size, x + 1, y)]; + data++; + *data = grid_masks[CCG_grid_xy_to_index(key.grid_size, x + 1, y + 1)]; + data++; + *data = grid_masks[CCG_grid_xy_to_index(key.grid_size, x, y + 1)]; data++; } } } } else { - vert_buf.data().fill(0.0f); + for (const int grid : grids) { + const Span grid_masks = masks.slice(bke::ccg::grid_range(key, grid)); + std::copy_n(grid_masks.data(), grid_masks.size(), data); + data += grid_masks.size(); + } } } @@ -855,13 +849,13 @@ static void fill_vbos_grids(const Object &object, const Span nodes = pbvh.nodes(); const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span grids = subdiv_ccg.grids; if (const CustomRequest *request_type = std::get_if(&request)) { switch (*request_type) { case CustomRequest::Position: { node_mask.foreach_index(GrainSize(1), [&](const int i) { - fill_vbo_position_grids(key, grids, use_flat_layout[i], nodes[i].grids(), *vbos[i]); + fill_vbo_position_grids( + key, subdiv_ccg.positions, use_flat_layout[i], nodes[i].grids(), *vbos[i]); }); break; } @@ -872,7 +866,8 @@ static void fill_vbos_grids(const Object &object, bke::AttrDomain::Face); node_mask.foreach_index(GrainSize(1), [&](const int i) { fill_vbo_normal_grids(key, - grids, + subdiv_ccg.positions, + subdiv_ccg.normals, grid_to_face_map, sharp_faces, use_flat_layout[i], @@ -883,9 +878,16 @@ static void fill_vbos_grids(const Object &object, break; } case CustomRequest::Mask: { - node_mask.foreach_index(GrainSize(1), [&](const int i) { - fill_vbo_mask_grids(key, grids, use_flat_layout[i], nodes[i].grids(), *vbos[i]); - }); + const Span masks = subdiv_ccg.masks; + if (!masks.is_empty()) { + node_mask.foreach_index(GrainSize(1), [&](const int i) { + fill_vbo_mask_grids(key, masks, use_flat_layout[i], nodes[i].grids(), *vbos[i]); + }); + } + else { + node_mask.foreach_index(GrainSize(64), + [&](const int i) { vbos[i]->data().fill(0.0f); }); + } break; } case CustomRequest::FaceSet: { diff --git a/source/blender/editors/sculpt_paint/brushes/enhance_details.cc b/source/blender/editors/sculpt_paint/brushes/enhance_details.cc index e8999d8ecb9..434fee15bdf 100644 --- a/source/blender/editors/sculpt_paint/brushes/enhance_details.cc +++ b/source/blender/editors/sculpt_paint/brushes/enhance_details.cc @@ -205,7 +205,7 @@ static void calc_translations_grids(const SubdivCCG &subdiv_ccg, tls.new_positions.resize(positions.size()); const MutableSpan new_positions = tls.new_positions; - smooth::neighbor_position_average_grids(subdiv_ccg, grids, new_positions); + smooth::average_data_grids(subdiv_ccg, subdiv_ccg.positions.as_span(), grids, new_positions); tls.translations.resize(positions.size()); const MutableSpan translations = tls.translations; diff --git a/source/blender/editors/sculpt_paint/brushes/multires_displacement_smear.cc b/source/blender/editors/sculpt_paint/brushes/multires_displacement_smear.cc index 1c7df5b6114..282f750c148 100644 --- a/source/blender/editors/sculpt_paint/brushes/multires_displacement_smear.cc +++ b/source/blender/editors/sculpt_paint/brushes/multires_displacement_smear.cc @@ -43,7 +43,7 @@ static void calc_node(const Depsgraph &depsgraph, SculptSession &ss = *object.sculpt; const StrokeCache &cache = *ss.cache; SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; - const Span elems = subdiv_ccg.grids; + MutableSpan ccg_positions = subdiv_ccg.positions; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); const Span grids = node.grids(); @@ -73,7 +73,6 @@ static void calc_node(const Depsgraph &depsgraph, const int node_start = i * key.grid_area; const int grid = grids[i]; const int start = grid * key.grid_area; - CCGElem *elem = elems[grid]; for (const int y : IndexRange(key.grid_size)) { for (const int x : IndexRange(key.grid_size)) { const int offset = CCG_grid_xy_to_index(key.grid_size, x, y); @@ -134,7 +133,7 @@ static void calc_node(const Depsgraph &depsgraph, float3 new_co = cache.displacement_smear.limit_surface_co[grid_vert_index] + interp_limit_surface_disp; - CCG_elem_offset_co(key, elem, offset) = math::interpolate( + ccg_positions[grid_vert_index] = math::interpolate( positions[node_vert_index], new_co, factors[node_vert_index]); } } @@ -145,26 +144,24 @@ BLI_NOINLINE static void eval_all_limit_positions(const SubdivCCG &subdiv_ccg, const MutableSpan limit_positions) { const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - threading::parallel_for(subdiv_ccg.grids.index_range(), 1024, [&](const IndexRange range) { + threading::parallel_for(IndexRange(subdiv_ccg.grids_num), 1024, [&](const IndexRange range) { for (const int grid : range) { - const MutableSpan grid_limit_positions = limit_positions.slice(grid * key.grid_area, - key.grid_area); + const MutableSpan grid_limit_positions = limit_positions.slice( + bke::ccg::grid_range(key.grid_area, grid)); BKE_subdiv_ccg_eval_limit_positions(subdiv_ccg, key, grid, grid_limit_positions); } }); } BLI_NOINLINE static void store_node_prev_displacement(const Span limit_positions, - const Span elems, + const Span positions, const CCGKey &key, const bke::pbvh::GridsNode &node, const MutableSpan prev_displacement) { for (const int grid : node.grids()) { - const int start = grid * key.grid_area; - CCGElem *elem = elems[grid]; - for (const int i : IndexRange(key.grid_area)) { - prev_displacement[start + i] = CCG_elem_offset_co(key, elem, i) - limit_positions[start + i]; + for (const int i : bke::ccg::grid_range(key.grid_area, grid)) { + prev_displacement[i] = positions[i] - limit_positions[i]; } } } @@ -182,12 +179,12 @@ void do_displacement_smear_brush(const Depsgraph &depsgraph, MutableSpan nodes = pbvh.nodes(); SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; - const Span elems = subdiv_ccg.grids; + MutableSpan positions = subdiv_ccg.positions; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); if (ss.cache->displacement_smear.limit_surface_co.is_empty()) { - ss.cache->displacement_smear.prev_displacement = Array(elems.size() * key.grid_area); - ss.cache->displacement_smear.limit_surface_co = Array(elems.size() * key.grid_area); + ss.cache->displacement_smear.prev_displacement = Array(positions.size()); + ss.cache->displacement_smear.limit_surface_co = Array(positions.size()); eval_all_limit_positions(subdiv_ccg, ss.cache->displacement_smear.limit_surface_co); } @@ -195,7 +192,7 @@ void do_displacement_smear_brush(const Depsgraph &depsgraph, threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { node_mask.slice(range).foreach_index([&](const int i) { store_node_prev_displacement(ss.cache->displacement_smear.limit_surface_co, - elems, + subdiv_ccg.positions, key, nodes[i], ss.cache->displacement_smear.prev_displacement); diff --git a/source/blender/editors/sculpt_paint/brushes/relax.cc b/source/blender/editors/sculpt_paint/brushes/relax.cc index 1c2d6c8677c..cc259bb5390 100644 --- a/source/blender/editors/sculpt_paint/brushes/relax.cc +++ b/source/blender/editors/sculpt_paint/brushes/relax.cc @@ -226,13 +226,13 @@ BLI_NOINLINE static void calc_factors_grids(const Depsgraph &depsgraph, { SculptSession &ss = *object.sculpt; const StrokeCache &cache = *ss.cache; - SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; + const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); const Span grids = node.grids(); const int grid_verts_num = grids.size() * key.grid_area; - gather_grids_positions(key, subdiv_ccg.grids, grids, positions); + gather_data_grids(subdiv_ccg, subdiv_ccg.positions.as_span(), grids, positions); fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors); filter_region_clip_factors(ss, positions, factors); @@ -319,7 +319,6 @@ static void do_relax_face_sets_brush_grids(const Depsgraph &depsgraph, nodes[i].grids(), relax_face_sets, factors.as_span().slice(node_vert_offsets[pos]), - current_positions.as_span().slice(node_vert_offsets[pos]), tls.vert_neighbors, translations.as_mutable_span().slice(node_vert_offsets[pos])); }); @@ -549,7 +548,7 @@ BLI_NOINLINE static void calc_topology_relax_factors_grids(const Depsgraph &deps const Span grids = node.grids(); const int grid_verts_num = grids.size() * key.grid_area; - gather_grids_positions(key, subdiv_ccg.grids, grids, positions); + gather_data_grids(subdiv_ccg, subdiv_ccg.positions.as_span(), grids, positions); const OrigPositionData orig_data = orig_position_data_get_grids(object, node); fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors); @@ -626,7 +625,6 @@ static void do_topology_relax_brush_grids(const Depsgraph &depsgraph, nodes[i].grids(), false, factors.as_span().slice(node_vert_offsets[pos]), - current_positions.as_span().slice(node_vert_offsets[pos]), tls.vert_neighbors, translations.as_mutable_span().slice(node_vert_offsets[pos])); }); diff --git a/source/blender/editors/sculpt_paint/brushes/smooth_mask.cc b/source/blender/editors/sculpt_paint/brushes/smooth_mask.cc index 9c50d99ab17..4fdba67f57d 100644 --- a/source/blender/editors/sculpt_paint/brushes/smooth_mask.cc +++ b/source/blender/editors/sculpt_paint/brushes/smooth_mask.cc @@ -221,7 +221,7 @@ static void calc_grids(const Depsgraph &depsgraph, tls.new_masks.resize(positions.size()); const MutableSpan new_masks = tls.new_masks; - mask::average_neighbor_mask_grids(subdiv_ccg, grids, new_masks); + smooth::average_data_grids(subdiv_ccg, subdiv_ccg.masks.as_span(), grids, new_masks); mask::mix_new_masks(new_masks, factors, masks); mask::clamp_mask(masks); diff --git a/source/blender/editors/sculpt_paint/brushes/surface_smooth.cc b/source/blender/editors/sculpt_paint/brushes/surface_smooth.cc index 4ae6427e30b..8aa2c2a82fe 100644 --- a/source/blender/editors/sculpt_paint/brushes/surface_smooth.cc +++ b/source/blender/editors/sculpt_paint/brushes/surface_smooth.cc @@ -222,7 +222,8 @@ BLI_NOINLINE static void do_surface_smooth_brush_grids( tls.average_positions.resize(positions.size()); const MutableSpan average_positions = tls.average_positions; - smooth::neighbor_position_average_grids(subdiv_ccg, grids, average_positions); + smooth::average_data_grids( + subdiv_ccg, subdiv_ccg.positions.as_span(), grids, average_positions); tls.laplacian_disp.resize(positions.size()); const MutableSpan laplacian_disp = tls.laplacian_disp; diff --git a/source/blender/editors/sculpt_paint/brushes/topology_slide.cc b/source/blender/editors/sculpt_paint/brushes/topology_slide.cc index 83bec8ef9b4..c7c6859c22c 100644 --- a/source/blender/editors/sculpt_paint/brushes/topology_slide.cc +++ b/source/blender/editors/sculpt_paint/brushes/topology_slide.cc @@ -91,22 +91,23 @@ BLI_NOINLINE static void calc_neighbor_influence(const Span vert_positio } BLI_NOINLINE static void calc_neighbor_influence(const SubdivCCG &subdiv_ccg, - const Span positions, const Span grids, const MutableSpan translations) { const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span elems = subdiv_ccg.grids; + const Span positions = subdiv_ccg.positions; for (const int i : grids.index_range()) { const int node_start = i * key.grid_area; const int grid = grids[i]; + const int start = grid * key.grid_area; for (const int y : IndexRange(key.grid_size)) { for (const int x : IndexRange(key.grid_size)) { const int offset = CCG_grid_xy_to_index(key.grid_size, x, y); - const int node_vert_index = node_start + offset; + const int vert = start + offset; + const int node_vert = node_start + offset; - const float3 &position = positions[node_vert_index]; - const float3 &dir = translations[node_vert_index]; + const float3 &position = positions[vert]; + const float3 &dir = translations[node_vert]; SubdivCCGCoord coord{}; coord.grid_index = grid; @@ -119,13 +120,10 @@ BLI_NOINLINE static void calc_neighbor_influence(const SubdivCCG &subdiv_ccg, float3 final_translation(0); for (const SubdivCCGCoord neighbor : neighbors.coords) { add_neighbor_influence( - position, - dir, - CCG_grid_elem_co(key, elems[neighbor.grid_index], neighbor.x, neighbor.y), - final_translation); + position, dir, positions[neighbor.to_index(key)], final_translation); } - translations[node_vert_index] = final_translation; + translations[node_vert] = final_translation; } } } @@ -247,7 +245,7 @@ static void calc_grids(const Depsgraph &depsgraph, tls.translations.resize(positions.size()); const MutableSpan translations = tls.translations; calc_translation_directions(brush, cache, positions, translations); - calc_neighbor_influence(subdiv_ccg, positions, grids, translations); + calc_neighbor_influence(subdiv_ccg, grids, translations); scale_translations(translations, factors); clip_and_lock_translations(sd, ss, orig_data.positions, translations); diff --git a/source/blender/editors/sculpt_paint/mesh_brush_common.hh b/source/blender/editors/sculpt_paint/mesh_brush_common.hh index b41913b6c69..27ff1e588b5 100644 --- a/source/blender/editors/sculpt_paint/mesh_brush_common.hh +++ b/source/blender/editors/sculpt_paint/mesh_brush_common.hh @@ -137,17 +137,13 @@ void scatter_data_bmesh(Span node_data, const Set &verts, Mutabl */ /** Fill the output array with all positions in the geometry referenced by the indices. */ -void gather_grids_positions(const CCGKey &key, - Span elems, - Span grids, - MutableSpan positions); inline MutableSpan gather_grids_positions(const SubdivCCG &subdiv_ccg, const Span grids, Vector &positions) { const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); positions.resize(key.grid_area * grids.size()); - gather_grids_positions(key, subdiv_ccg.grids, grids, positions); + gather_data_grids(subdiv_ccg, subdiv_ccg.positions.as_span(), grids, positions); return positions; } void gather_bmesh_positions(const Set &verts, MutableSpan positions); diff --git a/source/blender/editors/sculpt_paint/paint_hide.cc b/source/blender/editors/sculpt_paint/paint_hide.cc index a617c0c5d46..35f1c206787 100644 --- a/source/blender/editors/sculpt_paint/paint_hide.cc +++ b/source/blender/editors/sculpt_paint/paint_hide.cc @@ -574,8 +574,8 @@ static void partialvis_masked_update_grids(Depsgraph &depsgraph, const bool value = action_to_hide(action); const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span grids = subdiv_ccg.grids; - if (!key.has_mask) { + const Span masks = subdiv_ccg.masks; + if (masks.is_empty()) { grid_hide_update(depsgraph, object, node_mask, @@ -583,14 +583,11 @@ static void partialvis_masked_update_grids(Depsgraph &depsgraph, } else { grid_hide_update( - depsgraph, object, node_mask, [&](const int grid_index, MutableBoundedBitSpan hide) { - CCGElem *grid = grids[grid_index]; - for (const int y : IndexRange(key.grid_size)) { - for (const int x : IndexRange(key.grid_size)) { - CCGElem *elem = CCG_grid_elem(key, grid, x, y); - if (CCG_elem_mask(key, elem) > 0.5f) { - hide[y * key.grid_size + x].set(value); - } + depsgraph, object, node_mask, [&](const int grid, MutableBoundedBitSpan hide) { + const Span grid_masks = masks.slice(bke::ccg::grid_range(key, grid)); + for (const int i : grid_masks.index_range()) { + if (grid_masks[i] > 0.5f) { + hide[i].set(value); } } }); @@ -1236,20 +1233,17 @@ static void partialvis_gesture_update_grids(Depsgraph &depsgraph, const bool value = action_to_hide(action); const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span grids = subdiv_ccg.grids; - grid_hide_update( - depsgraph, *object, node_mask, [&](const int grid_index, MutableBoundedBitSpan hide) { - CCGElem *grid = grids[grid_index]; - for (const int y : IndexRange(key.grid_size)) { - for (const int x : IndexRange(key.grid_size)) { - CCGElem *elem = CCG_grid_elem(key, grid, x, y); - if (gesture::is_affected(gesture_data, CCG_elem_co(key, elem), CCG_elem_no(key, elem))) - { - hide[y * key.grid_size + x].set(value); - } - } - } - }); + const Span positions = subdiv_ccg.positions; + const Span normals = subdiv_ccg.normals; + grid_hide_update(depsgraph, *object, node_mask, [&](const int grid, MutableBoundedBitSpan hide) { + const Span grid_positions = positions.slice(bke::ccg::grid_range(key, grid)); + const Span grid_normals = normals.slice(bke::ccg::grid_range(key, grid)); + for (const int i : grid_positions.index_range()) { + if (gesture::is_affected(gesture_data, grid_positions[i], grid_normals[i])) { + hide[i].set(value); + } + } + }); } static void partialvis_gesture_update_bmesh(gesture::GestureData &gesture_data) diff --git a/source/blender/editors/sculpt_paint/paint_mask.cc b/source/blender/editors/sculpt_paint/paint_mask.cc index 99e2e31ad4d..53e640556b5 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.cc +++ b/source/blender/editors/sculpt_paint/paint_mask.cc @@ -69,19 +69,10 @@ Array duplicate_mask(const Object &object) } case bke::pbvh::Type::Grids: { const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; - const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span grids = subdiv_ccg.grids; - - Array result(grids.size() * key.grid_area); - int index = 0; - for (const int grid : grids.index_range()) { - CCGElem *elem = grids[grid]; - for (const int i : IndexRange(key.grid_area)) { - result[index] = CCG_elem_offset_mask(key, elem, i); - index++; - } + if (subdiv_ccg.masks.is_empty()) { + return Array(subdiv_ccg.positions.size(), 0.0f); } - return result; + return subdiv_ccg.masks; } case bke::pbvh::Type::BMesh: { BMesh &bm = *ss.bm; @@ -141,18 +132,8 @@ void gather_mask_grids(const SubdivCCG &subdiv_ccg, const Span grids, const MutableSpan r_mask) { - const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span elems = subdiv_ccg.grids; - BLI_assert(grids.size() * key.grid_area == r_mask.size()); - - if (key.has_mask) { - for (const int i : grids.index_range()) { - CCGElem *elem = elems[grids[i]]; - const int start = i * key.grid_area; - for (const int offset : IndexRange(key.grid_area)) { - r_mask[start + offset] = CCG_elem_offset_mask(key, elem, offset); - } - } + if (!subdiv_ccg.masks.is_empty()) { + gather_data_grids(subdiv_ccg, subdiv_ccg.masks.as_span(), grids, r_mask); } else { r_mask.fill(0.0f); @@ -161,17 +142,7 @@ void gather_mask_grids(const SubdivCCG &subdiv_ccg, void scatter_mask_grids(const Span mask, SubdivCCG &subdiv_ccg, const Span grids) { - const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span elems = subdiv_ccg.grids; - BLI_assert(key.has_mask); - BLI_assert(mask.size() == grids.size() * key.grid_area); - for (const int i : grids.index_range()) { - CCGElem *elem = elems[grids[i]]; - const int start = i * key.grid_area; - for (const int offset : IndexRange(key.grid_area)) { - CCG_elem_offset_mask(key, elem, offset) = mask[start + offset]; - } - } + scatter_data_grids(subdiv_ccg, mask, grids, subdiv_ccg.masks.as_mutable_span()); } void scatter_mask_bmesh(const Span mask, const BMesh &bm, const Set &verts) @@ -187,47 +158,6 @@ void scatter_mask_bmesh(const Span mask, const BMesh &bm, const Set elems, - const Span coords) -{ - float sum = 0; - for (const SubdivCCGCoord coord : coords) { - sum += CCG_grid_elem_mask(key, elems[coord.grid_index], coord.x, coord.y); - } - return sum / float(coords.size()); -} - -void average_neighbor_mask_grids(const SubdivCCG &subdiv_ccg, - const Span grids, - const MutableSpan new_masks) -{ - const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span elems = subdiv_ccg.grids; - - for (const int i : grids.index_range()) { - const int grid = grids[i]; - const int node_verts_start = i * key.grid_area; - - for (const int y : IndexRange(key.grid_size)) { - for (const int x : IndexRange(key.grid_size)) { - const int offset = CCG_grid_xy_to_index(key.grid_size, x, y); - const int node_vert_index = node_verts_start + offset; - - SubdivCCGCoord coord{}; - coord.grid_index = grid; - coord.x = x; - coord.y = y; - - SubdivCCGNeighbors neighbors; - BKE_subdiv_ccg_neighbor_coords_get(subdiv_ccg, coord, false, neighbors); - - new_masks[node_vert_index] = average_masks(key, elems, neighbors.coords); - } - } - } -} - static float average_masks(const int mask_offset, const Span verts) { float sum = 0; @@ -292,7 +222,7 @@ void update_mask_mesh(const Depsgraph &depsgraph, mask.finish(); } -bool mask_equals_array_grids(const Span elems, +bool mask_equals_array_grids(const Span masks, const CCGKey &key, const Span grids, const Span values) @@ -301,15 +231,8 @@ bool mask_equals_array_grids(const Span elems, const IndexRange range = grids.index_range(); return std::all_of(range.begin(), range.end(), [&](const int i) { - const int grid = grids[i]; - const int node_verts_start = i * key.grid_area; - - CCGElem *elem = elems[grid]; - for (const int offset : IndexRange(key.grid_area)) { - if (CCG_elem_offset_mask(key, elem, i) != values[node_verts_start + offset]) { - return false; - } - } + return masks.slice(bke::ccg::grid_range(key, grids[i])) == + values.slice(bke::ccg::grid_range(key, i)); return true; }); } @@ -502,8 +425,8 @@ static void fill_mask_grids(Main &bmain, SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - if (value == 0.0f && !key.has_mask) { - /* Unlike meshes, don't dynamically remove masks since it is interleaved with other data. */ + if (value == 0.0f && subdiv_ccg.masks.is_empty()) { + /* NOTE: Deleting the mask array would be possible here. */ return; } @@ -512,18 +435,15 @@ static void fill_mask_grids(Main &bmain, const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden; - const Span grids = subdiv_ccg.grids; + MutableSpan masks = subdiv_ccg.masks; bool any_changed = false; node_mask.foreach_index(GrainSize(1), [&](const int i) { const Span grid_indices = nodes[i].grids(); if (std::all_of(grid_indices.begin(), grid_indices.end(), [&](const int grid) { - CCGElem *elem = grids[grid]; - for (const int i : IndexRange(key.grid_area)) { - if (CCG_elem_offset_mask(key, elem, i) != value) { - return false; - } - } - return true; + const Span grid_masks = masks.slice(bke::ccg::grid_range(key, grid)); + return std::all_of(grid_masks.begin(), grid_masks.end(), [&](const float mask) { + return mask == value; + }); })) { return; @@ -532,17 +452,13 @@ static void fill_mask_grids(Main &bmain, if (grid_hidden.is_empty()) { for (const int grid : grid_indices) { - CCGElem *elem = grids[grid]; - for (const int i : IndexRange(key.grid_area)) { - CCG_elem_offset_mask(key, elem, i) = value; - } + masks.slice(bke::ccg::grid_range(key, grid)).fill(value); } } else { for (const int grid : grid_indices) { - CCGElem *elem = grids[grid]; - bits::foreach_0_index(grid_hidden[grid], - [&](const int i) { CCG_elem_offset_mask(key, elem, i) = value; }); + MutableSpan grid_masks = masks.slice(bke::ccg::grid_range(key, grid)); + bits::foreach_0_index(grid_hidden[grid], [&](const int i) { grid_masks[i] = value; }); } } BKE_pbvh_node_mark_redraw(nodes[i]); @@ -640,27 +556,25 @@ static void invert_mask_grids(Main &bmain, const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span grids = subdiv_ccg.grids; + MutableSpan masks = subdiv_ccg.masks; node_mask.foreach_index(GrainSize(1), [&](const int i) { const Span grid_indices = nodes[i].grids(); if (grid_hidden.is_empty()) { for (const int grid : grid_indices) { - CCGElem *elem = grids[grid]; - for (const int i : IndexRange(key.grid_area)) { - CCG_elem_offset_mask(key, elem, i) = 1.0f - CCG_elem_offset_mask(key, elem, i); + for (float &value : masks.slice(bke::ccg::grid_range(key, grid))) { + value = 1.0f - value; } } } else { for (const int grid : grid_indices) { - CCGElem *elem = grids[grid]; - bits::foreach_0_index(grid_hidden[grid], [&](const int i) { - CCG_elem_offset_mask(key, elem, i) = 1.0f - CCG_elem_offset_mask(key, elem, i); - }); + MutableSpan grid_masks = masks.slice(bke::ccg::grid_range(key, grid)); + bits::foreach_0_index(grid_hidden[grid], + [&](const int i) { grid_masks[i] = 1.0f - grid_masks[i]; }); } } BKE_pbvh_node_mark_update_mask(nodes[i]); - bke::pbvh::node_update_mask_grids(key, grids, nodes[i]); + bke::pbvh::node_update_mask_grids(key, masks, nodes[i]); }); multires_mark_as_modified(&depsgraph, &object, MULTIRES_COORDS_MODIFIED); @@ -832,20 +746,20 @@ static void gesture_apply_for_symmetry_pass(bContext & /*C*/, gesture::GestureDa bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object); MutableSpan nodes = pbvh.nodes(); SubdivCCG &subdiv_ccg = *gesture_data.ss->subdiv_ccg; - const Span grids = subdiv_ccg.grids; + const Span positions = subdiv_ccg.positions; + const Span normals = subdiv_ccg.normals; + MutableSpan masks = subdiv_ccg.masks; const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { node_mask.slice(range).foreach_index([&](const int i) { bool any_changed = false; for (const int grid : nodes[i].grids()) { - CCGElem *elem = grids[grid]; + const int vert_start = grid * key.grid_area; BKE_subdiv_ccg_foreach_visible_grid_vert(key, grid_hidden, grid, [&](const int i) { - if (gesture::is_affected(gesture_data, - CCG_elem_offset_co(key, elem, i), - CCG_elem_offset_no(key, elem, i))) - { - float &mask = CCG_elem_offset_mask(key, elem, i); + const int vert = vert_start + i; + if (gesture::is_affected(gesture_data, positions[vert], normals[vert])) { + float &mask = masks[vert]; if (!any_changed) { any_changed = true; undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask); diff --git a/source/blender/editors/sculpt_paint/paint_mask.hh b/source/blender/editors/sculpt_paint/paint_mask.hh index 59564768ba5..6d17d14b691 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.hh +++ b/source/blender/editors/sculpt_paint/paint_mask.hh @@ -15,7 +15,6 @@ struct BMesh; struct BMVert; -struct CCGElem; struct CCGKey; struct Depsgraph; struct Object; @@ -37,9 +36,6 @@ void gather_mask_bmesh(const BMesh &bm, const Set &verts, MutableSp void scatter_mask_grids(Span mask, SubdivCCG &subdiv_ccg, Span grids); void scatter_mask_bmesh(Span mask, const BMesh &bm, const Set &verts); -void average_neighbor_mask_grids(const SubdivCCG &subdiv_ccg, - Span grids, - MutableSpan new_masks); void average_neighbor_mask_bmesh(int mask_offset, const Set &verts, MutableSpan new_masks); @@ -60,7 +56,7 @@ void update_mask_mesh(const Depsgraph &depsgraph, FunctionRef, Span)> update_fn); /** Check whether array data is the same as the stored mask for the referenced geometry. */ -bool mask_equals_array_grids(Span elems, +bool mask_equals_array_grids(Span masks, const CCGKey &key, Span grids, Span values); diff --git a/source/blender/editors/sculpt_paint/sculpt.cc b/source/blender/editors/sculpt_paint/sculpt.cc index c6a45723dcb..662f713e1e2 100644 --- a/source/blender/editors/sculpt_paint/sculpt.cc +++ b/source/blender/editors/sculpt_paint/sculpt.cc @@ -176,11 +176,8 @@ const float *SCULPT_vertex_co_get(const Depsgraph &depsgraph, case blender::bke::pbvh::Type::BMesh: return ((BMVert *)vertex.i)->co; case blender::bke::pbvh::Type::Grids: { - const CCGKey key = BKE_subdiv_ccg_key_top_level(*ss.subdiv_ccg); - const int grid_index = vertex.i / key.grid_area; - const int index_in_grid = vertex.i - grid_index * key.grid_area; - CCGElem *elem = ss.subdiv_ccg->grids[grid_index]; - return CCG_elem_co(key, CCG_elem_offset(key, elem, index_in_grid)); + const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; + return subdiv_ccg.positions[vertex.i]; } } return nullptr; @@ -201,11 +198,8 @@ const blender::float3 SCULPT_vertex_normal_get(const Depsgraph &depsgraph, return v->no; } case blender::bke::pbvh::Type::Grids: { - const CCGKey key = BKE_subdiv_ccg_key_top_level(*ss.subdiv_ccg); - const int grid_index = vertex.i / key.grid_area; - const int index_in_grid = vertex.i - grid_index * key.grid_area; - CCGElem *elem = ss.subdiv_ccg->grids[grid_index]; - return CCG_elem_no(key, CCG_elem_offset(key, elem, index_in_grid)); + const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; + return subdiv_ccg.normals[vertex.i]; } } BLI_assert_unreachable(); @@ -913,7 +907,7 @@ std::optional nearest_vert_calc_grids(const bke::pbvh::Tree &pbv const BitGroupVector<> grid_hidden = subdiv_ccg.grid_hidden; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span elems = subdiv_ccg.grids; + const Span positions = subdiv_ccg.positions; const Span nodes = pbvh.nodes(); const NearestData nearest = threading::parallel_reduce( @@ -923,10 +917,9 @@ std::optional nearest_vert_calc_grids(const bke::pbvh::Tree &pbv [&](const IndexRange range, NearestData nearest) { nodes_in_sphere.slice(range).foreach_index([&](const int i) { for (const int grid : nodes[i].grids()) { - CCGElem *elem = elems[grid]; + const IndexRange grid_range = bke::ccg::grid_range(key, grid); BKE_subdiv_ccg_foreach_visible_grid_vert(key, grid_hidden, grid, [&](const int i) { - const float distance_sq = math::distance_squared(CCG_elem_offset_co(key, elem, i), - location); + const float distance_sq = math::distance_squared(positions[grid_range[i]], location); if (distance_sq < nearest.distance_sq) { SubdivCCGCoord coord{}; coord.grid_index = grid; @@ -1218,17 +1211,17 @@ static void restore_mask_from_undo_step(Object &object) SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const BitGroupVector<> grid_hidden = subdiv_ccg.grid_hidden; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span grids = subdiv_ccg.grids; + MutableSpan masks = subdiv_ccg.masks; node_mask.foreach_index(GrainSize(1), [&](const int i) { if (const std::optional> orig_data = orig_mask_data_lookup_grids(object, nodes[i])) { int index = 0; for (const int grid : nodes[i].grids()) { - CCGElem *elem = grids[grid]; + const IndexRange grid_range = bke::ccg::grid_range(key, grid); for (const int i : IndexRange(key.grid_area)) { if (grid_hidden.is_empty() || !grid_hidden[grid][i]) { - CCG_elem_offset_mask(key, elem, i) = (*orig_data)[index]; + masks[grid_range[i]] = (*orig_data)[index]; } index++; } @@ -1408,17 +1401,17 @@ void restore_position_from_undo_step(const Depsgraph &depsgraph, Object &object) SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const BitGroupVector<> grid_hidden = subdiv_ccg.grid_hidden; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span grids = subdiv_ccg.grids; + MutableSpan positions = subdiv_ccg.positions; node_mask.foreach_index(GrainSize(1), [&](const int i) { if (const std::optional orig_data = orig_position_data_lookup_grids( object, nodes[i])) { int index = 0; for (const int grid : nodes[i].grids()) { - CCGElem *elem = grids[grid]; + const IndexRange grid_range = bke::ccg::grid_range(key, grid); for (const int i : IndexRange(key.grid_area)) { if (grid_hidden.is_empty() || !grid_hidden[grid][i]) { - CCG_elem_offset_co(key, elem, i) = orig_data->positions[index]; + positions[grid_range[i]] = orig_data->positions[index]; } index++; } @@ -1801,7 +1794,7 @@ static void calc_area_normal_and_center_node_grids(const Object &object, const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const CCGKey key = BKE_subdiv_ccg_key_top_level(*ss.subdiv_ccg); - const Span elems = subdiv_ccg.grids; + const Span normals = subdiv_ccg.normals; const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden; const Span grids = node.grids(); @@ -1818,25 +1811,29 @@ static void calc_area_normal_and_center_node_grids(const Object &object, ss, orig_positions, eBrushFalloffShape(brush.falloff_shape), distances_sq); for (const int i : grids.index_range()) { - const int node_verts_start = i * key.grid_area; + const IndexRange grid_range_node = bke::ccg::grid_range(key, i); const int grid = grids[i]; for (const int offset : IndexRange(key.grid_area)) { if (!grid_hidden.is_empty() && grid_hidden[grid][offset]) { continue; } - const int vert = node_verts_start + offset; + const int node_vert = grid_range_node[offset]; - const bool normal_test_r = use_area_nos && distances_sq[vert] <= normal_radius_sq; - const bool area_test_r = use_area_cos && distances_sq[vert] <= position_radius_sq; + const bool normal_test_r = use_area_nos && distances_sq[node_vert] <= normal_radius_sq; + const bool area_test_r = use_area_cos && distances_sq[node_vert] <= position_radius_sq; if (!normal_test_r && !area_test_r) { continue; } - const float3 &normal = orig_normals[vert]; - const float distance = std::sqrt(distances_sq[vert]); + const float3 &normal = orig_normals[node_vert]; + const float distance = std::sqrt(distances_sq[node_vert]); const int flip_index = math::dot(view_normal, normal) <= 0.0f; if (area_test_r) { - accumulate_area_center( - location, orig_positions[vert], distance, position_radius_inv, flip_index, anctd); + accumulate_area_center(location, + orig_positions[node_vert], + distance, + position_radius_inv, + flip_index, + anctd); } if (normal_test_r) { accumulate_area_normal(normal, distance, normal_radius_inv, flip_index, anctd); @@ -1854,30 +1851,27 @@ static void calc_area_normal_and_center_node_grids(const Object &object, ss, positions, eBrushFalloffShape(brush.falloff_shape), distances_sq); for (const int i : grids.index_range()) { - const int node_verts_start = i * key.grid_area; + const IndexRange grid_range_node = bke::ccg::grid_range(key, i); const int grid = grids[i]; - CCGElem *elem = elems[grid]; + const IndexRange grid_range = bke::ccg::grid_range(key, grid); for (const int offset : IndexRange(key.grid_area)) { if (!grid_hidden.is_empty() && grid_hidden[grid][offset]) { continue; } - const int vert = node_verts_start + offset; + const int node_vert = grid_range_node[offset]; + const int vert = grid_range[offset]; - const bool normal_test_r = use_area_nos && distances_sq[vert] <= normal_radius_sq; - const bool area_test_r = use_area_cos && distances_sq[vert] <= position_radius_sq; + const bool normal_test_r = use_area_nos && distances_sq[node_vert] <= normal_radius_sq; + const bool area_test_r = use_area_cos && distances_sq[node_vert] <= position_radius_sq; if (!normal_test_r && !area_test_r) { continue; } - const float3 &normal = CCG_elem_offset_no(key, elem, offset); - const float distance = std::sqrt(distances_sq[vert]); + const float3 &normal = normals[vert]; + const float distance = std::sqrt(distances_sq[node_vert]); const int flip_index = math::dot(view_normal, normal) <= 0.0f; if (area_test_r) { - accumulate_area_center(location, - CCG_elem_offset_co(key, elem, offset), - distance, - position_radius_inv, - flip_index, - anctd); + accumulate_area_center( + location, positions[node_vert], distance, position_radius_inv, flip_index, anctd); } if (normal_test_r) { accumulate_area_normal(normal, distance, normal_radius_inv, flip_index, anctd); @@ -5981,7 +5975,7 @@ static void fake_neighbor_search_mesh(const SculptSession &ss, static void fake_neighbor_search_grids(const SculptSession &ss, const CCGKey &key, - const Span elems, + const Span positions, const BitGroupVector<> &grid_hidden, const float3 &location, const float max_distance_sq, @@ -5990,21 +5984,18 @@ static void fake_neighbor_search_grids(const SculptSession &ss, NearestVertData &nvtd) { for (const int grid : node.grids()) { - const int verts_start = grid * key.grid_area; - CCGElem *elem = elems[grid]; + const IndexRange grid_range = bke::ccg::grid_range(key, grid); BKE_subdiv_ccg_foreach_visible_grid_vert(key, grid_hidden, grid, [&](const int offset) { - const int vert = verts_start + offset; + const int vert = grid_range[offset]; if (ss.fake_neighbors.fake_neighbor_index[vert] != FAKE_NEIGHBOR_NONE) { return; } if (islands::vert_id_get(ss, vert) == island_id) { return; } - const float distance_sq = math::distance_squared(CCG_elem_offset_co(key, elem, offset), - location); + const float distance_sq = math::distance_squared(positions[vert], location); if (distance_sq < max_distance_sq && distance_sq < nvtd.distance_sq) { nvtd.vert = vert; - BLI_assert(nvtd.vert < key.grid_area * elems.size()); nvtd.distance_sq = distance_sq; } }); @@ -6101,15 +6092,14 @@ static void fake_neighbor_search(const Depsgraph &depsgraph, case bke::pbvh::Type::Grids: { const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span elems = subdiv_ccg.grids; + const Span positions = subdiv_ccg.positions; const BitGroupVector<> grid_hidden = subdiv_ccg.grid_hidden; - for (const int vert : IndexRange(elems.size() * key.grid_area)) { + for (const int vert : positions.index_range()) { if (fake_neighbors[vert] != FAKE_NEIGHBOR_NONE) { continue; } const int island_id = islands::vert_id_get(ss, vert); - const SubdivCCGCoord coord = SubdivCCGCoord::from_index(key, vert); - const float3 &location = CCG_grid_elem_co(key, elems[coord.grid_index], coord.x, coord.y); + const float3 &location = positions[vert]; IndexMaskMemory memory; const IndexMask nodes_in_sphere = bke::pbvh::search_nodes( pbvh, memory, [&](const bke::pbvh::Node &node) { @@ -6127,7 +6117,7 @@ static void fake_neighbor_search(const Depsgraph &depsgraph, nodes_in_sphere.slice(range).foreach_index([&](const int i) { fake_neighbor_search_grids(ss, key, - elems, + positions, grid_hidden, location, max_distance_sq, @@ -6402,9 +6392,8 @@ static SculptTopologyIslandCache calc_topology_islands_grids(const Object &objec const SculptSession &ss = *object.sculpt; const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const int verts_num = subdiv_ccg.grids.size() * key.grid_area; - AtomicDisjointSet disjoint_set(verts_num); - threading::parallel_for(subdiv_ccg.grids.index_range(), 512, [&](const IndexRange range) { + AtomicDisjointSet disjoint_set(subdiv_ccg.positions.size()); + threading::parallel_for(IndexRange(subdiv_ccg.grids_num), 512, [&](const IndexRange range) { for (const int grid : range) { SubdivCCGNeighbors neighbors; for (const short y : IndexRange(key.grid_size)) { @@ -6420,7 +6409,7 @@ static SculptTopologyIslandCache calc_topology_islands_grids(const Object &objec } }); - return vert_disjoint_set_to_islands(disjoint_set, verts_num); + return vert_disjoint_set_to_islands(disjoint_set, subdiv_ccg.positions.size()); } static SculptTopologyIslandCache calc_topology_islands_bmesh(const Object &object) @@ -6506,22 +6495,6 @@ void SCULPT_cube_tip_init(const Sculpt & /*sd*/, namespace blender::ed::sculpt_paint { -void gather_grids_positions(const CCGKey &key, - const Span elems, - const Span grids, - const MutableSpan positions) -{ - BLI_assert(grids.size() * key.grid_area == positions.size()); - - for (const int i : grids.index_range()) { - CCGElem *elem = elems[grids[i]]; - const int start = i * key.grid_area; - for (const int offset : IndexRange(key.grid_area)) { - positions[start + offset] = CCG_elem_offset_co(key, elem, offset); - } - } -} - void gather_bmesh_positions(const Set &verts, const MutableSpan positions) { BLI_assert(verts.size() == positions.size()); @@ -6537,17 +6510,7 @@ void gather_grids_normals(const SubdivCCG &subdiv_ccg, const Span grids, const MutableSpan normals) { - const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span elems = subdiv_ccg.grids; - BLI_assert(grids.size() * key.grid_area == normals.size()); - - for (const int i : grids.index_range()) { - CCGElem *elem = elems[grids[i]]; - const int start = i * key.grid_area; - for (const int offset : IndexRange(key.grid_area)) { - normals[start + offset] = CCG_elem_offset_no(key, elem, offset); - } - } + gather_data_grids(subdiv_ccg, subdiv_ccg.normals.as_span(), grids, normals); } void gather_bmesh_normals(const Set &verts, const MutableSpan normals) @@ -6579,9 +6542,9 @@ void gather_data_grids(const SubdivCCG &subdiv_ccg, BLI_assert(grids.size() * key.grid_area == node_data.size()); for (const int i : grids.index_range()) { - const int node_start = i * key.grid_area; - const int grids_start = grids[i] * key.grid_area; - node_data.slice(node_start, key.grid_area).copy_from(src.slice(grids_start, key.grid_area)); + const IndexRange grids_range = bke::ccg::grid_range(key, grids[i]); + const IndexRange node_range = bke::ccg::grid_range(key, i); + node_data.slice(node_range).copy_from(src.slice(grids_range)); } } @@ -6619,9 +6582,9 @@ void scatter_data_grids(const SubdivCCG &subdiv_ccg, BLI_assert(grids.size() * key.grid_area == node_data.size()); for (const int i : grids.index_range()) { - const int node_start = i * key.grid_area; - const int grids_start = grids[i] * key.grid_area; - dst.slice(grids_start, key.grid_area).copy_from(node_data.slice(node_start, key.grid_area)); + const IndexRange grids_range = bke::ccg::grid_range(key, grids[i]); + const IndexRange node_range = bke::ccg::grid_range(key, i); + dst.slice(grids_range).copy_from(node_data.slice(node_range)); } } @@ -6778,15 +6741,15 @@ void fill_factor_from_hide_and_mask(const SubdivCCG &subdiv_ccg, const MutableSpan r_factors) { const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span elems = subdiv_ccg.grids; BLI_assert(grids.size() * key.grid_area == r_factors.size()); - if (key.has_mask) { + if (!subdiv_ccg.masks.is_empty()) { + const Span masks = subdiv_ccg.masks; for (const int i : grids.index_range()) { - CCGElem *elem = elems[grids[i]]; - const int start = i * key.grid_area; - for (const int offset : IndexRange(key.grid_area)) { - r_factors[start + offset] = 1.0f - CCG_elem_offset_mask(key, elem, offset); + const Span src = masks.slice(bke::ccg::grid_range(key, grids[i])); + MutableSpan dst = r_factors.slice(bke::ccg::grid_range(key, i)); + for (const int offset : dst.index_range()) { + dst[offset] = 1.0f - src[offset]; } } } @@ -6838,15 +6801,15 @@ void calc_front_face(const float3 &view_normal, const MutableSpan factors) { const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span elems = subdiv_ccg.grids; + const Span normals = subdiv_ccg.normals; BLI_assert(grids.size() * key.grid_area == factors.size()); for (const int i : grids.index_range()) { - CCGElem *elem = elems[grids[i]]; - const int start = i * key.grid_area; - for (const int offset : IndexRange(key.grid_area)) { - const float dot = math::dot(view_normal, CCG_elem_offset_no(key, elem, offset)); - factors[start + offset] *= std::max(dot, 0.0f); + const Span grid_normals = normals.slice(bke::ccg::grid_range(key, grids[i])); + MutableSpan grid_factors = factors.slice(bke::ccg::grid_range(key, i)); + for (const int offset : grid_factors.index_range()) { + const float dot = math::dot(view_normal, grid_normals[offset]); + grid_factors[offset] *= std::max(dot, 0.0f); } } } @@ -7217,14 +7180,14 @@ void apply_translations(const Span translations, SubdivCCG &subdiv_ccg) { const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span elems = subdiv_ccg.grids; + MutableSpan positions = subdiv_ccg.positions; BLI_assert(grids.size() * key.grid_area == translations.size()); for (const int i : grids.index_range()) { - CCGElem *elem = elems[grids[i]]; - const int start = i * key.grid_area; - for (const int offset : IndexRange(key.grid_area)) { - CCG_elem_offset_co(key, elem, offset) += translations[start + offset]; + const Span grid_translations = translations.slice(bke::ccg::grid_range(key, i)); + MutableSpan grid_positions = positions.slice(bke::ccg::grid_range(key, grids[i])); + for (const int offset : grid_positions.index_range()) { + grid_positions[offset] += grid_translations[offset]; } } } diff --git a/source/blender/editors/sculpt_paint/sculpt_automasking.cc b/source/blender/editors/sculpt_paint/sculpt_automasking.cc index 0d59a8f7a79..eaf16b06d71 100644 --- a/source/blender/editors/sculpt_paint/sculpt_automasking.cc +++ b/source/blender/editors/sculpt_paint/sculpt_automasking.cc @@ -434,14 +434,14 @@ static void calc_blurred_cavity_grids(const Object &object, const SubdivCCGCoord vert) { struct CavityBlurVert { - SubdivCCGCoord vertex; - int index; + int vert; int depth; }; const SculptSession &ss = *object.sculpt; const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; - const Span grids = subdiv_ccg.grids; + const Span positions = subdiv_ccg.positions; + const Span normals = subdiv_ccg.normals; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); AccumulatedVert all_verts; @@ -454,23 +454,21 @@ static void calc_blurred_cavity_grids(const Object &object, std::queue queue; Set visited_verts; - const CavityBlurVert initial{vert, vert.to_index(key), 0}; - visited_verts.add_new(initial.index); + const CavityBlurVert initial{vert.to_index(key), 0}; + visited_verts.add_new(initial.vert); queue.push(initial); - const float3 starting_position = CCG_grid_elem_co(key, grids[vert.grid_index], vert.x, vert.y); + const float3 starting_position = positions[vert.to_index(key)]; SubdivCCGNeighbors neighbors; while (!queue.empty()) { const CavityBlurVert blurvert = queue.front(); queue.pop(); - const SubdivCCGCoord current_vert = blurvert.vertex; + const int current_vert = blurvert.vert; - const float3 blur_vert_position = CCG_grid_elem_co( - key, grids[current_vert.grid_index], current_vert.x, current_vert.y); - const float3 blur_vert_normal = CCG_grid_elem_no( - key, grids[current_vert.grid_index], current_vert.x, current_vert.y); + const float3 blur_vert_position = positions[current_vert]; + const float3 blur_vert_normal = normals[current_vert]; const float dist_to_start = math::distance(blur_vert_position, starting_position); @@ -490,7 +488,8 @@ static void calc_blurred_cavity_grids(const Object &object, continue; } - BKE_subdiv_ccg_neighbor_coords_get(subdiv_ccg, current_vert, false, neighbors); + BKE_subdiv_ccg_neighbor_coords_get( + subdiv_ccg, SubdivCCGCoord::from_index(key, current_vert), false, neighbors); for (const SubdivCCGCoord neighbor : neighbors.coords) { const int neighbor_idx = neighbor.to_index(key); if (visited_verts.contains(neighbor_idx)) { @@ -498,14 +497,14 @@ static void calc_blurred_cavity_grids(const Object &object, } visited_verts.add_new(neighbor_idx); - queue.push({neighbor, neighbor_idx, blurvert.depth + 1}); + queue.push({neighbor_idx, blurvert.depth + 1}); } } BLI_assert(all_verts.count != verts_in_range.count); if (all_verts.count == 0) { - all_verts.position = CCG_grid_elem_co(key, grids[vert.grid_index], vert.x, vert.y); + all_verts.position = positions[vert.to_index(key)]; } else { all_verts.position /= float(all_verts.count); @@ -513,7 +512,7 @@ static void calc_blurred_cavity_grids(const Object &object, } if (verts_in_range.count == 0) { - verts_in_range.position = CCG_grid_elem_co(key, grids[vert.grid_index], vert.x, vert.y); + verts_in_range.position = positions[vert.to_index(key)]; } else { verts_in_range.position /= float(verts_in_range.count); @@ -521,7 +520,7 @@ static void calc_blurred_cavity_grids(const Object &object, verts_in_range.normal = math::normalize(verts_in_range.normal); if (math::dot(verts_in_range.normal, verts_in_range.normal) == 0.0f) { - verts_in_range.normal = CCG_grid_elem_no(key, grids[vert.grid_index], vert.x, vert.y); + verts_in_range.normal = normals[vert.to_index(key)]; } const float3 vec = all_verts.position - verts_in_range.position; @@ -948,29 +947,24 @@ static void fill_topology_automasking_factors_grids(const Sculpt &sd, const float radius = ss.cache ? ss.cache->radius : std::numeric_limits::max(); const SubdivCCGCoord active_vert = std::get(ss.active_vert()); - const Span grids = subdiv_ccg.grids; + const Span positions = subdiv_ccg.positions; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const int grid_verts_num = subdiv_ccg.grids.size() * key.grid_area; - flood_fill::FillDataGrids flood = flood_fill::FillDataGrids(grid_verts_num); + flood_fill::FillDataGrids flood = flood_fill::FillDataGrids(positions.size()); flood.add_initial_with_symmetry(ob, *bke::object::pbvh_get(ob), subdiv_ccg, active_vert, radius); const bool use_radius = ss.cache && is_constrained_by_radius(brush); const ePaintSymmetryFlags symm = SCULPT_mesh_symmetry_xyz_get(ob); - float3 location = CCG_grid_elem_co( - key, grids[active_vert.grid_index], active_vert.x, active_vert.y); + float3 location = positions[active_vert.to_index(key)]; flood.execute( ob, subdiv_ccg, [&](SubdivCCGCoord from_v, SubdivCCGCoord to_v, bool /*is_duplicate*/) { *(float *)SCULPT_vertex_attr_get(key, to_v, ss.attrs.automasking_factor) = 1.0f; *(float *)SCULPT_vertex_attr_get(key, from_v, ss.attrs.automasking_factor) = 1.0f; return (use_radius || SCULPT_is_vertex_inside_brush_radius_symm( - CCG_grid_elem_co(key, grids[to_v.grid_index], to_v.x, to_v.y), - location, - radius, - symm)); + positions[to_v.to_index(key)], location, radius, symm)); }); } @@ -1119,15 +1113,14 @@ static void init_boundary_masking_grids(Object &object, const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; Mesh &mesh = *static_cast(object.data); - const Span grids = subdiv_ccg.grids; + const Span positions = subdiv_ccg.positions; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); const OffsetIndices faces = mesh.faces(); const Span corner_verts = mesh.corner_verts(); - const int num_grids = key.grid_area * grids.size(); - Array edge_distance(num_grids, EDGE_DISTANCE_INF); - for (const int i : IndexRange(num_grids)) { + Array edge_distance(positions.size(), EDGE_DISTANCE_INF); + for (const int i : positions.index_range()) { const SubdivCCGCoord coord = SubdivCCGCoord::from_index(key, i); switch (mode) { case BoundaryAutomaskMode::Edges: @@ -1149,7 +1142,7 @@ static void init_boundary_masking_grids(Object &object, SubdivCCGNeighbors neighbors; for (const int propagation_it : IndexRange(propagation_steps)) { - for (const int i : IndexRange(num_grids)) { + for (const int i : positions.index_range()) { if (edge_distance[i] != EDGE_DISTANCE_INF) { continue; } @@ -1166,7 +1159,7 @@ static void init_boundary_masking_grids(Object &object, } } - for (const int i : IndexRange(num_grids)) { + for (const int i : positions.index_range()) { if (edge_distance[i] == EDGE_DISTANCE_INF) { continue; } diff --git a/source/blender/editors/sculpt_paint/sculpt_boundary.cc b/source/blender/editors/sculpt_paint/sculpt_boundary.cc index 10b343248fe..6b555c3e4c1 100644 --- a/source/blender/editors/sculpt_paint/sculpt_boundary.cc +++ b/source/blender/editors/sculpt_paint/sculpt_boundary.cc @@ -204,19 +204,17 @@ static std::optional get_closest_boundary_vert_grids( return initial_vert; } - const Span grids = subdiv_ccg.grids; + const Span positions = subdiv_ccg.positions; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const int num_grids = key.grid_area * grids.size(); - flood_fill::FillDataGrids flood_fill(num_grids); + flood_fill::FillDataGrids flood_fill(positions.size()); flood_fill.add_initial(initial_vert); - const float3 initial_vert_position = CCG_grid_elem_co( - key, grids[initial_vert.grid_index], initial_vert.x, initial_vert.y); + const float3 initial_vert_position = positions[initial_vert.to_index(key)]; const float radius_sq = radius * radius; int boundary_initial_vert_steps = std::numeric_limits::max(); - Array floodfill_steps(num_grids, 0); + Array floodfill_steps(positions.size(), 0); std::optional boundary_initial_vert; flood_fill.execute( @@ -242,8 +240,8 @@ static std::optional get_closest_boundary_vert_grids( } } - const float len_sq = math::distance_squared( - initial_vert_position, CCG_grid_elem_co(key, grids[to_v.grid_index], to_v.x, to_v.y)); + const float len_sq = math::distance_squared(initial_vert_position, + positions[to_v.to_index(key)]); return len_sq < radius_sq; }); @@ -361,10 +359,9 @@ static void indices_init_grids(Object &object, const SubdivCCGCoord initial_vert, SculptBoundary &boundary) { - const Span grids = subdiv_ccg.grids; + const Span positions = subdiv_ccg.positions; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const int num_grids = key.grid_area * grids.size(); - flood_fill::FillDataGrids flood_fill(num_grids); + flood_fill::FillDataGrids flood_fill(positions.size()); const int initial_boundary_index = initial_vert.to_index(key); Set included_verts; @@ -378,12 +375,8 @@ static void indices_init_grids(Object &object, const int from_v_i = from_v.to_index(key); const int to_v_i = to_v.to_index(key); - const float3 from_v_co = CCG_elem_offset_co( - key, - grids[from_v.grid_index], - CCG_grid_xy_to_index(key.grid_size, from_v.x, from_v.y)); - const float3 to_v_co = CCG_elem_offset_co( - key, grids[to_v.grid_index], CCG_grid_xy_to_index(key.grid_size, to_v.x, to_v.y)); + const float3 &from_v_co = positions[from_v_i]; + const float3 &to_v_co = positions[to_v_i]; if (!boundary::vert_is_boundary(subdiv_ccg, corner_verts, faces, boundary_verts, to_v)) { return false; @@ -534,13 +527,12 @@ static void edit_data_init_grids(const SubdivCCG &subdiv_ccg, const float radius, SculptBoundary &boundary) { - const Span grids = subdiv_ccg.grids; + const Span positions = subdiv_ccg.positions; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const int num_grids = key.grid_area * grids.size(); - boundary.edit_info.original_vertex_i = Array(num_grids, BOUNDARY_VERTEX_NONE); - boundary.edit_info.propagation_steps_num = Array(num_grids, BOUNDARY_STEPS_NONE); - boundary.edit_info.strength_factor = Array(num_grids, 0.0f); + boundary.edit_info.original_vertex_i = Array(positions.size(), BOUNDARY_VERTEX_NONE); + boundary.edit_info.propagation_steps_num = Array(positions.size(), BOUNDARY_STEPS_NONE); + boundary.edit_info.strength_factor = Array(positions.size(), 0.0f); std::queue current_iteration; @@ -639,11 +631,8 @@ static void edit_data_init_grids(const SubdivCCG &subdiv_ccg, /* Check the distance using the vertex that was propagated from the initial vertex that * was used to initialize the boundary. */ if (boundary.edit_info.original_vertex_i[from_v_i] == initial_vert_i) { - boundary.pivot_position = CCG_elem_offset_co( - key, grids[neighbor.grid_index], index_in_grid); - accum_distance += math::distance( - CCG_grid_elem_co(key, grids[from_v.grid_index], from_v.x, from_v.y), - boundary.pivot_position); + boundary.pivot_position = positions[neighbor_idx]; + accum_distance += math::distance(positions[from_v_i], boundary.pivot_position); } } } @@ -798,8 +787,8 @@ static void bend_data_init_grids(const SubdivCCG &subdiv_ccg, SculptBoundary &bo const int num_elements = boundary.edit_info.strength_factor.size(); - const CCGKey &key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - Span grids = subdiv_ccg.grids; + const Span positions = subdiv_ccg.positions; + const Span normals = subdiv_ccg.normals; boundary.bend.pivot_rotation_axis = Array(num_elements, float3(0)); boundary.bend.pivot_positions = Array(num_elements, float3(0)); @@ -809,17 +798,12 @@ static void bend_data_init_grids(const SubdivCCG &subdiv_ccg, SculptBoundary &bo continue; } - const SubdivCCGCoord vert = SubdivCCGCoord::from_index(key, i); const int orig_vert_i = boundary.edit_info.original_vertex_i[i]; - const SubdivCCGCoord orig_vert = SubdivCCGCoord::from_index(key, orig_vert_i); - const float3 normal = CCG_grid_elem_no(key, grids[vert.grid_index], vert.x, vert.y); - const float3 dir = CCG_grid_elem_co( - key, grids[orig_vert.grid_index], orig_vert.x, orig_vert.y) - - CCG_grid_elem_co(key, grids[vert.grid_index], vert.x, vert.y); + const float3 normal = normals[i]; + const float3 dir = positions[orig_vert_i] - positions[i]; boundary.bend.pivot_rotation_axis[orig_vert_i] = math::normalize(math::cross(dir, normal)); - boundary.bend.pivot_positions[orig_vert_i] = CCG_grid_elem_co( - key, grids[vert.grid_index], vert.x, vert.y); + boundary.bend.pivot_positions[orig_vert_i] = positions[i]; } for (const int i : IndexRange(num_elements)) { @@ -906,8 +890,7 @@ static void slide_data_init_grids(const SubdivCCG &subdiv_ccg, SculptBoundary &b boundary.edit_info.strength_factor.size()); const int num_elements = boundary.edit_info.strength_factor.size(); - const CCGKey &key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - Span grids = subdiv_ccg.grids; + const Span positions = subdiv_ccg.positions; boundary.slide.directions = Array(num_elements, float3(0)); @@ -915,13 +898,10 @@ static void slide_data_init_grids(const SubdivCCG &subdiv_ccg, SculptBoundary &b if (boundary.edit_info.propagation_steps_num[i] != boundary.max_propagation_steps) { continue; } - const SubdivCCGCoord vert = SubdivCCGCoord::from_index(key, i); const int orig_vert_i = boundary.edit_info.original_vertex_i[i]; - const SubdivCCGCoord orig_vert = SubdivCCGCoord::from_index(key, orig_vert_i); - boundary.slide.directions[orig_vert_i] = math::normalize( - CCG_grid_elem_co(key, grids[orig_vert.grid_index], orig_vert.x, orig_vert.y) - - CCG_grid_elem_co(key, grids[vert.grid_index], vert.x, vert.y)); + boundary.slide.directions[orig_vert_i] = math::normalize(positions[orig_vert_i] - + positions[i]); } for (const int i : IndexRange(num_elements)) { @@ -983,14 +963,9 @@ static void twist_data_init_mesh(const Span vert_positions, SculptBounda static void twist_data_init_grids(const SubdivCCG &subdiv_ccg, SculptBoundary &boundary) { - const CCGKey &key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span grids = subdiv_ccg.grids; - + const Span vert_positions = subdiv_ccg.positions; Array positions(boundary.verts.size()); - for (const int i : positions.index_range()) { - const SubdivCCGCoord vert = SubdivCCGCoord::from_index(key, boundary.verts[i]); - positions[i] = CCG_grid_elem_co(key, grids[vert.grid_index], vert.x, vert.y); - } + array_utils::gather(vert_positions, boundary.verts.as_span(), positions.as_mutable_span()); populate_twist_data(positions, boundary); } @@ -2571,7 +2546,7 @@ BLI_NOINLINE static void calc_average_position(const SubdivCCG &subdiv_ccg, const MutableSpan average_positions) { const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - Span grids = subdiv_ccg.grids; + const Span positions = subdiv_ccg.positions; BLI_assert(neighbors.size() == propagation_steps.size()); BLI_assert(neighbors.size() == factors.size()); @@ -2582,8 +2557,7 @@ BLI_NOINLINE static void calc_average_position(const SubdivCCG &subdiv_ccg, int valid_neighbors = 0; for (const SubdivCCGCoord neighbor : neighbors[i]) { if (propagation_steps[i] == vert_propagation_steps[neighbor.to_index(key)]) { - average_positions[i] += CCG_grid_elem_co( - key, grids[neighbor.grid_index], neighbor.x, neighbor.y); + average_positions[i] += positions[neighbor.to_index(key)]; valid_neighbors++; } } @@ -3027,18 +3001,14 @@ static void init_falloff_grids(const SubdivCCG &subdiv_ccg, boundary.edit_info.strength_factor.size()); const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - Span grids = subdiv_ccg.grids; BKE_curvemapping_init(brush.curve); - for (const int i : grids.index_range()) { - const int start = i * key.grid_area; - for (const int offset : IndexRange(key.grid_area)) { - const int index = start + offset; + for (const int grid : IndexRange(subdiv_ccg.grids_num)) { + for (const int index : bke::ccg::grid_range(key, grid)) { if (boundary.edit_info.propagation_steps_num[index] != BOUNDARY_STEPS_NONE) { - const float mask_factor = key.has_mask ? - 1.0f - CCG_elem_offset_mask(key, grids[i], offset) : - 1.0f; + const float mask_factor = subdiv_ccg.masks.is_empty() ? 1.0f - subdiv_ccg.masks[index] : + 1.0f; boundary.edit_info.strength_factor[index] = mask_factor * BKE_brush_curve_strength(&brush, boundary.edit_info.propagation_steps_num[index], @@ -3189,7 +3159,7 @@ static void init_boundary_grids(Object &object, const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const CCGKey &key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - Span grids = subdiv_ccg.grids; + const Span positions = subdiv_ccg.positions; ActiveVert initial_vert_ref = ss.active_vert(); if (std::holds_alternative(initial_vert_ref)) { @@ -3202,9 +3172,7 @@ static void init_boundary_grids(Object &object, } else { const SubdivCCGCoord active_vert = std::get(initial_vert_ref); - float3 location = symmetry_flip( - CCG_grid_elem_co(key, grids[active_vert.grid_index], active_vert.x, active_vert.y), - symm_area); + float3 location = symmetry_flip(positions[active_vert.to_index(key)], symm_area); initial_vert = nearest_vert_calc_grids( pbvh, subdiv_ccg, location, ss.cache->radius_squared, false); } @@ -3553,7 +3521,7 @@ std::unique_ptr data_init_grids(Object &object, const OffsetIndices faces = mesh.faces(); const Span corner_verts = mesh.corner_verts(); const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; - const Span grids = subdiv_ccg.grids; + const Span positions = subdiv_ccg.positions; const CCGKey &key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); const std::optional boundary_initial_vert = get_closest_boundary_vert_grids( @@ -3577,8 +3545,7 @@ std::unique_ptr data_init_grids(Object &object, SubdivCCGCoord boundary_vert = *boundary_initial_vert; const int boundary_initial_vert_index = boundary_vert.to_index(key); boundary->initial_vert_i = boundary_initial_vert_index; - boundary->initial_vert_position = CCG_grid_elem_co( - key, grids[boundary_vert.grid_index], boundary_vert.x, boundary_vert.y); + boundary->initial_vert_position = positions[boundary_initial_vert_index]; indices_init_grids( object, faces, corner_verts, subdiv_ccg, ss.vertex_info.boundary, boundary_vert, *boundary); diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.cc b/source/blender/editors/sculpt_paint/sculpt_cloth.cc index 696a0b5c13c..bac2aa75c25 100644 --- a/source/blender/editors/sculpt_paint/sculpt_cloth.cc +++ b/source/blender/editors/sculpt_paint/sculpt_cloth.cc @@ -1443,7 +1443,8 @@ void do_simulation_step(const Depsgraph &depsgraph, }); SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span elems = subdiv_ccg.grids; + const Span cloth_positions = cloth_sim.pos; + MutableSpan positions = subdiv_ccg.positions; threading::parallel_for(active_nodes.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); active_nodes.slice(range).foreach_index([&](const int i) { @@ -1459,14 +1460,9 @@ void do_simulation_step(const Depsgraph &depsgraph, const Span verts = calc_vert_indices_grids(key, grids, tls.vert_indices); solve_verts_simulation(object, brush, sim_location, verts, factors, tls, cloth_sim); - for (const int i : grids.index_range()) { - const int grid = grids[i]; - const int start = grid * key.grid_area; - CCGElem *elem = elems[grid]; - for (const int offset : IndexRange(key.grid_area)) { - const int grid_vert_index = start + offset; - CCG_elem_offset_co(key, elem, offset) = cloth_sim.pos[grid_vert_index]; - } + for (const int grid : grids) { + const IndexRange grid_range = bke::ccg::grid_range(key, grid); + positions.slice(grid_range).copy_from(cloth_positions.slice(grid_range)); } cloth_sim.node_state[cloth_sim.node_state_index.lookup(&nodes[i])] = diff --git a/source/blender/editors/sculpt_paint/sculpt_expand.cc b/source/blender/editors/sculpt_paint/sculpt_expand.cc index deecd113049..e1277995435 100644 --- a/source/blender/editors/sculpt_paint/sculpt_expand.cc +++ b/source/blender/editors/sculpt_paint/sculpt_expand.cc @@ -394,11 +394,10 @@ static BitVector<> enabled_state_to_bitmap(const Depsgraph &depsgraph, SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const Span grid_to_face_map = subdiv_ccg.grid_to_face_map; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span elems = subdiv_ccg.grids; + const Span positions = subdiv_ccg.positions; BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden; - for (const int grid : subdiv_ccg.grids.index_range()) { + for (const int grid : IndexRange(subdiv_ccg.grids_num)) { const int start = grid * key.grid_area; - CCGElem *elem = elems[grid]; const int face_set = face_sets[grid_to_face_map[grid]]; BKE_subdiv_ccg_foreach_visible_grid_vert(key, grid_hidden, grid, [&](const int offset) { const int vert = start + offset; @@ -409,8 +408,8 @@ static BitVector<> enabled_state_to_bitmap(const Depsgraph &depsgraph, enabled_verts[vert].set(expand_cache.snap_enabled_face_sets->contains(face_set)); return; } - enabled_verts[vert].set(vert_falloff_is_enabled( - ss, expand_cache, CCG_elem_offset_co(key, elem, offset), vert)); + enabled_verts[vert].set( + vert_falloff_is_enabled(ss, expand_cache, positions[vert], vert)); }); } break; @@ -593,10 +592,8 @@ static Vector calc_symmetry_vert_indices(const Depsgraph &depsgraph, case bke::pbvh::Type::Grids: { SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span elems = subdiv_ccg.grids; - const SubdivCCGCoord original_coord = SubdivCCGCoord::from_index(key, original_vert); - const float3 location = CCG_grid_elem_co( - key, elems[original_coord.grid_index], original_coord.x, original_coord.y); + const Span positions = subdiv_ccg.positions; + const float3 location = positions[original_vert]; for (char symm_it = 1; symm_it <= symm; symm_it++) { if (!SCULPT_is_symmetry_iteration_valid(symm_it, symm)) { continue; @@ -812,13 +809,11 @@ static Array normals_falloff_create(const Depsgraph &depsgraph, case bke::pbvh::Type::Grids: { const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span elems = subdiv_ccg.grids; - - const SubdivCCGCoord orig_coord = SubdivCCGCoord::from_index(key, v.i); - const float3 orig_normal = CCG_grid_elem_no( - key, elems[orig_coord.grid_index], orig_coord.x, orig_coord.y); + const Span normals = subdiv_ccg.normals; + const float3 orig_normal = normals[v.i]; flood_fill::FillDataGrids flood(totvert); - flood.add_initial_with_symmetry(ob, pbvh, subdiv_ccg, orig_coord, FLT_MAX); + flood.add_initial_with_symmetry( + ob, pbvh, subdiv_ccg, SubdivCCGCoord::from_index(key, v.i), FLT_MAX); flood.execute( ob, subdiv_ccg, @@ -830,9 +825,8 @@ static Array normals_falloff_create(const Depsgraph &depsgraph, dists[to_vert] = dists[from_vert]; } else { - const float3 &from_normal = CCG_grid_elem_no( - key, elems[from.grid_index], from.x, from.y); - const float3 &to_normal = CCG_grid_elem_no(key, elems[to.grid_index], to.x, to.y); + const float3 &from_normal = normals[from_vert]; + const float3 &to_normal = normals[to_vert]; const float from_edge_factor = edge_factors[from_vert]; const float dist = math::dot(orig_normal, to_normal) * powf(from_edge_factor, edge_sensitivity); @@ -908,28 +902,20 @@ static Array spherical_falloff_create(const Depsgraph &depsgraph, } case bke::pbvh::Type::Grids: { SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; - const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span elems = subdiv_ccg.grids; + const Span positions = subdiv_ccg.positions; Array locations(symm_verts.size()); for (const int i : symm_verts.index_range()) { - const SubdivCCGCoord coord = SubdivCCGCoord::from_index(key, symm_verts[i]); - locations[i] = CCG_grid_elem_co(key, elems[coord.grid_index], coord.x, coord.y); + locations[i] = positions[symm_verts[i]]; } - threading::parallel_for(elems.index_range(), 1024, [&](const IndexRange range) { - for (const int grid : range) { - const int start = grid * key.grid_area; - CCGElem *elem = elems[grid]; - for (const int offset : IndexRange(key.grid_area)) { - const int vert = start + offset; - float dist = std::numeric_limits::max(); - for (const float3 &location : locations) { - dist = std::min(dist, - math::distance(CCG_elem_offset_co(key, elem, offset), location)); - } - dists[vert] = dist; + threading::parallel_for(positions.index_range(), 1024, [&](const IndexRange range) { + for (const int vert : range) { + float dist = std::numeric_limits::max(); + for (const float3 &location : locations) { + dist = std::min(dist, math::distance(positions[vert], location)); } + dists[vert] = dist; } }); break; @@ -1517,19 +1503,9 @@ static void write_mask_data(Object &object, const Span mask) break; } case bke::pbvh::Type::Grids: { - const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; - const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span grids = subdiv_ccg.grids; - - int index = 0; - for (const int grid : grids.index_range()) { - CCGElem *elem = grids[grid]; - for (const int i : IndexRange(key.grid_area)) { - CCG_elem_offset_mask(key, elem, i) = mask[index]; - index++; - } - } - MutableSpan nodes = pbvh.nodes(); + SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; + subdiv_ccg.masks.as_mutable_span().copy_from(mask); + MutableSpan nodes = pbvh.nodes(); node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_mask(nodes[i]); }); break; } @@ -1620,17 +1596,13 @@ static void update_mask_grids(const SculptSession &ss, { const Cache &expand_cache = *ss.expand_cache; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span elems = subdiv_ccg.grids; + const Span positions = subdiv_ccg.positions; + MutableSpan masks = subdiv_ccg.masks; bool any_changed = false; - const Span grids = node.grids(); - for (const int i : grids.index_range()) { - const int grid = grids[i]; - const int start = grid * key.grid_area; - CCGElem *elem = elems[grid]; - for (const int offset : IndexRange(key.grid_area)) { - const int vert = start + offset; - const float initial_mask = CCG_elem_offset_mask(key, elem, offset); + for (const int grid : node.grids()) { + for (const int vert : bke::ccg::grid_range(key, grid)) { + const float initial_mask = masks[vert]; if (expand_cache.check_islands && !is_vert_in_active_component(ss, expand_cache, vert)) { continue; @@ -1639,8 +1611,7 @@ static void update_mask_grids(const SculptSession &ss, float new_mask; if (enabled_verts[vert]) { - new_mask = gradient_value_get( - ss, expand_cache, CCG_elem_offset_co(key, elem, offset), vert); + new_mask = gradient_value_get(ss, expand_cache, positions[vert], vert); } else { new_mask = 0.0f; @@ -1659,7 +1630,7 @@ static void update_mask_grids(const SculptSession &ss, continue; } - CCG_elem_offset_mask(key, elem, offset) = clamp_f(new_mask, 0.0f, 1.0f); + masks[vert] = clamp_f(new_mask, 0.0f, 1.0f); any_changed = true; } } @@ -2578,18 +2549,12 @@ static bool any_nonzero_mask(const Object &object) } case bke::pbvh::Type::Grids: { const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; - const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - if (!key.has_mask) { + const Span mask = subdiv_ccg.masks; + if (mask.is_empty()) { return false; } - return std::any_of(subdiv_ccg.grids.begin(), subdiv_ccg.grids.end(), [&](CCGElem *elem) { - for (const int i : IndexRange(key.grid_area)) { - if (CCG_elem_offset_mask(key, elem, i) > 0.0f) { - return true; - } - } - return false; - }); + return std::any_of( + mask.begin(), mask.end(), [&](const float value) { return value > 0.0f; }); } case bke::pbvh::Type::BMesh: { BMesh &bm = *ss.bm; diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mask.cc b/source/blender/editors/sculpt_paint/sculpt_filter_mask.cc index 71664b69003..41728037d0b 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mask.cc +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mask.cc @@ -275,13 +275,12 @@ BLI_NOINLINE static void copy_old_hidden_mask_grids(const SubdivCCG &subdiv_ccg, return; } const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span elems = subdiv_ccg.grids; + const Span masks = subdiv_ccg.masks; for (const int i : grids.index_range()) { - const int node_verts_start = i * key.grid_area; - CCGElem *elem = elems[grids[i]]; - bits::foreach_1_index(grid_hidden[grids[i]], [&](const int offset) { - new_mask[node_verts_start + offset] = CCG_elem_offset_mask(key, elem, offset); - }); + const Span grid_masks = masks.slice(bke::ccg::grid_range(key, grids[i])); + MutableSpan grid_dst = new_mask.slice(bke::ccg::grid_range(key, i)); + bits::foreach_1_index(grid_hidden[grids[i]], + [&](const int offset) { grid_dst[offset] = grid_masks[offset]; }); } } @@ -296,15 +295,16 @@ static void apply_new_mask_grids(const Depsgraph &depsgraph, MutableSpan nodes = pbvh.nodes(); SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); + MutableSpan masks = subdiv_ccg.masks; node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) { const Span grids = nodes[i].grids(); const Span new_node_mask = new_mask.slice(node_verts[pos]); - if (mask_equals_array_grids(subdiv_ccg.grids, key, grids, new_node_mask)) { + if (mask_equals_array_grids(masks, key, grids, new_node_mask)) { return; } undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask); - scatter_mask_grids(new_node_mask, subdiv_ccg, grids); + scatter_data_grids(subdiv_ccg, new_node_mask, grids, masks); BKE_pbvh_node_mark_update_mask(nodes[i]); }); @@ -317,7 +317,7 @@ static void smooth_mask_grids(const SubdivCCG &subdiv_ccg, MutableSpan new_mask) { const Span grids = node.grids(); - average_neighbor_mask_grids(subdiv_ccg, node.grids(), new_mask); + smooth::average_data_grids(subdiv_ccg, subdiv_ccg.masks.as_span(), grids, new_mask); copy_old_hidden_mask_grids(subdiv_ccg, grids, new_mask); } @@ -333,9 +333,9 @@ static void sharpen_mask_grids(const SubdivCCG &subdiv_ccg, tls.node_mask.resize(grid_verts_num); const MutableSpan node_mask = tls.node_mask; - gather_mask_grids(subdiv_ccg, grids, node_mask); + gather_data_grids(subdiv_ccg, subdiv_ccg.masks.as_span(), grids, node_mask); - average_neighbor_mask_grids(subdiv_ccg, grids, new_mask); + smooth::average_data_grids(subdiv_ccg, subdiv_ccg.masks.as_span(), grids, new_mask); sharpen_masks(node_mask, new_mask); @@ -347,28 +347,26 @@ static void grow_mask_grids(const SubdivCCG &subdiv_ccg, MutableSpan new_mask) { const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span elems = subdiv_ccg.grids; + const Span masks = subdiv_ccg.masks; const Span grids = node.grids(); for (const int i : grids.index_range()) { const int grid = grids[i]; - CCGElem *elem = elems[grid]; - const int node_verts_start = i * key.grid_area; + const Span grid_masks = masks.slice(bke::ccg::grid_range(key, grid)); + MutableSpan grid_dst = new_mask.slice(bke::ccg::grid_range(key, i)); for (const short y : IndexRange(key.grid_size)) { for (const short x : IndexRange(key.grid_size)) { const int offset = CCG_grid_xy_to_index(key.grid_size, x, y); - const int node_vert_index = node_verts_start + offset; SubdivCCGNeighbors neighbors; SubdivCCGCoord coord{grid, x, y}; BKE_subdiv_ccg_neighbor_coords_get(subdiv_ccg, coord, false, neighbors); - new_mask[node_vert_index] = CCG_elem_offset_mask(key, elem, offset); + grid_dst[offset] = grid_masks[offset]; for (const SubdivCCGCoord neighbor : neighbors.coords) { - new_mask[node_vert_index] = std::max( - CCG_grid_elem_mask(key, elem, neighbor.x, neighbor.y), new_mask[node_vert_index]); + grid_dst[offset] = std::max(masks[neighbor.to_index(key)], grid_dst[offset]); } } } @@ -382,28 +380,26 @@ static void shrink_mask_grids(const SubdivCCG &subdiv_ccg, MutableSpan new_mask) { const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span elems = subdiv_ccg.grids; + const Span masks = subdiv_ccg.masks; const Span grids = node.grids(); for (const int i : grids.index_range()) { const int grid = grids[i]; - CCGElem *elem = elems[grid]; - const int node_verts_start = i * key.grid_area; + const Span grid_masks = masks.slice(bke::ccg::grid_range(key, grid)); + MutableSpan grid_dst = new_mask.slice(bke::ccg::grid_range(key, i)); for (const short y : IndexRange(key.grid_size)) { for (const short x : IndexRange(key.grid_size)) { const int offset = CCG_grid_xy_to_index(key.grid_size, x, y); - const int node_vert_index = node_verts_start + offset; SubdivCCGNeighbors neighbors; SubdivCCGCoord coord{grid, x, y}; BKE_subdiv_ccg_neighbor_coords_get(subdiv_ccg, coord, false, neighbors); - new_mask[node_vert_index] = CCG_elem_offset_mask(key, elem, offset); + grid_dst[offset] = grid_masks[offset]; for (const SubdivCCGCoord neighbor : neighbors.coords) { - new_mask[node_vert_index] = std::min( - CCG_grid_elem_mask(key, elem, neighbor.x, neighbor.y), new_mask[node_vert_index]); + grid_dst[offset] = std::min(masks[neighbor.to_index(key)], grid_dst[offset]); } } } @@ -426,7 +422,7 @@ static void increase_contrast_mask_grids(const Depsgraph &depsgraph, tls.node_mask.resize(grid_verts_num); const MutableSpan node_mask = tls.node_mask; - gather_mask_grids(subdiv_ccg, grids, node_mask); + gather_data_grids(subdiv_ccg, subdiv_ccg.masks.as_span(), grids, node_mask); tls.new_mask.resize(grid_verts_num); const MutableSpan new_mask = tls.new_mask; @@ -439,7 +435,7 @@ static void increase_contrast_mask_grids(const Depsgraph &depsgraph, } undo::push_node(depsgraph, object, &node, undo::Type::Mask); - scatter_mask_grids(new_mask.as_span(), subdiv_ccg, grids); + scatter_data_grids(subdiv_ccg, new_mask.as_span(), grids, subdiv_ccg.masks.as_mutable_span()); BKE_pbvh_node_mark_update_mask(node); } @@ -457,7 +453,7 @@ static void decrease_contrast_mask_grids(const Depsgraph &depsgraph, tls.node_mask.resize(grid_verts_num); const MutableSpan node_mask = tls.node_mask; - gather_mask_grids(subdiv_ccg, grids, node_mask); + gather_data_grids(subdiv_ccg, subdiv_ccg.masks.as_span(), grids, node_mask); tls.new_mask.resize(grid_verts_num); const MutableSpan new_mask = tls.new_mask; @@ -470,7 +466,7 @@ static void decrease_contrast_mask_grids(const Depsgraph &depsgraph, } undo::push_node(depsgraph, object, &node, undo::Type::Mask); - scatter_mask_grids(new_mask.as_span(), subdiv_ccg, grids); + scatter_data_grids(subdiv_ccg, new_mask.as_span(), grids, subdiv_ccg.masks.as_mutable_span()); BKE_pbvh_node_mark_update_mask(node); } diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.cc b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.cc index 482e70b0012..517aa25594c 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.cc +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.cc @@ -1097,7 +1097,6 @@ static void calc_relax_filter(const Depsgraph &depsgraph, grids, false, factors, - positions, tls.vert_neighbors, translations); @@ -1274,7 +1273,6 @@ static void calc_relax_face_sets_filter(const Depsgraph &depsgraph, grids, relax_face_sets, factors, - positions, tls.vert_neighbors, translations); @@ -1464,7 +1462,8 @@ static void calc_surface_smooth_filter(const Depsgraph &depsgraph, tls.average_positions.resize(positions.size()); const MutableSpan average_positions = tls.average_positions; - smooth::neighbor_position_average_grids(subdiv_ccg, grids, average_positions); + smooth::average_data_grids( + subdiv_ccg, subdiv_ccg.positions.as_span(), grids, average_positions); tls.laplacian_disp.resize(positions.size()); const MutableSpan laplacian_disp = tls.laplacian_disp; @@ -1726,7 +1725,7 @@ static void calc_sharpen_filter(const Depsgraph &depsgraph, case bke::pbvh::Type::Grids: { SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span elems = subdiv_ccg.grids; + MutableSpan vert_positions = subdiv_ccg.positions; threading::EnumerableThreadSpecific all_tls; MutableSpan nodes = pbvh.nodes(); @@ -1755,7 +1754,8 @@ static void calc_sharpen_filter(const Depsgraph &depsgraph, tls.smooth_positions.resize(positions.size()); const MutableSpan smooth_positions = tls.smooth_positions; - smooth::neighbor_position_average_grids(subdiv_ccg, grids, smooth_positions); + smooth::average_data_grids( + subdiv_ccg, subdiv_ccg.positions.as_span(), grids, smooth_positions); const Span sharpen_factors = gather_data_grids( subdiv_ccg, ss.filter_cache->sharpen_factor.as_span(), grids, tls.sharpen_factors); @@ -1777,9 +1777,7 @@ static void calc_sharpen_filter(const Depsgraph &depsgraph, BKE_subdiv_ccg_neighbor_coords_get( subdiv_ccg, SubdivCCGCoord{grid, x, y}, false, neighbors); for (const SubdivCCGCoord neighbor : neighbors.coords) { - float3 disp_n = CCG_grid_elem_co( - key, elems[neighbor.grid_index], neighbor.x, neighbor.y) - - position; + float3 disp_n = vert_positions[neighbor.to_index(key)] - position; disp_n *= ss.filter_cache->sharpen_factor[neighbor.to_index(key)]; disp_sharpen += disp_n; } @@ -2074,13 +2072,11 @@ static void calc_limit_surface_positions(const Object &object, MutableSpan elems = subdiv_ccg.grids; - threading::parallel_for(elems.index_range(), 512, [&](const IndexRange range) { + threading::parallel_for(IndexRange(subdiv_ccg.grids_num), 512, [&](const IndexRange range) { for (const int grid : range) { - const int start = grid * key.grid_area; - BKE_subdiv_ccg_eval_limit_positions( - subdiv_ccg, key, grid, limit_positions.slice(start, key.grid_area)); + MutableSpan grid_dst = limit_positions.slice(bke::ccg::grid_range(key, grid)); + BKE_subdiv_ccg_eval_limit_positions(subdiv_ccg, key, grid, grid_dst); } }); } diff --git a/source/blender/editors/sculpt_paint/sculpt_flood_fill.cc b/source/blender/editors/sculpt_paint/sculpt_flood_fill.cc index 87fdfbf4fd9..c95215d15a5 100644 --- a/source/blender/editors/sculpt_paint/sculpt_flood_fill.cc +++ b/source/blender/editors/sculpt_paint/sculpt_flood_fill.cc @@ -175,8 +175,7 @@ void FillDataGrids::add_initial_with_symmetry(const Object &object, else { BLI_assert(radius > 0.0f); const float radius_squared = (radius == FLT_MAX) ? FLT_MAX : radius * radius; - CCGElem *elem = subdiv_ccg.grids[vertex.grid_index]; - float3 location = symmetry_flip(CCG_grid_elem_co(key, elem, vertex.x, vertex.y), + float3 location = symmetry_flip(subdiv_ccg.positions[vertex.to_index(key)], ePaintSymmetryFlags(i)); vert_to_add = nearest_vert_calc_grids(pbvh, subdiv_ccg, location, radius_squared, false); } diff --git a/source/blender/editors/sculpt_paint/sculpt_mask_init.cc b/source/blender/editors/sculpt_paint/sculpt_mask_init.cc index b75710b7824..f791999d02a 100644 --- a/source/blender/editors/sculpt_paint/sculpt_mask_init.cc +++ b/source/blender/editors/sculpt_paint/sculpt_mask_init.cc @@ -78,12 +78,13 @@ void write_mask_mesh(const Depsgraph &depsgraph, mask.finish(); } -static void init_mask_grids(Main &bmain, - Scene &scene, - Depsgraph &depsgraph, - Object &object, - const IndexMask &node_mask, - FunctionRef &, int, CCGElem *)> write_fn) +static void init_mask_grids( + Main &bmain, + Scene &scene, + Depsgraph &depsgraph, + Object &object, + const IndexMask &node_mask, + FunctionRef &, int, MutableSpan)> write_fn) { MultiresModifierData *mmd = BKE_sculpt_multires_active(&scene, &object); BKE_sculpt_mask_layers_ensure(&depsgraph, &bmain, &object, mmd); @@ -92,14 +93,15 @@ static void init_mask_grids(Main &bmain, bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object); MutableSpan nodes = pbvh.nodes(); SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; - const Span grids = subdiv_ccg.grids; + const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); + MutableSpan masks = subdiv_ccg.masks; const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden; undo::push_nodes(depsgraph, object, node_mask, undo::Type::Mask); node_mask.foreach_index(GrainSize(1), [&](const int i) { for (const int grid : nodes[i].grids()) { - write_fn(grid_hidden, grid, grids[grid]); + write_fn(grid_hidden, grid, masks.slice(bke::ccg::grid_range(key, grid))); } BKE_pbvh_node_mark_update_mask(nodes[i]); }); @@ -169,19 +171,20 @@ static int sculpt_mask_init_exec(bContext *C, wmOperator *op) const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); switch (mode) { case InitMode::Random: { - init_mask_grids( - bmain, - scene, - depsgraph, - ob, - node_mask, - [&](const BitGroupVector<> &grid_hidden, const int grid_index, CCGElem *grid) { - const int verts_start = grid_index * key.grid_area; - BKE_subdiv_ccg_foreach_visible_grid_vert( - key, grid_hidden, grid_index, [&](const int i) { - CCG_elem_offset_mask(key, grid, i) = BLI_hash_int_01(verts_start + i + seed); - }); - }); + init_mask_grids(bmain, + scene, + depsgraph, + ob, + node_mask, + [&](const BitGroupVector<> &grid_hidden, + const int grid_index, + MutableSpan grid_masks) { + const int verts_start = grid_index * key.grid_area; + BKE_subdiv_ccg_foreach_visible_grid_vert( + key, grid_hidden, grid_index, [&](const int i) { + grid_masks[i] = BLI_hash_int_01(verts_start + i + seed); + }); + }); break; } case InitMode::FaceSet: { @@ -196,32 +199,33 @@ static int sculpt_mask_init_exec(bContext *C, wmOperator *op) depsgraph, ob, node_mask, - [&](const BitGroupVector<> &grid_hidden, const int grid_index, CCGElem *grid) { + [&](const BitGroupVector<> &grid_hidden, + const int grid_index, + MutableSpan grid_masks) { const int face_set = face_sets[grid_to_face[grid_index]]; const float value = BLI_hash_int_01(face_set + seed); BKE_subdiv_ccg_foreach_visible_grid_vert( - key, grid_hidden, grid_index, [&](const int i) { - CCG_elem_offset_mask(key, grid, i) = value; - }); + key, grid_hidden, grid_index, [&](const int i) { grid_masks[i] = value; }); }); break; } case InitMode::Island: { islands::ensure_cache(ob); - init_mask_grids( - bmain, - scene, - depsgraph, - ob, - node_mask, - [&](const BitGroupVector<> &grid_hidden, const int grid_index, CCGElem *grid) { - const int verts_start = grid_index * key.grid_area; - BKE_subdiv_ccg_foreach_visible_grid_vert( - key, grid_hidden, grid_index, [&](const int i) { - const int island = islands::vert_id_get(ss, verts_start + i); - CCG_elem_offset_mask(key, grid, i) = BLI_hash_int_01(island + seed); - }); - }); + init_mask_grids(bmain, + scene, + depsgraph, + ob, + node_mask, + [&](const BitGroupVector<> &grid_hidden, + const int grid_index, + MutableSpan grid_masks) { + const int verts_start = grid_index * key.grid_area; + BKE_subdiv_ccg_foreach_visible_grid_vert( + key, grid_hidden, grid_index, [&](const int i) { + const int island = islands::vert_id_get(ss, verts_start + i); + grid_masks[i] = BLI_hash_int_01(island + seed); + }); + }); break; } } diff --git a/source/blender/editors/sculpt_paint/sculpt_pose.cc b/source/blender/editors/sculpt_paint/sculpt_pose.cc index 515f1ff3959..c9263291b82 100644 --- a/source/blender/editors/sculpt_paint/sculpt_pose.cc +++ b/source/blender/editors/sculpt_paint/sculpt_pose.cc @@ -394,25 +394,24 @@ static void grow_factors_grids(const ePaintSymmetryFlags symm, PoseGrowFactorData &gftd) { const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span elems = subdiv_ccg.grids; + const Span positions = subdiv_ccg.positions; const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden; const Span grids = node.grids(); for (const int i : grids.index_range()) { const int grid = grids[i]; - CCGElem *elem = elems[grid]; - const int start = key.grid_area * grid; + const IndexRange grid_range = bke::ccg::grid_range(key, grid); for (const short y : IndexRange(key.grid_size)) { for (const short x : IndexRange(key.grid_size)) { const int offset = CCG_grid_xy_to_index(key.grid_size, x, y); if (!grid_hidden.is_empty() && grid_hidden[grid][offset]) { continue; } - const int vert = start + offset; + const int vert = grid_range[offset]; SubdivCCGNeighbors neighbors; BKE_subdiv_ccg_neighbor_coords_get( - subdiv_ccg, SubdivCCGCoord{grids[i], x, y}, false, neighbors); + subdiv_ccg, SubdivCCGCoord{grid, x, y}, false, neighbors); float max = 0.0f; for (const SubdivCCGCoord neighbor : neighbors.coords) { @@ -425,7 +424,7 @@ static void grow_factors_grids(const ePaintSymmetryFlags symm, } if (max > prev_mask[vert]) { - const float3 &position = CCG_elem_offset_co(key, elem, offset); + const float3 &position = positions[vert]; pose_factor[vert] = max; if (SCULPT_check_vertex_pivot_symmetry(position, pose_initial_position, symm)) { gftd.pos_avg += position; @@ -821,11 +820,10 @@ static void calc_pose_origin_and_factor_grids(Object &object, const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object); - const Span grids = subdiv_ccg.grids; + const Span positions = subdiv_ccg.positions; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const int num_grids = key.grid_area * grids.size(); /* Calculate the pose rotation point based on the boundaries of the brush factor. */ - flood_fill::FillDataGrids flood(num_grids); + flood_fill::FillDataGrids flood(positions.size()); flood.add_initial_with_symmetry( object, pbvh, subdiv_ccg, std::get(ss.active_vert()), radius); @@ -840,7 +838,7 @@ static void calc_pose_origin_and_factor_grids(Object &object, r_pose_factor[to_v_i] = 1.0f; - const float3 co = CCG_grid_elem_co(key, grids[to_v.grid_index], to_v.x, to_v.y); + const float3 &co = positions[to_v_i]; if (math::distance_squared(initial_location, fallback_floodfill_origin) < math::distance_squared(initial_location, co)) { diff --git a/source/blender/editors/sculpt_paint/sculpt_smooth.cc b/source/blender/editors/sculpt_paint/sculpt_smooth.cc index b293ed39685..d39e9cb6496 100644 --- a/source/blender/editors/sculpt_paint/sculpt_smooth.cc +++ b/source/blender/editors/sculpt_paint/sculpt_smooth.cc @@ -96,51 +96,17 @@ template void neighbor_data_average_mesh(Span, MutableSpan); static float3 average_positions(const CCGKey &key, - const Span elems, + const Span positions, const Span coords) { const float factor = math::rcp(float(coords.size())); float3 result(0); for (const SubdivCCGCoord coord : coords) { - result += CCG_grid_elem_co(key, elems[coord.grid_index], coord.x, coord.y) * factor; + result += positions[coord.to_index(key)] * factor; } return result; } -void neighbor_position_average_grids(const SubdivCCG &subdiv_ccg, - const Span grids, - const MutableSpan new_positions) -{ - const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span elems = subdiv_ccg.grids; - - BLI_assert(grids.size() * key.grid_area == new_positions.size()); - - for (const int i : grids.index_range()) { - const int grid = grids[i]; - const int node_verts_start = i * key.grid_area; - - /* TODO: This loop could be optimized in the future by skipping unnecessary logic for - * non-boundary grid vertices. */ - for (const int y : IndexRange(key.grid_size)) { - for (const int x : IndexRange(key.grid_size)) { - const int offset = CCG_grid_xy_to_index(key.grid_size, x, y); - const int node_vert_index = node_verts_start + offset; - - SubdivCCGCoord coord{}; - coord.grid_index = grid; - coord.x = x; - coord.y = y; - - SubdivCCGNeighbors neighbors; - BKE_subdiv_ccg_neighbor_coords_get(subdiv_ccg, coord, false, neighbors); - - new_positions[node_vert_index] = average_positions(key, elems, neighbors.coords); - } - } - } -} - void neighbor_position_average_interior_grids(const OffsetIndices faces, const Span corner_verts, const BitSpan boundary_verts, @@ -149,14 +115,14 @@ void neighbor_position_average_interior_grids(const OffsetIndices faces, const MutableSpan new_positions) { const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - const Span elems = subdiv_ccg.grids; + const Span positions = subdiv_ccg.positions; BLI_assert(grids.size() * key.grid_area == new_positions.size()); for (const int i : grids.index_range()) { - const int grid = grids[i]; - CCGElem *elem = elems[grid]; const int node_verts_start = i * key.grid_area; + const int grid = grids[i]; + const IndexRange grid_range = bke::ccg::grid_range(key, grid); /* TODO: This loop could be optimized in the future by skipping unnecessary logic for * non-boundary grid vertices. */ @@ -164,6 +130,7 @@ void neighbor_position_average_interior_grids(const OffsetIndices faces, for (const int x : IndexRange(key.grid_size)) { const int offset = CCG_grid_xy_to_index(key.grid_size, x, y); const int node_vert_index = node_verts_start + offset; + const int vert = grid_range[offset]; SubdivCCGCoord coord{}; coord.grid_index = grid; @@ -190,10 +157,10 @@ void neighbor_position_average_interior_grids(const OffsetIndices faces, } if (neighbors.coords.is_empty()) { - new_positions[node_vert_index] = CCG_elem_offset_co(key, elem, offset); + new_positions[node_vert_index] = positions[vert]; } else { - new_positions[node_vert_index] = average_positions(key, elems, neighbors.coords); + new_positions[node_vert_index] = average_positions(key, positions, neighbors.coords); } } } @@ -446,40 +413,18 @@ static float3 calc_boundary_normal_corner(const float3 ¤t_position, } static float3 calc_boundary_normal_corner(const CCGKey &key, - const Span elems, + const Span positions, const float3 ¤t_position, const Span neighbors) { float3 normal(0); for (const SubdivCCGCoord &coord : neighbors) { - const float3 to_neighbor = CCG_grid_elem_co(key, elems[coord.grid_index], coord.x, coord.y) - - current_position; + const float3 to_neighbor = positions[coord.to_index(key)] - current_position; normal += math::normalize(to_neighbor); } return math::normalize(normal); } -static float3 average_positions(const CCGKey &key, - const Span elems, - const Span positions, - const Span neighbors, - const int current_grid, - const int current_grid_start) -{ - const float factor = math::rcp(float(neighbors.size())); - float3 result(0); - for (const SubdivCCGCoord &coord : neighbors) { - if (current_grid == coord.grid_index) { - const int offset = CCG_grid_xy_to_index(key.grid_size, coord.x, coord.y); - result += positions[current_grid_start + offset] * factor; - } - else { - result += CCG_grid_elem_co(key, elems[coord.grid_index], coord.x, coord.y) * factor; - } - } - return result; -} - static float3 calc_boundary_normal_corner(const float3 ¤t_position, const Span neighbors) { @@ -572,11 +517,11 @@ void calc_relaxed_translations_grids(const SubdivCCG &subdiv_ccg, const Span grids, const bool filter_boundary_face_sets, const Span factors, - const Span positions, Vector> &neighbors, const MutableSpan translations) { - const Span elems = subdiv_ccg.grids; + const Span positions = subdiv_ccg.positions; + const Span normals = subdiv_ccg.normals; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); const int grid_verts_num = grids.size() * key.grid_area; @@ -587,12 +532,13 @@ void calc_relaxed_translations_grids(const SubdivCCG &subdiv_ccg, calc_vert_neighbors_interior(faces, corner_verts, boundary_verts, subdiv_ccg, grids, neighbors); for (const int i : grids.index_range()) { - CCGElem *elem = elems[grids[i]]; + const IndexRange grid_range = bke::ccg::grid_range(key, grids[i]); const int node_start = i * key.grid_area; for (const int y : IndexRange(key.grid_size)) { for (const int x : IndexRange(key.grid_size)) { const int offset = CCG_grid_xy_to_index(key.grid_size, x, y); const int node_vert = node_start + offset; + const int vert = grid_range[offset]; if (factors[node_vert] == 0.0f) { translations[node_vert] = float3(0); continue; @@ -631,25 +577,24 @@ void calc_relaxed_translations_grids(const SubdivCCG &subdiv_ccg, continue; } - const float3 smoothed_position = average_positions( - key, elems, positions, neighbors[node_vert], grids[i], node_start); + const float3 smoothed_position = average_positions(key, positions, neighbors[node_vert]); /* Normal Calculation */ float3 normal; if (is_boundary && neighbors[i].size() == 2) { normal = calc_boundary_normal_corner( - key, elems, positions[node_vert], neighbors[node_vert]); + key, positions, positions[vert], neighbors[node_vert]); if (math::is_zero(normal)) { translations[node_vert] = float3(0); continue; } } else { - normal = CCG_elem_offset_no(key, elem, offset); + normal = normals[vert]; } const float3 translation = translation_to_plane( - positions[node_vert], normal, smoothed_position); + positions[vert], normal, smoothed_position); translations[node_vert] = translation * factors[node_vert]; } diff --git a/source/blender/editors/sculpt_paint/sculpt_smooth.hh b/source/blender/editors/sculpt_paint/sculpt_smooth.hh index 07f523f2fd4..58d683860af 100644 --- a/source/blender/editors/sculpt_paint/sculpt_smooth.hh +++ b/source/blender/editors/sculpt_paint/sculpt_smooth.hh @@ -39,9 +39,6 @@ void neighbor_color_average(OffsetIndices faces, Span> vert_neighbors, MutableSpan smooth_colors); -void neighbor_position_average_grids(const SubdivCCG &subdiv_ccg, - Span grids, - MutableSpan new_positions); void neighbor_position_average_interior_grids(OffsetIndices faces, Span corner_verts, BitSpan boundary_verts, @@ -109,7 +106,6 @@ void calc_relaxed_translations_grids(const SubdivCCG &subdiv_ccg, Span grids, bool filter_boundary_face_sets, Span factors, - Span positions, Vector> &neighbors, MutableSpan translations); void calc_relaxed_translations_bmesh(const Set &verts, diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.cc b/source/blender/editors/sculpt_paint/sculpt_undo.cc index f5baaafd313..08f71acbcea 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.cc +++ b/source/blender/editors/sculpt_paint/sculpt_undo.cc @@ -80,6 +80,7 @@ #include "ED_undo.hh" #include "bmesh.hh" +#include "mesh_brush_common.hh" #include "paint_hide.hh" #include "paint_intern.hh" #include "sculpt_color.hh" @@ -418,7 +419,7 @@ static bool topology_matches(const StepData &step_data, const Object &object) const SculptSession &ss = *object.sculpt; if (use_multires_undo(step_data, ss)) { const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; - return subdiv_ccg.grids.size() == step_data.mesh_grids_num && + return subdiv_ccg.grids_num == step_data.mesh_grids_num && subdiv_ccg.grid_size == step_data.grid_size; } Mesh &mesh = *static_cast(object.data); @@ -548,24 +549,23 @@ static void restore_position_mesh(Object &object, } } -static void restore_position_grids(MutableSpan grids, +static void restore_position_grids(MutableSpan positions, const CCGKey &key, Node &unode, MutableSpan modified_grids) { - const Span grid_indices = unode.grids; - MutableSpan position = unode.position; + const Span grids = unode.grids; + MutableSpan undo_position = unode.position; - int index = 0; - for (const int i : grid_indices.index_range()) { - CCGElem *grid = grids[grid_indices[i]]; - for (const int j : IndexRange(key.grid_area)) { - std::swap(CCG_elem_offset_co(key, grid, j), position[index]); - index++; + for (const int i : grids.index_range()) { + MutableSpan data = positions.slice(bke::ccg::grid_range(key, grids[i])); + MutableSpan undo_data = undo_position.slice(bke::ccg::grid_range(key, i)); + for (const int offset : data.index_range()) { + std::swap(data[offset], undo_data[offset]); } } - modified_grids.fill_indices(grid_indices, true); + modified_grids.fill_indices(grids, true); } static void restore_vert_visibility_mesh(Object &object, @@ -681,18 +681,18 @@ static void restore_mask_grids(Object &object, Node &unode, MutableSpan mo { SculptSession &ss = *object.sculpt; SubdivCCG *subdiv_ccg = ss.subdiv_ccg; + MutableSpan masks = subdiv_ccg->masks; const CCGKey key = BKE_subdiv_ccg_key_top_level(*subdiv_ccg); - MutableSpan mask = unode.mask; - MutableSpan grids = subdiv_ccg->grids; + const Span grids = unode.grids; + MutableSpan undo_mask = unode.mask; - int index = 0; - for (const int grid : unode.grids) { - CCGElem *elem = grids[grid]; - for (const int j : IndexRange(key.grid_area)) { - std::swap(CCG_elem_offset_mask(key, elem, j), mask[index]); - index++; + for (const int i : grids.index_range()) { + MutableSpan data = masks.slice(bke::ccg::grid_range(key, grids[i])); + MutableSpan undo_data = undo_mask.slice(bke::ccg::grid_range(key, i)); + for (const int offset : data.index_range()) { + std::swap(data[offset], undo_data[offset]); } } @@ -1001,12 +1001,11 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data) if (use_multires_undo(step_data, ss)) { MutableSpan nodes = pbvh.nodes(); SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; - MutableSpan grids = subdiv_ccg.grids; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - Array modified_grids(grids.size(), false); + Array modified_grids(subdiv_ccg.grids_num, false); for (std::unique_ptr &unode : step_data.nodes) { - restore_position_grids(grids, key, *unode, modified_grids); + restore_position_grids(subdiv_ccg.positions, key, *unode, modified_grids); } node_mask.foreach_index([&](const int i) { const Span grids = nodes[i].grids(); @@ -1051,7 +1050,7 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data) if (use_multires_undo(step_data, ss)) { MutableSpan nodes = pbvh.nodes(); SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; - Array modified_grids(subdiv_ccg.grids.size(), false); + Array modified_grids(subdiv_ccg.grids_num, false); for (std::unique_ptr &unode : step_data.nodes) { restore_vert_visibility_grids(subdiv_ccg, *unode, modified_grids); } @@ -1133,7 +1132,7 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data) if (use_multires_undo(step_data, ss)) { MutableSpan nodes = pbvh.nodes(); - Array modified_grids(ss.subdiv_ccg->grids.size(), false); + Array modified_grids(ss.subdiv_ccg->grids_num, false); for (std::unique_ptr &unode : step_data.nodes) { restore_mask_grids(object, *unode, modified_grids); } @@ -1311,29 +1310,10 @@ static void store_positions_mesh(const Depsgraph &depsgraph, const Object &objec static void store_positions_grids(const SubdivCCG &subdiv_ccg, Node &unode) { - const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - - const Span grids = subdiv_ccg.grids; - { - int index = 0; - for (const int grid : unode.grids) { - CCGElem *elem = grids[grid]; - for (const int i : IndexRange(key.grid_area)) { - unode.position[index] = CCG_elem_offset_co(key, elem, i); - index++; - } - } - } - if (key.has_normals) { - int index = 0; - for (const int grid : unode.grids) { - CCGElem *elem = grids[grid]; - for (const int i : IndexRange(key.grid_area)) { - unode.normal[index] = CCG_elem_offset_no(key, elem, i); - index++; - } - } - } + gather_data_grids( + subdiv_ccg, subdiv_ccg.positions.as_span(), unode.grids, unode.position.as_mutable_span()); + gather_data_grids( + subdiv_ccg, subdiv_ccg.normals.as_span(), unode.grids, unode.normal.as_mutable_span()); } static void store_vert_visibility_mesh(const Mesh &mesh, const bke::pbvh::Node &node, Node &unode) @@ -1378,17 +1358,9 @@ static void store_mask_mesh(const Mesh &mesh, Node &unode) static void store_mask_grids(const SubdivCCG &subdiv_ccg, Node &unode) { - const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - if (key.has_mask) { - const Span grids = subdiv_ccg.grids; - int index = 0; - for (const int grid : unode.grids) { - CCGElem *elem = grids[grid]; - for (const int i : IndexRange(key.grid_area)) { - unode.mask[index] = CCG_elem_offset_mask(key, elem, i); - index++; - } - } + if (!subdiv_ccg.masks.is_empty()) { + gather_data_grids( + subdiv_ccg, subdiv_ccg.masks.as_span(), unode.grids, unode.mask.as_mutable_span()); } else { unode.mask.fill(0.0f); @@ -1869,7 +1841,7 @@ void push_begin_ex(Object &ob, const char *name) break; } case bke::pbvh::Type::Grids: { - us->data.mesh_grids_num = ss.subdiv_ccg->grids.size(); + us->data.mesh_grids_num = ss.subdiv_ccg->grids_num; us->data.grid_size = ss.subdiv_ccg->grid_size; break; }