Refactor: Reorganize sculpt_boundary.cc calculations

* Moves boundary initialization out of indices_init
* Change parameters for edit_data_init since all it needs is the index
* Revert change to queues to use PBVHVertRef again since the newly
  refactored code will have to use int / SubdivCCGCoord / BMVert* for
  neighbor processing anyways
* Reduce scope of some variables
* Reduce nested branching

Pull Request: https://projects.blender.org/blender/blender/pulls/125390
This commit is contained in:
Sean Kim
2024-07-26 06:00:25 +02:00
committed by Sean Kim
parent 8d454ba13f
commit 31e636a29e

View File

@@ -58,7 +58,7 @@ static void indices_init(SculptSession &ss,
*/
static void edit_data_init(SculptSession &ss,
SculptBoundary &boundary,
const PBVHVertRef initial_vert,
const int initial_vert_i,
const float radius);
std::unique_ptr<SculptBoundary> data_init(Object &object,
@@ -90,10 +90,15 @@ std::unique_ptr<SculptBoundary> data_init(Object &object,
std::unique_ptr<SculptBoundary> boundary = std::make_unique<SculptBoundary>();
*boundary = {};
const int boundary_initial_vert_index = BKE_pbvh_vertex_to_index(*ss.pbvh,
boundary_initial_vert);
boundary->initial_vert_i = boundary_initial_vert_index;
copy_v3_v3(boundary->initial_vert_position, SCULPT_vertex_co_get(ss, boundary_initial_vert));
indices_init(ss, *boundary, boundary_initial_vert);
const float boundary_radius = brush ? radius * (1.0f + brush->boundary_offset) : radius;
edit_data_init(ss, *boundary, boundary_initial_vert, boundary_radius);
edit_data_init(ss, *boundary, boundary_initial_vert_index, boundary_radius);
return boundary;
}
@@ -272,14 +277,10 @@ static void indices_init(SculptSession &ss,
flood_fill::FillData flood = flood_fill::init_fill(ss);
int initial_boundary_index = BKE_pbvh_vertex_to_index(*ss.pbvh, initial_boundary_vert);
boundary.initial_vert_i = initial_boundary_index;
copy_v3_v3(boundary.initial_vert_position, SCULPT_vertex_co_get(ss, initial_boundary_vert));
BoundaryFloodFillData fdata{};
fdata.boundary = &boundary;
const int initial_boundary_index = BKE_pbvh_vertex_to_index(*ss.pbvh, initial_boundary_vert);
add_index(boundary, initial_boundary_index, 0.0f, fdata.included_verts);
flood_fill::add_initial(flood, initial_boundary_vert);
@@ -296,17 +297,15 @@ static void indices_init(SculptSession &ss,
static void edit_data_init(SculptSession &ss,
SculptBoundary &boundary,
const PBVHVertRef initial_vert,
const int initial_vert_i,
const float radius)
{
const int totvert = SCULPT_vertex_count_get(ss);
const bool has_duplicates = ss.pbvh->type() == bke::pbvh::Type::Grids;
boundary.edit_info = Array<SculptBoundaryEditInfo>(totvert);
std::queue<int> current_iteration;
std::queue<int> next_iteration;
std::queue<PBVHVertRef> current_iteration;
const bool has_duplicates = ss.pbvh->type() == bke::pbvh::Type::Grids;
for (int i = 0; i < boundary.verts.size(); i++) {
const PBVHVertRef vert = BKE_pbvh_index_to_vertex(*ss.pbvh, boundary.verts[i]);
@@ -327,12 +326,14 @@ static void edit_data_init(SculptSession &ss,
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni_duplis);
}
current_iteration.push(index);
current_iteration.push(vert);
}
int propagation_steps_num = 0;
float accum_distance = 0.0f;
std::queue<PBVHVertRef> next_iteration;
while (true) {
/* Stop adding steps to edit info. This happens when a steps is further away from the boundary
* than the brush radius or when the entire mesh was already processed. */
@@ -342,10 +343,10 @@ static void edit_data_init(SculptSession &ss,
}
while (!current_iteration.empty()) {
const int from_v_i = current_iteration.front();
const PBVHVertRef from_v = current_iteration.front();
current_iteration.pop();
const PBVHVertRef from_v = BKE_pbvh_index_to_vertex(*ss.pbvh, from_v_i);
const int from_v_i = BKE_pbvh_vertex_to_index(*ss.pbvh, from_v);
SculptVertexNeighborIter ni;
SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, from_v, ni) {
@@ -362,38 +363,36 @@ static void edit_data_init(SculptSession &ss,
/* Grids duplicates handling. */
boundary.edit_info[ni.index].propagation_steps_num =
boundary.edit_info[from_v_i].propagation_steps_num;
continue;
}
else {
boundary.edit_info[ni.index].propagation_steps_num =
boundary.edit_info[from_v_i].propagation_steps_num + 1;
next_iteration.push(ni.index);
boundary.edit_info[ni.index].propagation_steps_num =
boundary.edit_info[from_v_i].propagation_steps_num + 1;
/* When copying the data to the neighbor for the next iteration, it has to be copied to
* all its duplicates too. This is because it is not possible to know if the updated
* neighbor or one if its uninitialized duplicates is going to come first in order to
* copy the data in the from_v neighbor iterator. */
if (has_duplicates) {
SculptVertexNeighborIter ni_duplis;
SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, ni.vertex, ni_duplis) {
if (ni_duplis.is_duplicate) {
boundary.edit_info[ni_duplis.index].original_vertex_i =
boundary.edit_info[from_v_i].original_vertex_i;
boundary.edit_info[ni_duplis.index].propagation_steps_num =
boundary.edit_info[from_v_i].propagation_steps_num + 1;
}
next_iteration.push(ni.vertex);
/* When copying the data to the neighbor for the next iteration, it has to be copied to
* all its duplicates too. This is because it is not possible to know if the updated
* neighbor or one if its uninitialized duplicates is going to come first in order to
* copy the data in the from_v neighbor iterator. */
if (has_duplicates) {
SculptVertexNeighborIter ni_duplis;
SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, ni.vertex, ni_duplis) {
if (ni_duplis.is_duplicate) {
boundary.edit_info[ni_duplis.index].original_vertex_i =
boundary.edit_info[from_v_i].original_vertex_i;
boundary.edit_info[ni_duplis.index].propagation_steps_num =
boundary.edit_info[from_v_i].propagation_steps_num + 1;
}
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni_duplis);
}
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni_duplis);
}
/* Check the distance using the vertex that was propagated from the initial vertex that
* was used to initialize the boundary. */
if (boundary.edit_info[from_v_i].original_vertex_i ==
BKE_pbvh_vertex_to_index(*ss.pbvh, initial_vert))
{
boundary.pivot_position = SCULPT_vertex_co_get(ss, ni.vertex);
accum_distance += len_v3v3(SCULPT_vertex_co_get(ss, from_v), boundary.pivot_position);
}
/* Check the distance using the vertex that was propagated from the initial vertex that
* was used to initialize the boundary. */
if (boundary.edit_info[from_v_i].original_vertex_i == initial_vert_i) {
boundary.pivot_position = SCULPT_vertex_co_get(ss, ni.vertex);
accum_distance += len_v3v3(SCULPT_vertex_co_get(ss, from_v), boundary.pivot_position);
}
}
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
@@ -401,7 +400,7 @@ static void edit_data_init(SculptSession &ss,
/* Copy the new vertices to the queue to be processed in the next iteration. */
while (!next_iteration.empty()) {
const int next_v = next_iteration.front();
const PBVHVertRef next_v = next_iteration.front();
next_iteration.pop();
current_iteration.push(next_v);
}
@@ -784,8 +783,9 @@ static void brush_smooth_task(Object &ob, const Brush &brush, bke::pbvh::Node *n
BKE_pbvh_vertex_iter_end;
}
/* This functions assigns a falloff factor to each one of the SculptBoundaryEditInfo structs based
* on the brush curve and its propagation steps. The falloff goes from the boundary into the mesh.
/* This functions assigns a falloff factor to each one of the SculptBoundaryEditInfo structs
* based on the brush curve and its propagation steps. The falloff goes from the boundary into
* the mesh.
*/
static void init_falloff(SculptSession &ss,
SculptBoundary &boundary,
@@ -973,18 +973,23 @@ std::unique_ptr<SculptBoundaryPreview> preview_data_init(Object &object,
return nullptr;
}
/* Starting from a vertex that is the limit of a boundary is ambiguous, so return nullptr instead
* of forcing a random active boundary from a corner. */
/* Starting from a vertex that is the limit of a boundary is ambiguous, so return nullptr
* instead of forcing a random active boundary from a corner. */
if (!is_vert_in_editable_boundary(ss, initial_vert)) {
return nullptr;
}
const int boundary_initial_vert_index = BKE_pbvh_vertex_to_index(*ss.pbvh,
boundary_initial_vert);
SculptBoundary boundary;
boundary.initial_vert_i = boundary_initial_vert_index;
copy_v3_v3(boundary.initial_vert_position, SCULPT_vertex_co_get(ss, boundary_initial_vert));
indices_init(ss, boundary, boundary_initial_vert);
const float boundary_radius = brush ? radius * (1.0f + brush->boundary_offset) : radius;
edit_data_init(ss, boundary, boundary_initial_vert, boundary_radius);
edit_data_init(ss, boundary, boundary_initial_vert_index, boundary_radius);
std::unique_ptr<SculptBoundaryPreview> preview = std::make_unique<SculptBoundaryPreview>();
preview->edges = boundary.edges;