Cleanup: 3 sculpt cleanups #120708
|
@ -1003,25 +1003,25 @@ void SCULPT_tag_update_overlays(bContext *C)
|
|||
|
||||
namespace blender::ed::sculpt_paint::flood_fill {
|
||||
|
||||
void init_fill(SculptSession *ss, SculptFloodFill *flood)
|
||||
void init_fill(SculptSession *ss, FillData *flood)
|
||||
{
|
||||
SCULPT_vertex_random_access_ensure(ss);
|
||||
flood->visited_verts.resize(SCULPT_vertex_count_get(ss));
|
||||
}
|
||||
|
||||
void add_initial(SculptFloodFill *flood, PBVHVertRef vertex)
|
||||
void add_initial(FillData *flood, PBVHVertRef vertex)
|
||||
{
|
||||
flood->queue.push(vertex);
|
||||
}
|
||||
|
||||
void add_and_skip_initial(SculptFloodFill *flood, PBVHVertRef vertex)
|
||||
void add_and_skip_initial(FillData *flood, PBVHVertRef vertex)
|
||||
{
|
||||
flood->queue.push(vertex);
|
||||
flood->visited_verts[vertex.i].set(vertex.i);
|
||||
}
|
||||
|
||||
void add_initial_with_symmetry(
|
||||
Object *ob, SculptSession *ss, SculptFloodFill *flood, PBVHVertRef vertex, float radius)
|
||||
Object *ob, SculptSession *ss, FillData *flood, PBVHVertRef vertex, float radius)
|
||||
{
|
||||
/* Add active vertex and symmetric vertices to the queue. */
|
||||
const char symm = SCULPT_mesh_symmetry_xyz_get(ob);
|
||||
|
@ -1047,7 +1047,7 @@ void add_initial_with_symmetry(
|
|||
}
|
||||
}
|
||||
|
||||
void add_active(Object *ob, SculptSession *ss, SculptFloodFill *flood, float radius)
|
||||
void add_active(Object *ob, SculptSession *ss, FillData *flood, float radius)
|
||||
{
|
||||
/* Add active vertex and symmetric vertices to the queue. */
|
||||
const char symm = SCULPT_mesh_symmetry_xyz_get(ob);
|
||||
|
@ -1073,14 +1073,11 @@ void add_active(Object *ob, SculptSession *ss, SculptFloodFill *flood, float rad
|
|||
}
|
||||
}
|
||||
|
||||
void execute(SculptSession *ss,
|
||||
SculptFloodFill *flood,
|
||||
bool (*func)(SculptSession *ss,
|
||||
PBVHVertRef from_v,
|
||||
PBVHVertRef to_v,
|
||||
bool is_duplicate,
|
||||
void *userdata),
|
||||
void *userdata)
|
||||
void execute(
|
||||
SculptSession *ss,
|
||||
FillData *flood,
|
||||
FunctionRef<bool(SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate)>
|
||||
func)
|
||||
{
|
||||
while (!flood->queue.empty()) {
|
||||
PBVHVertRef from_v = flood->queue.front();
|
||||
|
@ -1101,7 +1098,7 @@ void execute(SculptSession *ss,
|
|||
|
||||
flood->visited_verts[BKE_pbvh_vertex_to_index(ss->pbvh, to_v)].set();
|
||||
|
||||
if (func(ss, from_v, to_v, ni.is_duplicate, userdata)) {
|
||||
if (func(ss, from_v, to_v, ni.is_duplicate)) {
|
||||
flood->queue.push(to_v);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -600,11 +600,11 @@ struct AutomaskFloodFillData {
|
|||
char symm;
|
||||
};
|
||||
|
||||
static bool floodfill_cb(
|
||||
SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool /*is_duplicate*/, void *userdata)
|
||||
static bool floodfill_cb(SculptSession *ss,
|
||||
PBVHVertRef from_v,
|
||||
PBVHVertRef to_v,
|
||||
AutomaskFloodFillData *data)
|
||||
{
|
||||
AutomaskFloodFillData *data = (AutomaskFloodFillData *)userdata;
|
||||
|
||||
*(float *)SCULPT_vertex_attr_get(to_v, ss->attrs.automasking_factor) = 1.0f;
|
||||
*(float *)SCULPT_vertex_attr_get(from_v, ss->attrs.automasking_factor) = 1.0f;
|
||||
return (!data->use_radius ||
|
||||
|
@ -626,7 +626,7 @@ static void topology_automasking_init(const Sculpt *sd, Object *ob)
|
|||
|
||||
/* Flood fill automask to connected vertices. Limited to vertices inside
|
||||
* the brush radius if the tool requires it. */
|
||||
SculptFloodFill flood;
|
||||
flood_fill::FillData flood;
|
||||
flood_fill::init_fill(ss, &flood);
|
||||
const float radius = ss->cache ? ss->cache->radius : FLT_MAX;
|
||||
flood_fill::add_active(ob, ss, &flood, radius);
|
||||
|
@ -638,7 +638,12 @@ static void topology_automasking_init(const Sculpt *sd, Object *ob)
|
|||
fdata.symm = SCULPT_mesh_symmetry_xyz_get(ob);
|
||||
|
||||
copy_v3_v3(fdata.location, SCULPT_active_vertex_co_get(ss));
|
||||
flood_fill::execute(ss, &flood, floodfill_cb, &fdata);
|
||||
flood_fill::execute(
|
||||
ss,
|
||||
&flood,
|
||||
[&](SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool /*is_duplicate*/) {
|
||||
return floodfill_cb(ss, from_v, to_v, &fdata);
|
||||
});
|
||||
}
|
||||
|
||||
static void init_face_sets_masking(const Sculpt *sd, Object *ob)
|
||||
|
|
|
@ -43,12 +43,12 @@ struct BoundaryInitialVertexFloodFillData {
|
|||
float radius_sq;
|
||||
};
|
||||
|
||||
static bool boundary_initial_vertex_floodfill_cb(
|
||||
SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate, void *userdata)
|
||||
static bool boundary_initial_vertex_floodfill_cb(SculptSession *ss,
|
||||
PBVHVertRef from_v,
|
||||
PBVHVertRef to_v,
|
||||
bool is_duplicate,
|
||||
BoundaryInitialVertexFloodFillData *data)
|
||||
{
|
||||
BoundaryInitialVertexFloodFillData *data = static_cast<BoundaryInitialVertexFloodFillData *>(
|
||||
userdata);
|
||||
|
||||
int from_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, from_v);
|
||||
int to_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, to_v);
|
||||
|
||||
|
@ -87,7 +87,7 @@ static PBVHVertRef sculpt_boundary_get_closest_boundary_vertex(SculptSession *ss
|
|||
return initial_vertex;
|
||||
}
|
||||
|
||||
SculptFloodFill flood;
|
||||
flood_fill::FillData flood;
|
||||
flood_fill::init_fill(ss, &flood);
|
||||
flood_fill::add_initial(&flood, initial_vertex);
|
||||
|
||||
|
@ -99,7 +99,10 @@ static PBVHVertRef sculpt_boundary_get_closest_boundary_vertex(SculptSession *ss
|
|||
|
||||
fdata.floodfill_steps = MEM_cnew_array<int>(SCULPT_vertex_count_get(ss), __func__);
|
||||
|
||||
flood_fill::execute(ss, &flood, boundary_initial_vertex_floodfill_cb, &fdata);
|
||||
flood_fill::execute(
|
||||
ss, &flood, [&](SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate) {
|
||||
return boundary_initial_vertex_floodfill_cb(ss, from_v, to_v, is_duplicate, &fdata);
|
||||
});
|
||||
|
||||
MEM_freeN(fdata.floodfill_steps);
|
||||
return fdata.boundary_initial_vertex;
|
||||
|
@ -201,13 +204,15 @@ struct BoundaryFloodFillData {
|
|||
PBVHVertRef last_visited_vertex;
|
||||
};
|
||||
|
||||
static bool boundary_floodfill_cb(
|
||||
SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate, void *userdata)
|
||||
static bool boundary_floodfill_cb(SculptSession *ss,
|
||||
PBVHVertRef from_v,
|
||||
PBVHVertRef to_v,
|
||||
bool is_duplicate,
|
||||
BoundaryFloodFillData *data)
|
||||
{
|
||||
int from_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, from_v);
|
||||
int to_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, to_v);
|
||||
|
||||
BoundaryFloodFillData *data = static_cast<BoundaryFloodFillData *>(userdata);
|
||||
SculptBoundary *boundary = data->boundary;
|
||||
if (!SCULPT_vertex_is_boundary(ss, to_v)) {
|
||||
return false;
|
||||
|
@ -242,7 +247,7 @@ static void sculpt_boundary_indices_init(SculptSession *ss,
|
|||
MEM_malloc_arrayN(BOUNDARY_INDICES_BLOCK_SIZE, sizeof(SculptBoundaryPreviewEdge), __func__));
|
||||
|
||||
GSet *included_verts = BLI_gset_int_new_ex("included verts", BOUNDARY_INDICES_BLOCK_SIZE);
|
||||
SculptFloodFill flood;
|
||||
flood_fill::FillData flood;
|
||||
flood_fill::init_fill(ss, &flood);
|
||||
|
||||
int initial_boundary_index = BKE_pbvh_vertex_to_index(ss->pbvh, initial_boundary_vertex);
|
||||
|
@ -261,7 +266,10 @@ static void sculpt_boundary_indices_init(SculptSession *ss,
|
|||
fdata.included_verts = included_verts;
|
||||
fdata.last_visited_vertex = {BOUNDARY_VERTEX_NONE};
|
||||
|
||||
flood_fill::execute(ss, &flood, boundary_floodfill_cb, &fdata);
|
||||
flood_fill::execute(
|
||||
ss, &flood, [&](SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate) {
|
||||
return boundary_floodfill_cb(ss, from_v, to_v, is_duplicate, &fdata);
|
||||
});
|
||||
|
||||
/* Check if the boundary loops into itself and add the extra preview edge to close the loop. */
|
||||
if (fdata.last_visited_vertex.i != BOUNDARY_VERTEX_NONE &&
|
||||
|
|
|
@ -452,7 +452,7 @@ static PBVHVertRef sculpt_expand_get_vertex_index_for_symmetry_pass(
|
|||
* Geodesic: Initializes the falloff with geodesic distances from the given active vertex, taking
|
||||
* symmetry into account.
|
||||
*/
|
||||
static float *sculpt_expand_geodesic_falloff_create(Object *ob, const PBVHVertRef v)
|
||||
static Array<float> sculpt_expand_geodesic_falloff_create(Object *ob, const PBVHVertRef v)
|
||||
{
|
||||
return geodesic::distances_create_from_vert_and_symm(ob, v, FLT_MAX);
|
||||
}
|
||||
|
@ -464,41 +464,43 @@ static float *sculpt_expand_geodesic_falloff_create(Object *ob, const PBVHVertRe
|
|||
struct ExpandFloodFillData {
|
||||
float original_normal[3];
|
||||
float edge_sensitivity;
|
||||
float *dists;
|
||||
float *edge_factor;
|
||||
MutableSpan<float> dists;
|
||||
MutableSpan<float> edge_factor;
|
||||
};
|
||||
|
||||
static bool expand_topology_floodfill_cb(
|
||||
SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate, void *userdata)
|
||||
static bool expand_topology_floodfill_cb(SculptSession *ss,
|
||||
PBVHVertRef from_v,
|
||||
PBVHVertRef to_v,
|
||||
bool is_duplicate,
|
||||
MutableSpan<float> dists)
|
||||
{
|
||||
int from_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, from_v);
|
||||
int to_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, to_v);
|
||||
|
||||
ExpandFloodFillData *data = static_cast<ExpandFloodFillData *>(userdata);
|
||||
if (!is_duplicate) {
|
||||
const float to_it = data->dists[from_v_i] + 1.0f;
|
||||
data->dists[to_v_i] = to_it;
|
||||
const float to_it = dists[from_v_i] + 1.0f;
|
||||
dists[to_v_i] = to_it;
|
||||
}
|
||||
else {
|
||||
data->dists[to_v_i] = data->dists[from_v_i];
|
||||
dists[to_v_i] = dists[from_v_i];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static float *sculpt_expand_topology_falloff_create(Object *ob, const PBVHVertRef v)
|
||||
static Array<float> sculpt_expand_topology_falloff_create(Object *ob, const PBVHVertRef v)
|
||||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
const int totvert = SCULPT_vertex_count_get(ss);
|
||||
float *dists = static_cast<float *>(MEM_calloc_arrayN(totvert, sizeof(float), __func__));
|
||||
Array<float> dists(totvert, 0.0f);
|
||||
|
||||
SculptFloodFill flood;
|
||||
flood_fill::FillData flood;
|
||||
flood_fill::init_fill(ss, &flood);
|
||||
flood_fill::add_initial_with_symmetry(ob, ss, &flood, v, FLT_MAX);
|
||||
|
||||
ExpandFloodFillData fdata;
|
||||
fdata.dists = dists;
|
||||
|
||||
flood_fill::execute(ss, &flood, expand_topology_floodfill_cb, &fdata);
|
||||
flood_fill::execute(
|
||||
ss, &flood, [&](SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate) {
|
||||
return expand_topology_floodfill_cb(ss, from_v, to_v, is_duplicate, dists);
|
||||
});
|
||||
|
||||
return dists;
|
||||
}
|
||||
|
@ -508,13 +510,15 @@ static float *sculpt_expand_topology_falloff_create(Object *ob, const PBVHVertRe
|
|||
* each vertex and the previous one.
|
||||
* This creates falloff patterns that follow and snap to the hard edges of the object.
|
||||
*/
|
||||
static bool mask_expand_normal_floodfill_cb(
|
||||
SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate, void *userdata)
|
||||
static bool mask_expand_normal_floodfill_cb(SculptSession *ss,
|
||||
PBVHVertRef from_v,
|
||||
PBVHVertRef to_v,
|
||||
bool is_duplicate,
|
||||
ExpandFloodFillData *data)
|
||||
{
|
||||
int from_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, from_v);
|
||||
int to_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, to_v);
|
||||
|
||||
ExpandFloodFillData *data = static_cast<ExpandFloodFillData *>(userdata);
|
||||
if (!is_duplicate) {
|
||||
float current_normal[3], prev_normal[3];
|
||||
SCULPT_vertex_normal_get(ss, to_v, current_normal);
|
||||
|
@ -534,20 +538,17 @@ static bool mask_expand_normal_floodfill_cb(
|
|||
return true;
|
||||
}
|
||||
|
||||
static float *sculpt_expand_normal_falloff_create(Object *ob,
|
||||
const PBVHVertRef v,
|
||||
const float edge_sensitivity,
|
||||
const int blur_steps)
|
||||
static Array<float> sculpt_expand_normal_falloff_create(Object *ob,
|
||||
const PBVHVertRef v,
|
||||
const float edge_sensitivity,
|
||||
const int blur_steps)
|
||||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
const int totvert = SCULPT_vertex_count_get(ss);
|
||||
float *dists = static_cast<float *>(MEM_calloc_arrayN(totvert, sizeof(float), __func__));
|
||||
float *edge_factor = static_cast<float *>(MEM_callocN(sizeof(float) * totvert, __func__));
|
||||
for (int i = 0; i < totvert; i++) {
|
||||
edge_factor[i] = 1.0f;
|
||||
}
|
||||
Array<float> dists(totvert, 0.0f);
|
||||
Array<float> edge_factor(totvert, 1.0f);
|
||||
|
||||
SculptFloodFill flood;
|
||||
flood_fill::FillData flood;
|
||||
flood_fill::init_fill(ss, &flood);
|
||||
flood_fill::add_initial_with_symmetry(ob, ss, &flood, v, FLT_MAX);
|
||||
|
||||
|
@ -557,7 +558,10 @@ static float *sculpt_expand_normal_falloff_create(Object *ob,
|
|||
fdata.edge_sensitivity = edge_sensitivity;
|
||||
SCULPT_vertex_normal_get(ss, v, fdata.original_normal);
|
||||
|
||||
flood_fill::execute(ss, &flood, mask_expand_normal_floodfill_cb, &fdata);
|
||||
flood_fill::execute(
|
||||
ss, &flood, [&](SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate) {
|
||||
return mask_expand_normal_floodfill_cb(ss, from_v, to_v, is_duplicate, &fdata);
|
||||
});
|
||||
|
||||
for (int repeat = 0; repeat < blur_steps; repeat++) {
|
||||
for (int i = 0; i < totvert; i++) {
|
||||
|
@ -580,8 +584,6 @@ static float *sculpt_expand_normal_falloff_create(Object *ob,
|
|||
dists[i] = 1.0 - dists[i];
|
||||
}
|
||||
|
||||
MEM_SAFE_FREE(edge_factor);
|
||||
|
||||
return dists;
|
||||
}
|
||||
|
||||
|
@ -589,15 +591,12 @@ static float *sculpt_expand_normal_falloff_create(Object *ob,
|
|||
* Spherical: Initializes the falloff based on the distance from a vertex, taking symmetry into
|
||||
* account.
|
||||
*/
|
||||
static float *sculpt_expand_spherical_falloff_create(Object *ob, const PBVHVertRef v)
|
||||
static Array<float> sculpt_expand_spherical_falloff_create(Object *ob, const PBVHVertRef v)
|
||||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
const int totvert = SCULPT_vertex_count_get(ss);
|
||||
|
||||
float *dists = static_cast<float *>(MEM_malloc_arrayN(totvert, sizeof(float), __func__));
|
||||
for (int i = 0; i < totvert; i++) {
|
||||
dists[i] = FLT_MAX;
|
||||
}
|
||||
Array<float> dists(totvert, FLT_MAX);
|
||||
const char symm = SCULPT_mesh_symmetry_xyz_get(ob);
|
||||
|
||||
for (char symm_it = 0; symm_it <= symm; symm_it++) {
|
||||
|
@ -624,11 +623,11 @@ static float *sculpt_expand_spherical_falloff_create(Object *ob, const PBVHVertR
|
|||
* boundary to a falloff value of 0. Then, it propagates that falloff to the rest of the mesh so it
|
||||
* stays parallel to the boundary, increasing the falloff value by 1 on each step.
|
||||
*/
|
||||
static float *sculpt_expand_boundary_topology_falloff_create(Object *ob, const PBVHVertRef v)
|
||||
static Array<float> sculpt_expand_boundary_topology_falloff_create(Object *ob, const PBVHVertRef v)
|
||||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
const int totvert = SCULPT_vertex_count_get(ss);
|
||||
float *dists = static_cast<float *>(MEM_calloc_arrayN(totvert, sizeof(float), __func__));
|
||||
Array<float> dists(totvert, 0.0f);
|
||||
BitVector<> visited_verts(totvert);
|
||||
std::queue<PBVHVertRef> queue;
|
||||
|
||||
|
@ -686,11 +685,11 @@ static float *sculpt_expand_boundary_topology_falloff_create(Object *ob, const P
|
|||
* the base mesh faces when checking a vertex neighbor. For this reason, this is not implement
|
||||
* using the general flood-fill and sculpt neighbors accessors.
|
||||
*/
|
||||
static float *sculpt_expand_diagonals_falloff_create(Object *ob, const PBVHVertRef v)
|
||||
static Array<float> sculpt_expand_diagonals_falloff_create(Object *ob, const PBVHVertRef v)
|
||||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
const int totvert = SCULPT_vertex_count_get(ss);
|
||||
float *dists = static_cast<float *>(MEM_calloc_arrayN(totvert, sizeof(float), __func__));
|
||||
Array<float> dists(totvert, 0.0f);
|
||||
|
||||
/* This algorithm uses mesh data (faces and loops), so this falloff type can't be initialized for
|
||||
* Multires. It also does not make sense to implement it for dyntopo as the result will be the
|
||||
|
@ -838,7 +837,7 @@ static void sculpt_expand_mesh_face_falloff_from_vertex_falloff(SculptSession *s
|
|||
Mesh *mesh,
|
||||
Cache *expand_cache)
|
||||
{
|
||||
BLI_assert(expand_cache->vert_falloff != nullptr);
|
||||
BLI_assert(!expand_cache->vert_falloff.is_empty());
|
||||
|
||||
if (!expand_cache->face_falloff) {
|
||||
expand_cache->face_falloff = static_cast<float *>(
|
||||
|
@ -870,21 +869,19 @@ static void sculpt_expand_geodesics_from_state_boundary(Object *ob,
|
|||
SculptSession *ss = ob->sculpt;
|
||||
BLI_assert(BKE_pbvh_type(ss->pbvh) == PBVH_FACES);
|
||||
|
||||
GSet *initial_verts = BLI_gset_int_new("initial_verts");
|
||||
Set<int> initial_verts;
|
||||
const BitVector<> boundary_verts = sculpt_expand_boundary_from_enabled(ss, enabled_verts, false);
|
||||
const int totvert = SCULPT_vertex_count_get(ss);
|
||||
for (int i = 0; i < totvert; i++) {
|
||||
if (!boundary_verts[i]) {
|
||||
continue;
|
||||
}
|
||||
BLI_gset_add(initial_verts, POINTER_FROM_INT(i));
|
||||
initial_verts.add(i);
|
||||
}
|
||||
|
||||
MEM_SAFE_FREE(expand_cache->vert_falloff);
|
||||
MEM_SAFE_FREE(expand_cache->face_falloff);
|
||||
|
||||
expand_cache->vert_falloff = geodesic::distances_create(ob, initial_verts, FLT_MAX);
|
||||
BLI_gset_free(initial_verts, nullptr);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -895,16 +892,16 @@ static void sculpt_expand_topology_from_state_boundary(Object *ob,
|
|||
Cache *expand_cache,
|
||||
const BitSpan enabled_verts)
|
||||
{
|
||||
MEM_SAFE_FREE(expand_cache->vert_falloff);
|
||||
MEM_SAFE_FREE(expand_cache->face_falloff);
|
||||
|
||||
SculptSession *ss = ob->sculpt;
|
||||
const int totvert = SCULPT_vertex_count_get(ss);
|
||||
|
||||
float *dists = static_cast<float *>(MEM_calloc_arrayN(totvert, sizeof(float), __func__));
|
||||
expand_cache->vert_falloff.reinitialize(totvert);
|
||||
expand_cache->vert_falloff.fill(0);
|
||||
const BitVector<> boundary_verts = sculpt_expand_boundary_from_enabled(ss, enabled_verts, false);
|
||||
|
||||
SculptFloodFill flood;
|
||||
flood_fill::FillData flood;
|
||||
flood_fill::init_fill(ss, &flood);
|
||||
for (int i = 0; i < totvert; i++) {
|
||||
if (!boundary_verts[i]) {
|
||||
|
@ -915,11 +912,11 @@ static void sculpt_expand_topology_from_state_boundary(Object *ob,
|
|||
flood_fill::add_and_skip_initial(&flood, vertex);
|
||||
}
|
||||
|
||||
ExpandFloodFillData fdata;
|
||||
fdata.dists = dists;
|
||||
flood_fill::execute(ss, &flood, expand_topology_floodfill_cb, &fdata);
|
||||
|
||||
expand_cache->vert_falloff = dists;
|
||||
MutableSpan<float> dists = expand_cache->vert_falloff;
|
||||
flood_fill::execute(
|
||||
ss, &flood, [&](SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate) {
|
||||
return expand_topology_floodfill_cb(ss, from_v, to_v, is_duplicate, dists);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1033,7 +1030,6 @@ static void sculpt_expand_initialize_from_face_set_boundary(Object *ob,
|
|||
static void sculpt_expand_falloff_factors_from_vertex_and_symm_create(
|
||||
Cache *expand_cache, Object *ob, const PBVHVertRef v, eSculptExpandFalloffType falloff_type)
|
||||
{
|
||||
MEM_SAFE_FREE(expand_cache->vert_falloff);
|
||||
expand_cache->falloff_type = falloff_type;
|
||||
|
||||
SculptSession *ss = ob->sculpt;
|
||||
|
@ -1131,7 +1127,6 @@ static void sculpt_expand_snap_initialize_from_enabled(SculptSession *ss, Cache
|
|||
*/
|
||||
static void sculpt_expand_cache_data_free(Cache *expand_cache)
|
||||
{
|
||||
MEM_SAFE_FREE(expand_cache->vert_falloff);
|
||||
MEM_SAFE_FREE(expand_cache->face_falloff);
|
||||
MEM_SAFE_FREE(expand_cache->original_colors);
|
||||
MEM_delete<Cache>(expand_cache);
|
||||
|
|
|
@ -42,10 +42,10 @@ static bool sculpt_geodesic_mesh_test_dist_add(Span<float3> vert_positions,
|
|||
const int v0,
|
||||
const int v1,
|
||||
const int v2,
|
||||
float *dists,
|
||||
GSet *initial_verts)
|
||||
MutableSpan<float> dists,
|
||||
const Set<int> &initial_verts)
|
||||
{
|
||||
if (BLI_gset_haskey(initial_verts, POINTER_FROM_INT(v0))) {
|
||||
if (initial_verts.contains(v0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,9 @@ static bool sculpt_geodesic_mesh_test_dist_add(Span<float3> vert_positions,
|
|||
return false;
|
||||
}
|
||||
|
||||
static float *geodesic_mesh_create(Object *ob, GSet *initial_verts, const float limit_radius)
|
||||
static Array<float> geodesic_mesh_create(Object *ob,
|
||||
const Set<int> &initial_verts,
|
||||
const float limit_radius)
|
||||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
Mesh *mesh = BKE_object_get_original_mesh(ob);
|
||||
|
@ -95,7 +97,7 @@ static float *geodesic_mesh_create(Object *ob, GSet *initial_verts, const float
|
|||
const bke::AttributeAccessor attributes = mesh->attributes();
|
||||
const VArraySpan<bool> hide_poly = *attributes.lookup<bool>(".hide_poly", bke::AttrDomain::Face);
|
||||
|
||||
float *dists = static_cast<float *>(MEM_malloc_arrayN(totvert, sizeof(float), __func__));
|
||||
Array<float> dists(totvert);
|
||||
BitVector<> edge_tag(totedge);
|
||||
|
||||
if (ss->edge_to_face_map.is_empty()) {
|
||||
|
@ -115,7 +117,7 @@ static float *geodesic_mesh_create(Object *ob, GSet *initial_verts, const float
|
|||
BLI_LINKSTACK_INIT(queue_next);
|
||||
|
||||
for (int i = 0; i < totvert; i++) {
|
||||
if (BLI_gset_haskey(initial_verts, POINTER_FROM_INT(i))) {
|
||||
if (initial_verts.contains(i)) {
|
||||
dists[i] = 0.0f;
|
||||
}
|
||||
else {
|
||||
|
@ -126,7 +128,6 @@ static float *geodesic_mesh_create(Object *ob, GSet *initial_verts, const float
|
|||
/* Masks vertices that are further than limit radius from an initial vertex. As there is no need
|
||||
* to define a distance to them the algorithm can stop earlier by skipping them. */
|
||||
BitVector<> affected_vert(totvert);
|
||||
GSetIterator gs_iter;
|
||||
|
||||
if (limit_radius == FLT_MAX) {
|
||||
/* In this case, no need to loop through all initial vertices to check distances as they are
|
||||
|
@ -137,8 +138,7 @@ static float *geodesic_mesh_create(Object *ob, GSet *initial_verts, const float
|
|||
/* This is an O(n^2) loop used to limit the geodesic distance calculation to a radius. When
|
||||
* this optimization is needed, it is expected for the tool to request the distance to a low
|
||||
* number of vertices (usually just 1 or 2). */
|
||||
GSET_ITER (gs_iter, initial_verts) {
|
||||
const int v = POINTER_AS_INT(BLI_gsetIterator_getKey(&gs_iter));
|
||||
for (const int v : initial_verts) {
|
||||
const float *v_co = vert_positions[v];
|
||||
for (int i = 0; i < totvert; i++) {
|
||||
if (len_squared_v3v3(v_co, vert_positions[i]) <= limit_radius_sq) {
|
||||
|
@ -226,23 +226,15 @@ static float *geodesic_mesh_create(Object *ob, GSet *initial_verts, const float
|
|||
/* For sculpt mesh data that does not support a geodesic distances algorithm, fallback to the
|
||||
* distance to each vertex. In this case, only one of the initial vertices will be used to
|
||||
* calculate the distance. */
|
||||
static float *geodesic_fallback_create(Object *ob, GSet *initial_verts)
|
||||
static Array<float> geodesic_fallback_create(Object *ob, const Set<int> &initial_verts)
|
||||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
Mesh *mesh = BKE_object_get_original_mesh(ob);
|
||||
const int totvert = mesh->verts_num;
|
||||
float *dists = static_cast<float *>(MEM_malloc_arrayN(totvert, sizeof(float), __func__));
|
||||
int first_affected = SCULPT_GEODESIC_VERTEX_NONE;
|
||||
GSetIterator gs_iter;
|
||||
GSET_ITER (gs_iter, initial_verts) {
|
||||
first_affected = POINTER_AS_INT(BLI_gsetIterator_getKey(&gs_iter));
|
||||
break;
|
||||
}
|
||||
|
||||
Array<float> dists(totvert, 0.0f);
|
||||
const int first_affected = *initial_verts.begin();
|
||||
if (first_affected == SCULPT_GEODESIC_VERTEX_NONE) {
|
||||
for (int i = 0; i < totvert; i++) {
|
||||
dists[i] = FLT_MAX;
|
||||
}
|
||||
dists.fill(FLT_MAX);
|
||||
return dists;
|
||||
}
|
||||
|
||||
|
@ -257,7 +249,7 @@ static float *geodesic_fallback_create(Object *ob, GSet *initial_verts)
|
|||
return dists;
|
||||
}
|
||||
|
||||
float *distances_create(Object *ob, GSet *initial_verts, const float limit_radius)
|
||||
Array<float> distances_create(Object *ob, const Set<int> &initial_verts, const float limit_radius)
|
||||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
switch (BKE_pbvh_type(ss->pbvh)) {
|
||||
|
@ -268,15 +260,15 @@ float *distances_create(Object *ob, GSet *initial_verts, const float limit_radiu
|
|||
return geodesic_fallback_create(ob, initial_verts);
|
||||
}
|
||||
BLI_assert_unreachable();
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
float *distances_create_from_vert_and_symm(Object *ob,
|
||||
const PBVHVertRef vertex,
|
||||
const float limit_radius)
|
||||
Array<float> distances_create_from_vert_and_symm(Object *ob,
|
||||
const PBVHVertRef vertex,
|
||||
const float limit_radius)
|
||||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
GSet *initial_verts = BLI_gset_int_new("initial_verts");
|
||||
Set<int> initial_verts;
|
||||
|
||||
const char symm = SCULPT_mesh_symmetry_xyz_get(ob);
|
||||
for (char i = 0; i <= symm; ++i) {
|
||||
|
@ -292,14 +284,12 @@ float *distances_create_from_vert_and_symm(Object *ob,
|
|||
v = SCULPT_nearest_vertex_get(ob, location, FLT_MAX, false);
|
||||
}
|
||||
if (v.i != PBVH_REF_NONE) {
|
||||
BLI_gset_add(initial_verts, POINTER_FROM_INT(BKE_pbvh_vertex_to_index(ss->pbvh, v)));
|
||||
initial_verts.add(BKE_pbvh_vertex_to_index(ss->pbvh, v));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float *dists = distances_create(ob, initial_verts, limit_radius);
|
||||
BLI_gset_free(initial_verts, nullptr);
|
||||
return dists;
|
||||
return distances_create(ob, initial_verts, limit_radius);
|
||||
}
|
||||
|
||||
} // namespace blender::ed::sculpt_paint::geodesic
|
||||
|
|
|
@ -121,12 +121,6 @@ struct SculptOrigFaceData {
|
|||
int face_set;
|
||||
};
|
||||
|
||||
/* Flood Fill. */
|
||||
struct SculptFloodFill {
|
||||
std::queue<PBVHVertRef> queue;
|
||||
blender::BitVector<> visited_verts;
|
||||
};
|
||||
|
||||
enum eBoundaryAutomaskMode {
|
||||
AUTOMASK_INIT_BOUNDARY_EDGES = 1,
|
||||
AUTOMASK_INIT_BOUNDARY_FACE_SETS = 2,
|
||||
|
@ -578,7 +572,7 @@ struct Cache {
|
|||
|
||||
/* Indexed by vertex index, precalculated falloff value of that vertex (without any falloff
|
||||
* editing modification applied). */
|
||||
float *vert_falloff;
|
||||
Array<float> vert_falloff;
|
||||
/* Max falloff value in *vert_falloff. */
|
||||
float max_vert_falloff;
|
||||
|
||||
|
@ -1175,20 +1169,22 @@ void SCULPT_tilt_effective_normal_get(const SculptSession *ss, const Brush *brus
|
|||
|
||||
namespace blender::ed::sculpt_paint::flood_fill {
|
||||
|
||||
void init_fill(SculptSession *ss, SculptFloodFill *flood);
|
||||
void add_active(Object *ob, SculptSession *ss, SculptFloodFill *flood, float radius);
|
||||
struct FillData {
|
||||
std::queue<PBVHVertRef> queue;
|
||||
blender::BitVector<> visited_verts;
|
||||
};
|
||||
|
||||
void init_fill(SculptSession *ss, FillData *flood);
|
||||
void add_active(Object *ob, SculptSession *ss, FillData *flood, float radius);
|
||||
void add_initial_with_symmetry(
|
||||
Object *ob, SculptSession *ss, SculptFloodFill *flood, PBVHVertRef vertex, float radius);
|
||||
void add_initial(SculptFloodFill *flood, PBVHVertRef vertex);
|
||||
void add_and_skip_initial(SculptFloodFill *flood, PBVHVertRef vertex);
|
||||
void execute(SculptSession *ss,
|
||||
SculptFloodFill *flood,
|
||||
bool (*func)(SculptSession *ss,
|
||||
PBVHVertRef from_v,
|
||||
PBVHVertRef to_v,
|
||||
bool is_duplicate,
|
||||
void *userdata),
|
||||
void *userdata);
|
||||
Object *ob, SculptSession *ss, FillData *flood, PBVHVertRef vertex, float radius);
|
||||
void add_initial(FillData *flood, PBVHVertRef vertex);
|
||||
void add_and_skip_initial(FillData *flood, PBVHVertRef vertex);
|
||||
void execute(
|
||||
SculptSession *ss,
|
||||
FillData *flood,
|
||||
FunctionRef<bool(SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate)>
|
||||
func);
|
||||
|
||||
}
|
||||
|
||||
|
@ -1362,8 +1358,10 @@ namespace blender::ed::sculpt_paint::geodesic {
|
|||
* Geodesic distances will only work when used with PBVH_FACES, for other types of PBVH it will
|
||||
* fallback to euclidean distances to one of the initial vertices in the set.
|
||||
*/
|
||||
float *distances_create(Object *ob, GSet *initial_verts, float limit_radius);
|
||||
float *distances_create_from_vert_and_symm(Object *ob, PBVHVertRef vertex, float limit_radius);
|
||||
Array<float> distances_create(Object *ob, const Set<int> &initial_verts, float limit_radius);
|
||||
Array<float> distances_create_from_vert_and_symm(Object *ob,
|
||||
PBVHVertRef vertex,
|
||||
float limit_radius);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -781,14 +781,15 @@ static void do_mask_by_color_contiguous_update_node(Object *ob,
|
|||
}
|
||||
}
|
||||
|
||||
static bool sculpt_mask_by_color_contiguous_floodfill(
|
||||
SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate, void *userdata)
|
||||
static bool sculpt_mask_by_color_contiguous_floodfill(SculptSession *ss,
|
||||
PBVHVertRef from_v,
|
||||
PBVHVertRef to_v,
|
||||
bool is_duplicate,
|
||||
MaskByColorContiguousFloodFillData *data)
|
||||
{
|
||||
int from_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, from_v);
|
||||
int to_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, to_v);
|
||||
|
||||
MaskByColorContiguousFloodFillData *data = static_cast<MaskByColorContiguousFloodFillData *>(
|
||||
userdata);
|
||||
float current_color[4];
|
||||
|
||||
SCULPT_vertex_color_get(ss, to_v, current_color);
|
||||
|
@ -825,7 +826,7 @@ static void sculpt_mask_by_color_contiguous(Object *object,
|
|||
}
|
||||
}
|
||||
|
||||
SculptFloodFill flood;
|
||||
flood_fill::FillData flood;
|
||||
flood_fill::init_fill(ss, &flood);
|
||||
flood_fill::add_initial(&flood, vertex);
|
||||
|
||||
|
@ -839,7 +840,10 @@ static void sculpt_mask_by_color_contiguous(Object *object,
|
|||
|
||||
copy_v3_v3(ffd.initial_color, color);
|
||||
|
||||
flood_fill::execute(ss, &flood, sculpt_mask_by_color_contiguous_floodfill, &ffd);
|
||||
flood_fill::execute(
|
||||
ss, &flood, [&](SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate) {
|
||||
return sculpt_mask_by_color_contiguous_floodfill(ss, from_v, to_v, is_duplicate, &ffd);
|
||||
});
|
||||
|
||||
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(ss->pbvh, {});
|
||||
const SculptMaskWriteInfo mask_write = SCULPT_mask_get_for_write(ss);
|
||||
|
|
|
@ -379,12 +379,14 @@ struct PoseFloodFillData {
|
|||
int target_face_set;
|
||||
};
|
||||
|
||||
static bool pose_topology_floodfill_cb(
|
||||
SculptSession *ss, PBVHVertRef /*from_v*/, PBVHVertRef to_v, bool is_duplicate, void *userdata)
|
||||
static bool pose_topology_floodfill_cb(SculptSession *ss,
|
||||
PBVHVertRef /*from_v*/,
|
||||
PBVHVertRef to_v,
|
||||
bool is_duplicate,
|
||||
PoseFloodFillData *data)
|
||||
{
|
||||
int to_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, to_v);
|
||||
|
||||
PoseFloodFillData *data = static_cast<PoseFloodFillData *>(userdata);
|
||||
const float *co = SCULPT_vertex_co_get(ss, to_v);
|
||||
|
||||
if (data->pose_factor) {
|
||||
|
@ -412,11 +414,12 @@ static bool pose_topology_floodfill_cb(
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool pose_face_sets_floodfill_cb(
|
||||
SculptSession *ss, PBVHVertRef /*from_v*/, PBVHVertRef to_v, bool is_duplicate, void *userdata)
|
||||
static bool pose_face_sets_floodfill_cb(SculptSession *ss,
|
||||
PBVHVertRef /*from_v*/,
|
||||
PBVHVertRef to_v,
|
||||
bool is_duplicate,
|
||||
PoseFloodFillData *data)
|
||||
{
|
||||
PoseFloodFillData *data = static_cast<PoseFloodFillData *>(userdata);
|
||||
|
||||
const int index = BKE_pbvh_vertex_to_index(ss->pbvh, to_v);
|
||||
const PBVHVertRef vertex = to_v;
|
||||
bool visit_next = false;
|
||||
|
@ -524,7 +527,7 @@ void calc_pose_data(Object *ob,
|
|||
SCULPT_vertex_random_access_ensure(ss);
|
||||
|
||||
/* Calculate the pose rotation point based on the boundaries of the brush factor. */
|
||||
SculptFloodFill flood;
|
||||
flood_fill::FillData flood;
|
||||
flood_fill::init_fill(ss, &flood);
|
||||
flood_fill::add_active(ob, ss, &flood, (r_pose_factor) ? radius : 0.0f);
|
||||
|
||||
|
@ -537,7 +540,10 @@ void calc_pose_data(Object *ob,
|
|||
zero_v3(fdata.pose_origin);
|
||||
copy_v3_v3(fdata.pose_initial_co, initial_location);
|
||||
copy_v3_v3(fdata.fallback_floodfill_origin, initial_location);
|
||||
flood_fill::execute(ss, &flood, pose_topology_floodfill_cb, &fdata);
|
||||
flood_fill::execute(
|
||||
ss, &flood, [&](SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate) {
|
||||
return pose_topology_floodfill_cb(ss, from_v, to_v, is_duplicate, &fdata);
|
||||
});
|
||||
|
||||
if (fdata.tot_co > 0) {
|
||||
mul_v3_fl(fdata.pose_origin, 1.0f / float(fdata.tot_co));
|
||||
|
@ -728,7 +734,7 @@ static SculptPoseIKChain *pose_ik_chain_init_face_sets(Object *ob,
|
|||
|
||||
for (int s = 0; s < ik_chain->tot_segments; s++) {
|
||||
|
||||
SculptFloodFill flood;
|
||||
flood_fill::FillData flood;
|
||||
flood_fill::init_fill(ss, &flood);
|
||||
flood_fill::add_initial_with_symmetry(ob, ss, &flood, current_vertex, FLT_MAX);
|
||||
|
||||
|
@ -750,7 +756,12 @@ static SculptPoseIKChain *pose_ik_chain_init_face_sets(Object *ob,
|
|||
zero_v3(fdata.pose_origin);
|
||||
zero_v3(fdata.fallback_origin);
|
||||
copy_v3_v3(fdata.pose_initial_co, SCULPT_vertex_co_get(ss, current_vertex));
|
||||
flood_fill::execute(ss, &flood, pose_face_sets_floodfill_cb, &fdata);
|
||||
flood_fill::execute(
|
||||
ss,
|
||||
&flood,
|
||||
[&](SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate) {
|
||||
return pose_face_sets_floodfill_cb(ss, from_v, to_v, is_duplicate, &fdata);
|
||||
});
|
||||
|
||||
if (fdata.tot_co > 0) {
|
||||
mul_v3_fl(fdata.pose_origin, 1.0f / float(fdata.tot_co));
|
||||
|
@ -776,11 +787,12 @@ static SculptPoseIKChain *pose_ik_chain_init_face_sets(Object *ob,
|
|||
return ik_chain;
|
||||
}
|
||||
|
||||
static bool pose_face_sets_fk_find_masked_floodfill_cb(
|
||||
SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate, void *userdata)
|
||||
static bool pose_face_sets_fk_find_masked_floodfill_cb(SculptSession *ss,
|
||||
PBVHVertRef from_v,
|
||||
PBVHVertRef to_v,
|
||||
bool is_duplicate,
|
||||
PoseFloodFillData *data)
|
||||
{
|
||||
PoseFloodFillData *data = static_cast<PoseFloodFillData *>(userdata);
|
||||
|
||||
int from_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, from_v);
|
||||
int to_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, to_v);
|
||||
|
||||
|
@ -817,11 +829,8 @@ static bool pose_face_sets_fk_find_masked_floodfill_cb(
|
|||
static bool pose_face_sets_fk_set_weights_floodfill_cb(SculptSession *ss,
|
||||
PBVHVertRef /*from_v*/,
|
||||
PBVHVertRef to_v,
|
||||
bool /*is_duplicate*/,
|
||||
void *userdata)
|
||||
PoseFloodFillData *data)
|
||||
{
|
||||
PoseFloodFillData *data = static_cast<PoseFloodFillData *>(userdata);
|
||||
|
||||
int to_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, to_v);
|
||||
|
||||
data->fk_weights[to_v_i] = 1.0f;
|
||||
|
@ -842,7 +851,7 @@ static SculptPoseIKChain *pose_ik_chain_init_face_sets_fk(Object *ob,
|
|||
|
||||
const int active_face_set = face_set::active_face_set_get(ss);
|
||||
|
||||
SculptFloodFill flood;
|
||||
flood_fill::FillData flood;
|
||||
flood_fill::init_fill(ss, &flood);
|
||||
flood_fill::add_initial(&flood, active_vertex);
|
||||
PoseFloodFillData fdata;
|
||||
|
@ -853,7 +862,10 @@ static SculptPoseIKChain *pose_ik_chain_init_face_sets_fk(Object *ob,
|
|||
fdata.target_face_set = SCULPT_FACE_SET_NONE;
|
||||
fdata.masked_face_set_it = 0;
|
||||
fdata.visited_face_sets = BLI_gset_int_new_ex("visited_face_sets", 3);
|
||||
flood_fill::execute(ss, &flood, pose_face_sets_fk_find_masked_floodfill_cb, &fdata);
|
||||
flood_fill::execute(
|
||||
ss, &flood, [&](SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate) {
|
||||
return pose_face_sets_fk_find_masked_floodfill_cb(ss, from_v, to_v, is_duplicate, &fdata);
|
||||
});
|
||||
BLI_gset_free(fdata.visited_face_sets, nullptr);
|
||||
|
||||
int origin_count = 0;
|
||||
|
@ -908,7 +920,12 @@ static SculptPoseIKChain *pose_ik_chain_init_face_sets_fk(Object *ob,
|
|||
flood_fill::init_fill(ss, &flood);
|
||||
flood_fill::add_active(ob, ss, &flood, radius);
|
||||
fdata.fk_weights = ik_chain->segments[0].weights;
|
||||
flood_fill::execute(ss, &flood, pose_face_sets_fk_set_weights_floodfill_cb, &fdata);
|
||||
flood_fill::execute(
|
||||
ss,
|
||||
&flood,
|
||||
[&](SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool /*is_duplicate*/) {
|
||||
return pose_face_sets_fk_set_weights_floodfill_cb(ss, from_v, to_v, &fdata);
|
||||
});
|
||||
|
||||
pose_ik_chain_origin_heads_init(ik_chain, ik_chain->segments[0].head);
|
||||
return ik_chain;
|
||||
|
|
Loading…
Reference in New Issue