Cleanup: Use BitVector instead of BLI_bitmap in sculpt code

This commit is contained in:
Hans Goudey
2023-12-26 09:43:00 -05:00
parent b26cd6a4b9
commit a683d1b0c6
10 changed files with 29 additions and 66 deletions

View File

@@ -164,8 +164,7 @@ static bool is_vertex_diagonal(BMVert *from_v, BMVert *to_v)
*/
static void unsubdivide_face_center_vertex_tag(BMesh *bm, BMVert *initial_vertex)
{
bool *visited_verts = static_cast<bool *>(
MEM_calloc_arrayN(bm->totvert, sizeof(bool), "visited vertices"));
blender::BitVector<> visited_verts(bm->totvert);
std::queue<BMVert *> queue;
/* Add and tag the vertices connected by a diagonal to initial_vertex to the flood fill queue. If
@@ -180,7 +179,7 @@ static void unsubdivide_face_center_vertex_tag(BMesh *bm, BMVert *initial_vertex
int neighbor_vertex_index = BM_elem_index_get(neighbor_v);
if (neighbor_v != initial_vertex && is_vertex_diagonal(neighbor_v, initial_vertex)) {
queue.push(neighbor_v);
visited_verts[neighbor_vertex_index] = true;
visited_verts[neighbor_vertex_index].set();
BM_elem_flag_set(neighbor_v, BM_ELEM_TAG, true);
}
}
@@ -217,15 +216,13 @@ static void unsubdivide_face_center_vertex_tag(BMesh *bm, BMVert *initial_vertex
is_vertex_diagonal(neighbor_v, diagonal_v))
{
queue.push(neighbor_v);
visited_verts[neighbor_vertex_index] = true;
visited_verts[neighbor_vertex_index].set();
BM_elem_flag_set(neighbor_v, BM_ELEM_TAG, true);
}
}
}
}
}
MEM_freeN(visited_verts);
}
/**

View File

@@ -534,7 +534,7 @@ struct LassoGestureData {
int width;
/* 2D bitmap to test if a vertex is affected by the lasso shape. */
BLI_bitmap *mask_px;
blender::BitVector<> mask_px;
};
struct LineGestureData {
@@ -668,7 +668,7 @@ static void sculpt_gesture_lasso_px_cb(int x, int x_end, int y, void *user_data)
int index = (y * lasso->width) + x;
int index_end = (y * lasso->width) + x_end;
do {
BLI_BITMAP_ENABLE(lasso->mask_px, index);
lasso->mask_px[index].set();
} while (++index != index_end);
}
@@ -692,7 +692,7 @@ static SculptGestureContext *sculpt_gesture_init_from_lasso(bContext *C, wmOpera
const int lasso_width = 1 + sgcontext->lasso.boundbox.xmax - sgcontext->lasso.boundbox.xmin;
const int lasso_height = 1 + sgcontext->lasso.boundbox.ymax - sgcontext->lasso.boundbox.ymin;
sgcontext->lasso.width = lasso_width;
sgcontext->lasso.mask_px = BLI_BITMAP_NEW(lasso_width * lasso_height, __func__);
sgcontext->lasso.mask_px.resize(lasso_width * lasso_height);
BLI_bitmap_draw_2d_poly_v2i_n(sgcontext->lasso.boundbox.xmin,
sgcontext->lasso.boundbox.ymin,
@@ -847,7 +847,6 @@ static SculptGestureContext *sculpt_gesture_init_from_line(bContext *C, wmOperat
static void sculpt_gesture_context_free(SculptGestureContext *sgcontext)
{
MEM_SAFE_FREE(sgcontext->lasso.mask_px);
MEM_SAFE_FREE(sgcontext->gesture_points);
MEM_SAFE_FREE(sgcontext->operation);
MEM_delete(sgcontext);
@@ -964,7 +963,7 @@ static bool sculpt_gesture_is_effected_lasso(SculptGestureContext *sgcontext, co
scr_co_s[0] -= lasso->boundbox.xmin;
scr_co_s[1] -= lasso->boundbox.ymin;
return BLI_BITMAP_TEST_BOOL(lasso->mask_px, scr_co_s[1] * lasso->width + scr_co_s[0]);
return lasso->mask_px[scr_co_s[1] * lasso->width + scr_co_s[0]].test();
}
static bool sculpt_gesture_is_effected(SculptGestureContext *sgcontext,

View File

@@ -1009,10 +1009,8 @@ namespace blender::ed::sculpt_paint::flood_fill {
void init_fill(SculptSession *ss, SculptFloodFill *flood)
{
int vertex_count = SCULPT_vertex_count_get(ss);
SCULPT_vertex_random_access_ensure(ss);
flood->visited_verts = BLI_BITMAP_NEW(vertex_count, "visited verts");
flood->visited_verts.resize(SCULPT_vertex_count_get(ss));
}
void add_initial(SculptFloodFill *flood, PBVHVertRef vertex)
@@ -1023,7 +1021,7 @@ void add_initial(SculptFloodFill *flood, PBVHVertRef vertex)
void add_and_skip_initial(SculptFloodFill *flood, PBVHVertRef vertex)
{
flood->queue.push(vertex);
BLI_BITMAP_ENABLE(flood->visited_verts, vertex.i);
flood->visited_verts[vertex.i].set(vertex.i);
}
void add_initial_with_symmetry(Sculpt *sd,
@@ -1101,7 +1099,7 @@ void execute(SculptSession *ss,
const PBVHVertRef to_v = ni.vertex;
int to_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, to_v);
if (BLI_BITMAP_TEST(flood->visited_verts, to_v_i)) {
if (flood->visited_verts[to_v_i]) {
continue;
}
@@ -1109,7 +1107,7 @@ void execute(SculptSession *ss,
continue;
}
BLI_BITMAP_ENABLE(flood->visited_verts, BKE_pbvh_vertex_to_index(ss->pbvh, to_v));
flood->visited_verts[BKE_pbvh_vertex_to_index(ss->pbvh, to_v)].set();
if (func(ss, from_v, to_v, ni.is_duplicate, userdata)) {
flood->queue.push(to_v);
@@ -1119,11 +1117,6 @@ void execute(SculptSession *ss,
}
}
void free_fill(SculptFloodFill *flood)
{
MEM_SAFE_FREE(flood->visited_verts);
}
} // namespace blender::ed::sculpt_paint::flood_fill
/** \} */

View File

@@ -653,7 +653,6 @@ static void SCULPT_topology_automasking_init(Sculpt *sd, Object *ob)
copy_v3_v3(fdata.location, SCULPT_active_vertex_co_get(ss));
flood_fill::execute(ss, &flood, automask_floodfill_cb, &fdata);
flood_fill::free_fill(&flood);
}
static void sculpt_face_sets_automasking_init(Sculpt *sd, Object *ob)

View File

@@ -101,7 +101,6 @@ 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::free_fill(&flood);
MEM_freeN(fdata.floodfill_steps);
return fdata.boundary_initial_vertex;
@@ -264,7 +263,6 @@ static void sculpt_boundary_indices_init(SculptSession *ss,
fdata.last_visited_vertex = {BOUNDARY_VERTEX_NONE};
flood_fill::execute(ss, &flood, boundary_floodfill_cb, &fdata);
flood_fill::free_fill(&flood);
/* 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 &&
@@ -311,9 +309,6 @@ static void sculpt_boundary_edit_data_init(SculptSession *ss,
std::queue<PBVHVertRef> current_iteration;
std::queue<PBVHVertRef> next_iteration;
/* Initialized the first iteration with the vertices already in the boundary. This is propagation
* step 0. */
BLI_bitmap *visited_verts = BLI_BITMAP_NEW(SCULPT_vertex_count_get(ss), "visited_verts");
for (int i = 0; i < boundary->verts_num; i++) {
int index = BKE_pbvh_vertex_to_index(ss->pbvh, boundary->verts[i]);
@@ -364,8 +359,6 @@ static void sculpt_boundary_edit_data_init(SculptSession *ss,
boundary->edit_info[ni.index].original_vertex_i =
boundary->edit_info[from_v_i].original_vertex_i;
BLI_BITMAP_ENABLE(visited_verts, ni.index);
if (ni.is_duplicate) {
/* Grids duplicates handling. */
boundary->edit_info[ni.index].propagation_steps_num =
@@ -418,8 +411,6 @@ static void sculpt_boundary_edit_data_init(SculptSession *ss,
propagation_steps_num++;
}
MEM_SAFE_FREE(visited_verts);
}
/* This functions assigns a falloff factor to each one of the SculptBoundaryEditInfo structs based

View File

@@ -503,7 +503,6 @@ static float *sculpt_expand_topology_falloff_create(Sculpt *sd, Object *ob, cons
fdata.dists = dists;
flood_fill::execute(ss, &flood, expand_topology_floodfill_cb, &fdata);
flood_fill::free_fill(&flood);
return dists;
}
@@ -564,7 +563,6 @@ static float *sculpt_expand_normal_falloff_create(Sculpt *sd,
SCULPT_vertex_normal_get(ss, v, fdata.original_normal);
flood_fill::execute(ss, &flood, mask_expand_normal_floodfill_cb, &fdata);
flood_fill::free_fill(&flood);
for (int repeat = 0; repeat < blur_steps; repeat++) {
for (int i = 0; i < totvert; i++) {
@@ -925,7 +923,6 @@ static void sculpt_expand_topology_from_state_boundary(Object *ob,
ExpandFloodFillData fdata;
fdata.dists = dists;
flood_fill::execute(ss, &flood, expand_topology_floodfill_cb, &fdata);
flood_fill::free_fill(&flood);
expand_cache->vert_falloff = dists;
}

View File

@@ -96,7 +96,7 @@ static float *geodesic_mesh_create(Object *ob, GSet *initial_verts, const float
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__));
BLI_bitmap *edge_tag = BLI_BITMAP_NEW(totedge, "edge tag");
BitVector<> edge_tag(totedge);
if (ss->epmap.is_empty()) {
ss->epmap = bke::mesh::build_edge_to_face_map(
@@ -125,13 +125,13 @@ 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. */
BLI_bitmap *affected_vertex = BLI_BITMAP_NEW(totvert, "affected vertex");
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
* all going to be affected. */
BLI_bitmap_set_all(affected_vertex, true, totvert);
affected_vert.fill(true);
}
else {
/* This is an O(n^2) loop used to limit the geodesic distance calculation to a radius. When
@@ -142,7 +142,7 @@ static float *geodesic_mesh_create(Object *ob, GSet *initial_verts, const float
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) {
BLI_BITMAP_ENABLE(affected_vertex, i);
affected_vert[i].set();
}
}
}
@@ -152,7 +152,7 @@ static float *geodesic_mesh_create(Object *ob, GSet *initial_verts, const float
for (int i = 0; i < totedge; i++) {
const int v1 = edges[i][0];
const int v2 = edges[i][1];
if (!BLI_BITMAP_TEST(affected_vertex, v1) && !BLI_BITMAP_TEST(affected_vertex, v2)) {
if (!affected_vert[v1] && !affected_vert[v2]) {
continue;
}
if (dists[v1] != FLT_MAX || dists[v2] != FLT_MAX) {
@@ -197,12 +197,11 @@ static float *geodesic_mesh_create(Object *ob, GSet *initial_verts, const float
ev_other = edges[e_other][0];
}
if (e_other != e && !BLI_BITMAP_TEST(edge_tag, e_other) &&
if (e_other != e && !edge_tag[e_other] &&
(ss->epmap[e_other].is_empty() || dists[ev_other] != FLT_MAX))
{
if (BLI_BITMAP_TEST(affected_vertex, v_other) ||
BLI_BITMAP_TEST(affected_vertex, ev_other)) {
BLI_BITMAP_ENABLE(edge_tag, e_other);
if (affected_vert[v_other] || affected_vert[ev_other]) {
edge_tag[e_other].set();
BLI_LINKSTACK_PUSH(queue_next, POINTER_FROM_INT(e_other));
}
}
@@ -215,7 +214,7 @@ static float *geodesic_mesh_create(Object *ob, GSet *initial_verts, const float
for (LinkNode *lnk = queue_next; lnk; lnk = lnk->next) {
const int e = POINTER_AS_INT(lnk->link);
BLI_BITMAP_DISABLE(edge_tag, e);
edge_tag[e].reset();
}
BLI_LINKSTACK_SWAP(queue, queue_next);
@@ -224,8 +223,6 @@ static float *geodesic_mesh_create(Object *ob, GSet *initial_verts, const float
BLI_LINKSTACK_FREE(queue);
BLI_LINKSTACK_FREE(queue_next);
MEM_SAFE_FREE(edge_tag);
MEM_SAFE_FREE(affected_vertex);
return dists;
}

View File

@@ -135,7 +135,7 @@ struct SculptOrigFaceData {
/* Flood Fill. */
struct SculptFloodFill {
std::queue<PBVHVertRef> queue;
BLI_bitmap *visited_verts;
blender::BitVector<> visited_verts;
};
enum eBoundaryAutomaskMode {
@@ -1249,7 +1249,6 @@ void execute(SculptSession *ss,
bool is_duplicate,
void *userdata),
void *userdata);
void free_fill(SculptFloodFill *flood);
}

View File

@@ -585,7 +585,7 @@ void SCULPT_geometry_preview_lines_update(bContext *C, SculptSession *ss, float
float brush_co[3];
copy_v3_v3(brush_co, SCULPT_active_vertex_co_get(ss));
BLI_bitmap *visited_verts = BLI_BITMAP_NEW(SCULPT_vertex_count_get(ss), "visited_verts");
blender::BitVector<> visited_verts(SCULPT_vertex_count_get(ss));
/* Assuming an average of 6 edges per vertex in a triangulated mesh. */
const int max_preview_verts = SCULPT_vertex_count_get(ss) * 3 * 2;
@@ -610,10 +610,10 @@ void SCULPT_geometry_preview_lines_update(bContext *C, SculptSession *ss, float
totpoints++;
ss->preview_vert_list[totpoints] = to_v;
totpoints++;
if (BLI_BITMAP_TEST(visited_verts, to_v_i)) {
if (visited_verts[to_v_i]) {
continue;
}
BLI_BITMAP_ENABLE(visited_verts, to_v_i);
visited_verts[to_v_i].set();
const float *co = SCULPT_vertex_co_for_grab_active_get(ss, to_v);
if (len_squared_v3v3(brush_co, co) < radius * radius) {
non_visited_verts.push(to_v);
@@ -623,8 +623,6 @@ void SCULPT_geometry_preview_lines_update(bContext *C, SculptSession *ss, float
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
}
MEM_freeN(visited_verts);
ss->preview_vert_count = totpoints;
}
@@ -826,7 +824,6 @@ 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::free_fill(&flood);
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(ss->pbvh, {});
const SculptMaskWriteInfo mask_write = SCULPT_mask_get_for_write(ss);

View File

@@ -361,7 +361,7 @@ struct PoseFloodFillData {
GSet *visited_face_sets;
/* In face sets origin mode, each vertex can only be assigned to one face set. */
BLI_bitmap *is_weighted;
MutableBoundedBitSpan is_weighted;
bool is_first_iteration;
@@ -435,7 +435,7 @@ static bool pose_face_sets_floodfill_cb(
if (data->current_face_set == SCULPT_FACE_SET_NONE) {
data->pose_factor[index] = 1.0f;
BLI_BITMAP_ENABLE(data->is_weighted, index);
data->is_weighted[index].set();
if (sculpt_pose_brush_is_vertex_inside_brush_radius(
co, data->pose_initial_co, data->radius, data->symm))
@@ -469,9 +469,9 @@ static bool pose_face_sets_floodfill_cb(
return visit_next;
}
if (!BLI_BITMAP_TEST(data->is_weighted, index)) {
if (!data->is_weighted[index]) {
data->pose_factor[index] = 1.0f;
BLI_BITMAP_ENABLE(data->is_weighted, index);
data->is_weighted[index].set();
visit_next = true;
}
@@ -543,7 +543,6 @@ void calc_pose_data(Sculpt *sd,
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::free_fill(&flood);
if (fdata.tot_co > 0) {
mul_v3_fl(fdata.pose_origin, 1.0f / float(fdata.tot_co));
@@ -728,7 +727,7 @@ static SculptPoseIKChain *pose_ik_chain_init_face_sets(
GSet *visited_face_sets = BLI_gset_int_new_ex("visited_face_sets", ik_chain->tot_segments);
BLI_bitmap *is_weighted = BLI_BITMAP_NEW(totvert, "weighted");
BitVector<> is_weighted(totvert);
int current_face_set = SCULPT_FACE_SET_NONE;
int prev_face_set = SCULPT_FACE_SET_NONE;
@@ -760,7 +759,6 @@ static SculptPoseIKChain *pose_ik_chain_init_face_sets(
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::free_fill(&flood);
if (fdata.tot_co > 0) {
mul_v3_fl(fdata.pose_origin, 1.0f / float(fdata.tot_co));
@@ -783,8 +781,6 @@ static SculptPoseIKChain *pose_ik_chain_init_face_sets(
pose_ik_chain_origin_heads_init(ik_chain, SCULPT_active_vertex_co_get(ss));
MEM_SAFE_FREE(is_weighted);
return ik_chain;
}
@@ -864,7 +860,6 @@ static SculptPoseIKChain *pose_ik_chain_init_face_sets_fk(
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::free_fill(&flood);
BLI_gset_free(fdata.visited_face_sets, nullptr);
int origin_count = 0;
@@ -920,7 +915,6 @@ static SculptPoseIKChain *pose_ik_chain_init_face_sets_fk(
flood_fill::add_active(sd, 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::free_fill(&flood);
pose_ik_chain_origin_heads_init(ik_chain, ik_chain->segments[0].head);
return ik_chain;