Sculpt: Avoid expensive mask access in remaining cases
In the last couple places, avoid retrieving the mask attribute per vertex. Use existing attribute data pointers instead. This also avoids function calls and branches for every vertex, since there is no PBVH type switch at the lowest level of the loop anymore.
This commit is contained in:
parent
27582ddb93
commit
bd51bb7623
|
@ -372,14 +372,11 @@ static void fill_mask_bmesh(Object &object, const float value, const Span<PBVHNo
|
|||
});
|
||||
}
|
||||
|
||||
static void fill_mask(Main &bmain,
|
||||
const Scene &scene,
|
||||
Depsgraph &depsgraph,
|
||||
Object &object,
|
||||
const float value,
|
||||
const Span<PBVHNode *> nodes)
|
||||
static void fill_mask(
|
||||
Main &bmain, const Scene &scene, Depsgraph &depsgraph, Object &object, const float value)
|
||||
{
|
||||
PBVH &pbvh = *object.sculpt->pbvh;
|
||||
Vector<PBVHNode *> nodes = bke::pbvh::search_gather(&pbvh, {});
|
||||
switch (BKE_pbvh_type(&pbvh)) {
|
||||
case PBVH_FACES:
|
||||
fill_mask_mesh(object, value, nodes);
|
||||
|
@ -489,12 +486,9 @@ static void invert_mask_bmesh(Object &object, const Span<PBVHNode *> nodes)
|
|||
});
|
||||
}
|
||||
|
||||
static void invert_mask(Main &bmain,
|
||||
const Scene &scene,
|
||||
Depsgraph &depsgraph,
|
||||
Object &object,
|
||||
const Span<PBVHNode *> nodes)
|
||||
static void invert_mask(Main &bmain, const Scene &scene, Depsgraph &depsgraph, Object &object)
|
||||
{
|
||||
Vector<PBVHNode *> nodes = bke::pbvh::search_gather(object.sculpt->pbvh, {});
|
||||
switch (BKE_pbvh_type(object.sculpt->pbvh)) {
|
||||
case PBVH_FACES:
|
||||
invert_mask_mesh(object, nodes);
|
||||
|
@ -521,16 +515,15 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op)
|
|||
BKE_sculpt_update_object_for_edit(&depsgraph, &object, false);
|
||||
|
||||
undo::push_begin(&object, op);
|
||||
Vector<PBVHNode *> nodes = bke::pbvh::search_gather(object.sculpt->pbvh, {});
|
||||
switch (mode) {
|
||||
case PAINT_MASK_FLOOD_VALUE:
|
||||
fill_mask(bmain, scene, depsgraph, object, value, nodes);
|
||||
fill_mask(bmain, scene, depsgraph, object, value);
|
||||
break;
|
||||
case PAINT_MASK_FLOOD_VALUE_INVERSE:
|
||||
fill_mask(bmain, scene, depsgraph, object, 1.0f - value, nodes);
|
||||
fill_mask(bmain, scene, depsgraph, object, 1.0f - value);
|
||||
break;
|
||||
case PAINT_MASK_INVERT:
|
||||
invert_mask(bmain, scene, depsgraph, object, nodes);
|
||||
invert_mask(bmain, scene, depsgraph, object);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -303,33 +303,6 @@ float SCULPT_mask_get_at_grids_vert_index(const SubdivCCG &subdiv_ccg,
|
|||
return *CCG_elem_offset_mask(&key, elem, index_in_grid);
|
||||
}
|
||||
|
||||
float SCULPT_vertex_mask_get(SculptSession *ss, PBVHVertRef vertex)
|
||||
{
|
||||
using namespace blender;
|
||||
switch (BKE_pbvh_type(ss->pbvh)) {
|
||||
case PBVH_FACES: {
|
||||
const Mesh *mesh = BKE_pbvh_get_mesh(ss->pbvh);
|
||||
const bke::AttributeAccessor attributes = mesh->attributes();
|
||||
const VArray mask = *attributes.lookup_or_default<float>(
|
||||
".sculpt_mask", bke::AttrDomain::Point, 0.0f);
|
||||
return mask[vertex.i];
|
||||
}
|
||||
case PBVH_BMESH: {
|
||||
BMVert *v;
|
||||
int cd_mask = CustomData_get_offset_named(&ss->bm->vdata, CD_PROP_FLOAT, ".sculpt_mask");
|
||||
|
||||
v = (BMVert *)vertex.i;
|
||||
return cd_mask != -1 ? BM_ELEM_CD_GET_FLOAT(v, cd_mask) : 0.0f;
|
||||
}
|
||||
case PBVH_GRIDS: {
|
||||
return SCULPT_mask_get_at_grids_vert_index(
|
||||
*ss->subdiv_ccg, *BKE_pbvh_get_grid_key(ss->pbvh), vertex.i);
|
||||
}
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
PBVHVertRef SCULPT_active_vertex_get(SculptSession *ss)
|
||||
{
|
||||
if (ELEM(BKE_pbvh_type(ss->pbvh), PBVH_FACES, PBVH_BMESH, PBVH_GRIDS)) {
|
||||
|
|
|
@ -2105,6 +2105,54 @@ static void sculpt_expand_undo_push(Object *ob, Cache *expand_cache)
|
|||
}
|
||||
}
|
||||
|
||||
static bool any_nonzero_mask(const Object &object)
|
||||
{
|
||||
const SculptSession &ss = *object.sculpt;
|
||||
switch (BKE_pbvh_type(ss.pbvh)) {
|
||||
case PBVH_FACES: {
|
||||
const Mesh &mesh = *static_cast<const Mesh *>(object.data);
|
||||
const bke::AttributeAccessor attributes = mesh.attributes();
|
||||
const VArraySpan mask = *attributes.lookup<float>(".sculpt_mask");
|
||||
if (mask.is_empty()) {
|
||||
return false;
|
||||
}
|
||||
return std::any_of(
|
||||
mask.begin(), mask.end(), [&](const float value) { return value > 0.0f; });
|
||||
}
|
||||
case PBVH_GRIDS: {
|
||||
const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
|
||||
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
|
||||
if (!key.has_mask) {
|
||||
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;
|
||||
});
|
||||
}
|
||||
case PBVH_BMESH: {
|
||||
BMesh &bm = *ss.bm;
|
||||
const int offset = CustomData_get_offset_named(&bm.vdata, CD_PROP_FLOAT, ".sculpt_mask");
|
||||
if (offset == -1) {
|
||||
return false;
|
||||
}
|
||||
BMIter iter;
|
||||
BMVert *vert;
|
||||
BM_ITER_MESH (vert, &iter, &bm, BM_VERTS_OF_MESH) {
|
||||
if (BM_ELEM_CD_GET_FLOAT(vert, offset) > 0.0f) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int sculpt_expand_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
||||
|
@ -2134,19 +2182,7 @@ static int sculpt_expand_invoke(bContext *C, wmOperator *op, const wmEvent *even
|
|||
BKE_sculpt_mask_layers_ensure(depsgraph, CTX_data_main(C), ob, mmd);
|
||||
|
||||
if (RNA_boolean_get(op->ptr, "use_auto_mask")) {
|
||||
int verts_num = SCULPT_vertex_count_get(ss);
|
||||
bool ok = true;
|
||||
|
||||
for (int i = 0; i < verts_num; i++) {
|
||||
PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ss->pbvh, i);
|
||||
|
||||
if (SCULPT_vertex_mask_get(ss, vertex) != 0.0f) {
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
if (any_nonzero_mask(*ob)) {
|
||||
write_mask_data(ss, Array<float>(SCULPT_vertex_count_get(ss), 1.0f));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ static void mask_filter_task(SculptSession *ss,
|
|||
switch (mode) {
|
||||
case MASK_FILTER_SMOOTH:
|
||||
case MASK_FILTER_SHARPEN: {
|
||||
float val = smooth::neighbor_mask_average(ss, vd.vertex);
|
||||
float val = smooth::neighbor_mask_average(ss, mask_write, vd.vertex);
|
||||
|
||||
val -= mask;
|
||||
|
||||
|
|
|
@ -877,7 +877,6 @@ void SCULPT_vertex_normal_get(const SculptSession *ss, PBVHVertRef vertex, float
|
|||
float SCULPT_mask_get_at_grids_vert_index(const SubdivCCG &subdiv_ccg,
|
||||
const CCGKey &key,
|
||||
int vert_index);
|
||||
float SCULPT_vertex_mask_get(SculptSession *ss, PBVHVertRef vertex);
|
||||
void SCULPT_vertex_color_get(const SculptSession *ss, PBVHVertRef vertex, float r_color[4]);
|
||||
void SCULPT_vertex_color_set(SculptSession *ss, PBVHVertRef vertex, const float color[4]);
|
||||
|
||||
|
@ -1522,7 +1521,7 @@ namespace blender::ed::sculpt_paint::smooth {
|
|||
void bmesh_four_neighbor_average(float avg[3], float direction[3], BMVert *v);
|
||||
|
||||
void neighbor_coords_average(SculptSession *ss, float result[3], PBVHVertRef vertex);
|
||||
float neighbor_mask_average(SculptSession *ss, PBVHVertRef vertex);
|
||||
float neighbor_mask_average(SculptSession *ss, SculptMaskWriteInfo write_info, PBVHVertRef vertex);
|
||||
void neighbor_color_average(SculptSession *ss, float result[4], PBVHVertRef vertex);
|
||||
|
||||
/**
|
||||
|
|
|
@ -134,22 +134,40 @@ void neighbor_coords_average(SculptSession *ss, float result[3], PBVHVertRef ver
|
|||
}
|
||||
}
|
||||
|
||||
float neighbor_mask_average(SculptSession *ss, PBVHVertRef vertex)
|
||||
float neighbor_mask_average(SculptSession *ss,
|
||||
const SculptMaskWriteInfo mask_write,
|
||||
PBVHVertRef vertex)
|
||||
{
|
||||
float avg = 0.0f;
|
||||
int total = 0;
|
||||
|
||||
SculptVertexNeighborIter ni;
|
||||
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vertex, ni) {
|
||||
avg += SCULPT_vertex_mask_get(ss, ni.vertex);
|
||||
total++;
|
||||
switch (BKE_pbvh_type(ss->pbvh)) {
|
||||
case PBVH_FACES:
|
||||
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vertex, ni) {
|
||||
avg += mask_write.layer[ni.vertex.i];
|
||||
total++;
|
||||
}
|
||||
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
|
||||
break;
|
||||
case PBVH_GRIDS:
|
||||
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vertex, ni) {
|
||||
avg += SCULPT_mask_get_at_grids_vert_index(
|
||||
*ss->subdiv_ccg, *BKE_pbvh_get_grid_key(ss->pbvh), vertex.i);
|
||||
total++;
|
||||
}
|
||||
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
|
||||
break;
|
||||
case PBVH_BMESH:
|
||||
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vertex, ni) {
|
||||
BMVert *vert = reinterpret_cast<BMVert *>(vertex.i);
|
||||
avg += BM_ELEM_CD_GET_FLOAT(vert, mask_write.bm_offset);
|
||||
total++;
|
||||
}
|
||||
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
|
||||
break;
|
||||
}
|
||||
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
|
||||
|
||||
if (total > 0) {
|
||||
return avg / total;
|
||||
}
|
||||
return SCULPT_vertex_mask_get(ss, vertex);
|
||||
BLI_assert(total > 0);
|
||||
return avg / total;
|
||||
}
|
||||
|
||||
void neighbor_color_average(SculptSession *ss, float result[4], PBVHVertRef vertex)
|
||||
|
@ -289,7 +307,7 @@ static void smooth_mask_node(Object *ob,
|
|||
vd.vertex,
|
||||
thread_id,
|
||||
&automask_data);
|
||||
float val = neighbor_mask_average(ss, vd.vertex) - vd.mask;
|
||||
float val = neighbor_mask_average(ss, mask_write, vd.vertex) - vd.mask;
|
||||
val *= fade * bstrength;
|
||||
float new_mask = vd.mask + val;
|
||||
CLAMP(new_mask, 0.0f, 1.0f);
|
||||
|
|
Loading…
Reference in New Issue