Refactor: Sculpt: Switch to new API for BVH node selection & data access

Use `IndexMask` for a selection of nodes, and remove the temporarily
added type-agnostic functions for PBVH node data access. This change
results in a lot of boilerplate change since all iteration over nodes is
affected, and the proper types for nodes need to be used to access
their data.

Until leaf and inner nodes are split, the `all_leaf_nodes` function has
an unfortunate signature now since it needs to return an `IndexMask`
as well. That should be simplified in the future.

Pull Request: https://projects.blender.org/blender/blender/pulls/126944
This commit is contained in:
Hans Goudey
2024-08-29 19:34:22 +02:00
committed by Hans Goudey
parent 1c1e389d4b
commit 347ec1acd7
74 changed files with 3557 additions and 2982 deletions

View File

@@ -527,7 +527,7 @@ int BKE_pbvh_debug_draw_gen_get(blender::bke::pbvh::Node &node);
namespace blender::bke::pbvh {
/** Return pointers to all the leaf nodes in the BVH tree. */
Vector<Node *> all_leaf_nodes(Tree &pbvh);
IndexMask all_leaf_nodes(const Tree &pbvh, IndexMaskMemory &memory);
/** Create a selection of nodes that match the filter function. */
IndexMask search_nodes(const Tree &pbvh,
@@ -551,34 +551,3 @@ void update_node_bounds_grids(const CCGKey &key, Span<CCGElem *> grids, GridsNod
void update_node_bounds_bmesh(BMeshNode &node);
} // namespace blender::bke::pbvh
/* TODO: Temporary inline definitions with generic #Node type signature. To be removed as
* refactoring changes code to use explicit node types. */
namespace blender::bke::pbvh {
inline Span<int> node_grid_indices(const Node &node)
{
return node_grid_indices(static_cast<const GridsNode &>(node));
}
inline Span<int> node_verts(const Node &node)
{
return node_verts(static_cast<const MeshNode &>(node));
}
inline Span<int> node_unique_verts(const Node &node)
{
return node_unique_verts(static_cast<const MeshNode &>(node));
}
} // namespace blender::bke::pbvh
inline const blender::Set<BMVert *, 0> &BKE_pbvh_bmesh_node_unique_verts(
blender::bke::pbvh::Node *node)
{
return BKE_pbvh_bmesh_node_unique_verts(static_cast<blender::bke::pbvh::BMeshNode *>(node));
}
inline const blender::Set<BMVert *, 0> &BKE_pbvh_bmesh_node_other_verts(
blender::bke::pbvh::Node *node)
{
return BKE_pbvh_bmesh_node_other_verts(static_cast<blender::bke::pbvh::BMeshNode *>(node));
}
inline const blender::Set<BMFace *, 0> &BKE_pbvh_bmesh_node_faces(blender::bke::pbvh::Node *node)
{
return BKE_pbvh_bmesh_node_faces(static_cast<blender::bke::pbvh::BMeshNode *>(node));
}

View File

@@ -2095,6 +2095,7 @@ static void sculpt_update_object(Depsgraph *depsgraph,
void BKE_sculpt_update_object_before_eval(Object *ob_eval)
{
using namespace blender;
/* Update before mesh evaluation in the dependency graph. */
SculptSession *ss = ob_eval->sculpt;
@@ -2120,8 +2121,24 @@ void BKE_sculpt_update_object_before_eval(Object *ob_eval)
BKE_sculptsession_free_vwpaint_data(ob_eval->sculpt);
}
else if (ss->pbvh) {
for (blender::bke::pbvh::Node *node : blender::bke::pbvh::all_leaf_nodes(*ss->pbvh)) {
BKE_pbvh_node_mark_update(*node);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss->pbvh, memory);
switch (ss->pbvh->type()) {
case bke::pbvh::Type::Mesh: {
MutableSpan<bke::pbvh::MeshNode> nodes = ss->pbvh->nodes<bke::pbvh::MeshNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update(nodes[i]); });
break;
}
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss->pbvh->nodes<bke::pbvh::GridsNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update(nodes[i]); });
break;
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss->pbvh->nodes<bke::pbvh::BMeshNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update(nodes[i]); });
break;
}
}
}
}

View File

@@ -3055,18 +3055,14 @@ void BKE_pbvh_sync_visibility_from_verts(Object &object)
namespace blender::bke::pbvh {
Vector<Node *> all_leaf_nodes(Tree &pbvh)
IndexMask all_leaf_nodes(const Tree &pbvh, IndexMaskMemory &memory)
{
Vector<Node *> leaf_nodes;
return std::visit(
[&](auto &nodes) {
leaf_nodes.reserve(nodes.size());
for (Node &node : nodes) {
if (node.flag_ & PBVH_Leaf) {
leaf_nodes.append(&node);
}
}
return leaf_nodes;
[&](const auto &nodes) {
return IndexMask::from_predicate(
nodes.index_range(), GrainSize(1024), memory, [&](const int i) {
return (nodes[i].flag_ & PBVH_Leaf) != 0;
});
},
pbvh.nodes_);
}

View File

@@ -7,11 +7,13 @@
namespace blender::index_mask {
class IndexMask;
class IndexMaskMemory;
} // namespace blender::index_mask
namespace blender {
using index_mask::IndexMask;
using index_mask::IndexMaskMemory;
} // namespace blender

View File

@@ -49,7 +49,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
const Brush &brush,
const float3 &direction,
const float strength,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -93,7 +93,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
void do_bmesh_topology_rake_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
const float input_strength)
{
const SculptSession &ss = *object.sculpt;
@@ -120,12 +120,13 @@ void do_bmesh_topology_rake_brush(const Depsgraph &depsgraph,
threading::EnumerableThreadSpecific<LocalData> all_tls;
for ([[maybe_unused]] const int i : IndexRange(count)) {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(
depsgraph, sd, object, brush, direction, factor * ss.cache->pressure, *nodes[i], tls);
}
depsgraph, sd, object, brush, direction, factor * ss.cache->pressure, nodes[i], tls);
});
});
}
}

View File

@@ -61,7 +61,7 @@ static void calc_faces(const Depsgraph &depsgraph,
const float strength,
const Span<float3> positions_eval,
const Span<float3> vert_normals,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
Object &object,
LocalData &tls,
const MutableSpan<float3> positions_orig)
@@ -106,7 +106,7 @@ static void calc_grids(const Depsgraph &depsgraph,
const Brush &brush,
const float4 &test_plane,
const float strength,
bke::pbvh::Node &node,
bke::pbvh::GridsNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -150,7 +150,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
const Brush &brush,
const float4 &test_plane,
const float strength,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -191,14 +191,14 @@ static void calc_bmesh(const Depsgraph &depsgraph,
void do_clay_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
SculptSession &ss = *object.sculpt;
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
float3 area_no;
float3 area_co;
calc_brush_plane(depsgraph, brush, object, nodes, area_no, area_co);
calc_brush_plane(depsgraph, brush, object, node_mask, area_no, area_co);
const float initial_radius = fabsf(ss.cache->initial_radius);
const float offset = SCULPT_brush_plane_offset_get(sd, ss);
@@ -227,9 +227,10 @@ void do_clay_brush(const Depsgraph &depsgraph,
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object);
const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_faces(depsgraph,
sd,
brush,
@@ -237,31 +238,36 @@ void do_clay_brush(const Depsgraph &depsgraph,
bstrength,
positions_eval,
vert_normals,
*nodes[i],
nodes[i],
object,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_grids(depsgraph, sd, object, brush, test_plane, bstrength, *nodes[i], tls);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_grids(depsgraph, sd, object, brush, test_plane, bstrength, nodes[i], tls);
});
});
break;
case bke::pbvh::Type::BMesh:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_bmesh(depsgraph, sd, object, brush, test_plane, bstrength, *nodes[i], tls);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(depsgraph, sd, object, brush, test_plane, bstrength, nodes[i], tls);
});
});
break;
}
}
}
} // namespace blender::ed::sculpt_paint

View File

@@ -47,7 +47,7 @@ static void calc_faces(const Depsgraph &depsgraph,
const bool flip,
const Span<float3> positions_eval,
const Span<float3> vert_normals,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
Object &object,
LocalData &tls,
const MutableSpan<float3> positions_orig)
@@ -103,7 +103,7 @@ static void calc_grids(const Depsgraph &depsgraph,
const float4 &plane,
const float strength,
const bool flip,
bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -159,7 +159,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
const float4 &plane,
const float strength,
const bool flip,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -211,7 +211,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
void do_clay_strips_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
SculptSession &ss = *object.sculpt;
if (math::is_zero(ss.cache->grab_delta_symmetry)) {
@@ -226,13 +226,13 @@ void do_clay_strips_brush(const Depsgraph &depsgraph,
float3 area_position;
float3 plane_normal;
calc_brush_plane(depsgraph, brush, object, nodes, plane_normal, area_position);
calc_brush_plane(depsgraph, brush, object, node_mask, plane_normal, area_position);
SCULPT_tilt_apply_to_normal(plane_normal, ss.cache, brush.tilt_strength_factor);
area_position += plane_normal * ss.cache->scale * displace;
float3 area_normal;
if (brush.sculpt_plane != SCULPT_DISP_DIR_AREA || (brush.flag & BRUSH_ORIGINAL_NORMAL)) {
area_normal = calc_area_normal(depsgraph, brush, object, nodes).value_or(float3(0));
area_normal = calc_area_normal(depsgraph, brush, object, node_mask).value_or(float3(0));
}
else {
area_normal = plane_normal;
@@ -274,15 +274,16 @@ void do_clay_strips_brush(const Depsgraph &depsgraph,
const float strength = std::abs(ss.cache->bstrength);
threading::EnumerableThreadSpecific<LocalData> all_tls;
switch (object.sculpt->pbvh->type()) {
switch (ss.pbvh->type()) {
case bke::pbvh::Type::Mesh: {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
Mesh &mesh = *static_cast<Mesh *>(object.data);
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object);
const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_faces(depsgraph,
sd,
brush,
@@ -292,31 +293,35 @@ void do_clay_strips_brush(const Depsgraph &depsgraph,
flip,
positions_eval,
vert_normals,
*nodes[i],
nodes[i],
object,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_grids(depsgraph, sd, object, brush, mat, plane, strength, flip, *nodes[i], tls);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_grids(depsgraph, sd, object, brush, mat, plane, strength, flip, nodes[i], tls);
});
});
break;
case bke::pbvh::Type::BMesh:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_bmesh(depsgraph, sd, object, brush, mat, plane, strength, flip, *nodes[i], tls);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(depsgraph, sd, object, brush, mat, plane, strength, flip, nodes[i], tls);
});
});
break;
}
}
}

View File

@@ -47,7 +47,7 @@ static void calc_faces(const Depsgraph &depsgraph,
const float strength,
const Span<float3> positions_eval,
const Span<float3> vert_normals,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
Object &object,
LocalData &tls,
const MutableSpan<float3> positions_orig)
@@ -95,7 +95,7 @@ static void calc_grids(const Depsgraph &depsgraph,
const Brush &brush,
const float4 &plane_tilt,
const float strength,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
Object &object,
LocalData &tls)
{
@@ -143,7 +143,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
const float4 &plane_tilt,
const float strength,
Object &object,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -188,7 +188,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
void do_clay_thumb_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
const SculptSession &ss = *object.sculpt;
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
@@ -201,10 +201,10 @@ void do_clay_thumb_brush(const Depsgraph &depsgraph,
float4x4 tmat;
calc_brush_plane(depsgraph, brush, object, nodes, area_no_sp, area_co_tmp);
calc_brush_plane(depsgraph, brush, object, node_mask, area_no_sp, area_co_tmp);
if (brush.sculpt_plane != SCULPT_DISP_DIR_AREA || (brush.flag & BRUSH_ORIGINAL_NORMAL)) {
area_no = calc_area_normal(depsgraph, brush, object, nodes).value_or(float3(0));
area_no = calc_area_normal(depsgraph, brush, object, node_mask).value_or(float3(0));
}
else {
area_no = area_no_sp;
@@ -257,13 +257,14 @@ void do_clay_thumb_brush(const Depsgraph &depsgraph,
threading::EnumerableThreadSpecific<LocalData> all_tls;
switch (object.sculpt->pbvh->type()) {
case bke::pbvh::Type::Mesh: {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
Mesh &mesh = *static_cast<Mesh *>(object.data);
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object);
const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_faces(depsgraph,
sd,
brush,
@@ -271,31 +272,35 @@ void do_clay_thumb_brush(const Depsgraph &depsgraph,
clay_strength,
positions_eval,
vert_normals,
*nodes[i],
nodes[i],
object,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_grids(depsgraph, sd, brush, plane_tilt, clay_strength, *nodes[i], object, tls);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_grids(depsgraph, sd, brush, plane_tilt, clay_strength, nodes[i], object, tls);
});
});
break;
case bke::pbvh::Type::BMesh:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_bmesh(depsgraph, sd, brush, plane_tilt, clay_strength, object, *nodes[i], tls);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(depsgraph, sd, brush, plane_tilt, clay_strength, object, nodes[i], tls);
});
});
break;
}
}
}

View File

@@ -73,7 +73,7 @@ static void calc_faces(const Depsgraph &depsgraph,
const float strength,
const Span<float3> positions_eval,
const Span<float3> vert_normals,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
Object &object,
LocalData &tls,
const MutableSpan<float3> positions_orig)
@@ -130,7 +130,7 @@ static void calc_grids(const Depsgraph &depsgraph,
const Brush &brush,
const float3 &offset,
const float strength,
bke::pbvh::Node &node,
bke::pbvh::GridsNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -184,7 +184,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
const Brush &brush,
const float3 &offset,
const float strength,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -236,7 +236,7 @@ static void do_crease_or_blob_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
const bool invert_strength,
Object &object,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
const SculptSession &ss = *object.sculpt;
const StrokeCache &cache = *ss.cache;
@@ -264,9 +264,10 @@ static void do_crease_or_blob_brush(const Depsgraph &depsgraph,
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object);
const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_faces(depsgraph,
sd,
brush,
@@ -274,31 +275,35 @@ static void do_crease_or_blob_brush(const Depsgraph &depsgraph,
strength,
positions_eval,
vert_normals,
*nodes[i],
nodes[i],
object,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_grids(depsgraph, sd, object, brush, offset, strength, *nodes[i], tls);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_grids(depsgraph, sd, object, brush, offset, strength, nodes[i], tls);
});
});
break;
case bke::pbvh::Type::BMesh:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_bmesh(depsgraph, sd, object, brush, offset, strength, *nodes[i], tls);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(depsgraph, sd, object, brush, offset, strength, nodes[i], tls);
});
});
break;
}
}
}
@@ -308,18 +313,18 @@ void do_crease_brush(const Depsgraph &depsgraph,
const Scene &scene,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
do_crease_or_blob_brush(depsgraph, scene, sd, false, object, nodes);
do_crease_or_blob_brush(depsgraph, scene, sd, false, object, node_mask);
}
void do_blob_brush(const Depsgraph &depsgraph,
const Scene &scene,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
do_crease_or_blob_brush(depsgraph, scene, sd, true, object, nodes);
do_crease_or_blob_brush(depsgraph, scene, sd, true, object, node_mask);
}
} // namespace blender::ed::sculpt_paint

View File

@@ -42,7 +42,7 @@ static void calc_faces(const Depsgraph &depsgraph,
const float3 &offset,
const Span<float3> positions_eval,
const Span<float3> vert_normals,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
Object &object,
LocalData &tls,
const MutableSpan<float3> positions_orig)
@@ -85,7 +85,7 @@ static void calc_grids(const Depsgraph &depsgraph,
Object &object,
const Brush &brush,
const float3 &offset,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -127,7 +127,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
Object &object,
const Brush &brush,
const float3 &offset,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -169,58 +169,62 @@ static void offset_positions(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
const float3 &offset,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
SculptSession &ss = *object.sculpt;
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
threading::EnumerableThreadSpecific<LocalData> all_tls;
switch (object.sculpt->pbvh->type()) {
switch (ss.pbvh->type()) {
case bke::pbvh::Type::Mesh: {
Mesh &mesh = *static_cast<Mesh *>(object.data);
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object);
const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_faces(depsgraph,
sd,
brush,
offset,
positions_eval,
vert_normals,
*nodes[i],
nodes[i],
object,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_grids(depsgraph, sd, object, brush, offset, *nodes[i], tls);
}
node_mask.slice(range).foreach_index(
[&](const int i) { calc_grids(depsgraph, sd, object, brush, offset, nodes[i], tls); });
});
break;
case bke::pbvh::Type::BMesh:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_bmesh(depsgraph, sd, object, brush, offset, *nodes[i], tls);
}
node_mask.slice(range).foreach_index(
[&](const int i) { calc_bmesh(depsgraph, sd, object, brush, offset, nodes[i], tls); });
});
break;
}
}
}
void do_draw_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
const SculptSession &ss = *object.sculpt;
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
@@ -231,13 +235,13 @@ void do_draw_brush(const Depsgraph &depsgraph,
const float3 offset = effective_normal * ss.cache->radius * ss.cache->scale *
ss.cache->bstrength;
offset_positions(depsgraph, sd, object, offset, nodes);
offset_positions(depsgraph, sd, object, offset, node_mask);
}
void do_nudge_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
const SculptSession &ss = *object.sculpt;
@@ -245,20 +249,20 @@ void do_nudge_brush(const Depsgraph &depsgraph,
math::cross(ss.cache->sculpt_normal_symm, ss.cache->grab_delta_symmetry),
ss.cache->sculpt_normal_symm);
offset_positions(depsgraph, sd, object, offset * ss.cache->bstrength, nodes);
offset_positions(depsgraph, sd, object, offset * ss.cache->bstrength, node_mask);
}
void do_gravity_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
const SculptSession &ss = *object.sculpt;
const float3 offset = ss.cache->gravity_direction * -ss.cache->radius_squared * ss.cache->scale *
sd.gravity_factor;
offset_positions(depsgraph, sd, object, offset, nodes);
offset_positions(depsgraph, sd, object, offset, node_mask);
}
} // namespace blender::ed::sculpt_paint

View File

@@ -117,7 +117,7 @@ static void calc_faces(const Depsgraph &depsgraph,
const float strength,
const int face_set_id,
Span<float3> positions_eval,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
const Span<int> face_indices,
MeshLocalData &tls,
const MutableSpan<int> face_sets)
@@ -169,7 +169,7 @@ static void calc_faces(const Depsgraph &depsgraph,
static void do_draw_face_sets_brush_mesh(const Depsgraph &depsgraph,
Object &object,
const Brush &brush,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
const SculptSession &ss = *object.sculpt;
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object);
@@ -181,13 +181,14 @@ static void do_draw_face_sets_brush_mesh(const Depsgraph &depsgraph,
MutableSpan<int> face_sets = attribute.span;
threading::EnumerableThreadSpecific<MeshLocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
MeshLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> face_indices = bke::pbvh::node_face_indices_calc_mesh(
corner_tris, static_cast<bke::pbvh::MeshNode &>(*nodes[i]), tls.face_indices);
corner_tris, nodes[i], tls.face_indices);
undo::push_node(depsgraph, object, nodes[i], undo::Type::FaceSet);
undo::push_node(depsgraph, object, &nodes[i], undo::Type::FaceSet);
calc_faces(depsgraph,
object,
@@ -195,11 +196,11 @@ static void do_draw_face_sets_brush_mesh(const Depsgraph &depsgraph,
ss.cache->bstrength,
ss.cache->paint_face_set,
positions_eval,
*nodes[i],
nodes[i],
face_indices,
tls,
face_sets);
}
});
});
attribute.finish();
@@ -232,7 +233,7 @@ static void calc_grids(const Depsgraph &depsgraph,
const Brush &brush,
const float strength,
const int face_set_id,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
GridLocalData &tls,
const MutableSpan<int> face_sets)
{
@@ -273,7 +274,7 @@ static void calc_grids(const Depsgraph &depsgraph,
static void do_draw_face_sets_brush_grids(const Depsgraph &depsgraph,
Object &object,
const Brush &brush,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
SculptSession &ss = *object.sculpt;
@@ -281,22 +282,21 @@ static void do_draw_face_sets_brush_grids(const Depsgraph &depsgraph,
MutableSpan<int> face_sets = attribute.span;
threading::EnumerableThreadSpecific<GridLocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
GridLocalData &tls = all_tls.local();
for (bke::pbvh::Node *node : nodes.slice(range)) {
for (const int i : range) {
undo::push_node(depsgraph, object, node, undo::Type::FaceSet);
node_mask.slice(range).foreach_index([&](const int i) {
undo::push_node(depsgraph, object, &nodes[i], undo::Type::FaceSet);
calc_grids(depsgraph,
object,
brush,
ss.cache->bstrength,
ss.cache->paint_face_set,
*nodes[i],
tls,
face_sets);
}
}
calc_grids(depsgraph,
object,
brush,
ss.cache->bstrength,
ss.cache->paint_face_set,
nodes[i],
tls,
face_sets);
});
});
attribute.finish();
}
@@ -370,7 +370,7 @@ static void calc_bmesh(Object &object,
const Brush &brush,
const float strength,
const int face_set_id,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
BMeshLocalData &tls,
const int cd_offset)
{
@@ -406,19 +406,20 @@ static void calc_bmesh(Object &object,
static void do_draw_face_sets_brush_bmesh(const Depsgraph &depsgraph,
Object &object,
const Brush &brush,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
SculptSession &ss = *object.sculpt;
const int cd_offset = face_set::ensure_face_sets_bmesh(object);
threading::EnumerableThreadSpecific<BMeshLocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
BMeshLocalData &tls = all_tls.local();
for (const int i : range) {
undo::push_node(depsgraph, object, nodes[i], undo::Type::FaceSet);
node_mask.slice(range).foreach_index([&](const int i) {
undo::push_node(depsgraph, object, &nodes[i], undo::Type::FaceSet);
calc_bmesh(
object, brush, ss.cache->bstrength, ss.cache->paint_face_set, *nodes[i], tls, cd_offset);
}
object, brush, ss.cache->bstrength, ss.cache->paint_face_set, nodes[i], tls, cd_offset);
});
});
}
@@ -427,20 +428,20 @@ static void do_draw_face_sets_brush_bmesh(const Depsgraph &depsgraph,
void do_draw_face_sets_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
SculptSession &ss = *object.sculpt;
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
switch (ss.pbvh->type()) {
case bke::pbvh::Type::Mesh:
do_draw_face_sets_brush_mesh(depsgraph, object, brush, nodes);
do_draw_face_sets_brush_mesh(depsgraph, object, brush, node_mask);
break;
case bke::pbvh::Type::Grids:
do_draw_face_sets_brush_grids(depsgraph, object, brush, nodes);
do_draw_face_sets_brush_grids(depsgraph, object, brush, node_mask);
break;
case bke::pbvh::Type::BMesh:
do_draw_face_sets_brush_bmesh(depsgraph, object, brush, nodes);
do_draw_face_sets_brush_bmesh(depsgraph, object, brush, node_mask);
break;
}
}

View File

@@ -40,7 +40,7 @@ static void calc_faces(const Depsgraph &depsgraph,
const Brush &brush,
const float3 &offset,
const Span<float3> positions_eval,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
Object &object,
LocalData &tls,
const MutableSpan<float3> positions_orig)
@@ -84,7 +84,7 @@ static void calc_grids(const Depsgraph &depsgraph,
Object &object,
const Brush &brush,
const float3 &offset,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -129,7 +129,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
Object &object,
const Brush &brush,
const float3 &offset,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -174,8 +174,9 @@ static void offset_positions(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
const float3 &offset,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
SculptSession &ss = *object.sculpt;
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
threading::EnumerableThreadSpecific<LocalData> all_tls;
@@ -184,46 +185,42 @@ static void offset_positions(const Depsgraph &depsgraph,
Mesh &mesh = *static_cast<Mesh *>(object.data);
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object);
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_faces(depsgraph,
sd,
brush,
offset,
positions_eval,
*nodes[i],
object,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_faces(
depsgraph, sd, brush, offset, positions_eval, nodes[i], object, tls, positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_grids(depsgraph, sd, object, brush, offset, *nodes[i], tls);
}
node_mask.slice(range).foreach_index(
[&](const int i) { calc_grids(depsgraph, sd, object, brush, offset, nodes[i], tls); });
});
break;
case bke::pbvh::Type::BMesh:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_bmesh(depsgraph, sd, object, brush, offset, *nodes[i], tls);
}
node_mask.slice(range).foreach_index(
[&](const int i) { calc_bmesh(depsgraph, sd, object, brush, offset, nodes[i], tls); });
});
break;
}
}
}
void do_draw_sharp_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
const SculptSession &ss = *object.sculpt;
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
@@ -234,7 +231,7 @@ void do_draw_sharp_brush(const Depsgraph &depsgraph,
const float3 offset = effective_normal * ss.cache->radius * ss.cache->scale *
ss.cache->bstrength;
offset_positions(depsgraph, sd, object, offset, nodes);
offset_positions(depsgraph, sd, object, offset, node_mask);
}
} // namespace blender::ed::sculpt_paint

View File

@@ -83,7 +83,7 @@ static void calc_faces(const Depsgraph &depsgraph,
const Brush &brush,
const Span<float3> positions_eval,
const Span<float3> vert_normals,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
Object &object,
LocalData &tls,
MutableSpan<float3> positions_orig)
@@ -129,7 +129,7 @@ static void calc_grids(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
const Brush &brush,
bke::pbvh::Node &node,
bke::pbvh::GridsNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -174,7 +174,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
const Brush &brush,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -219,50 +219,54 @@ static void calc_bmesh(const Depsgraph &depsgraph,
void do_draw_vector_displacement_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
SculptSession &ss = *object.sculpt;
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
threading::EnumerableThreadSpecific<LocalData> all_tls;
switch (object.sculpt->pbvh->type()) {
switch (ss.pbvh->type()) {
case bke::pbvh::Type::Mesh: {
Mesh &mesh = *static_cast<Mesh *>(object.data);
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object);
const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_faces(depsgraph,
sd,
brush,
positions_eval,
vert_normals,
*nodes[i],
nodes[i],
object,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_grids(depsgraph, sd, object, brush, *nodes[i], tls);
}
node_mask.slice(range).foreach_index(
[&](const int i) { calc_grids(depsgraph, sd, object, brush, nodes[i], tls); });
});
break;
case bke::pbvh::Type::BMesh:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_bmesh(depsgraph, sd, object, brush, *nodes[i], tls);
}
node_mask.slice(range).foreach_index(
[&](const int i) { calc_bmesh(depsgraph, sd, object, brush, nodes[i], tls); });
});
break;
}
}
}

View File

@@ -90,7 +90,7 @@ static void calc_faces(const Depsgraph &depsgraph,
const KelvinletParams &kelvinet_params,
const float3 &offset,
const Span<float3> positions_eval,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
Object &object,
LocalData &tls,
const MutableSpan<float3> positions_orig)
@@ -125,7 +125,7 @@ static void calc_grids(const Depsgraph &depsgraph,
const Brush &brush,
const KelvinletParams &kelvinet_params,
const float3 &offset,
bke::pbvh::Node &node,
bke::pbvh::GridsNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -161,7 +161,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
const Brush &brush,
const KelvinletParams &kelvinet_params,
const float3 &offset,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -196,7 +196,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
void do_elastic_deform_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
const SculptSession &ss = *object.sculpt;
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
@@ -233,40 +233,44 @@ void do_elastic_deform_brush(const Depsgraph &depsgraph,
Mesh &mesh = *static_cast<Mesh *>(object.data);
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object);
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_faces(depsgraph,
sd,
brush,
params,
grab_delta,
positions_eval,
*nodes[i],
nodes[i],
object,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_grids(depsgraph, sd, object, brush, params, grab_delta, *nodes[i], tls);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_grids(depsgraph, sd, object, brush, params, grab_delta, nodes[i], tls);
});
});
break;
case bke::pbvh::Type::BMesh:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_bmesh(depsgraph, sd, object, brush, params, grab_delta, *nodes[i], tls);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(depsgraph, sd, object, brush, params, grab_delta, nodes[i], tls);
});
});
break;
} break;
}
}

View File

@@ -42,7 +42,7 @@ static void calc_faces(const Depsgraph &depsgraph,
const Span<float3> vert_normals,
const Span<float3> all_translations,
const float strength,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
Object &object,
LocalData &tls,
const MutableSpan<float3> positions_orig)
@@ -89,7 +89,7 @@ static void calc_grids(const Depsgraph &depsgraph,
const Brush &brush,
const Span<float3> all_translations,
const float strength,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -134,7 +134,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
const Brush &brush,
const Span<float3> all_translations,
const float strength,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -176,7 +176,7 @@ static void calc_translations_faces(const Span<float3> vert_positions,
const OffsetIndices<int> faces,
const Span<int> corner_verts,
const GroupedSpan<int> vert_to_face_map,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
LocalData &tls,
const MutableSpan<float3> all_translations)
{
@@ -197,7 +197,7 @@ static void calc_translations_faces(const Span<float3> vert_positions,
}
static void calc_translations_grids(const SubdivCCG &subdiv_ccg,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
LocalData &tls,
const MutableSpan<float3> all_translations)
{
@@ -214,11 +214,12 @@ static void calc_translations_grids(const SubdivCCG &subdiv_ccg,
scatter_data_grids(subdiv_ccg, translations.as_span(), grids, all_translations);
}
static void calc_translations_bmesh(bke::pbvh::Node &node,
static void calc_translations_bmesh(const bke::pbvh::BMeshNode &node,
LocalData &tls,
const MutableSpan<float3> all_translations)
{
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&node);
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(
const_cast<bke::pbvh::BMeshNode *>(&node));
const MutableSpan positions = gather_bmesh_positions(verts, tls.positions);
tls.new_positions.resize(verts.size());
@@ -241,7 +242,7 @@ static void calc_translations_bmesh(bke::pbvh::Node &node,
*/
void calc_smooth_translations(const Depsgraph &depsgraph,
const Object &object,
const Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
const MutableSpan<float3> translations)
{
const SculptSession &ss = *object.sculpt;
@@ -254,38 +255,40 @@ void calc_smooth_translations(const Depsgraph &depsgraph,
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object);
const OffsetIndices faces = mesh.faces();
const Span<int> corner_verts = mesh.corner_verts();
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
const Span<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_translations_faces(positions_eval,
faces,
corner_verts,
ss.vert_to_face_map,
*nodes[i],
nodes[i],
tls,
translations);
}
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
const Span<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_translations_grids(subdiv_ccg, *nodes[i], tls, translations);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_translations_grids(subdiv_ccg, nodes[i], tls, translations);
});
});
break;
}
case bke::pbvh::Type::BMesh:
BM_mesh_elem_index_ensure(ss.bm, BM_VERT);
BM_mesh_elem_table_ensure(ss.bm, BM_VERT);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
const Span<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_translations_bmesh(*nodes[i], tls, translations);
}
node_mask.slice(range).foreach_index(
[&](const int i) { calc_translations_bmesh(nodes[i], tls, translations); });
});
break;
}
@@ -294,7 +297,7 @@ void calc_smooth_translations(const Depsgraph &depsgraph,
void do_enhance_details_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
SculptSession &ss = *object.sculpt;
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
@@ -302,8 +305,11 @@ void do_enhance_details_brush(const Depsgraph &depsgraph,
if (SCULPT_stroke_is_first_brush_step(*ss.cache)) {
ss.cache->detail_directions.reinitialize(SCULPT_vertex_count_get(object));
Vector<bke::pbvh::Node *> effective_nodes = bke::pbvh::search_gather(
pbvh, [&](bke::pbvh::Node &node) { return !node_fully_masked_or_hidden(node); });
IndexMaskMemory memory;
const IndexMask effective_nodes = bke::pbvh::search_nodes(
pbvh, memory, [&](const bke::pbvh::Node &node) {
return !node_fully_masked_or_hidden(node);
});
calc_smooth_translations(depsgraph, object, effective_nodes, ss.cache->detail_directions);
}
@@ -317,9 +323,10 @@ void do_enhance_details_brush(const Depsgraph &depsgraph,
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object);
const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_faces(depsgraph,
sd,
brush,
@@ -327,31 +334,35 @@ void do_enhance_details_brush(const Depsgraph &depsgraph,
vert_normals,
translations,
strength,
*nodes[i],
nodes[i],
object,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_grids(depsgraph, sd, object, brush, translations, strength, *nodes[i], tls);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_grids(depsgraph, sd, object, brush, translations, strength, nodes[i], tls);
});
});
break;
case bke::pbvh::Type::BMesh:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_bmesh(depsgraph, sd, object, brush, translations, strength, *nodes[i], tls);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(depsgraph, sd, object, brush, translations, strength, nodes[i], tls);
});
});
break;
}
}
}

View File

@@ -44,7 +44,7 @@ static void calc_faces(const Depsgraph &depsgraph,
const float strength,
const Span<float3> positions_eval,
const Span<float3> vert_normals,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
Object &object,
LocalData &tls,
const MutableSpan<float3> positions_orig)
@@ -94,7 +94,7 @@ static void calc_grids(const Depsgraph &depsgraph,
const Brush &brush,
const float4 &plane,
const float strength,
bke::pbvh::Node &node,
bke::pbvh::GridsNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -143,7 +143,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
const Brush &brush,
const float4 &plane,
const float strength,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -190,14 +190,14 @@ static void calc_bmesh(const Depsgraph &depsgraph,
void do_fill_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
const SculptSession &ss = *object.sculpt;
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
float3 area_no;
float3 area_co;
calc_brush_plane(depsgraph, brush, object, nodes, area_no, area_co);
calc_brush_plane(depsgraph, brush, object, node_mask, area_no, area_co);
SCULPT_tilt_apply_to_normal(area_no, ss.cache, brush.tilt_strength_factor);
const float offset = SCULPT_brush_plane_offset_get(sd, ss);
@@ -214,9 +214,10 @@ void do_fill_brush(const Depsgraph &depsgraph,
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object);
const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_faces(depsgraph,
sd,
brush,
@@ -224,31 +225,35 @@ void do_fill_brush(const Depsgraph &depsgraph,
ss.cache->bstrength,
positions_eval,
vert_normals,
*nodes[i],
nodes[i],
object,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_grids(depsgraph, sd, object, brush, plane, ss.cache->bstrength, *nodes[i], tls);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_grids(depsgraph, sd, object, brush, plane, ss.cache->bstrength, nodes[i], tls);
});
});
break;
case bke::pbvh::Type::BMesh:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_bmesh(depsgraph, sd, object, brush, plane, ss.cache->bstrength, *nodes[i], tls);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(depsgraph, sd, object, brush, plane, ss.cache->bstrength, nodes[i], tls);
});
});
break;
}
}
}

View File

@@ -43,7 +43,7 @@ static void calc_faces(const Depsgraph &depsgraph,
const float strength,
const Span<float3> positions_eval,
const Span<float3> vert_normals,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
Object &object,
LocalData &tls,
const MutableSpan<float3> positions_orig)
@@ -91,7 +91,7 @@ static void calc_grids(const Depsgraph &depsgraph,
const Brush &brush,
const float4 &plane,
const float strength,
bke::pbvh::Node &node,
bke::pbvh::GridsNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -138,7 +138,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
const Brush &brush,
const float4 &plane,
const float strength,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -183,14 +183,14 @@ static void calc_bmesh(const Depsgraph &depsgraph,
void do_flatten_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
const SculptSession &ss = *object.sculpt;
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
float3 area_no;
float3 area_co;
calc_brush_plane(depsgraph, brush, object, nodes, area_no, area_co);
calc_brush_plane(depsgraph, brush, object, node_mask, area_no, area_co);
SCULPT_tilt_apply_to_normal(area_no, ss.cache, brush.tilt_strength_factor);
const float offset = SCULPT_brush_plane_offset_get(sd, ss);
@@ -207,9 +207,10 @@ void do_flatten_brush(const Depsgraph &depsgraph,
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object);
const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_faces(depsgraph,
sd,
brush,
@@ -217,31 +218,35 @@ void do_flatten_brush(const Depsgraph &depsgraph,
ss.cache->bstrength,
positions_eval,
vert_normals,
*nodes[i],
nodes[i],
object,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_grids(depsgraph, sd, object, brush, plane, ss.cache->bstrength, *nodes[i], tls);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_grids(depsgraph, sd, object, brush, plane, ss.cache->bstrength, nodes[i], tls);
});
});
break;
case bke::pbvh::Type::BMesh:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_bmesh(depsgraph, sd, object, brush, plane, ss.cache->bstrength, *nodes[i], tls);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(depsgraph, sd, object, brush, plane, ss.cache->bstrength, nodes[i], tls);
});
});
break;
}
}
}

View File

@@ -54,7 +54,7 @@ static void calc_faces(const Depsgraph &depsgraph,
const Brush &brush,
const float3 &offset,
const Span<float3> positions_eval,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
Object &object,
LocalData &tls,
const MutableSpan<float3> positions_orig)
@@ -102,7 +102,7 @@ static void calc_grids(const Depsgraph &depsgraph,
Object &object,
const Brush &brush,
const float3 &offset,
bke::pbvh::Node &node,
bke::pbvh::GridsNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -151,7 +151,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
Object &object,
const Brush &brush,
const float3 &offset,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -199,7 +199,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
void do_grab_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
const SculptSession &ss = *object.sculpt;
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
@@ -218,39 +218,44 @@ void do_grab_brush(const Depsgraph &depsgraph,
Mesh &mesh = *static_cast<Mesh *>(object.data);
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object);
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_faces(depsgraph,
sd,
brush,
grab_delta,
positions_eval,
*nodes[i],
nodes[i],
object,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_grids(depsgraph, sd, object, brush, grab_delta, *nodes[i], tls);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_grids(depsgraph, sd, object, brush, grab_delta, nodes[i], tls);
});
});
break;
case bke::pbvh::Type::BMesh:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_bmesh(depsgraph, sd, object, brush, grab_delta, *nodes[i], tls);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(depsgraph, sd, object, brush, grab_delta, nodes[i], tls);
});
});
break;
}
}
}

View File

@@ -49,7 +49,7 @@ static void calc_faces(const Depsgraph &depsgraph,
const float3 &scale,
const Span<float3> positions_eval,
const Span<float3> vert_normals,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
Object &object,
LocalData &tls,
const MutableSpan<float3> positions_orig)
@@ -92,7 +92,7 @@ static void calc_grids(const Depsgraph &depsgraph,
Object &object,
const Brush &brush,
const float3 &scale,
bke::pbvh::Node &node,
bke::pbvh::GridsNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -136,7 +136,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
Object &object,
const Brush &brush,
const float3 &scale,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -179,7 +179,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
void do_inflate_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
const SculptSession &ss = *object.sculpt;
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
@@ -193,40 +193,43 @@ void do_inflate_brush(const Depsgraph &depsgraph,
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object);
const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_faces(depsgraph,
sd,
brush,
scale,
positions_eval,
vert_normals,
*nodes[i],
nodes[i],
object,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_grids(depsgraph, sd, object, brush, scale, *nodes[i], tls);
}
node_mask.slice(range).foreach_index(
[&](const int i) { calc_grids(depsgraph, sd, object, brush, scale, nodes[i], tls); });
});
break;
case bke::pbvh::Type::BMesh:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_bmesh(depsgraph, sd, object, brush, scale, *nodes[i], tls);
}
node_mask.slice(range).foreach_index(
[&](const int i) { calc_bmesh(depsgraph, sd, object, brush, scale, nodes[i], tls); });
});
break;
}
}
}

View File

@@ -124,7 +124,7 @@ static void calc_faces(const Depsgraph &depsgraph,
const Span<float3> persistent_base_positions,
const Span<float3> persistent_base_normals,
Object &object,
bke::pbvh::Node &node,
bke::pbvh::MeshNode &node,
LocalData &tls,
MutableSpan<float> layer_displacement_factor,
MutableSpan<float3> positions_orig)
@@ -218,7 +218,7 @@ static void calc_grids(const Depsgraph &depsgraph,
const Sculpt &sd,
const Brush &brush,
Object &object,
bke::pbvh::Node &node,
bke::pbvh::GridsNode &node,
LocalData &tls,
MutableSpan<float> layer_displacement_factor)
{
@@ -284,7 +284,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
const Sculpt &sd,
const Brush &brush,
Object &object,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
LocalData &tls,
MutableSpan<float> layer_displacement_factor)
{
@@ -349,7 +349,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
void do_layer_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
SculptSession &ss = *object.sculpt;
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
@@ -391,9 +391,10 @@ void do_layer_brush(const Depsgraph &depsgraph,
displacement = ss.cache->layer_displacement_factor;
}
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_faces(depsgraph,
sd,
brush,
@@ -404,11 +405,11 @@ void do_layer_brush(const Depsgraph &depsgraph,
persistent_position,
persistent_normal,
object,
*nodes[i],
nodes[i],
tls,
displacement,
positions_orig);
}
});
});
persistent_disp_attr.finish();
break;
@@ -418,11 +419,12 @@ void do_layer_brush(const Depsgraph &depsgraph,
ss.cache->layer_displacement_factor = Array<float>(SCULPT_vertex_count_get(object), 0.0f);
}
const MutableSpan<float> displacement = ss.cache->layer_displacement_factor;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_grids(depsgraph, sd, brush, object, *nodes[i], tls, displacement);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_grids(depsgraph, sd, brush, object, nodes[i], tls, displacement);
});
});
break;
}
@@ -431,11 +433,12 @@ void do_layer_brush(const Depsgraph &depsgraph,
ss.cache->layer_displacement_factor = Array<float>(SCULPT_vertex_count_get(object), 0.0f);
}
const MutableSpan<float> displacement = ss.cache->layer_displacement_factor;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_bmesh(depsgraph, sd, brush, object, *nodes[i], tls, displacement);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(depsgraph, sd, brush, object, nodes[i], tls, displacement);
});
});
break;
}

View File

@@ -65,7 +65,7 @@ static void calc_faces(const Depsgraph &depsgraph,
const float strength,
const Span<float3> positions,
const Span<float3> vert_normals,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
Object &object,
Mesh &mesh,
LocalData &tls,
@@ -114,7 +114,7 @@ static void calc_grids(const Depsgraph &depsgraph,
Object &object,
const Brush &brush,
const float strength,
bke::pbvh::Node &node,
bke::pbvh::GridsNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -162,7 +162,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
Object &object,
const Brush &brush,
const float strength,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -211,7 +211,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
void do_mask_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
SculptSession &ss = *object.sculpt;
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
@@ -220,6 +220,7 @@ void do_mask_brush(const Depsgraph &depsgraph,
threading::EnumerableThreadSpecific<LocalData> all_tls;
switch (ss.pbvh->type()) {
case blender::bke::pbvh::Type::Mesh: {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
Mesh &mesh = *static_cast<Mesh *>(object.data);
const Span<float3> positions = bke::pbvh::vert_positions_eval(depsgraph, object);
const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
@@ -229,39 +230,39 @@ void do_mask_brush(const Depsgraph &depsgraph,
bke::SpanAttributeWriter<float> mask = attributes.lookup_or_add_for_write_span<float>(
".sculpt_mask", bke::AttrDomain::Point);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_faces(depsgraph,
brush,
bstrength,
positions,
vert_normals,
*nodes[i],
nodes[i],
object,
mesh,
tls,
mask.span);
}
});
});
mask.finish();
break;
}
case blender::bke::pbvh::Type::Grids: {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_grids(depsgraph, object, brush, bstrength, *nodes[i], tls);
}
node_mask.slice(range).foreach_index(
[&](const int i) { calc_grids(depsgraph, object, brush, bstrength, nodes[i], tls); });
});
break;
}
case blender::bke::pbvh::Type::BMesh: {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_bmesh(depsgraph, object, brush, bstrength, *nodes[i], tls);
}
node_mask.slice(range).foreach_index(
[&](const int i) { calc_bmesh(depsgraph, object, brush, bstrength, nodes[i], tls); });
});
break;
}

View File

@@ -131,7 +131,7 @@ static void sample_node_surface_mesh(const Depsgraph &depsgraph,
const float4x4 &mat,
const Span<float3> vert_positions,
const Span<float3> vert_normals,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
ScrapeSampleData &sample,
LocalData &tls)
{
@@ -174,7 +174,7 @@ static void sample_node_surface_grids(const Depsgraph &depsgraph,
const Object &object,
const Brush &brush,
const float4x4 &mat,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
ScrapeSampleData &sample,
LocalData &tls)
{
@@ -219,14 +219,15 @@ static void sample_node_surface_bmesh(const Depsgraph &depsgraph,
const Object &object,
const Brush &brush,
const float4x4 &mat,
bke::pbvh::Node &node,
const bke::pbvh::BMeshNode &node,
ScrapeSampleData &sample,
LocalData &tls)
{
const SculptSession &ss = *object.sculpt;
const StrokeCache &cache = *ss.cache;
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&node);
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(
const_cast<bke::pbvh::BMeshNode *>(&node));
const MutableSpan positions = gather_bmesh_positions(verts, tls.positions);
@@ -264,62 +265,65 @@ static ScrapeSampleData sample_surface(const Depsgraph &depsgraph,
const Object &object,
const Brush &brush,
const float4x4 &mat,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
const SculptSession &ss = *object.sculpt;
const bke::pbvh::Tree &pbvh = *ss.pbvh;
threading::EnumerableThreadSpecific<LocalData> all_tls;
switch (pbvh.type()) {
case bke::pbvh::Type::Mesh: {
const Span<bke::pbvh::MeshNode> nodes = pbvh.nodes<bke::pbvh::MeshNode>();
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object);
const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
return threading::parallel_reduce(
nodes.index_range(),
node_mask.index_range(),
1,
ScrapeSampleData{},
[&](const IndexRange range, ScrapeSampleData sample) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
sample_node_surface_mesh(depsgraph,
object,
brush,
mat,
positions_eval,
vert_normals,
*nodes[i],
nodes[i],
sample,
tls);
}
});
return sample;
},
join_samples);
break;
}
case bke::pbvh::Type::Grids: {
const Span<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
return threading::parallel_reduce(
nodes.index_range(),
node_mask.index_range(),
1,
ScrapeSampleData{},
[&](const IndexRange range, ScrapeSampleData sample) {
LocalData &tls = all_tls.local();
for (const int i : range) {
sample_node_surface_grids(depsgraph, object, brush, mat, *nodes[i], sample, tls);
}
node_mask.slice(range).foreach_index([&](const int i) {
sample_node_surface_grids(depsgraph, object, brush, mat, nodes[i], sample, tls);
});
return sample;
},
join_samples);
break;
}
case bke::pbvh::Type::BMesh: {
const Span<bke::pbvh::BMeshNode> nodes = pbvh.nodes<bke::pbvh::BMeshNode>();
return threading::parallel_reduce(
nodes.index_range(),
node_mask.index_range(),
1,
ScrapeSampleData{},
[&](const IndexRange range, ScrapeSampleData sample) {
LocalData &tls = all_tls.local();
for (const int i : range) {
sample_node_surface_bmesh(depsgraph, object, brush, mat, *nodes[i], sample, tls);
}
node_mask.slice(range).foreach_index([&](const int i) {
sample_node_surface_bmesh(depsgraph, object, brush, mat, nodes[i], sample, tls);
});
return sample;
},
join_samples);
@@ -339,7 +343,7 @@ static void calc_faces(const Depsgraph &depsgraph,
const float strength,
const Span<float3> positions_eval,
const Span<float3> vert_normals,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
Object &object,
LocalData &tls,
const MutableSpan<float3> positions_orig)
@@ -398,7 +402,7 @@ static void calc_grids(const Depsgraph &depsgraph,
const std::array<float4, 2> &scrape_planes,
const float angle,
const float strength,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
Object &object,
LocalData &tls)
{
@@ -457,7 +461,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
const std::array<float4, 2> &scrape_planes,
const float angle,
const float strength,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
Object &object,
LocalData &tls)
{
@@ -511,7 +515,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
void do_multiplane_scrape_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
SculptSession &ss = *object.sculpt;
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
@@ -523,11 +527,11 @@ void do_multiplane_scrape_brush(const Depsgraph &depsgraph,
float3 area_no_sp;
float3 area_co;
calc_brush_plane(depsgraph, brush, object, nodes, area_no_sp, area_co);
calc_brush_plane(depsgraph, brush, object, node_mask, area_no_sp, area_co);
float3 area_no;
if (brush.sculpt_plane != SCULPT_DISP_DIR_AREA || (brush.flag & BRUSH_ORIGINAL_NORMAL)) {
area_no = calc_area_normal(depsgraph, brush, object, nodes).value_or(float3(0));
area_no = calc_area_normal(depsgraph, brush, object, node_mask).value_or(float3(0));
}
else {
area_no = area_no_sp;
@@ -564,7 +568,7 @@ void do_multiplane_scrape_brush(const Depsgraph &depsgraph,
if (brush.flag2 & BRUSH_MULTIPLANE_SCRAPE_DYNAMIC) {
/* Sample the individual normal and area center of the areas at both sides of the cursor. */
const ScrapeSampleData sample = sample_surface(depsgraph, object, brush, mat, nodes);
const ScrapeSampleData sample = sample_surface(depsgraph, object, brush, mat, node_mask);
/* Use the plane centers to check if we are sculpting along a concave or convex edge. */
const std::array<float3, 2> sampled_plane_co{
@@ -637,6 +641,7 @@ void do_multiplane_scrape_brush(const Depsgraph &depsgraph,
threading::EnumerableThreadSpecific<LocalData> all_tls;
switch (object.sculpt->pbvh->type()) {
case bke::pbvh::Type::Mesh: {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
Mesh &mesh = *static_cast<Mesh *>(object.data);
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object);
const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
@@ -653,19 +658,20 @@ void do_multiplane_scrape_brush(const Depsgraph &depsgraph,
strength,
positions_eval,
vert_normals,
*nodes[i],
nodes[i],
object,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
BKE_pbvh_node_mark_positions_update(nodes[i]);
}
});
break;
}
case bke::pbvh::Type::Grids:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_grids(depsgraph,
sd,
brush,
@@ -673,16 +679,18 @@ void do_multiplane_scrape_brush(const Depsgraph &depsgraph,
multiplane_scrape_planes,
ss.cache->multiplane_scrape_angle,
strength,
*nodes[i],
nodes[i],
object,
tls);
}
});
});
break;
case bke::pbvh::Type::BMesh:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(depsgraph,
sd,
brush,
@@ -690,12 +698,13 @@ void do_multiplane_scrape_brush(const Depsgraph &depsgraph,
multiplane_scrape_planes,
ss.cache->multiplane_scrape_angle,
strength,
*nodes[i],
nodes[i],
object,
tls);
}
});
});
break;
}
}
}

View File

@@ -50,7 +50,7 @@ static void calc_node(const Depsgraph &depsgraph,
Object &object,
const Brush &brush,
const float strength,
bke::pbvh::Node &node,
bke::pbvh::GridsNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -97,18 +97,18 @@ static void calc_node(const Depsgraph &depsgraph,
void do_displacement_eraser_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
SculptSession &ss = *object.sculpt;
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
const float strength = std::min(ss.cache->bstrength, 1.0f);
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_node(depsgraph, sd, object, brush, strength, *nodes[i], tls);
}
node_mask.slice(range).foreach_index(
[&](const int i) { calc_node(depsgraph, sd, object, brush, strength, nodes[i], tls); });
});
}

View File

@@ -37,7 +37,7 @@ static void calc_node(const Depsgraph &depsgraph,
Object &object,
const Brush &brush,
const float strength,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -157,7 +157,7 @@ BLI_NOINLINE static void eval_all_limit_positions(const SubdivCCG &subdiv_ccg,
BLI_NOINLINE static void store_node_prev_displacement(const Span<float3> limit_positions,
const Span<CCGElem *> elems,
const CCGKey &key,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
const MutableSpan<float3> prev_displacement)
{
for (const int grid : bke::pbvh::node_grid_indices(node)) {
@@ -174,10 +174,12 @@ BLI_NOINLINE static void store_node_prev_displacement(const Span<float3> limit_p
void do_displacement_smear_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &ob,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
SculptSession &ss = *ob.sculpt;
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
const Span<CCGElem *> elems = subdiv_ccg.grids;
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
@@ -189,24 +191,23 @@ void do_displacement_smear_brush(const Depsgraph &depsgraph,
eval_all_limit_positions(subdiv_ccg, ss.cache->displacement_smear.limit_surface_co);
}
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (const int i : range) {
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,
key,
*nodes[i],
nodes[i],
ss.cache->displacement_smear.prev_displacement);
}
});
});
const float strength = std::clamp(ss.cache->bstrength, 0.0f, 1.0f);
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_node(depsgraph, ob, brush, strength, *nodes[i], tls);
}
node_mask.slice(range).foreach_index(
[&](const int i) { calc_node(depsgraph, ob, brush, strength, nodes[i], tls); });
});
}

View File

@@ -67,7 +67,7 @@ static void calc_faces(const Depsgraph &depsgraph,
const float strength,
const Span<float3> positions_eval,
const Span<float3> vert_normals,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
Object &object,
LocalData &tls,
const MutableSpan<float3> positions_orig)
@@ -118,7 +118,7 @@ static void calc_grids(const Depsgraph &depsgraph,
const Brush &brush,
const std::array<float3, 2> &stroke_xz,
const float strength,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -168,7 +168,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
const Brush &brush,
const std::array<float3, 2> &stroke_xz,
const float strength,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -217,14 +217,14 @@ static void calc_bmesh(const Depsgraph &depsgraph,
void do_pinch_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
const SculptSession &ss = *object.sculpt;
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
float3 area_no;
float3 area_co;
calc_brush_plane(depsgraph, brush, object, nodes, area_no, area_co);
calc_brush_plane(depsgraph, brush, object, node_mask, area_no, area_co);
/* delay the first daub because grab delta is not setup */
if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(*ss.cache)) {
@@ -253,9 +253,10 @@ void do_pinch_brush(const Depsgraph &depsgraph,
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object);
const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_faces(depsgraph,
sd,
brush,
@@ -263,31 +264,35 @@ void do_pinch_brush(const Depsgraph &depsgraph,
ss.cache->bstrength,
positions_eval,
vert_normals,
*nodes[i],
nodes[i],
object,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_grids(depsgraph, sd, object, brush, stroke_xz, ss.cache->bstrength, *nodes[i], tls);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_grids(depsgraph, sd, object, brush, stroke_xz, ss.cache->bstrength, nodes[i], tls);
});
});
break;
case bke::pbvh::Type::BMesh:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_bmesh(depsgraph, sd, object, brush, stroke_xz, ss.cache->bstrength, *nodes[i], tls);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(depsgraph, sd, object, brush, stroke_xz, ss.cache->bstrength, nodes[i], tls);
});
});
break;
}
}
}

View File

@@ -106,7 +106,7 @@ BLI_NOINLINE static void calc_factors_faces(const Depsgraph &depsgraph,
const float strength,
const bool relax_face_sets,
const Object &object,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
MeshLocalData &tls,
const MutableSpan<float> factors)
{
@@ -144,11 +144,12 @@ static void do_relax_face_sets_brush_mesh(const Depsgraph &depsgraph,
const Sculpt &sd,
const Brush &brush,
Object &object,
const Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
const float strength,
const bool relax_face_sets)
{
const SculptSession &ss = *object.sculpt;
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
Mesh &mesh = *static_cast<Mesh *>(object.data);
const OffsetIndices faces = mesh.faces();
const Span<int> corner_verts = mesh.corner_verts();
@@ -160,15 +161,16 @@ static void do_relax_face_sets_brush_mesh(const Depsgraph &depsgraph,
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
Array<int> node_offset_data;
const OffsetIndices<int> node_vert_offsets = create_node_vert_offsets(nodes, node_offset_data);
const OffsetIndices<int> node_vert_offsets = create_node_vert_offsets(
nodes, node_mask, node_offset_data);
Array<float3> translations(node_vert_offsets.total_size());
Array<float> factors(node_vert_offsets.total_size());
threading::EnumerableThreadSpecific<MeshLocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
MeshLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_factors_faces(depsgraph,
brush,
positions_eval,
@@ -176,15 +178,15 @@ static void do_relax_face_sets_brush_mesh(const Depsgraph &depsgraph,
strength,
relax_face_sets,
object,
*nodes[i],
nodes[i],
tls,
factors.as_mutable_span().slice(node_vert_offsets[i]));
}
});
});
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
MeshLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
smooth::calc_relaxed_translations_faces(
positions_eval,
vert_normals,
@@ -195,23 +197,21 @@ static void do_relax_face_sets_brush_mesh(const Depsgraph &depsgraph,
ss.face_sets,
hide_poly,
relax_face_sets,
bke::pbvh::node_unique_verts(*nodes[i]),
bke::pbvh::node_unique_verts(nodes[i]),
factors.as_span().slice(node_vert_offsets[i]),
tls.vert_neighbors,
translations.as_mutable_span().slice(node_vert_offsets[i]));
}
});
});
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (const int i : range) {
apply_positions_faces(depsgraph,
sd,
positions_eval,
bke::pbvh::node_unique_verts(*nodes[i]),
object,
translations.as_mutable_span().slice(node_vert_offsets[i]),
positions_orig);
}
node_mask.foreach_index(GrainSize(1), [&](const int i) {
apply_positions_faces(depsgraph,
sd,
positions_eval,
bke::pbvh::node_unique_verts(nodes[i]),
object,
translations.as_mutable_span().slice(node_vert_offsets[i]),
positions_orig);
});
}
@@ -219,7 +219,7 @@ BLI_NOINLINE static void calc_factors_grids(const Depsgraph &depsgraph,
const Brush &brush,
const Span<int> corner_verts,
const OffsetIndices<int> faces,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
const float strength,
const bool relax_face_sets,
Object &object,
@@ -270,11 +270,12 @@ static void do_relax_face_sets_brush_grids(const Depsgraph &depsgraph,
const Sculpt &sd,
const Brush &brush,
Object &object,
const Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
const float strength,
const bool relax_face_sets)
{
const SculptSession &ss = *object.sculpt;
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
@@ -286,33 +287,33 @@ static void do_relax_face_sets_brush_grids(const Depsgraph &depsgraph,
Array<int> node_offset_data;
const OffsetIndices<int> node_vert_offsets = create_node_vert_offsets(
nodes, key, node_offset_data);
key, nodes, node_mask, node_offset_data);
Array<float3> current_positions(node_vert_offsets.total_size());
Array<float3> translations(node_vert_offsets.total_size());
Array<float> factors(node_vert_offsets.total_size());
threading::EnumerableThreadSpecific<GridLocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
GridLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_factors_grids(depsgraph,
brush,
corner_verts,
faces,
*nodes[i],
nodes[i],
strength,
relax_face_sets,
object,
tls,
current_positions.as_mutable_span().slice(node_vert_offsets[i]),
factors.as_mutable_span().slice(node_vert_offsets[i]));
}
});
});
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
GridLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
smooth::calc_relaxed_translations_grids(
subdiv_ccg,
faces,
@@ -320,30 +321,28 @@ static void do_relax_face_sets_brush_grids(const Depsgraph &depsgraph,
ss.face_sets,
ss.vert_to_face_map,
ss.vertex_info.boundary,
bke::pbvh::node_grid_indices(*nodes[i]),
bke::pbvh::node_grid_indices(nodes[i]),
relax_face_sets,
factors.as_span().slice(node_vert_offsets[i]),
current_positions.as_span().slice(node_vert_offsets[i]),
tls.vert_neighbors,
translations.as_mutable_span().slice(node_vert_offsets[i]));
}
});
});
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (const int i : range) {
apply_positions_grids(sd,
bke::pbvh::node_grid_indices(*nodes[i]),
object,
current_positions.as_mutable_span().slice(node_vert_offsets[i]),
translations.as_mutable_span().slice(node_vert_offsets[i]));
}
node_mask.foreach_index(GrainSize(1), [&](const int i) {
apply_positions_grids(sd,
bke::pbvh::node_grid_indices(nodes[i]),
object,
current_positions.as_mutable_span().slice(node_vert_offsets[i]),
translations.as_mutable_span().slice(node_vert_offsets[i]));
});
}
static void calc_factors_bmesh(const Depsgraph &depsgraph,
Object &object,
const Brush &brush,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
const float strength,
const bool relax_face_sets,
BMeshLocalData &tls,
@@ -382,55 +381,55 @@ static void do_relax_face_sets_brush_bmesh(const Depsgraph &depsgraph,
const Sculpt &sd,
const Brush &brush,
Object &object,
const Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
const float strength,
const bool relax_face_sets)
{
SculptSession &ss = *object.sculpt;
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
Array<int> node_offset_data;
const OffsetIndices<int> node_vert_offsets = create_node_vert_offsets_bmesh(nodes,
node_offset_data);
const OffsetIndices<int> node_vert_offsets = create_node_vert_offsets_bmesh(
nodes, node_mask, node_offset_data);
Array<float3> current_positions(node_vert_offsets.total_size());
Array<float3> translations(node_vert_offsets.total_size());
Array<float> factors(node_vert_offsets.total_size());
threading::EnumerableThreadSpecific<BMeshLocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
BMeshLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_factors_bmesh(depsgraph,
object,
brush,
*nodes[i],
nodes[i],
strength,
relax_face_sets,
tls,
current_positions.as_mutable_span().slice(node_vert_offsets[i]),
factors.as_mutable_span().slice(node_vert_offsets[i]));
}
});
});
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
BMeshLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
smooth::calc_relaxed_translations_bmesh(
BKE_pbvh_bmesh_node_unique_verts(nodes[i]),
BKE_pbvh_bmesh_node_unique_verts(&nodes[i]),
current_positions.as_mutable_span().slice(node_vert_offsets[i]),
relax_face_sets,
factors.as_span().slice(node_vert_offsets[i]),
tls.vert_neighbors,
translations.as_mutable_span().slice(node_vert_offsets[i]));
}
});
});
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (const int i : range) {
apply_positions_bmesh(sd,
BKE_pbvh_bmesh_node_unique_verts(nodes[i]),
object,
translations.as_mutable_span().slice(node_vert_offsets[i]),
current_positions.as_span().slice(node_vert_offsets[i]));
}
node_mask.foreach_index(GrainSize(1), [&](const int i) {
apply_positions_bmesh(sd,
BKE_pbvh_bmesh_node_unique_verts(&nodes[i]),
object,
translations.as_mutable_span().slice(node_vert_offsets[i]),
current_positions.as_span().slice(node_vert_offsets[i]));
});
}
@@ -443,7 +442,7 @@ BLI_NOINLINE static void calc_topology_relax_factors_faces(const Depsgraph &deps
const Brush &brush,
const float strength,
const Object &object,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
MeshLocalData &tls,
const MutableSpan<float> factors)
{
@@ -479,10 +478,11 @@ static void do_topology_relax_brush_mesh(const Depsgraph &depsgraph,
const Sculpt &sd,
const Brush &brush,
Object &object,
const Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
const float strength)
{
const SculptSession &ss = *object.sculpt;
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
Mesh &mesh = *static_cast<Mesh *>(object.data);
const OffsetIndices faces = mesh.faces();
const Span<int> corner_verts = mesh.corner_verts();
@@ -494,28 +494,29 @@ static void do_topology_relax_brush_mesh(const Depsgraph &depsgraph,
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
Array<int> node_offset_data;
const OffsetIndices<int> node_vert_offsets = create_node_vert_offsets(nodes, node_offset_data);
const OffsetIndices<int> node_vert_offsets = create_node_vert_offsets(
nodes, node_mask, node_offset_data);
Array<float3> translations(node_vert_offsets.total_size());
Array<float> factors(node_vert_offsets.total_size());
threading::EnumerableThreadSpecific<MeshLocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
MeshLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_topology_relax_factors_faces(depsgraph,
brush,
strength,
object,
*nodes[i],
nodes[i],
tls,
factors.as_mutable_span().slice(node_vert_offsets[i]));
}
});
});
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
MeshLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
smooth::calc_relaxed_translations_faces(
positions_eval,
vert_normals,
@@ -526,23 +527,21 @@ static void do_topology_relax_brush_mesh(const Depsgraph &depsgraph,
ss.face_sets,
hide_poly,
false,
bke::pbvh::node_unique_verts(*nodes[i]),
bke::pbvh::node_unique_verts(nodes[i]),
factors.as_span().slice(node_vert_offsets[i]),
tls.vert_neighbors,
translations.as_mutable_span().slice(node_vert_offsets[i]));
}
});
});
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (const int i : range) {
apply_positions_faces(depsgraph,
sd,
positions_eval,
bke::pbvh::node_unique_verts(*nodes[i]),
object,
translations.as_mutable_span().slice(node_vert_offsets[i]),
positions_orig);
}
node_mask.foreach_index(GrainSize(1), [&](const int i) {
apply_positions_faces(depsgraph,
sd,
positions_eval,
bke::pbvh::node_unique_verts(nodes[i]),
object,
translations.as_mutable_span().slice(node_vert_offsets[i]),
positions_orig);
});
}
@@ -550,7 +549,7 @@ BLI_NOINLINE static void calc_topology_relax_factors_grids(const Depsgraph &deps
const Brush &brush,
const float strength,
const Object &object,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
GridLocalData &tls,
const MutableSpan<float3> positions,
const MutableSpan<float> factors)
@@ -591,10 +590,11 @@ static void do_topology_relax_brush_grids(const Depsgraph &depsgraph,
const Sculpt &sd,
const Brush &brush,
Object &object,
const Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
const float strength)
{
const SculptSession &ss = *object.sculpt;
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
@@ -606,31 +606,31 @@ static void do_topology_relax_brush_grids(const Depsgraph &depsgraph,
Array<int> node_offset_data;
const OffsetIndices<int> node_vert_offsets = create_node_vert_offsets(
nodes, key, node_offset_data);
key, nodes, node_mask, node_offset_data);
Array<float3> current_positions(node_vert_offsets.total_size());
Array<float3> translations(node_vert_offsets.total_size());
Array<float> factors(node_vert_offsets.total_size());
threading::EnumerableThreadSpecific<GridLocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
GridLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_topology_relax_factors_grids(
depsgraph,
brush,
strength,
object,
*nodes[i],
nodes[i],
tls,
current_positions.as_mutable_span().slice(node_vert_offsets[i]),
factors.as_mutable_span().slice(node_vert_offsets[i]));
}
});
});
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
GridLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
smooth::calc_relaxed_translations_grids(
subdiv_ccg,
faces,
@@ -638,30 +638,28 @@ static void do_topology_relax_brush_grids(const Depsgraph &depsgraph,
ss.face_sets,
ss.vert_to_face_map,
ss.vertex_info.boundary,
bke::pbvh::node_grid_indices(*nodes[i]),
bke::pbvh::node_grid_indices(nodes[i]),
false,
factors.as_span().slice(node_vert_offsets[i]),
current_positions.as_span().slice(node_vert_offsets[i]),
tls.vert_neighbors,
translations.as_mutable_span().slice(node_vert_offsets[i]));
}
});
});
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (const int i : range) {
apply_positions_grids(sd,
bke::pbvh::node_grid_indices(*nodes[i]),
object,
current_positions.as_mutable_span().slice(node_vert_offsets[i]),
translations.as_mutable_span().slice(node_vert_offsets[i]));
}
node_mask.foreach_index(GrainSize(1), [&](const int i) {
apply_positions_grids(sd,
bke::pbvh::node_grid_indices(nodes[i]),
object,
current_positions.as_mutable_span().slice(node_vert_offsets[i]),
translations.as_mutable_span().slice(node_vert_offsets[i]));
});
}
static void calc_topology_relax_factors_bmesh(const Depsgraph &depsgraph,
Object &object,
const Brush &brush,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
const float strength,
BMeshLocalData &tls,
MutableSpan<float3> positions,
@@ -702,54 +700,55 @@ static void do_topology_relax_brush_bmesh(const Depsgraph &depsgraph,
const Sculpt &sd,
const Brush &brush,
Object &object,
const Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
const float strength)
{
const SculptSession &ss = *object.sculpt;
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
Array<int> node_offset_data;
const OffsetIndices<int> node_vert_offsets = create_node_vert_offsets_bmesh(nodes,
node_offset_data);
const OffsetIndices<int> node_vert_offsets = create_node_vert_offsets_bmesh(
nodes, node_mask, node_offset_data);
Array<float3> current_positions(node_vert_offsets.total_size());
Array<float3> translations(node_vert_offsets.total_size());
Array<float> factors(node_vert_offsets.total_size());
threading::EnumerableThreadSpecific<BMeshLocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
BMeshLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_topology_relax_factors_bmesh(
depsgraph,
object,
brush,
*nodes[i],
nodes[i],
strength,
tls,
current_positions.as_mutable_span().slice(node_vert_offsets[i]),
factors.as_mutable_span().slice(node_vert_offsets[i]));
}
});
});
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
BMeshLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
smooth::calc_relaxed_translations_bmesh(
BKE_pbvh_bmesh_node_unique_verts(nodes[i]),
BKE_pbvh_bmesh_node_unique_verts(&nodes[i]),
current_positions.as_mutable_span().slice(node_vert_offsets[i]),
false,
factors.as_span().slice(node_vert_offsets[i]),
tls.vert_neighbors,
translations.as_mutable_span().slice(node_vert_offsets[i]));
}
});
});
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (const int i : range) {
apply_positions_bmesh(sd,
BKE_pbvh_bmesh_node_unique_verts(nodes[i]),
object,
translations.as_mutable_span().slice(node_vert_offsets[i]),
current_positions.as_span().slice(node_vert_offsets[i]));
}
node_mask.foreach_index(GrainSize(1), [&](const int i) {
apply_positions_bmesh(sd,
BKE_pbvh_bmesh_node_unique_verts(&nodes[i]),
object,
translations.as_mutable_span().slice(node_vert_offsets[i]),
current_positions.as_span().slice(node_vert_offsets[i]));
});
}
/** \} */
@@ -759,7 +758,7 @@ static void do_topology_relax_brush_bmesh(const Depsgraph &depsgraph,
void do_relax_face_sets_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
@@ -776,15 +775,15 @@ void do_relax_face_sets_brush(const Depsgraph &depsgraph,
switch (ss.pbvh->type()) {
case bke::pbvh::Type::Mesh:
do_relax_face_sets_brush_mesh(
depsgraph, sd, brush, object, nodes, strength * strength, relax_face_sets);
depsgraph, sd, brush, object, node_mask, strength * strength, relax_face_sets);
break;
case bke::pbvh::Type::Grids:
do_relax_face_sets_brush_grids(
depsgraph, sd, brush, object, nodes, strength * strength, relax_face_sets);
depsgraph, sd, brush, object, node_mask, strength * strength, relax_face_sets);
break;
case bke::pbvh::Type::BMesh:
do_relax_face_sets_brush_bmesh(
depsgraph, sd, brush, object, nodes, strength * strength, relax_face_sets);
depsgraph, sd, brush, object, node_mask, strength * strength, relax_face_sets);
break;
}
}
@@ -793,7 +792,7 @@ void do_relax_face_sets_brush(const Depsgraph &depsgraph,
void do_topology_relax_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
const SculptSession &ss = *object.sculpt;
@@ -809,13 +808,13 @@ void do_topology_relax_brush(const Depsgraph &depsgraph,
for (int i = 0; i < 4; i++) {
switch (ss.pbvh->type()) {
case bke::pbvh::Type::Mesh:
do_topology_relax_brush_mesh(depsgraph, sd, brush, object, nodes, strength);
do_topology_relax_brush_mesh(depsgraph, sd, brush, object, node_mask, strength);
break;
case bke::pbvh::Type::Grids:
do_topology_relax_brush_grids(depsgraph, sd, brush, object, nodes, strength);
do_topology_relax_brush_grids(depsgraph, sd, brush, object, node_mask, strength);
break;
case bke::pbvh::Type::BMesh:
do_topology_relax_brush_bmesh(depsgraph, sd, brush, object, nodes, strength);
do_topology_relax_brush_bmesh(depsgraph, sd, brush, object, node_mask, strength);
break;
}
}

View File

@@ -58,7 +58,7 @@ static void calc_faces(const Depsgraph &depsgraph,
const Brush &brush,
const float angle,
const Span<float3> positions_eval,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
Object &object,
LocalData &tls,
const MutableSpan<float3> positions_orig)
@@ -105,7 +105,7 @@ static void calc_grids(const Depsgraph &depsgraph,
Object &object,
const Brush &brush,
const float angle,
bke::pbvh::Node &node,
bke::pbvh::GridsNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -154,7 +154,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
Object &object,
const Brush &brush,
const float angle,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -201,7 +201,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
void do_rotate_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
const SculptSession &ss = *object.sculpt;
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
@@ -215,32 +215,35 @@ void do_rotate_brush(const Depsgraph &depsgraph,
Mesh &mesh = *static_cast<Mesh *>(object.data);
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object);
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_faces(
depsgraph, sd, brush, angle, positions_eval, *nodes[i], object, tls, positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
depsgraph, sd, brush, angle, positions_eval, nodes[i], object, tls, positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_grids(depsgraph, sd, object, brush, angle, *nodes[i], tls);
}
node_mask.slice(range).foreach_index(
[&](const int i) { calc_grids(depsgraph, sd, object, brush, angle, nodes[i], tls); });
});
break;
case bke::pbvh::Type::BMesh:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_bmesh(depsgraph, sd, object, brush, angle, *nodes[i], tls);
}
node_mask.slice(range).foreach_index(
[&](const int i) { calc_bmesh(depsgraph, sd, object, brush, angle, nodes[i], tls); });
});
break;
}
}
}

View File

@@ -44,7 +44,7 @@ static void calc_faces(const Depsgraph &depsgraph,
const float strength,
const Span<float3> positions_eval,
const Span<float3> vert_normals,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
Object &object,
LocalData &tls,
const MutableSpan<float3> positions_orig)
@@ -94,7 +94,7 @@ static void calc_grids(const Depsgraph &depsgraph,
const Brush &brush,
const float4 &plane,
const float strength,
bke::pbvh::Node &node,
bke::pbvh::GridsNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -143,7 +143,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
const Brush &brush,
const float4 &plane,
const float strength,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -191,14 +191,14 @@ static void calc_bmesh(const Depsgraph &depsgraph,
void do_scrape_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
const SculptSession &ss = *object.sculpt;
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
float3 area_no;
float3 area_co;
calc_brush_plane(depsgraph, brush, object, nodes, area_no, area_co);
calc_brush_plane(depsgraph, brush, object, node_mask, area_no, area_co);
SCULPT_tilt_apply_to_normal(area_no, ss.cache, brush.tilt_strength_factor);
const float offset = SCULPT_brush_plane_offset_get(sd, ss);
@@ -215,9 +215,10 @@ void do_scrape_brush(const Depsgraph &depsgraph,
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object);
const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_faces(depsgraph,
sd,
brush,
@@ -225,31 +226,35 @@ void do_scrape_brush(const Depsgraph &depsgraph,
ss.cache->bstrength,
positions_eval,
vert_normals,
*nodes[i],
nodes[i],
object,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_grids(depsgraph, sd, object, brush, plane, ss.cache->bstrength, *nodes[i], tls);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_grids(depsgraph, sd, object, brush, plane, ss.cache->bstrength, nodes[i], tls);
});
});
break;
case bke::pbvh::Type::BMesh:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_bmesh(depsgraph, sd, object, brush, plane, ss.cache->bstrength, *nodes[i], tls);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(depsgraph, sd, object, brush, plane, ss.cache->bstrength, nodes[i], tls);
});
});
break;
}
}
}

View File

@@ -59,7 +59,7 @@ BLI_NOINLINE static void apply_positions_faces(const Depsgraph &depsgraph,
const Brush &brush,
const Span<float3> positions_eval,
const Span<float3> vert_normals,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
const float strength,
Object &object,
LocalData &tls,
@@ -106,10 +106,11 @@ BLI_NOINLINE static void do_smooth_brush_mesh(const Depsgraph &depsgraph,
const Sculpt &sd,
const Brush &brush,
Object &object,
Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
const float brush_strength)
{
const SculptSession &ss = *object.sculpt;
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
Mesh &mesh = *static_cast<Mesh *>(object.data);
const OffsetIndices faces = mesh.faces();
const Span<int> corner_verts = mesh.corner_verts();
@@ -121,7 +122,8 @@ BLI_NOINLINE static void do_smooth_brush_mesh(const Depsgraph &depsgraph,
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
Array<int> node_offset_data;
const OffsetIndices<int> node_vert_offsets = create_node_vert_offsets(nodes, node_offset_data);
const OffsetIndices<int> node_vert_offsets = create_node_vert_offsets(
nodes, node_mask, node_offset_data);
Array<float3> new_positions(node_vert_offsets.total_size());
threading::EnumerableThreadSpecific<LocalData> all_tls;
@@ -130,10 +132,10 @@ BLI_NOINLINE static void do_smooth_brush_mesh(const Depsgraph &depsgraph,
* are updated in parallel. Without this there would be non-threadsafe access to changing
* positions in other bke::pbvh::Tree nodes. */
for (const float strength : iteration_strengths(brush_strength)) {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> verts = bke::pbvh::node_unique_verts(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
tls.vert_neighbors.resize(verts.size());
calc_vert_neighbors_interior(faces,
corner_verts,
@@ -147,24 +149,24 @@ BLI_NOINLINE static void do_smooth_brush_mesh(const Depsgraph &depsgraph,
verts,
tls.vert_neighbors,
new_positions.as_mutable_span().slice(node_vert_offsets[i]));
}
});
});
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
apply_positions_faces(depsgraph,
sd,
brush,
positions_eval,
vert_normals,
*nodes[i],
nodes[i],
strength,
object,
tls,
new_positions.as_span().slice(node_vert_offsets[i]),
positions_orig);
}
});
});
}
}
@@ -177,7 +179,7 @@ static void calc_grids(const Depsgraph &depsgraph,
Object &object,
const Brush &brush,
const float strength,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -227,7 +229,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
Object &object,
const Brush &brush,
const float strength,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -275,7 +277,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
void do_smooth_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
const Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
const float brush_strength)
{
SculptSession &ss = *object.sculpt;
@@ -285,7 +287,7 @@ void do_smooth_brush(const Depsgraph &depsgraph,
switch (object.sculpt->pbvh->type()) {
case bke::pbvh::Type::Mesh:
do_smooth_brush_mesh(depsgraph, sd, brush, object, nodes, brush_strength);
do_smooth_brush_mesh(depsgraph, sd, brush, object, node_mask, brush_strength);
break;
case bke::pbvh::Type::Grids: {
const Mesh &base_mesh = *static_cast<const Mesh *>(object.data);
@@ -294,9 +296,10 @@ void do_smooth_brush(const Depsgraph &depsgraph,
threading::EnumerableThreadSpecific<LocalData> all_tls;
for (const float strength : iteration_strengths(brush_strength)) {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_grids(depsgraph,
sd,
faces,
@@ -305,9 +308,9 @@ void do_smooth_brush(const Depsgraph &depsgraph,
object,
brush,
strength,
*nodes[i],
nodes[i],
tls);
}
});
});
}
break;
@@ -317,11 +320,12 @@ void do_smooth_brush(const Depsgraph &depsgraph,
BM_mesh_elem_table_ensure(ss.bm, BM_VERT);
threading::EnumerableThreadSpecific<LocalData> all_tls;
for (const float strength : iteration_strengths(brush_strength)) {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_bmesh(depsgraph, sd, object, brush, strength, *nodes[i], tls);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(depsgraph, sd, object, brush, strength, nodes[i], tls);
});
});
}
break;

View File

@@ -70,7 +70,7 @@ static void apply_masks_faces(const Depsgraph &depsgraph,
const Brush &brush,
const Span<float3> positions_eval,
const Span<float3> vert_normals,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
const float strength,
Object &object,
LocalData &tls,
@@ -119,10 +119,11 @@ static void apply_masks_faces(const Depsgraph &depsgraph,
static void do_smooth_brush_mesh(const Depsgraph &depsgraph,
const Brush &brush,
Object &object,
Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
const float brush_strength)
{
const SculptSession &ss = *object.sculpt;
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
Mesh &mesh = *static_cast<Mesh *>(object.data);
const OffsetIndices faces = mesh.faces();
const Span<int> corner_verts = mesh.corner_verts();
@@ -133,7 +134,8 @@ static void do_smooth_brush_mesh(const Depsgraph &depsgraph,
const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
Array<int> node_vert_offset_data;
OffsetIndices node_vert_offsets = create_node_vert_offsets(nodes, node_vert_offset_data);
OffsetIndices node_vert_offsets = create_node_vert_offsets(
nodes, node_mask, node_vert_offset_data);
Array<float> new_masks(node_vert_offsets.total_size());
bke::MutableAttributeAccessor write_attributes = mesh.attributes_for_write();
@@ -145,34 +147,34 @@ static void do_smooth_brush_mesh(const Depsgraph &depsgraph,
for (const float strength : iteration_strengths(brush_strength)) {
/* Calculate new masks into a separate array to avoid non-threadsafe access of values from
* neighboring nodes. */
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_smooth_masks_faces(faces,
corner_verts,
ss.vert_to_face_map,
hide_poly,
bke::pbvh::node_unique_verts(*nodes[i]),
bke::pbvh::node_unique_verts(nodes[i]),
mask.span.as_span(),
tls,
new_masks.as_mutable_span().slice(node_vert_offsets[i]));
}
});
});
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
apply_masks_faces(depsgraph,
brush,
positions_eval,
vert_normals,
*nodes[i],
nodes[i],
strength,
object,
tls,
new_masks.as_span().slice(node_vert_offsets[i]),
mask.span);
}
});
});
}
mask.finish();
@@ -182,7 +184,7 @@ static void calc_grids(const Depsgraph &depsgraph,
Object &object,
const Brush &brush,
const float strength,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -235,7 +237,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
const int mask_offset,
const Brush &brush,
const float strength,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -287,7 +289,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
void do_smooth_mask_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
float brush_strength)
{
SculptSession &ss = *object.sculpt;
@@ -295,17 +297,17 @@ void do_smooth_mask_brush(const Depsgraph &depsgraph,
boundary::ensure_boundary_info(object);
switch (ss.pbvh->type()) {
case bke::pbvh::Type::Mesh: {
do_smooth_brush_mesh(depsgraph, brush, object, nodes, brush_strength);
do_smooth_brush_mesh(depsgraph, brush, object, node_mask, brush_strength);
break;
}
case bke::pbvh::Type::Grids: {
threading::EnumerableThreadSpecific<LocalData> all_tls;
for (const float strength : iteration_strengths(brush_strength)) {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_grids(depsgraph, object, brush, strength, *nodes[i], tls);
}
node_mask.slice(range).foreach_index(
[&](const int i) { calc_grids(depsgraph, object, brush, strength, nodes[i], tls); });
});
}
break;
@@ -317,11 +319,12 @@ void do_smooth_mask_brush(const Depsgraph &depsgraph,
const int mask_offset = CustomData_get_offset_named(
&ss.bm->vdata, CD_PROP_FLOAT, ".sculpt_mask");
for (const float strength : iteration_strengths(brush_strength)) {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_bmesh(depsgraph, object, mask_offset, brush, strength, *nodes[i], tls);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(depsgraph, object, mask_offset, brush, strength, nodes[i], tls);
});
});
}
break;

View File

@@ -163,7 +163,7 @@ static void calc_faces(const Depsgraph &depsgraph,
const float3 &grab_delta,
const Span<float3> positions_eval,
const Span<float3> vert_normals,
bke::pbvh::Node &node,
bke::pbvh::MeshNode &node,
LocalData &tls,
const MutableSpan<float3> positions_orig)
{
@@ -225,7 +225,7 @@ static void calc_grids(const Depsgraph &depsgraph,
const Brush &brush,
SculptProjectVector *spvc,
const float3 &grab_delta,
bke::pbvh::Node &node,
bke::pbvh::GridsNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -289,7 +289,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
const Brush &brush,
SculptProjectVector *spvc,
const float3 &grab_delta,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -349,7 +349,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
void do_snake_hook_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
SculptSession &ss = *object.sculpt;
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
@@ -379,9 +379,10 @@ void do_snake_hook_brush(const Depsgraph &depsgraph,
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object);
const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_faces(depsgraph,
sd,
object,
@@ -390,30 +391,34 @@ void do_snake_hook_brush(const Depsgraph &depsgraph,
grab_delta,
positions_eval,
vert_normals,
*nodes[i],
nodes[i],
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_grids(depsgraph, sd, object, brush, &spvc, grab_delta, *nodes[i], tls);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_grids(depsgraph, sd, object, brush, &spvc, grab_delta, nodes[i], tls);
});
});
break;
case bke::pbvh::Type::BMesh:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_bmesh(depsgraph, sd, object, brush, &spvc, grab_delta, *nodes[i], tls);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(depsgraph, sd, object, brush, &spvc, grab_delta, nodes[i], tls);
});
});
break;
}
}
}

View File

@@ -48,7 +48,7 @@ BLI_NOINLINE static void clamp_factors(const MutableSpan<float> factors)
BLI_NOINLINE static void do_surface_smooth_brush_mesh(const Depsgraph &depsgraph,
const Sculpt &sd,
const Brush &brush,
const Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
Object &object,
const MutableSpan<float3> all_laplacian_disp)
{
@@ -56,6 +56,7 @@ BLI_NOINLINE static void do_surface_smooth_brush_mesh(const Depsgraph &depsgraph
const StrokeCache &cache = *ss.cache;
const float alpha = brush.surface_smooth_shape_preservation;
const float beta = brush.surface_smooth_current_vertex;
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
Mesh &mesh = *static_cast<Mesh *>(object.data);
const OffsetIndices faces = mesh.faces();
@@ -68,16 +69,16 @@ BLI_NOINLINE static void do_surface_smooth_brush_mesh(const Depsgraph &depsgraph
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
Array<int> node_offset_data;
const OffsetIndices node_offsets = create_node_vert_offsets(nodes, node_offset_data);
const OffsetIndices node_offsets = create_node_vert_offsets(nodes, node_mask, node_offset_data);
Array<float> all_factors(node_offsets.total_size());
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> verts = bke::pbvh::node_unique_verts(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i, const int pos) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
const MutableSpan<float> factors = all_factors.as_mutable_span().slice(node_offsets[i]);
const MutableSpan<float> factors = all_factors.as_mutable_span().slice(node_offsets[pos]);
fill_factor_from_hide_and_mask(mesh, verts, factors);
filter_region_clip_factors(ss, positions_eval, verts, factors);
if (brush.flag & BRUSH_FRONTFACE) {
@@ -93,23 +94,23 @@ BLI_NOINLINE static void do_surface_smooth_brush_mesh(const Depsgraph &depsgraph
calc_brush_strength_factors(cache, brush, distances, factors);
auto_mask::calc_vert_factors(
depsgraph, object, cache.automasking.get(), *nodes[i], verts, factors);
depsgraph, object, cache.automasking.get(), nodes[i], verts, factors);
calc_brush_texture_factors(ss, brush, positions_eval, verts, factors);
scale_factors(factors, cache.bstrength);
clamp_factors(factors);
}
});
});
for ([[maybe_unused]] const int iteration : IndexRange(brush.surface_smooth_iterations)) {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> verts = bke::pbvh::node_unique_verts(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i, const int pos) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
const MutableSpan positions = gather_data_mesh(positions_eval, verts, tls.positions);
const OrigPositionData orig_data = orig_position_data_get_mesh(object, *nodes[i]);
const Span<float> factors = all_factors.as_span().slice(node_offsets[i]);
const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]);
const Span<float> factors = all_factors.as_span().slice(node_offsets[pos]);
tls.vert_neighbors.resize(verts.size());
calc_vert_neighbors(
@@ -135,14 +136,14 @@ BLI_NOINLINE static void do_surface_smooth_brush_mesh(const Depsgraph &depsgraph
write_translations(
depsgraph, sd, object, positions_eval, verts, translations, positions_orig);
}
});
});
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> verts = bke::pbvh::node_unique_verts(*nodes[i]);
const Span<float> factors = all_factors.as_span().slice(node_offsets[i]);
node_mask.slice(range).foreach_index([&](const int i, const int pos) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
const Span<float> factors = all_factors.as_span().slice(node_offsets[pos]);
const MutableSpan<float3> laplacian_disp = gather_data_mesh(
all_laplacian_disp.as_span(), verts, tls.laplacian_disp);
@@ -164,7 +165,7 @@ BLI_NOINLINE static void do_surface_smooth_brush_mesh(const Depsgraph &depsgraph
write_translations(
depsgraph, sd, object, positions_eval, verts, translations, positions_orig);
}
});
});
}
}
@@ -173,7 +174,7 @@ BLI_NOINLINE static void do_surface_smooth_brush_grids(
const Depsgraph &depsgraph,
const Sculpt &sd,
const Brush &brush,
const Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
Object &object,
const MutableSpan<float3> all_laplacian_disp)
{
@@ -181,22 +182,23 @@ BLI_NOINLINE static void do_surface_smooth_brush_grids(
const StrokeCache &cache = *ss.cache;
const float alpha = brush.surface_smooth_shape_preservation;
const float beta = brush.surface_smooth_current_vertex;
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
Array<int> node_offset_data;
const OffsetIndices node_offsets = create_node_vert_offsets(
nodes, BKE_subdiv_ccg_key_top_level(subdiv_ccg), node_offset_data);
BKE_subdiv_ccg_key_top_level(subdiv_ccg), nodes, node_mask, node_offset_data);
Array<float> all_factors(node_offsets.total_size());
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> grids = bke::pbvh::node_grid_indices(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i, const int pos) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
const MutableSpan positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
const MutableSpan<float> factors = all_factors.as_mutable_span().slice(node_offsets[i]);
const MutableSpan<float> factors = all_factors.as_mutable_span().slice(node_offsets[pos]);
fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
filter_region_clip_factors(ss, positions, factors);
if (brush.flag & BRUSH_FRONTFACE) {
@@ -211,23 +213,23 @@ BLI_NOINLINE static void do_surface_smooth_brush_grids(
calc_brush_strength_factors(cache, brush, distances, factors);
auto_mask::calc_grids_factors(
depsgraph, object, cache.automasking.get(), *nodes[i], grids, factors);
depsgraph, object, cache.automasking.get(), nodes[i], grids, factors);
calc_brush_texture_factors(ss, brush, positions, factors);
scale_factors(factors, cache.bstrength);
clamp_factors(factors);
}
});
});
for ([[maybe_unused]] const int iteration : IndexRange(brush.surface_smooth_iterations)) {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> grids = bke::pbvh::node_grid_indices(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i, const int pos) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
const MutableSpan positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
const OrigPositionData orig_data = orig_position_data_get_mesh(object, *nodes[i]);
const Span<float> factors = all_factors.as_span().slice(node_offsets[i]);
const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]);
const Span<float> factors = all_factors.as_span().slice(node_offsets[pos]);
tls.average_positions.resize(positions.size());
const MutableSpan<float3> average_positions = tls.average_positions;
@@ -249,15 +251,15 @@ BLI_NOINLINE static void do_surface_smooth_brush_grids(
clip_and_lock_translations(sd, ss, positions, translations);
apply_translations(translations, grids, subdiv_ccg);
}
});
});
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> grids = bke::pbvh::node_grid_indices(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i, const int pos) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
const MutableSpan positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
const Span<float> factors = all_factors.as_span().slice(node_offsets[i]);
const Span<float> factors = all_factors.as_span().slice(node_offsets[pos]);
const MutableSpan<float3> laplacian_disp = gather_data_grids(
subdiv_ccg, all_laplacian_disp.as_span(), grids, tls.laplacian_disp);
@@ -275,7 +277,7 @@ BLI_NOINLINE static void do_surface_smooth_brush_grids(
clip_and_lock_translations(sd, ss, positions, translations);
apply_translations(translations, grids, subdiv_ccg);
}
});
});
}
}
@@ -284,7 +286,7 @@ BLI_NOINLINE static void do_surface_smooth_brush_bmesh(
const Depsgraph &depsgraph,
const Sculpt &sd,
const Brush &brush,
const Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
Object &object,
const MutableSpan<float3> all_laplacian_disp)
{
@@ -292,19 +294,21 @@ BLI_NOINLINE static void do_surface_smooth_brush_bmesh(
const StrokeCache &cache = *ss.cache;
const float alpha = brush.surface_smooth_shape_preservation;
const float beta = brush.surface_smooth_current_vertex;
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
Array<int> node_offset_data;
const OffsetIndices node_offsets = create_node_vert_offsets_bmesh(nodes, node_offset_data);
const OffsetIndices node_offsets = create_node_vert_offsets_bmesh(
nodes, node_mask, node_offset_data);
Array<float> all_factors(node_offsets.total_size());
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]);
node_mask.slice(range).foreach_index([&](const int i, const int pos) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]);
const MutableSpan positions = gather_bmesh_positions(verts, tls.positions);
const MutableSpan<float> factors = all_factors.as_mutable_span().slice(node_offsets[i]);
const MutableSpan<float> factors = all_factors.as_mutable_span().slice(node_offsets[pos]);
fill_factor_from_hide_and_mask(*ss.bm, verts, factors);
filter_region_clip_factors(ss, positions, factors);
if (brush.flag & BRUSH_FRONTFACE) {
@@ -319,25 +323,25 @@ BLI_NOINLINE static void do_surface_smooth_brush_bmesh(
calc_brush_strength_factors(cache, brush, distances, factors);
auto_mask::calc_vert_factors(
depsgraph, object, cache.automasking.get(), *nodes[i], verts, factors);
depsgraph, object, cache.automasking.get(), nodes[i], verts, factors);
calc_brush_texture_factors(ss, brush, positions, factors);
scale_factors(factors, cache.bstrength);
clamp_factors(factors);
}
});
});
for ([[maybe_unused]] const int iteration : IndexRange(brush.surface_smooth_iterations)) {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]);
node_mask.slice(range).foreach_index([&](const int i, const int pos) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]);
const MutableSpan positions = gather_bmesh_positions(verts, tls.positions);
Array<float3> orig_positions(verts.size());
Array<float3> orig_normals(verts.size());
orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, orig_normals);
const Span<float> factors = all_factors.as_span().slice(node_offsets[i]);
const Span<float> factors = all_factors.as_span().slice(node_offsets[pos]);
tls.average_positions.resize(positions.size());
const MutableSpan<float3> average_positions = tls.average_positions;
@@ -355,15 +359,15 @@ BLI_NOINLINE static void do_surface_smooth_brush_bmesh(
clip_and_lock_translations(sd, ss, positions, translations);
apply_translations(translations, verts);
}
});
});
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]);
node_mask.slice(range).foreach_index([&](const int i, const int pos) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]);
const MutableSpan positions = gather_bmesh_positions(verts, tls.positions);
const Span<float> factors = all_factors.as_span().slice(node_offsets[i]);
const Span<float> factors = all_factors.as_span().slice(node_offsets[pos]);
const MutableSpan<float3> laplacian_disp = gather_data_vert_bmesh(
all_laplacian_disp.as_span(), verts, tls.laplacian_disp);
@@ -380,7 +384,7 @@ BLI_NOINLINE static void do_surface_smooth_brush_bmesh(
clip_and_lock_translations(sd, ss, positions, translations);
apply_translations(translations, verts);
}
});
});
}
}
@@ -390,7 +394,7 @@ BLI_NOINLINE static void do_surface_smooth_brush_bmesh(
void do_surface_smooth_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
SculptSession &ss = *object.sculpt;
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
@@ -398,17 +402,17 @@ void do_surface_smooth_brush(const Depsgraph &depsgraph,
switch (ss.pbvh->type()) {
case bke::pbvh::Type::Mesh:
do_surface_smooth_brush_mesh(
depsgraph, sd, brush, nodes, object, ss.cache->surface_smooth_laplacian_disp);
depsgraph, sd, brush, node_mask, object, ss.cache->surface_smooth_laplacian_disp);
break;
case bke::pbvh::Type::Grids: {
do_surface_smooth_brush_grids(
depsgraph, sd, brush, nodes, object, ss.cache->surface_smooth_laplacian_disp);
depsgraph, sd, brush, node_mask, object, ss.cache->surface_smooth_laplacian_disp);
break;
}
case bke::pbvh::Type::BMesh: {
BM_mesh_elem_index_ensure(ss.bm, BM_VERT);
do_surface_smooth_brush_bmesh(
depsgraph, sd, brush, nodes, object, ss.cache->surface_smooth_laplacian_disp);
depsgraph, sd, brush, node_mask, object, ss.cache->surface_smooth_laplacian_disp);
break;
}
}

View File

@@ -40,7 +40,7 @@ static void calc_faces(const Depsgraph &depsgraph,
const Brush &brush,
const float3 &offset,
const Span<float3> positions_eval,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
Object &object,
LocalData &tls,
const MutableSpan<float3> positions_orig)
@@ -85,7 +85,7 @@ static void calc_grids(const Depsgraph &depsgraph,
Object &object,
const Brush &brush,
const float3 &offset,
bke::pbvh::Node &node,
bke::pbvh::GridsNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -131,7 +131,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
Object &object,
const Brush &brush,
const float3 &offset,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -176,7 +176,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
void do_thumb_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
const SculptSession &ss = *object.sculpt;
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
@@ -191,39 +191,35 @@ void do_thumb_brush(const Depsgraph &depsgraph,
Mesh &mesh = *static_cast<Mesh *>(object.data);
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object);
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_faces(depsgraph,
sd,
brush,
offset,
positions_eval,
*nodes[i],
object,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_faces(
depsgraph, sd, brush, offset, positions_eval, nodes[i], object, tls, positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_grids(depsgraph, sd, object, brush, offset, *nodes[i], tls);
}
node_mask.slice(range).foreach_index(
[&](const int i) { calc_grids(depsgraph, sd, object, brush, offset, nodes[i], tls); });
});
break;
case bke::pbvh::Type::BMesh:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_bmesh(depsgraph, sd, object, brush, offset, *nodes[i], tls);
}
node_mask.slice(range).foreach_index(
[&](const int i) { calc_bmesh(depsgraph, sd, object, brush, offset, nodes[i], tls); });
});
break;
}
}
}

View File

@@ -160,7 +160,7 @@ static void calc_faces(const Depsgraph &depsgraph,
const Span<int> corner_verts,
const GroupedSpan<int> vert_to_face_map,
const Span<bool> hide_poly,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
Object &object,
LocalData &tls,
const MutableSpan<float3> positions_orig)
@@ -212,7 +212,7 @@ static void calc_grids(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
const Brush &brush,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -259,7 +259,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
const Brush &brush,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -308,7 +308,7 @@ static void calc_bmesh(const Depsgraph &depsgraph,
void do_topology_slide_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
const SculptSession &ss = *object.sculpt;
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
@@ -327,9 +327,10 @@ void do_topology_slide_brush(const Depsgraph &depsgraph,
const Span<int> corner_verts = mesh.corner_verts();
const bke::AttributeAccessor attributes = mesh.attributes();
const VArraySpan hide_poly = *attributes.lookup<bool>(".hide_poly", bke::AttrDomain::Face);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_faces(depsgraph,
sd,
brush,
@@ -338,31 +339,33 @@ void do_topology_slide_brush(const Depsgraph &depsgraph,
corner_verts,
ss.vert_to_face_map,
hide_poly,
*nodes[i],
nodes[i],
object,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_grids(depsgraph, sd, object, brush, *nodes[i], tls);
}
node_mask.slice(range).foreach_index(
[&](const int i) { calc_grids(depsgraph, sd, object, brush, nodes[i], tls); });
});
break;
case bke::pbvh::Type::BMesh:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
calc_bmesh(depsgraph, sd, object, brush, *nodes[i], tls);
}
node_mask.slice(range).foreach_index(
[&](const int i) { calc_bmesh(depsgraph, sd, object, brush, nodes[i], tls); });
});
break;
}
}
}

View File

@@ -4,6 +4,7 @@
#pragma once
#include "BLI_index_mask_fwd.hh"
#include "BLI_span.hh"
struct Depsgraph;
@@ -19,162 +20,162 @@ namespace blender::ed::sculpt_paint {
void do_clay_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &ob,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
void do_clay_strips_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &ob,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
void do_clay_thumb_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &ob,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
void do_crease_brush(const Depsgraph &depsgraph,
const Scene &scene,
const Sculpt &sd,
Object &ob,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
void do_blob_brush(const Depsgraph &depsgraph,
const Scene &scene,
const Sculpt &sd,
Object &ob,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
void do_bmesh_topology_rake_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &ob,
Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
float strength);
void do_displacement_eraser_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &ob,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
void do_displacement_smear_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &ob,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
void do_draw_face_sets_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
/** A simple normal-direction displacement. */
void do_draw_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
/** A simple normal-direction displacement based on image texture RGB/XYZ values. */
void do_draw_vector_displacement_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
void do_draw_sharp_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
void do_elastic_deform_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
void do_enhance_details_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
void do_fill_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
void do_flatten_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &ob,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
void do_grab_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &ob,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
void do_gravity_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &ob,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
void do_inflate_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &ob,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
void do_layer_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
/** A brush that modifies mask values instead of position. */
void do_mask_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
void do_multiplane_scrape_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
void do_pinch_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
void do_nudge_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
void do_relax_face_sets_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
void do_rotate_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
void do_scrape_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
/** Smooth positions with neighboring vertices. */
void do_smooth_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
float brush_strength);
/** Smooth mask values with neighboring vertices. */
void do_smooth_mask_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
float brush_strength);
void do_snake_hook_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
void do_surface_smooth_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
void do_thumb_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
void do_topology_slide_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
void do_topology_relax_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
namespace boundary {
void do_boundary_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
}
namespace cloth {
void do_cloth_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
}
} // namespace blender::ed::sculpt_paint

View File

@@ -304,13 +304,13 @@ namespace auto_mask {
void calc_vert_factors(const Depsgraph &depsgraph,
const Object &object,
const Cache &cache,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
Span<int> verts,
MutableSpan<float> factors);
inline void calc_vert_factors(const Depsgraph &depsgraph,
const Object &object,
const Cache *cache,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
Span<int> verts,
MutableSpan<float> factors)
{
@@ -322,13 +322,13 @@ inline void calc_vert_factors(const Depsgraph &depsgraph,
void calc_grids_factors(const Depsgraph &depsgraph,
const Object &object,
const Cache &cache,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
Span<int> grids,
MutableSpan<float> factors);
inline void calc_grids_factors(const Depsgraph &depsgraph,
const Object &object,
const Cache *cache,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
Span<int> grids,
MutableSpan<float> factors)
{
@@ -340,13 +340,13 @@ inline void calc_grids_factors(const Depsgraph &depsgraph,
void calc_vert_factors(const Depsgraph &depsgraph,
const Object &object,
const Cache &cache,
const bke::pbvh::Node &node,
const bke::pbvh::BMeshNode &node,
const Set<BMVert *, 0> &verts,
MutableSpan<float> factors);
inline void calc_vert_factors(const Depsgraph &depsgraph,
const Object &object,
const Cache *cache,
const bke::pbvh::Node &node,
const bke::pbvh::BMeshNode &node,
const Set<BMVert *, 0> &verts,
MutableSpan<float> factors)
{
@@ -364,7 +364,7 @@ void calc_face_factors(const Depsgraph &depsgraph,
OffsetIndices<int> faces,
Span<int> corner_verts,
const Cache &cache,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
Span<int> face_indices,
MutableSpan<float> factors);
@@ -447,11 +447,15 @@ void write_translations(const Depsgraph &depsgraph,
* Creates OffsetIndices based on each node's unique vertex count, allowing for easy slicing of a
* new array.
*/
OffsetIndices<int> create_node_vert_offsets(Span<bke::pbvh::Node *> nodes, Array<int> &node_data);
OffsetIndices<int> create_node_vert_offsets(Span<bke::pbvh::Node *> nodes,
const CCGKey &key,
OffsetIndices<int> create_node_vert_offsets(const Span<bke::pbvh::MeshNode> nodes,
const IndexMask &nodes_mask,
Array<int> &node_data);
OffsetIndices<int> create_node_vert_offsets_bmesh(Span<bke::pbvh::Node *> nodes,
OffsetIndices<int> create_node_vert_offsets(const CCGKey &key,
const Span<bke::pbvh::GridsNode> nodes,
const IndexMask &nodes_mask,
Array<int> &node_data);
OffsetIndices<int> create_node_vert_offsets_bmesh(const Span<bke::pbvh::BMeshNode> nodes,
const IndexMask &nodes_mask,
Array<int> &node_data);
/**

View File

@@ -122,57 +122,55 @@ void tag_update_visibility(const bContext &C)
}
}
void mesh_show_all(const Depsgraph &depsgraph, Object &object, const Span<bke::pbvh::Node *> nodes)
void mesh_show_all(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask)
{
SculptSession &ss = *object.sculpt;
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
Mesh &mesh = *static_cast<Mesh *>(object.data);
bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
if (const VArray<bool> attribute = *attributes.lookup<bool>(".hide_vert",
bke::AttrDomain::Point))
{
const VArraySpan hide_vert(attribute);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (bke::pbvh::Node *node : nodes.slice(range)) {
const Span<int> verts = bke::pbvh::node_unique_verts(*node);
if (std::any_of(verts.begin(), verts.end(), [&](const int i) { return hide_vert[i]; })) {
undo::push_node(depsgraph, object, node, undo::Type::HideVert);
BKE_pbvh_node_mark_rebuild_draw(*node);
}
node_mask.foreach_index(GrainSize(1), [&](const int i) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
if (std::any_of(verts.begin(), verts.end(), [&](const int i) { return hide_vert[i]; })) {
undo::push_node(depsgraph, object, &nodes[i], undo::Type::HideVert);
BKE_pbvh_node_mark_rebuild_draw(nodes[i]);
}
});
}
for (bke::pbvh::Node *node : nodes) {
BKE_pbvh_node_fully_hidden_set(*node, false);
}
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_fully_hidden_set(nodes[i], false); });
attributes.remove(".hide_vert");
bke::mesh_hide_vert_flush(mesh);
}
void grids_show_all(Depsgraph &depsgraph, Object &object, const Span<bke::pbvh::Node *> nodes)
void grids_show_all(Depsgraph &depsgraph, Object &object, const IndexMask &node_mask)
{
SculptSession &ss = *object.sculpt;
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden;
bool any_changed = false;
if (!grid_hidden.is_empty()) {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (bke::pbvh::Node *node : nodes.slice(range)) {
const Span<int> grids = bke::pbvh::node_grid_indices(*node);
if (std::any_of(grids.begin(), grids.end(), [&](const int i) {
return bits::any_bit_set(grid_hidden[i]);
}))
{
any_changed = true;
undo::push_node(depsgraph, object, node, undo::Type::HideVert);
BKE_pbvh_node_mark_rebuild_draw(*node);
}
node_mask.foreach_index(GrainSize(1), [&](const int i) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
if (std::any_of(grids.begin(), grids.end(), [&](const int i) {
return bits::any_bit_set(grid_hidden[i]);
}))
{
any_changed = true;
undo::push_node(depsgraph, object, &nodes[i], undo::Type::HideVert);
BKE_pbvh_node_mark_rebuild_draw(nodes[i]);
}
});
}
if (!any_changed) {
return;
}
for (bke::pbvh::Node *node : nodes) {
BKE_pbvh_node_fully_hidden_set(*node, false);
}
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_fully_hidden_set(nodes[i], false); });
BKE_subdiv_ccg_grid_hidden_free(subdiv_ccg);
BKE_pbvh_sync_visibility_from_verts(object);
multires_mark_as_modified(&depsgraph, &object, MULTIRES_HIDDEN_MODIFIED);
@@ -211,7 +209,8 @@ static void calc_face_hide(const Span<int> node_faces,
/* Updates a node's face's visibility based on the updated vertex visibility. */
static void flush_face_changes_node(Mesh &mesh,
const Span<bke::pbvh::Node *> nodes,
MutableSpan<bke::pbvh::MeshNode> nodes,
const IndexMask &node_mask,
const Span<bool> hide_vert)
{
bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
@@ -228,11 +227,11 @@ static void flush_face_changes_node(Mesh &mesh,
Vector<bool> new_hide;
};
threading::EnumerableThreadSpecific<TLS> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
TLS &tls = all_tls.local();
for (bke::pbvh::Node *node : nodes.slice(range)) {
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> node_faces = bke::pbvh::node_face_indices_calc_mesh(
tri_faces, static_cast<bke::pbvh::MeshNode &>(*node), tls.face_indices);
tri_faces, nodes[i], tls.face_indices);
tls.new_hide.resize(node_faces.size());
gather_data_mesh(hide_poly.span.as_span(), node_faces, tls.new_hide.as_mutable_span());
@@ -240,13 +239,13 @@ static void flush_face_changes_node(Mesh &mesh,
calc_face_hide(node_faces, faces, corner_verts, hide_vert, tls.new_hide.as_mutable_span());
if (array_utils::indexed_data_equal<bool>(hide_poly.span, node_faces, tls.new_hide)) {
continue;
return;
}
scatter_data_mesh(tls.new_hide.as_span(), node_faces, hide_poly.span);
BKE_pbvh_node_mark_update_visibility(*node);
bke::pbvh::node_update_visibility_mesh(hide_vert, static_cast<bke::pbvh::MeshNode &>(*node));
}
BKE_pbvh_node_mark_update_visibility(nodes[i]);
bke::pbvh::node_update_visibility_mesh(hide_vert, nodes[i]);
});
});
hide_poly.finish();
}
@@ -276,9 +275,12 @@ static void flush_edge_changes(Mesh &mesh, const Span<bool> hide_vert)
static void vert_hide_update(const Depsgraph &depsgraph,
Object &object,
const Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
const FunctionRef<void(Span<int>, MutableSpan<bool>)> calc_hide)
{
SculptSession &ss = *object.sculpt;
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
Mesh &mesh = *static_cast<Mesh *>(object.data);
bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
bke::SpanAttributeWriter<bool> hide_vert = attributes.lookup_or_add_for_write_span<bool>(
@@ -286,22 +288,22 @@ static void vert_hide_update(const Depsgraph &depsgraph,
bool any_changed = false;
threading::EnumerableThreadSpecific<Vector<bool>> all_new_hide;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
Vector<bool> &new_hide = all_new_hide.local();
for (bke::pbvh::Node *node : nodes.slice(range)) {
const Span<int> verts = bke::pbvh::node_unique_verts(*node);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
new_hide.resize(verts.size());
gather_data_mesh(hide_vert.span.as_span(), verts, new_hide.as_mutable_span());
calc_hide(verts, new_hide);
if (array_utils::indexed_data_equal<bool>(hide_vert.span, verts, new_hide)) {
continue;
return;
}
any_changed = true;
undo::push_node(depsgraph, object, node, undo::Type::HideVert);
undo::push_node(depsgraph, object, &nodes[i], undo::Type::HideVert);
scatter_data_mesh(new_hide.as_span(), verts, hide_vert.span);
}
});
});
hide_vert.finish();
@@ -309,23 +311,26 @@ static void vert_hide_update(const Depsgraph &depsgraph,
/* We handle flushing ourselves at the node level instead of delegating to
* bke::mesh_hide_vert_flush because we need to tag node visibility changes as well in cases
* where the vertices hidden are on a node boundary.*/
flush_face_changes_node(mesh, nodes, hide_vert.span);
flush_face_changes_node(mesh, nodes, node_mask, hide_vert.span);
flush_edge_changes(mesh, hide_vert.span);
}
}
static void grid_hide_update(Depsgraph &depsgraph,
Object &object,
const Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
const FunctionRef<void(const int, MutableBoundedBitSpan)> calc_hide)
{
SculptSession &ss = *object.sculpt;
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
BitGroupVector<> &grid_hidden = BKE_subdiv_ccg_grid_hidden_ensure(subdiv_ccg);
bool any_changed = false;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (bke::pbvh::Node *node : nodes.slice(range)) {
const Span<int> grids = bke::pbvh::node_grid_indices(*node);
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
BitGroupVector<> new_hide(grids.size(), grid_hidden.group_size());
for (const int i : grids.index_range()) {
new_hide[i].copy_from(grid_hidden[grids[i]].as_span());
@@ -339,20 +344,19 @@ static void grid_hide_update(Depsgraph &depsgraph,
return bits::spans_equal(grid_hidden[grids[i]], new_hide[i]);
}))
{
continue;
return;
}
any_changed = true;
undo::push_node(depsgraph, object, node, undo::Type::HideVert);
undo::push_node(depsgraph, object, &nodes[i], undo::Type::HideVert);
for (const int i : grids.index_range()) {
grid_hidden[grids[i]].copy_from(new_hide[i].as_span());
}
BKE_pbvh_node_mark_update_visibility(*node);
bke::pbvh::node_update_visibility_grids(grid_hidden,
static_cast<bke::pbvh::GridsNode &>(*node));
}
BKE_pbvh_node_mark_update_visibility(nodes[i]);
bke::pbvh::node_update_visibility_grids(grid_hidden, nodes[i]);
});
});
if (any_changed) {
@@ -398,30 +402,39 @@ static void partialvis_update_bmesh_faces(const Set<BMFace *, 0> &faces)
static void partialvis_update_bmesh_nodes(const Depsgraph &depsgraph,
Object &ob,
const Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
const VisAction action,
const FunctionRef<bool(BMVert *v)> vert_test_fn)
{
for (bke::pbvh::Node *node : nodes) {
SculptSession &ss = *ob.sculpt;
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
node_mask.foreach_index([&](const int i) {
bool any_changed = false;
bool any_visible = false;
undo::push_node(depsgraph, ob, node, undo::Type::HideVert);
undo::push_node(depsgraph, ob, &nodes[i], undo::Type::HideVert);
partialvis_update_bmesh_verts(
BKE_pbvh_bmesh_node_unique_verts(node), action, vert_test_fn, &any_changed, &any_visible);
partialvis_update_bmesh_verts(BKE_pbvh_bmesh_node_unique_verts(&nodes[i]),
action,
vert_test_fn,
&any_changed,
&any_visible);
partialvis_update_bmesh_verts(
BKE_pbvh_bmesh_node_other_verts(node), action, vert_test_fn, &any_changed, &any_visible);
partialvis_update_bmesh_verts(BKE_pbvh_bmesh_node_other_verts(&nodes[i]),
action,
vert_test_fn,
&any_changed,
&any_visible);
/* Finally loop over node faces and tag the ones that are fully hidden. */
partialvis_update_bmesh_faces(BKE_pbvh_bmesh_node_faces(node));
partialvis_update_bmesh_faces(BKE_pbvh_bmesh_node_faces(&nodes[i]));
if (any_changed) {
BKE_pbvh_node_mark_rebuild_draw(*node);
BKE_pbvh_node_fully_hidden_set(*node, !any_visible);
BKE_pbvh_node_mark_rebuild_draw(nodes[i]);
BKE_pbvh_node_fully_hidden_set(nodes[i], !any_visible);
}
}
});
}
/** \} */
@@ -434,7 +447,7 @@ static void partialvis_update_bmesh_nodes(const Depsgraph &depsgraph,
static void partialvis_all_update_mesh(const Depsgraph &depsgraph,
Object &object,
const VisAction action,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
Mesh &mesh = *static_cast<Mesh *>(object.data);
bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
@@ -446,12 +459,12 @@ static void partialvis_all_update_mesh(const Depsgraph &depsgraph,
switch (action) {
case VisAction::Hide:
vert_hide_update(
depsgraph, object, nodes, [&](const Span<int> /*verts*/, MutableSpan<bool> hide) {
depsgraph, object, node_mask, [&](const Span<int> /*verts*/, MutableSpan<bool> hide) {
hide.fill(true);
});
break;
case VisAction::Show:
mesh_show_all(depsgraph, object, nodes);
mesh_show_all(depsgraph, object, node_mask);
break;
}
}
@@ -459,17 +472,17 @@ static void partialvis_all_update_mesh(const Depsgraph &depsgraph,
static void partialvis_all_update_grids(Depsgraph &depsgraph,
Object &object,
const VisAction action,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
switch (action) {
case VisAction::Hide:
grid_hide_update(depsgraph,
object,
nodes,
node_mask,
[&](const int /*verts*/, MutableBoundedBitSpan hide) { hide.fill(true); });
break;
case VisAction::Show:
grids_show_all(depsgraph, object, nodes);
grids_show_all(depsgraph, object, node_mask);
break;
}
}
@@ -477,10 +490,10 @@ static void partialvis_all_update_grids(Depsgraph &depsgraph,
static void partialvis_all_update_bmesh(const Depsgraph &depsgraph,
Object &ob,
const VisAction action,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
partialvis_update_bmesh_nodes(
depsgraph, ob, nodes, action, [](const BMVert * /*vert*/) { return true; });
depsgraph, ob, node_mask, action, [](const BMVert * /*vert*/) { return true; });
}
static int hide_show_all_exec(bContext *C, wmOperator *op)
@@ -503,17 +516,18 @@ static int hide_show_all_exec(bContext *C, wmOperator *op)
break;
}
Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(*pbvh);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*pbvh, memory);
switch (pbvh->type()) {
case bke::pbvh::Type::Mesh:
partialvis_all_update_mesh(*depsgraph, ob, action, nodes);
partialvis_all_update_mesh(*depsgraph, ob, action, node_mask);
break;
case bke::pbvh::Type::Grids:
partialvis_all_update_grids(*depsgraph, ob, action, nodes);
partialvis_all_update_grids(*depsgraph, ob, action, node_mask);
break;
case bke::pbvh::Type::BMesh:
partialvis_all_update_bmesh(*depsgraph, ob, action, nodes);
partialvis_all_update_bmesh(*depsgraph, ob, action, node_mask);
break;
}
@@ -529,7 +543,7 @@ static int hide_show_all_exec(bContext *C, wmOperator *op)
static void partialvis_masked_update_mesh(const Depsgraph &depsgraph,
Object &object,
const VisAction action,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
Mesh &mesh = *static_cast<Mesh *>(object.data);
bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
@@ -541,23 +555,24 @@ static void partialvis_masked_update_mesh(const Depsgraph &depsgraph,
const bool value = action_to_hide(action);
const VArraySpan<float> mask = *attributes.lookup<float>(".sculpt_mask", bke::AttrDomain::Point);
if (action == VisAction::Show && mask.is_empty()) {
mesh_show_all(depsgraph, object, nodes);
mesh_show_all(depsgraph, object, node_mask);
}
else if (!mask.is_empty()) {
vert_hide_update(depsgraph, object, nodes, [&](const Span<int> verts, MutableSpan<bool> hide) {
for (const int i : verts.index_range()) {
if (mask[verts[i]] > 0.5f) {
hide[i] = value;
}
}
});
vert_hide_update(
depsgraph, object, node_mask, [&](const Span<int> verts, MutableSpan<bool> hide) {
for (const int i : verts.index_range()) {
if (mask[verts[i]] > 0.5f) {
hide[i] = value;
}
}
});
}
}
static void partialvis_masked_update_grids(Depsgraph &depsgraph,
Object &object,
const VisAction action,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
@@ -567,12 +582,12 @@ static void partialvis_masked_update_grids(Depsgraph &depsgraph,
if (!key.has_mask) {
grid_hide_update(depsgraph,
object,
nodes,
node_mask,
[&](const int /*verts*/, MutableBoundedBitSpan hide) { hide.fill(value); });
}
else {
grid_hide_update(
depsgraph, object, nodes, [&](const int grid_index, MutableBoundedBitSpan hide) {
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)) {
@@ -589,7 +604,7 @@ static void partialvis_masked_update_grids(Depsgraph &depsgraph,
static void partialvis_masked_update_bmesh(const Depsgraph &depsgraph,
Object &ob,
const VisAction action,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
BMesh *bm = ob.sculpt->bm;
const int mask_offset = CustomData_get_offset_named(&bm->vdata, CD_PROP_FLOAT, ".sculpt_mask");
@@ -598,7 +613,7 @@ static void partialvis_masked_update_bmesh(const Depsgraph &depsgraph,
return vmask > 0.5f;
};
partialvis_update_bmesh_nodes(depsgraph, ob, nodes, action, mask_test_fn);
partialvis_update_bmesh_nodes(depsgraph, ob, node_mask, action, mask_test_fn);
}
static int hide_show_masked_exec(bContext *C, wmOperator *op)
@@ -621,17 +636,18 @@ static int hide_show_masked_exec(bContext *C, wmOperator *op)
break;
}
Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(*pbvh);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*pbvh, memory);
switch (pbvh->type()) {
case bke::pbvh::Type::Mesh:
partialvis_masked_update_mesh(*depsgraph, ob, action, nodes);
partialvis_masked_update_mesh(*depsgraph, ob, action, node_mask);
break;
case bke::pbvh::Type::Grids:
partialvis_masked_update_grids(*depsgraph, ob, action, nodes);
partialvis_masked_update_grids(*depsgraph, ob, action, node_mask);
break;
case bke::pbvh::Type::BMesh:
partialvis_masked_update_bmesh(*depsgraph, ob, action, nodes);
partialvis_masked_update_bmesh(*depsgraph, ob, action, node_mask);
break;
}
@@ -692,27 +708,29 @@ void PAINT_OT_hide_show_all(wmOperatorType *ot)
static void invert_visibility_mesh(const Depsgraph &depsgraph,
Object &object,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
SculptSession &ss = *object.sculpt;
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
Mesh &mesh = *static_cast<Mesh *>(object.data);
const Span<int> tri_faces = mesh.corner_tri_faces();
bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
bke::SpanAttributeWriter<bool> hide_poly = attributes.lookup_or_add_for_write_span<bool>(
".hide_poly", bke::AttrDomain::Face);
undo::push_nodes(depsgraph, object, nodes, undo::Type::HideFace);
undo::push_nodes(depsgraph, object, node_mask, undo::Type::HideFace);
threading::EnumerableThreadSpecific<Vector<int>> all_index_data;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
Vector<int> &faces = all_index_data.local();
for (bke::pbvh::Node *node : nodes.slice(range)) {
bke::pbvh::node_face_indices_calc_mesh(
tri_faces, static_cast<bke::pbvh::MeshNode &>(*node), faces);
node_mask.slice(range).foreach_index([&](const int i) {
bke::pbvh::node_face_indices_calc_mesh(tri_faces, nodes[i], faces);
for (const int face : faces) {
hide_poly.span[face] = !hide_poly.span[face];
}
BKE_pbvh_node_mark_update_visibility(*node);
}
BKE_pbvh_node_mark_update_visibility(nodes[i]);
});
});
hide_poly.finish();
@@ -722,22 +740,21 @@ static void invert_visibility_mesh(const Depsgraph &depsgraph,
static void invert_visibility_grids(Depsgraph &depsgraph,
Object &object,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
SculptSession &ss = *object.sculpt;
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
undo::push_nodes(depsgraph, object, nodes, undo::Type::HideVert);
undo::push_nodes(depsgraph, object, node_mask, undo::Type::HideVert);
BitGroupVector<> &grid_hidden = BKE_subdiv_ccg_grid_hidden_ensure(subdiv_ccg);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (bke::pbvh::Node *node : nodes.slice(range)) {
for (const int i : bke::pbvh::node_grid_indices(*node)) {
bits::invert(grid_hidden[i]);
}
BKE_pbvh_node_mark_update_visibility(*node);
bke::pbvh::node_update_visibility_grids(grid_hidden,
static_cast<bke::pbvh::GridsNode &>(*node));
node_mask.foreach_index(GrainSize(1), [&](const int i) {
for (const int i : bke::pbvh::node_grid_indices(nodes[i])) {
bits::invert(grid_hidden[i]);
}
BKE_pbvh_node_mark_update_visibility(nodes[i]);
bke::pbvh::node_update_visibility_grids(grid_hidden, nodes[i]);
});
multires_mark_as_modified(&depsgraph, &object, MULTIRES_HIDDEN_MODIFIED);
@@ -746,25 +763,23 @@ static void invert_visibility_grids(Depsgraph &depsgraph,
static void invert_visibility_bmesh(const Depsgraph &depsgraph,
Object &object,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
undo::push_nodes(depsgraph, object, nodes, undo::Type::HideVert);
SculptSession &ss = *object.sculpt;
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
undo::push_nodes(depsgraph, object, node_mask, undo::Type::HideVert);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (bke::pbvh::Node *node : nodes.slice(range)) {
bool fully_hidden = true;
for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(node)) {
BM_elem_flag_toggle(vert, BM_ELEM_HIDDEN);
fully_hidden &= BM_elem_flag_test_bool(vert, BM_ELEM_HIDDEN);
}
BKE_pbvh_node_fully_hidden_set(*node, fully_hidden);
BKE_pbvh_node_mark_rebuild_draw(*node);
node_mask.foreach_index(GrainSize(1), [&](const int i) {
bool fully_hidden = true;
for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(&nodes[i])) {
BM_elem_flag_toggle(vert, BM_ELEM_HIDDEN);
fully_hidden &= BM_elem_flag_test_bool(vert, BM_ELEM_HIDDEN);
}
BKE_pbvh_node_fully_hidden_set(nodes[i], fully_hidden);
BKE_pbvh_node_mark_rebuild_draw(nodes[i]);
});
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (bke::pbvh::Node *node : nodes.slice(range)) {
partialvis_update_bmesh_faces(BKE_pbvh_bmesh_node_faces(node));
}
node_mask.foreach_index(GrainSize(1), [&](const int i) {
partialvis_update_bmesh_faces(BKE_pbvh_bmesh_node_faces(&nodes[i]));
});
}
@@ -776,17 +791,18 @@ static int visibility_invert_exec(bContext *C, wmOperator *op)
bke::pbvh::Tree *pbvh = BKE_sculpt_object_pbvh_ensure(&depsgraph, &object);
BLI_assert(BKE_object_sculpt_pbvh_get(&object) == pbvh);
Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(*pbvh);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*pbvh, memory);
undo::push_begin(object, op);
switch (pbvh->type()) {
case bke::pbvh::Type::Mesh:
invert_visibility_mesh(depsgraph, object, nodes);
invert_visibility_mesh(depsgraph, object, node_mask);
break;
case bke::pbvh::Type::Grids:
invert_visibility_grids(depsgraph, object, nodes);
invert_visibility_grids(depsgraph, object, node_mask);
break;
case bke::pbvh::Type::BMesh:
invert_visibility_bmesh(depsgraph, object, nodes);
invert_visibility_bmesh(depsgraph, object, node_mask);
break;
}
@@ -885,35 +901,38 @@ static void propagate_vertex_visibility(Mesh &mesh,
static void update_undo_state(const Depsgraph &depsgraph,
Object &object,
const Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
const Span<bool> old_hide_vert,
const Span<bool> new_hide_vert)
{
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (bke::pbvh::Node *node : nodes.slice(range)) {
for (const int vert : bke::pbvh::node_unique_verts(*node)) {
if (old_hide_vert[vert] != new_hide_vert[vert]) {
undo::push_node(depsgraph, object, node, undo::Type::HideVert);
break;
}
const SculptSession &ss = *object.sculpt;
const Span<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
node_mask.foreach_index(GrainSize(1), [&](const int i) {
for (const int vert : bke::pbvh::node_unique_verts(nodes[i])) {
if (old_hide_vert[vert] != new_hide_vert[vert]) {
undo::push_node(depsgraph, object, &nodes[i], undo::Type::HideVert);
break;
}
}
});
}
static void update_node_visibility_from_face_changes(const Span<bke::pbvh::Node *> nodes,
static void update_node_visibility_from_face_changes(MutableSpan<bke::pbvh::MeshNode> nodes,
const IndexMask &node_mask,
const Span<int> tri_faces,
const Span<bool> orig_hide_poly,
const Span<bool> new_hide_poly,
const Span<bool> hide_vert)
{
threading::EnumerableThreadSpecific<Vector<int>> all_face_indices;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
Vector<int> &face_indices = all_face_indices.local();
for (bke::pbvh::Node *node : nodes.slice(range)) {
node_mask.slice(range).foreach_index([&](const int i) {
bool any_changed = false;
const Span<int> indices = bke::pbvh::node_face_indices_calc_mesh(
tri_faces, static_cast<bke::pbvh::MeshNode &>(*node), face_indices);
tri_faces, nodes[i], face_indices);
for (const int face_index : indices) {
if (orig_hide_poly[face_index] != new_hide_poly[face_index]) {
any_changed = true;
@@ -922,17 +941,16 @@ static void update_node_visibility_from_face_changes(const Span<bke::pbvh::Node
}
if (any_changed) {
BKE_pbvh_node_mark_update_visibility(*node);
bke::pbvh::node_update_visibility_mesh(hide_vert,
static_cast<bke::pbvh::MeshNode &>(*node));
BKE_pbvh_node_mark_update_visibility(nodes[i]);
bke::pbvh::node_update_visibility_mesh(hide_vert, nodes[i]);
}
}
});
});
}
static void grow_shrink_visibility_mesh(const Depsgraph &depsgraph,
Object &object,
const Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
const VisAction action,
const int iterations)
{
@@ -959,14 +977,18 @@ static void grow_shrink_visibility_mesh(const Depsgraph &depsgraph,
const Span<bool> last_buffer = buffers.write_buffer(iterations - 1);
update_undo_state(depsgraph, object, nodes, hide_vert.span, last_buffer);
update_undo_state(depsgraph, object, node_mask, hide_vert.span, last_buffer);
/* We can wait until after all iterations are done to flush edge changes as they are
* not used for coarse filtering while iterating.*/
flush_edge_changes(mesh, last_buffer);
update_node_visibility_from_face_changes(
nodes, mesh.corner_tri_faces(), orig_hide_poly, hide_poly, last_buffer);
update_node_visibility_from_face_changes(object.sculpt->pbvh->nodes<bke::pbvh::MeshNode>(),
node_mask,
mesh.corner_tri_faces(),
orig_hide_poly,
hide_poly,
last_buffer);
array_utils::copy(last_buffer, hide_vert.span);
hide_vert.finish();
}
@@ -988,11 +1010,14 @@ struct DualBitBuffer {
static void grow_shrink_visibility_grid(Depsgraph &depsgraph,
Object &object,
const Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
const VisAction action,
const int iterations)
{
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
SculptSession &ss = *object.sculpt;
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
BitGroupVector<> &grid_hidden = BKE_subdiv_ccg_grid_hidden_ensure(subdiv_ccg);
@@ -1009,62 +1034,48 @@ static void grow_shrink_visibility_grid(Depsgraph &depsgraph,
BitGroupVector<> &read_buffer = buffers.read_buffer(i);
BitGroupVector<> &write_buffer = buffers.write_buffer(i);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (const int node_index : range) {
bke::pbvh::Node *node = nodes[node_index];
const Span<int> grids = bke::pbvh::node_grid_indices(*node);
node_mask.foreach_index(GrainSize(1), [&](const int i) {
for (const int grid : bke::pbvh::node_grid_indices(nodes[i])) {
for (const int y : IndexRange(key.grid_size)) {
for (const int x : IndexRange(key.grid_size)) {
const int grid_elem_idx = CCG_grid_xy_to_index(key.grid_size, x, y);
if (read_buffer[grid][grid_elem_idx] != desired_state) {
continue;
}
for (const int grid_index : grids) {
for (const int y : IndexRange(key.grid_size)) {
for (const int x : IndexRange(key.grid_size)) {
const int grid_elem_idx = CCG_grid_xy_to_index(key.grid_size, x, y);
if (read_buffer[grid_index][grid_elem_idx] != desired_state) {
continue;
}
SubdivCCGCoord coord{};
coord.grid_index = grid;
coord.x = x;
coord.y = y;
SubdivCCGCoord coord{};
coord.grid_index = grid_index;
coord.x = x;
coord.y = y;
SubdivCCGNeighbors neighbors;
BKE_subdiv_ccg_neighbor_coords_get(subdiv_ccg, coord, true, neighbors);
SubdivCCGNeighbors neighbors;
BKE_subdiv_ccg_neighbor_coords_get(subdiv_ccg, coord, true, neighbors);
for (const SubdivCCGCoord neighbor : neighbors.coords) {
const int neighbor_grid_elem_idx = CCG_grid_xy_to_index(
key.grid_size, neighbor.x, neighbor.y);
for (const SubdivCCGCoord neighbor : neighbors.coords) {
const int neighbor_grid_elem_idx = CCG_grid_xy_to_index(
key.grid_size, neighbor.x, neighbor.y);
write_buffer[neighbor.grid_index][neighbor_grid_elem_idx].set(desired_state);
}
write_buffer[neighbor.grid_index][neighbor_grid_elem_idx].set(desired_state);
}
}
}
node_changed[node_index] = true;
}
node_changed[i] = true;
});
}
IndexMaskMemory memory;
IndexMask mask = IndexMask::from_bools(node_changed, memory);
mask.foreach_index(GrainSize(1), [&](const int64_t index) {
undo::push_node(depsgraph, object, nodes[index], undo::Type::HideVert);
});
const IndexMask changed_nodes = IndexMask::from_bools(node_changed, memory);
undo::push_nodes(depsgraph, object, changed_nodes, undo::Type::HideVert);
BitGroupVector<> &last_buffer = buffers.write_buffer(iterations - 1);
grid_hidden = std::move(last_buffer);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (const int node_index : range) {
if (!node_changed[node_index]) {
continue;
}
bke::pbvh::Node *node = nodes[node_index];
BKE_pbvh_node_mark_update_visibility(*node);
bke::pbvh::node_update_visibility_grids(grid_hidden,
static_cast<bke::pbvh::GridsNode &>(*node));
}
changed_nodes.foreach_index(GrainSize(1), [&](const int i) {
BKE_pbvh_node_mark_update_visibility(nodes[i]);
bke::pbvh::node_update_visibility_grids(grid_hidden, nodes[i]);
});
multires_mark_as_modified(&depsgraph, &object, MULTIRES_HIDDEN_MODIFIED);
@@ -1085,14 +1096,14 @@ static Array<bool> duplicate_visibility_bmesh(const Object &object)
static void grow_shrink_visibility_bmesh(const Depsgraph &depsgraph,
Object &object,
const Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
const VisAction action,
const int iterations)
{
for (const int i : IndexRange(iterations)) {
UNUSED_VARS(i);
const Array<bool> prev_visibility = duplicate_visibility_bmesh(object);
partialvis_update_bmesh_nodes(depsgraph, object, nodes, action, [&](BMVert *vert) {
partialvis_update_bmesh_nodes(depsgraph, object, node_mask, action, [&](BMVert *vert) {
Vector<BMVert *, 64> neighbors;
for (BMVert *neighbor : vert_neighbors_get_bmesh(*vert, neighbors)) {
if (prev_visibility[BM_elem_index_get(neighbor)] == action_to_hide(action)) {
@@ -1114,7 +1125,8 @@ static int visibility_filter_exec(bContext *C, wmOperator *op)
const VisAction mode = VisAction(RNA_enum_get(op->ptr, "action"));
Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(pbvh);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
int num_verts = SCULPT_vertex_count_get(object);
@@ -1129,13 +1141,13 @@ static int visibility_filter_exec(bContext *C, wmOperator *op)
undo::push_begin(object, op);
switch (pbvh.type()) {
case bke::pbvh::Type::Mesh:
grow_shrink_visibility_mesh(depsgraph, object, nodes, mode, iterations);
grow_shrink_visibility_mesh(depsgraph, object, node_mask, mode, iterations);
break;
case bke::pbvh::Type::Grids:
grow_shrink_visibility_grid(depsgraph, object, nodes, mode, iterations);
grow_shrink_visibility_grid(depsgraph, object, node_mask, mode, iterations);
break;
case bke::pbvh::Type::BMesh:
grow_shrink_visibility_bmesh(depsgraph, object, nodes, mode, iterations);
grow_shrink_visibility_bmesh(depsgraph, object, node_mask, mode, iterations);
break;
}
undo::push_end(object);
@@ -1209,7 +1221,7 @@ static void partialvis_gesture_update_mesh(gesture::GestureData &gesture_data)
Object *object = gesture_data.vc.obact;
const Depsgraph &depsgraph = *gesture_data.vc.depsgraph;
const VisAction action = operation->action;
const Span<bke::pbvh::Node *> nodes = gesture_data.nodes;
const IndexMask &node_mask = gesture_data.node_mask;
Mesh *mesh = static_cast<Mesh *>(object->data);
bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
@@ -1221,13 +1233,14 @@ static void partialvis_gesture_update_mesh(gesture::GestureData &gesture_data)
const bool value = action_to_hide(action);
const Span<float3> positions = bke::pbvh::vert_positions_eval(depsgraph, *object);
const Span<float3> normals = bke::pbvh::vert_normals_eval(depsgraph, *object);
vert_hide_update(depsgraph, *object, nodes, [&](const Span<int> verts, MutableSpan<bool> hide) {
for (const int i : verts.index_range()) {
if (gesture::is_affected(gesture_data, positions[verts[i]], normals[verts[i]])) {
hide[i] = value;
}
}
});
vert_hide_update(
depsgraph, *object, node_mask, [&](const Span<int> verts, MutableSpan<bool> hide) {
for (const int i : verts.index_range()) {
if (gesture::is_affected(gesture_data, positions[verts[i]], normals[verts[i]])) {
hide[i] = value;
}
}
});
}
static void partialvis_gesture_update_grids(Depsgraph &depsgraph,
@@ -1236,7 +1249,7 @@ static void partialvis_gesture_update_grids(Depsgraph &depsgraph,
HideShowOperation *operation = reinterpret_cast<HideShowOperation *>(gesture_data.operation);
Object *object = gesture_data.vc.obact;
const VisAction action = operation->action;
const Span<bke::pbvh::Node *> nodes = gesture_data.nodes;
const IndexMask &node_mask = gesture_data.node_mask;
SubdivCCG &subdiv_ccg = *object->sculpt->subdiv_ccg;
@@ -1244,7 +1257,7 @@ static void partialvis_gesture_update_grids(Depsgraph &depsgraph,
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
const Span<CCGElem *> grids = subdiv_ccg.grids;
grid_hide_update(
depsgraph, *object, nodes, [&](const int grid_index, MutableBoundedBitSpan hide) {
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)) {
@@ -1268,7 +1281,7 @@ static void partialvis_gesture_update_bmesh(gesture::GestureData &gesture_data)
partialvis_update_bmesh_nodes(*gesture_data.vc.depsgraph,
*gesture_data.vc.obact,
gesture_data.nodes,
gesture_data.node_mask,
operation->action,
selection_test_fn);
}

View File

@@ -8,6 +8,7 @@
#pragma once
#include "BLI_index_mask_fwd.hh"
#include "BLI_span.hh"
struct bContext;
@@ -20,8 +21,8 @@ class Node;
namespace blender::ed::sculpt_paint::hide {
void sync_all_from_faces(Object &object);
void mesh_show_all(const Depsgraph &depsgraph, Object &object, Span<bke::pbvh::Node *> nodes);
void grids_show_all(Depsgraph &depsgraph, Object &object, Span<bke::pbvh::Node *> nodes);
void mesh_show_all(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask);
void grids_show_all(Depsgraph &depsgraph, Object &object, const IndexMask &node_mask);
void tag_update_visibility(const bContext &C);
void PAINT_OT_hide_show_masked(wmOperatorType *ot);

View File

@@ -11,6 +11,7 @@
#include "BLI_array.hh"
#include "BLI_compiler_compat.h"
#include "BLI_function_ref.hh"
#include "BLI_index_mask_fwd.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_set.hh"
#include "BLI_span.hh"
@@ -550,10 +551,11 @@ void init_session_data(const ToolSettings &ts, Object &ob);
void init_session(
Main &bmain, Depsgraph &depsgraph, Scene &scene, Object &ob, eObjectMode object_mode);
Vector<bke::pbvh::Node *> pbvh_gather_generic(const Depsgraph &depsgraph,
Object &ob,
const VPaint &wp,
const Brush &brush);
IndexMask pbvh_gather_generic(const Depsgraph &depsgraph,
const Object &ob,
const VPaint &wp,
const Brush &brush,
IndexMaskMemory &memory);
void mode_enter_generic(
Main &bmain, Depsgraph &depsgraph, Scene &scene, Object &ob, eObjectMode mode_flag);

View File

@@ -41,6 +41,7 @@
#include "bmesh.hh"
#include "mesh_brush_common.hh"
#include "paint_intern.hh"
#include "sculpt_gesture.hh"
#include "sculpt_hide.hh"
@@ -251,9 +252,12 @@ void average_neighbor_mask_bmesh(const int mask_offset,
void update_mask_mesh(const Depsgraph &depsgraph,
Object &object,
const Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
FunctionRef<void(MutableSpan<float>, Span<int>)> update_fn)
{
SculptSession &ss = *object.sculpt;
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
Mesh &mesh = *static_cast<Mesh *>(object.data);
bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
const VArraySpan hide_vert = *attributes.lookup<bool>(".hide_vert", bke::AttrDomain::Point);
@@ -269,22 +273,20 @@ void update_mask_mesh(const Depsgraph &depsgraph,
};
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
threading::isolate_task([&]() {
for (bke::pbvh::Node *node : nodes.slice(range)) {
const Span<int> verts = hide::node_visible_verts(*node, hide_vert, tls.visible_verts);
tls.mask.resize(verts.size());
array_utils::gather<float>(mask.span, verts, tls.mask);
update_fn(tls.mask, verts);
if (array_utils::indexed_data_equal<float>(mask.span, verts, tls.mask)) {
continue;
}
undo::push_node(depsgraph, object, node, undo::Type::Mask);
array_utils::scatter<float>(tls.mask, verts, mask.span);
bke::pbvh::node_update_mask_mesh(mask.span, static_cast<bke::pbvh::MeshNode &>(*node));
BKE_pbvh_node_mark_redraw(*node);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> verts = hide::node_visible_verts(nodes[i], hide_vert, tls.visible_verts);
tls.mask.resize(verts.size());
gather_data_mesh(mask.span.as_span(), verts, tls.mask.as_mutable_span());
update_fn(tls.mask, verts);
if (array_utils::indexed_data_equal<float>(mask.span, verts, tls.mask)) {
return;
}
undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask);
scatter_data_mesh(tls.mask.as_span(), verts, mask.span);
bke::pbvh::node_update_mask_mesh(mask.span, static_cast<bke::pbvh::MeshNode &>(nodes[i]));
BKE_pbvh_node_mark_redraw(nodes[i]);
});
});
@@ -363,7 +365,7 @@ static const EnumPropertyItem mode_items[] = {
{int(FloodFillMode::InverseMeshValue), "INVERT", 0, "Invert", "Invert the mask"},
{0}};
static Span<int> get_hidden_verts(const bke::pbvh::Node &node,
static Span<int> get_hidden_verts(const bke::pbvh::MeshNode &node,
const Span<bool> hide_vert,
Vector<int> &indices)
{
@@ -384,8 +386,10 @@ static Span<int> get_hidden_verts(const bke::pbvh::Node &node,
static bool try_remove_mask_mesh(const Depsgraph &depsgraph,
Object &object,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
SculptSession &ss = *object.sculpt;
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
Mesh &mesh = *static_cast<Mesh *>(object.data);
bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
const VArraySpan mask = *attributes.lookup<float>(".sculpt_mask", bke::AttrDomain::Point);
@@ -399,21 +403,25 @@ static bool try_remove_mask_mesh(const Depsgraph &depsgraph,
const VArraySpan hide_vert = *attributes.lookup<bool>(".hide_vert", bke::AttrDomain::Point);
threading::EnumerableThreadSpecific<Vector<int>> all_index_data;
const bool hidden_masked_verts = threading::parallel_reduce(
nodes.index_range(),
node_mask.index_range(),
1,
false,
[&](const IndexRange range, bool init) {
if (init) {
return init;
[&](const IndexRange range, bool value) {
if (value) {
return value;
}
Vector<int> &index_data = all_index_data.local();
for (const bke::pbvh::Node *node : nodes.slice(range)) {
const Span<int> verts = get_hidden_verts(*node, hide_vert, index_data);
if (std::any_of(verts.begin(), verts.end(), [&](int i) { return mask[i] > 0.0f; })) {
return true;
node_mask.slice(range).foreach_index([&](const int i) {
if (value) {
return;
}
}
return false;
const Span<int> verts = get_hidden_verts(nodes[i], hide_vert, index_data);
if (std::any_of(verts.begin(), verts.end(), [&](int i) { return mask[i] > 0.0f; })) {
value = true;
return;
}
});
return value;
},
std::logical_or());
if (hidden_masked_verts) {
@@ -421,31 +429,37 @@ static bool try_remove_mask_mesh(const Depsgraph &depsgraph,
}
/* Store undo data for nodes with changed mask. */
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (bke::pbvh::Node *node : nodes.slice(range)) {
const Span<int> verts = bke::pbvh::node_unique_verts(*node);
if (std::all_of(verts.begin(), verts.end(), [&](const int i) { return mask[i] == 0.0f; })) {
continue;
}
undo::push_node(depsgraph, object, node, undo::Type::Mask);
BKE_pbvh_node_mark_redraw(*node);
node_mask.foreach_index(GrainSize(1), [&](const int i) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
if (std::all_of(verts.begin(), verts.end(), [&](const int i) { return mask[i] == 0.0f; })) {
return;
}
undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask);
BKE_pbvh_node_mark_redraw(nodes[i]);
});
attributes.remove(".sculpt_mask");
/* Avoid calling #BKE_pbvh_node_mark_update_mask by doing that update here. */
node_mask.foreach_index([&](const int i) {
BKE_pbvh_node_fully_masked_set(nodes[i], false);
BKE_pbvh_node_fully_unmasked_set(nodes[i], true);
});
return true;
}
static void fill_mask_mesh(const Depsgraph &depsgraph,
Object &object,
const float value,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
SculptSession &ss = *object.sculpt;
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
Mesh &mesh = *static_cast<Mesh *>(object.data);
bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
const VArraySpan hide_vert = *attributes.lookup<bool>(".hide_vert", bke::AttrDomain::Point);
if (value == 0.0f) {
if (try_remove_mask_mesh(depsgraph, object, nodes)) {
if (try_remove_mask_mesh(depsgraph, object, node_mask)) {
return;
}
}
@@ -454,20 +468,25 @@ static void fill_mask_mesh(const Depsgraph &depsgraph,
".sculpt_mask", bke::AttrDomain::Point);
threading::EnumerableThreadSpecific<Vector<int>> all_index_data;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
Vector<int> &index_data = all_index_data.local();
for (bke::pbvh::Node *node : nodes.slice(range)) {
const Span<int> verts = hide::node_visible_verts(*node, hide_vert, index_data);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> verts = hide::node_visible_verts(nodes[i], hide_vert, index_data);
if (std::all_of(verts.begin(), verts.end(), [&](int i) { return mask.span[i] == value; })) {
continue;
return;
}
undo::push_node(depsgraph, object, node, undo::Type::Mask);
undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask);
mask.span.fill_indices(verts, value);
BKE_pbvh_node_mark_redraw(*node);
}
BKE_pbvh_node_mark_redraw(nodes[i]);
});
});
mask.finish();
/* Avoid calling #BKE_pbvh_node_mark_update_mask by doing that update here. */
node_mask.foreach_index([&](const int i) {
BKE_pbvh_node_fully_masked_set(nodes[i], value == 1.0f);
BKE_pbvh_node_fully_unmasked_set(nodes[i], value == 0.0f);
});
}
static void fill_mask_grids(Main &bmain,
@@ -475,9 +494,12 @@ static void fill_mask_grids(Main &bmain,
Depsgraph &depsgraph,
Object &object,
const float value,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
SculptSession &ss = *object.sculpt;
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
if (value == 0.0f && !key.has_mask) {
@@ -492,54 +514,60 @@ static void fill_mask_grids(Main &bmain,
const Span<CCGElem *> grids = subdiv_ccg.grids;
bool any_changed = false;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (bke::pbvh::Node *node : nodes.slice(range)) {
const Span<int> grid_indices = bke::pbvh::node_grid_indices(*node);
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;
}))
{
continue;
}
undo::push_node(depsgraph, object, node, undo::Type::Mask);
if (grid_hidden.is_empty()) {
for (const int grid : grid_indices) {
node_mask.foreach_index(GrainSize(1), [&](const int i) {
const Span<int> grid_indices = bke::pbvh::node_grid_indices(nodes[i]);
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)) {
CCG_elem_offset_mask(key, elem, i) = value;
if (CCG_elem_offset_mask(key, elem, i) != value) {
return false;
}
}
}
}
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; });
}
}
BKE_pbvh_node_mark_redraw(*node);
any_changed = true;
return true;
}))
{
return;
}
undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask);
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;
}
}
}
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; });
}
}
BKE_pbvh_node_mark_redraw(nodes[i]);
any_changed = true;
});
if (any_changed) {
multires_mark_as_modified(&depsgraph, &object, MULTIRES_COORDS_MODIFIED);
}
/* Avoid calling #BKE_pbvh_node_mark_update_mask by doing that update here. */
node_mask.foreach_index([&](const int i) {
BKE_pbvh_node_fully_masked_set(nodes[i], value == 1.0f);
BKE_pbvh_node_fully_unmasked_set(nodes[i], value == 0.0f);
});
}
static void fill_mask_bmesh(const Depsgraph &depsgraph,
Object &object,
const float value,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
BMesh &bm = *object.sculpt->bm;
SculptSession &ss = *object.sculpt;
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
BMesh &bm = *ss.bm;
const int offset = CustomData_get_offset_named(&bm.vdata, CD_PROP_FLOAT, ".sculpt_mask");
if (value == 0.0f && offset == -1) {
return;
@@ -550,22 +578,25 @@ static void fill_mask_bmesh(const Depsgraph &depsgraph,
return;
}
undo::push_node(depsgraph, object, nodes.first(), undo::Type::Mask);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (bke::pbvh::Node *node : nodes.slice(range)) {
bool redraw = false;
for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(node)) {
if (!BM_elem_flag_test(vert, BM_ELEM_HIDDEN)) {
if (BM_ELEM_CD_GET_FLOAT(vert, offset) != value) {
BM_ELEM_CD_SET_FLOAT(vert, offset, value);
redraw = true;
}
node_mask.foreach_index(GrainSize(1), [&](const int i) {
bool redraw = false;
undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask);
for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(&nodes[i])) {
if (!BM_elem_flag_test(vert, BM_ELEM_HIDDEN)) {
if (BM_ELEM_CD_GET_FLOAT(vert, offset) != value) {
BM_ELEM_CD_SET_FLOAT(vert, offset, value);
redraw = true;
}
}
if (redraw) {
BKE_pbvh_node_mark_redraw(*node);
}
}
if (redraw) {
BKE_pbvh_node_mark_redraw(nodes[i]);
}
});
/* Avoid calling #BKE_pbvh_node_mark_update_mask by doing that update here. */
node_mask.foreach_index([&](const int i) {
BKE_pbvh_node_fully_masked_set(nodes[i], value == 1.0f);
BKE_pbvh_node_fully_unmasked_set(nodes[i], value == 0.0f);
});
}
@@ -573,65 +604,61 @@ static void fill_mask(
Main &bmain, const Scene &scene, Depsgraph &depsgraph, Object &object, const float value)
{
bke::pbvh::Tree &pbvh = *object.sculpt->pbvh;
Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(pbvh);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
switch (pbvh.type()) {
case bke::pbvh::Type::Mesh:
fill_mask_mesh(depsgraph, object, value, nodes);
fill_mask_mesh(depsgraph, object, value, node_mask);
break;
case bke::pbvh::Type::Grids:
fill_mask_grids(bmain, scene, depsgraph, object, value, nodes);
fill_mask_grids(bmain, scene, depsgraph, object, value, node_mask);
break;
case bke::pbvh::Type::BMesh:
fill_mask_bmesh(depsgraph, object, value, nodes);
fill_mask_bmesh(depsgraph, object, value, node_mask);
break;
}
/* Avoid calling #BKE_pbvh_node_mark_update_mask by doing that update here. */
for (bke::pbvh::Node *node : nodes) {
BKE_pbvh_node_fully_masked_set(*node, value == 1.0f);
BKE_pbvh_node_fully_unmasked_set(*node, value == 0.0f);
}
}
static void invert_mask_grids(Main &bmain,
const Scene &scene,
Depsgraph &depsgraph,
Object &object,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
SculptSession &ss = *object.sculpt;
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
MultiresModifierData &mmd = *BKE_sculpt_multires_active(&scene, &object);
BKE_sculpt_mask_layers_ensure(&depsgraph, &bmain, &object, &mmd);
undo::push_nodes(depsgraph, object, nodes, undo::Type::Mask);
undo::push_nodes(depsgraph, object, node_mask, undo::Type::Mask);
const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden;
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
const Span<CCGElem *> grids = subdiv_ccg.grids;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (bke::pbvh::Node *node : nodes.slice(range)) {
const Span<int> grid_indices = bke::pbvh::node_grid_indices(*node);
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);
}
node_mask.foreach_index(GrainSize(1), [&](const int i) {
const Span<int> grid_indices = bke::pbvh::node_grid_indices(nodes[i]);
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);
}
}
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);
});
}
}
BKE_pbvh_node_mark_update_mask(*node);
bke::pbvh::node_update_mask_grids(key, grids, static_cast<bke::pbvh::GridsNode &>(*node));
}
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);
});
}
}
BKE_pbvh_node_mark_update_mask(nodes[i]);
bke::pbvh::node_update_mask_grids(key, grids, nodes[i]);
});
multires_mark_as_modified(&depsgraph, &object, MULTIRES_COORDS_MODIFIED);
@@ -639,8 +666,9 @@ static void invert_mask_grids(Main &bmain,
static void invert_mask_bmesh(const Depsgraph &depsgraph,
Object &object,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
MutableSpan<bke::pbvh::BMeshNode> nodes = object.sculpt->pbvh->nodes<bke::pbvh::BMeshNode>();
BMesh &bm = *object.sculpt->bm;
const int offset = CustomData_get_offset_named(&bm.vdata, CD_PROP_FLOAT, ".sculpt_mask");
if (offset == -1) {
@@ -648,37 +676,36 @@ static void invert_mask_bmesh(const Depsgraph &depsgraph,
return;
}
undo::push_nodes(depsgraph, object, nodes, undo::Type::Mask);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (bke::pbvh::Node *node : nodes.slice(range)) {
for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(node)) {
if (!BM_elem_flag_test(vert, BM_ELEM_HIDDEN)) {
BM_ELEM_CD_SET_FLOAT(vert, offset, 1.0f - BM_ELEM_CD_GET_FLOAT(vert, offset));
}
undo::push_nodes(depsgraph, object, node_mask, undo::Type::Mask);
node_mask.foreach_index(GrainSize(1), [&](const int i) {
for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(&nodes[i])) {
if (!BM_elem_flag_test(vert, BM_ELEM_HIDDEN)) {
BM_ELEM_CD_SET_FLOAT(vert, offset, 1.0f - BM_ELEM_CD_GET_FLOAT(vert, offset));
}
BKE_pbvh_node_mark_update_mask(*node);
bke::pbvh::node_update_mask_bmesh(offset, static_cast<bke::pbvh::BMeshNode &>(*node));
}
BKE_pbvh_node_mark_update_mask(nodes[i]);
bke::pbvh::node_update_mask_bmesh(offset, nodes[i]);
});
}
static void invert_mask(Main &bmain, const Scene &scene, Depsgraph &depsgraph, Object &object)
{
Vector<bke::pbvh::Node *> nodes = bke::pbvh::search_gather(*object.sculpt->pbvh, {});
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*object.sculpt->pbvh, memory);
switch (object.sculpt->pbvh->type()) {
case bke::pbvh::Type::Mesh:
write_mask_mesh(
depsgraph, object, nodes, [&](MutableSpan<float> mask, const Span<int> verts) {
depsgraph, object, node_mask, [&](MutableSpan<float> mask, const Span<int> verts) {
for (const int vert : verts) {
mask[vert] = 1.0f - mask[vert];
}
});
break;
case bke::pbvh::Type::Grids:
invert_mask_grids(bmain, scene, depsgraph, object, nodes);
invert_mask_grids(bmain, scene, depsgraph, object, node_mask);
break;
case bke::pbvh::Type::BMesh:
invert_mask_bmesh(depsgraph, object, nodes);
invert_mask_bmesh(depsgraph, object, node_mask);
break;
}
}
@@ -779,7 +806,8 @@ static float mask_gesture_get_new_value(const float elem, FloodFillMode mode, fl
static void gesture_apply_for_symmetry_pass(bContext & /*C*/, gesture::GestureData &gesture_data)
{
const Span<bke::pbvh::Node *> nodes = gesture_data.nodes;
SculptSession &ss = *gesture_data.ss;
const IndexMask &node_mask = gesture_data.node_mask;
const MaskOperation &op = *reinterpret_cast<const MaskOperation *>(gesture_data.operation);
Object &object = *gesture_data.vc.obact;
const Depsgraph &depsgraph = *gesture_data.vc.depsgraph;
@@ -788,7 +816,7 @@ static void gesture_apply_for_symmetry_pass(bContext & /*C*/, gesture::GestureDa
const Span<float3> positions = bke::pbvh::vert_positions_eval(depsgraph, object);
const Span<float3> normals = bke::pbvh::vert_normals_eval(depsgraph, object);
update_mask_mesh(
depsgraph, object, nodes, [&](MutableSpan<float> node_mask, const Span<int> verts) {
depsgraph, object, node_mask, [&](MutableSpan<float> node_mask, const Span<int> verts) {
for (const int i : verts.index_range()) {
const int vert = verts[i];
if (gesture::is_affected(gesture_data, positions[vert], normals[vert])) {
@@ -799,14 +827,15 @@ static void gesture_apply_for_symmetry_pass(bContext & /*C*/, gesture::GestureDa
break;
}
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
SubdivCCG &subdiv_ccg = *gesture_data.ss->subdiv_ccg;
const Span<CCGElem *> grids = subdiv_ccg.grids;
const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden;
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (bke::pbvh::Node *node : nodes.slice(range)) {
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 : bke::pbvh::node_grid_indices(*node)) {
for (const int grid : bke::pbvh::node_grid_indices(nodes[i])) {
CCGElem *elem = grids[grid];
BKE_subdiv_ccg_foreach_visible_grid_vert(key, grid_hidden, grid, [&](const int i) {
if (gesture::is_affected(gesture_data,
@@ -816,36 +845,37 @@ static void gesture_apply_for_symmetry_pass(bContext & /*C*/, gesture::GestureDa
float &mask = CCG_elem_offset_mask(key, elem, i);
if (!any_changed) {
any_changed = true;
undo::push_node(depsgraph, object, node, undo::Type::Mask);
undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask);
}
mask = mask_gesture_get_new_value(mask, op.mode, op.value);
}
});
BKE_pbvh_node_mark_update_mask(*node);
BKE_pbvh_node_mark_update_mask(nodes[i]);
}
}
});
});
break;
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
BMesh &bm = *gesture_data.ss->bm;
const int offset = CustomData_get_offset_named(&bm.vdata, CD_PROP_FLOAT, ".sculpt_mask");
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (bke::pbvh::Node *node : nodes.slice(range)) {
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 (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(node)) {
for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(&nodes[i])) {
if (gesture::is_affected(gesture_data, vert->co, vert->no)) {
const float old_mask = BM_ELEM_CD_GET_FLOAT(vert, offset);
if (!any_changed) {
any_changed = true;
undo::push_node(depsgraph, object, node, undo::Type::Mask);
undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask);
}
const float new_mask = mask_gesture_get_new_value(old_mask, op.mode, op.value);
BM_ELEM_CD_SET_FLOAT(vert, offset, new_mask);
}
}
BKE_pbvh_node_mark_update_mask(*node);
}
BKE_pbvh_node_mark_update_mask(nodes[i]);
});
});
break;
}

View File

@@ -10,6 +10,7 @@
#include "BLI_array.hh"
#include "BLI_function_ref.hh"
#include "BLI_index_mask_fwd.hh"
#include "BLI_set.hh"
struct BMesh;
@@ -46,7 +47,7 @@ void average_neighbor_mask_bmesh(int mask_offset,
/** Write to the mask attribute for each node, storing undo data. */
void write_mask_mesh(const Depsgraph &depsgraph,
Object &object,
Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
FunctionRef<void(MutableSpan<float>, Span<int>)> write_fn);
/**
@@ -55,7 +56,7 @@ void write_mask_mesh(const Depsgraph &depsgraph,
*/
void update_mask_mesh(const Depsgraph &depsgraph,
Object &object,
Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
FunctionRef<void(MutableSpan<float>, Span<int>)> update_fn);
/** Check whether array data is the same as the stored mask for the referenced geometry. */

View File

@@ -297,18 +297,19 @@ void init_session_data(const ToolSettings &ts, Object &ob)
}
}
Vector<bke::pbvh::Node *> pbvh_gather_generic(const Depsgraph &depsgraph,
Object &ob,
const VPaint &wp,
const Brush &brush)
IndexMask pbvh_gather_generic(const Depsgraph &depsgraph,
const Object &ob,
const VPaint &wp,
const Brush &brush,
IndexMaskMemory &memory)
{
SculptSession &ss = *ob.sculpt;
const bool use_normal = vwpaint::use_normal(wp);
Vector<bke::pbvh::Node *> nodes;
IndexMask nodes;
/* Build a list of all nodes that are potentially within the brush's area of influence */
if (brush.falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE) {
nodes = bke::pbvh::search_gather(*ss.pbvh, [&](bke::pbvh::Node &node) {
nodes = bke::pbvh::search_nodes(*ss.pbvh, memory, [&](const bke::pbvh::Node &node) {
return node_in_sphere(node, ss.cache->location, ss.cache->radius_squared, true);
});
@@ -318,7 +319,7 @@ Vector<bke::pbvh::Node *> pbvh_gather_generic(const Depsgraph &depsgraph,
else {
const DistRayAABB_Precalc ray_dist_precalc = dist_squared_ray_to_aabb_v3_precalc(
ss.cache->location, ss.cache->view_normal);
nodes = bke::pbvh::search_gather(*ss.pbvh, [&](bke::pbvh::Node &node) {
nodes = bke::pbvh::search_nodes(*ss.pbvh, memory, [&](const bke::pbvh::Node &node) {
return node_in_cylinder(ray_dist_precalc, node, ss.cache->radius_squared, true);
});
@@ -1045,7 +1046,8 @@ static void do_vpaint_brush_blur_loops(const bContext *C,
VPaintData &vpd,
Object &ob,
Mesh &mesh,
const Span<bke::pbvh::Node *> nodes,
const Span<bke::pbvh::MeshNode> nodes,
const IndexMask &node_mask,
GMutableSpan attribute)
{
SculptSession &ss = *ob.sculpt;
@@ -1089,10 +1091,10 @@ static void do_vpaint_brush_blur_loops(const bContext *C,
Vector<float> distances;
};
threading::EnumerableThreadSpecific<LocalData> all_tls;
blender::threading::parallel_for(nodes.index_range(), 1LL, [&](IndexRange range) {
blender::threading::parallel_for(node_mask.index_range(), 1LL, [&](IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> verts = bke::pbvh::node_unique_verts(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
tls.factors.resize(verts.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide(mesh, verts, factors);
@@ -1193,7 +1195,7 @@ static void do_vpaint_brush_blur_loops(const bContext *C,
}
});
}
};
});
});
}
@@ -1202,7 +1204,8 @@ static void do_vpaint_brush_blur_verts(const bContext *C,
VPaintData &vpd,
Object &ob,
Mesh &mesh,
const Span<bke::pbvh::Node *> nodes,
const Span<bke::pbvh::MeshNode> nodes,
const IndexMask &node_mask,
GMutableSpan attribute)
{
SculptSession &ss = *ob.sculpt;
@@ -1246,10 +1249,10 @@ static void do_vpaint_brush_blur_verts(const bContext *C,
Vector<float> distances;
};
threading::EnumerableThreadSpecific<LocalData> all_tls;
blender::threading::parallel_for(nodes.index_range(), 1LL, [&](IndexRange range) {
blender::threading::parallel_for(node_mask.index_range(), 1LL, [&](IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> verts = bke::pbvh::node_unique_verts(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
tls.factors.resize(verts.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide(mesh, verts, factors);
@@ -1341,7 +1344,7 @@ static void do_vpaint_brush_blur_verts(const bContext *C,
Traits::range * brush_strength);
});
}
};
});
});
}
@@ -1350,7 +1353,8 @@ static void do_vpaint_brush_smear(const bContext *C,
VPaintData &vpd,
Object &ob,
Mesh &mesh,
const Span<bke::pbvh::Node *> nodes,
const Span<bke::pbvh::MeshNode> nodes,
const IndexMask &node_mask,
GMutableSpan attribute)
{
SculptSession &ss = *ob.sculpt;
@@ -1406,10 +1410,10 @@ static void do_vpaint_brush_smear(const bContext *C,
Vector<float> distances;
};
threading::EnumerableThreadSpecific<LocalData> all_tls;
blender::threading::parallel_for(nodes.index_range(), 1LL, [&](IndexRange range) {
blender::threading::parallel_for(node_mask.index_range(), 1LL, [&](IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> verts = bke::pbvh::node_unique_verts(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
tls.factors.resize(verts.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide(mesh, verts, factors);
@@ -1544,7 +1548,7 @@ static void do_vpaint_brush_smear(const bContext *C,
}
});
}
}
});
});
}
@@ -1553,7 +1557,8 @@ static void calculate_average_color(VPaintData &vpd,
Mesh &mesh,
const Brush &brush,
const GSpan attribute,
const Span<bke::pbvh::Node *> nodes)
const Span<bke::pbvh::MeshNode> nodes,
const IndexMask &node_mask)
{
SculptSession &ss = *ob.sculpt;
const StrokeCache &cache = *ss.cache;
@@ -1587,14 +1592,14 @@ static void calculate_average_color(VPaintData &vpd,
const Span<Color> colors = attribute.typed<T>().template cast<Color>();
Array<VPaintAverageAccum<Blend>> accum(nodes.size());
blender::threading::parallel_for(nodes.index_range(), 1LL, [&](IndexRange range) {
blender::threading::parallel_for(node_mask.index_range(), 1LL, [&](IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
VPaintAverageAccum<Blend> &accum2 = accum[i];
accum2.len = 0;
memset(accum2.value, 0, sizeof(accum2.value));
const Span<int> verts = bke::pbvh::node_unique_verts(*nodes[i]);
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
tls.factors.resize(verts.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide(mesh, verts, factors);
@@ -1633,7 +1638,7 @@ static void calculate_average_color(VPaintData &vpd,
accum2.value[2] += col.b * col.b;
}
}
}
});
});
Blend accum_len = 0;
@@ -1678,7 +1683,8 @@ static void vpaint_do_draw(const bContext *C,
VPaintData &vpd,
Object &ob,
Mesh &mesh,
const Span<bke::pbvh::Node *> nodes,
const Span<bke::pbvh::MeshNode> nodes,
const IndexMask &node_mask,
GMutableSpan attribute)
{
SculptSession &ss = *ob.sculpt;
@@ -1721,10 +1727,10 @@ static void vpaint_do_draw(const bContext *C,
Vector<float> distances;
};
threading::EnumerableThreadSpecific<LocalData> all_tls;
blender::threading::parallel_for(nodes.index_range(), 1LL, [&](IndexRange range) {
blender::threading::parallel_for(node_mask.index_range(), 1LL, [&](IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> verts = bke::pbvh::node_unique_verts(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
tls.factors.resize(verts.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide(mesh, verts, factors);
@@ -1835,7 +1841,7 @@ static void vpaint_do_draw(const bContext *C,
}
});
}
}
});
});
}
@@ -1844,14 +1850,15 @@ static void vpaint_do_blur(const bContext *C,
VPaintData &vpd,
Object &ob,
Mesh &mesh,
const Span<bke::pbvh::Node *> nodes,
const Span<bke::pbvh::MeshNode> nodes,
const IndexMask &node_mask,
GMutableSpan attribute)
{
if (vpd.domain == AttrDomain::Point) {
do_vpaint_brush_blur_verts(C, vp, vpd, ob, mesh, nodes, attribute);
do_vpaint_brush_blur_verts(C, vp, vpd, ob, mesh, nodes, node_mask, attribute);
}
else {
do_vpaint_brush_blur_loops(C, vp, vpd, ob, mesh, nodes, attribute);
do_vpaint_brush_blur_loops(C, vp, vpd, ob, mesh, nodes, node_mask, attribute);
}
}
@@ -1861,26 +1868,27 @@ static void vpaint_paint_leaves(bContext *C,
Object &ob,
Mesh &mesh,
GMutableSpan attribute,
const Span<bke::pbvh::Node *> nodes)
const Span<bke::pbvh::MeshNode> nodes,
const IndexMask &node_mask)
{
const Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(C);
undo::push_nodes(depsgraph, ob, nodes, undo::Type::Color);
undo::push_nodes(depsgraph, ob, node_mask, undo::Type::Color);
const Brush &brush = *ob.sculpt->cache->brush;
switch ((eBrushVertexPaintTool)brush.vertexpaint_tool) {
case VPAINT_TOOL_AVERAGE:
calculate_average_color(vpd, ob, mesh, brush, attribute, nodes);
vpaint_do_draw(C, vp, vpd, ob, mesh, nodes, attribute);
calculate_average_color(vpd, ob, mesh, brush, attribute, nodes, node_mask);
vpaint_do_draw(C, vp, vpd, ob, mesh, nodes, node_mask, attribute);
break;
case VPAINT_TOOL_DRAW:
vpaint_do_draw(C, vp, vpd, ob, mesh, nodes, attribute);
vpaint_do_draw(C, vp, vpd, ob, mesh, nodes, node_mask, attribute);
break;
case VPAINT_TOOL_BLUR:
vpaint_do_blur(C, vp, vpd, ob, mesh, nodes, attribute);
vpaint_do_blur(C, vp, vpd, ob, mesh, nodes, node_mask, attribute);
break;
case VPAINT_TOOL_SMEAR:
do_vpaint_brush_smear(C, vp, vpd, ob, mesh, nodes, attribute);
do_vpaint_brush_smear(C, vp, vpd, ob, mesh, nodes, node_mask, attribute);
break;
default:
break;
@@ -1903,7 +1911,8 @@ static void vpaint_do_paint(bContext *C,
ss.cache->radial_symmetry_pass = i;
SCULPT_cache_calc_brushdata_symm(*ss.cache, symm, axis, angle);
Vector<bke::pbvh::Node *> nodes = vwpaint::pbvh_gather_generic(depsgraph, ob, vp, brush);
IndexMaskMemory memory;
const IndexMask node_mask = vwpaint::pbvh_gather_generic(depsgraph, ob, vp, brush, memory);
bke::GSpanAttributeWriter attribute = mesh.attributes_for_write().lookup_for_write_span(
mesh.active_color_attribute);
@@ -1916,7 +1925,8 @@ static void vpaint_do_paint(bContext *C,
}
/* Paint those leaves. */
vpaint_paint_leaves(C, vp, vpd, ob, mesh, attribute.span, nodes);
vpaint_paint_leaves(
C, vp, vpd, ob, mesh, attribute.span, ss.pbvh->nodes<bke::pbvh::MeshNode>(), node_mask);
attribute.finish();
}
@@ -2303,20 +2313,20 @@ static int vertex_color_set_exec(bContext *C, wmOperator *op)
BKE_sculpt_update_object_for_edit(CTX_data_ensure_evaluated_depsgraph(C), &obact, true);
undo::push_begin(obact, op);
Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(*obact.sculpt->pbvh);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*obact.sculpt->pbvh, memory);
const Mesh &mesh = *static_cast<const Mesh *>(obact.data);
/* The sculpt undo system needs bke::pbvh::Tree node corner indices for corner domain
* color attributes. */
BKE_pbvh_ensure_node_face_corners(*obact.sculpt->pbvh, mesh.corner_tris());
undo::push_nodes(depsgraph, obact, nodes, undo::Type::Color);
undo::push_nodes(depsgraph, obact, node_mask, undo::Type::Color);
fill_active_color(obact, paintcol, true, affect_alpha);
for (bke::pbvh::Node *node : nodes) {
BKE_pbvh_node_mark_update_color(*node);
}
MutableSpan<bke::pbvh::MeshNode> nodes = obact.sculpt->pbvh->nodes<bke::pbvh::MeshNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_color(nodes[i]); });
undo::push_end(obact);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, &obact);

View File

@@ -322,14 +322,14 @@ static void transform_active_color(bContext *C,
* attributes. */
BKE_pbvh_ensure_node_face_corners(pbvh, mesh.corner_tris());
Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(pbvh);
undo::push_nodes(depsgraph, obact, nodes, undo::Type::Color);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
undo::push_nodes(depsgraph, obact, node_mask, undo::Type::Color);
transform_active_color_data(*BKE_mesh_from_object(&obact), transform_fn);
for (bke::pbvh::Node *node : nodes) {
BKE_pbvh_node_mark_update_color(*node);
}
MutableSpan<bke::pbvh::MeshNode> nodes = pbvh.nodes<bke::pbvh::MeshNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_color(nodes[i]); });
undo::push_end(obact);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, &obact);

View File

@@ -1064,15 +1064,16 @@ static void precompute_weight_values(
* \{ */
static void parallel_nodes_loop_with_mirror_check(const Mesh &mesh,
const Span<blender::bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
FunctionRef<void(IndexRange)> fn)
{
/* NOTE: current mirroring code cannot be run in parallel */
if (ME_USING_MIRROR_X_VERTEX_GROUPS(&mesh)) {
fn(nodes.index_range());
fn(node_mask.index_range());
}
else {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { fn(range); });
threading::parallel_for(
node_mask.index_range(), 1, [&](const IndexRange range) { fn(range); });
}
}
@@ -1097,10 +1098,11 @@ static void do_wpaint_brush_blur(const Depsgraph &depsgraph,
WPaintData &wpd,
const WeightPaintInfo &wpi,
Mesh &mesh,
const Span<blender::bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
using namespace blender;
SculptSession &ss = *ob.sculpt;
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
const StrokeCache &cache = *ss.cache;
const GroupedSpan<int> vert_to_face = mesh.vert_to_face_map();
@@ -1130,10 +1132,10 @@ static void do_wpaint_brush_blur(const Depsgraph &depsgraph,
Vector<float> distances;
};
threading::EnumerableThreadSpecific<LocalData> all_tls;
parallel_nodes_loop_with_mirror_check(mesh, nodes, [&](const IndexRange range) {
parallel_nodes_loop_with_mirror_check(mesh, node_mask, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> verts = bke::pbvh::node_unique_verts(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
tls.factors.resize(verts.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide(mesh, verts, factors);
@@ -1192,7 +1194,7 @@ static void do_wpaint_brush_blur(const Depsgraph &depsgraph,
weight_final /= total_hit_loops;
do_weight_paint_vertex(vp, ob, wpi, vert, final_alpha, weight_final);
}
}
});
});
}
@@ -1204,10 +1206,11 @@ static void do_wpaint_brush_smear(const Depsgraph &depsgraph,
WPaintData &wpd,
const WeightPaintInfo &wpi,
Mesh &mesh,
const Span<blender::bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
using namespace blender;
SculptSession &ss = *ob.sculpt;
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
const GroupedSpan<int> vert_to_face = mesh.vert_to_face_map();
const StrokeCache &cache = *ss.cache;
if (!cache.is_last_valid) {
@@ -1247,10 +1250,10 @@ static void do_wpaint_brush_smear(const Depsgraph &depsgraph,
Vector<float> distances;
};
threading::EnumerableThreadSpecific<LocalData> all_tls;
parallel_nodes_loop_with_mirror_check(mesh, nodes, [&](const IndexRange range) {
parallel_nodes_loop_with_mirror_check(mesh, node_mask, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> verts = bke::pbvh::node_unique_verts(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
tls.factors.resize(verts.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide(mesh, verts, factors);
@@ -1317,7 +1320,7 @@ static void do_wpaint_brush_smear(const Depsgraph &depsgraph,
do_weight_paint_vertex(vp, ob, wpi, vert, final_alpha, float(weight_final));
}
}
}
});
});
}
@@ -1330,10 +1333,11 @@ static void do_wpaint_brush_draw(const Depsgraph &depsgraph,
const WeightPaintInfo &wpi,
Mesh &mesh,
const float strength,
const Span<blender::bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
using namespace blender;
SculptSession &ss = *ob.sculpt;
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
const StrokeCache &cache = *ss.cache;
/* NOTE: normally `BKE_brush_weight_get(scene, brush)` is used,
@@ -1363,10 +1367,10 @@ static void do_wpaint_brush_draw(const Depsgraph &depsgraph,
Vector<float> distances;
};
threading::EnumerableThreadSpecific<LocalData> all_tls;
parallel_nodes_loop_with_mirror_check(mesh, nodes, [&](const IndexRange range) {
parallel_nodes_loop_with_mirror_check(mesh, node_mask, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> verts = bke::pbvh::node_unique_verts(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
tls.factors.resize(verts.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide(mesh, verts, factors);
@@ -1408,7 +1412,7 @@ static void do_wpaint_brush_draw(const Depsgraph &depsgraph,
do_weight_paint_vertex(vp, ob, wpi, vert, final_alpha, paintweight);
}
}
});
});
}
@@ -1418,10 +1422,11 @@ static float calculate_average_weight(const Depsgraph &depsgraph,
const Brush &brush,
const VPaint &vp,
WeightPaintInfo &wpi,
const Span<blender::bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
using namespace blender;
SculptSession &ss = *ob.sculpt;
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
const StrokeCache &cache = *ss.cache;
const bool use_normal = vwpaint::use_normal(vp);
@@ -1446,13 +1451,13 @@ static float calculate_average_weight(const Depsgraph &depsgraph,
};
threading::EnumerableThreadSpecific<LocalData> all_tls;
const WPaintAverageAccum value = threading::parallel_reduce(
nodes.index_range(),
node_mask.index_range(),
1,
WPaintAverageAccum{},
[&](const IndexRange range, WPaintAverageAccum accum) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> verts = bke::pbvh::node_unique_verts(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
tls.factors.resize(verts.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide(mesh, verts, factors);
@@ -1482,7 +1487,7 @@ static float calculate_average_weight(const Depsgraph &depsgraph,
accum.len++;
accum.value += wpaint_get_active_weight(dv, wpi);
}
}
});
return accum;
},
[](const WPaintAverageAccum &a, const WPaintAverageAccum &b) {
@@ -1497,7 +1502,7 @@ static void wpaint_paint_leaves(bContext *C,
WPaintData &wpd,
WeightPaintInfo &wpi,
Mesh &mesh,
const Span<blender::bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
const Scene &scene = *CTX_data_scene(C);
const Brush &brush = *ob.sculpt->cache->brush;
@@ -1505,23 +1510,24 @@ static void wpaint_paint_leaves(bContext *C,
switch ((eBrushWeightPaintTool)brush.weightpaint_tool) {
case WPAINT_TOOL_AVERAGE: {
do_wpaint_brush_draw(depsgraph,
scene,
ob,
brush,
vp,
wpd,
wpi,
mesh,
calculate_average_weight(depsgraph, ob, mesh, brush, vp, wpi, nodes),
nodes);
do_wpaint_brush_draw(
depsgraph,
scene,
ob,
brush,
vp,
wpd,
wpi,
mesh,
calculate_average_weight(depsgraph, ob, mesh, brush, vp, wpi, node_mask),
node_mask);
break;
}
case WPAINT_TOOL_SMEAR:
do_wpaint_brush_smear(depsgraph, scene, ob, brush, vp, wpd, wpi, mesh, nodes);
do_wpaint_brush_smear(depsgraph, scene, ob, brush, vp, wpd, wpi, mesh, node_mask);
break;
case WPAINT_TOOL_BLUR:
do_wpaint_brush_blur(depsgraph, scene, ob, brush, vp, wpd, wpi, mesh, nodes);
do_wpaint_brush_blur(depsgraph, scene, ob, brush, vp, wpd, wpi, mesh, node_mask);
break;
case WPAINT_TOOL_DRAW:
do_wpaint_brush_draw(depsgraph,
@@ -1533,7 +1539,7 @@ static void wpaint_paint_leaves(bContext *C,
wpi,
mesh,
BKE_brush_weight_get(&scene, &brush),
nodes);
node_mask);
break;
}
}
@@ -1701,10 +1707,10 @@ static void wpaint_do_paint(bContext *C,
ss.cache->radial_symmetry_pass = i;
SCULPT_cache_calc_brushdata_symm(*ss.cache, symm, axis, angle);
Vector<blender::bke::pbvh::Node *> nodes = vwpaint::pbvh_gather_generic(
depsgraph, ob, wp, brush);
IndexMaskMemory memory;
const IndexMask node_mask = vwpaint::pbvh_gather_generic(depsgraph, ob, wp, brush, memory);
wpaint_paint_leaves(C, ob, wp, wpd, wpi, mesh, nodes);
wpaint_paint_leaves(C, ob, wp, wpd, wpi, mesh, node_mask);
}
static void wpaint_do_radial_symmetry(bContext *C,

View File

@@ -842,11 +842,12 @@ std::optional<int> nearest_vert_calc_mesh(const bke::pbvh::Tree &pbvh,
const bool use_original)
{
const float max_distance_sq = max_distance * max_distance;
Vector<bke::pbvh::Node *> nodes = bke::pbvh::search_gather(
const_cast<bke::pbvh::Tree &>(pbvh), [&](bke::pbvh::Node &node) {
IndexMaskMemory memory;
const IndexMask nodes_in_sphere = bke::pbvh::search_nodes(
pbvh, memory, [&](const bke::pbvh::Node &node) {
return node_in_sphere(node, location, max_distance_sq, use_original);
});
if (nodes.is_empty()) {
if (nodes_in_sphere.is_empty()) {
return std::nullopt;
}
@@ -855,13 +856,14 @@ std::optional<int> nearest_vert_calc_mesh(const bke::pbvh::Tree &pbvh,
float distance_sq = std::numeric_limits<float>::max();
};
const Span<bke::pbvh::MeshNode> nodes = pbvh.nodes<bke::pbvh::MeshNode>();
const NearestData nearest = threading::parallel_reduce(
nodes.index_range(),
nodes_in_sphere.index_range(),
1,
NearestData(),
[&](const IndexRange range, NearestData nearest) {
for (const int i : range) {
for (const int vert : bke::pbvh::node_unique_verts(*nodes[i])) {
nodes_in_sphere.slice(range).foreach_index([&](const int i) {
for (const int vert : bke::pbvh::node_unique_verts(nodes[i])) {
if (!hide_vert.is_empty() && hide_vert[vert]) {
continue;
}
@@ -870,7 +872,7 @@ std::optional<int> nearest_vert_calc_mesh(const bke::pbvh::Tree &pbvh,
nearest = {vert, distance_sq};
}
}
}
});
return nearest;
},
[](const NearestData a, const NearestData b) {
@@ -886,11 +888,12 @@ std::optional<SubdivCCGCoord> nearest_vert_calc_grids(const bke::pbvh::Tree &pbv
const bool use_original)
{
const float max_distance_sq = max_distance * max_distance;
Vector<bke::pbvh::Node *> nodes = bke::pbvh::search_gather(
const_cast<bke::pbvh::Tree &>(pbvh), [&](bke::pbvh::Node &node) {
IndexMaskMemory memory;
const IndexMask nodes_in_sphere = bke::pbvh::search_nodes(
pbvh, memory, [&](const bke::pbvh::Node &node) {
return node_in_sphere(node, location, max_distance_sq, use_original);
});
if (nodes.is_empty()) {
if (nodes_in_sphere.is_empty()) {
return std::nullopt;
}
@@ -903,13 +906,14 @@ std::optional<SubdivCCGCoord> nearest_vert_calc_grids(const bke::pbvh::Tree &pbv
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
const Span<CCGElem *> elems = subdiv_ccg.grids;
const Span<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
const NearestData nearest = threading::parallel_reduce(
nodes.index_range(),
nodes_in_sphere.index_range(),
1,
NearestData(),
[&](const IndexRange range, NearestData nearest) {
for (const int i : range) {
for (const int grid : bke::pbvh::node_grid_indices(*nodes[i])) {
nodes_in_sphere.slice(range).foreach_index([&](const int i) {
for (const int grid : bke::pbvh::node_grid_indices(nodes[i])) {
CCGElem *elem = elems[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),
@@ -923,7 +927,7 @@ std::optional<SubdivCCGCoord> nearest_vert_calc_grids(const bke::pbvh::Tree &pbv
}
});
}
}
});
return nearest;
},
[](const NearestData a, const NearestData b) {
@@ -938,11 +942,12 @@ std::optional<BMVert *> nearest_vert_calc_bmesh(const bke::pbvh::Tree &pbvh,
const bool use_original)
{
const float max_distance_sq = max_distance * max_distance;
Vector<bke::pbvh::Node *> nodes = bke::pbvh::search_gather(
const_cast<bke::pbvh::Tree &>(pbvh), [&](bke::pbvh::Node &node) {
IndexMaskMemory memory;
const IndexMask nodes_in_sphere = bke::pbvh::search_nodes(
pbvh, memory, [&](const bke::pbvh::Node &node) {
return node_in_sphere(node, location, max_distance_sq, use_original);
});
if (nodes.is_empty()) {
if (nodes_in_sphere.is_empty()) {
return std::nullopt;
}
@@ -951,13 +956,16 @@ std::optional<BMVert *> nearest_vert_calc_bmesh(const bke::pbvh::Tree &pbvh,
float distance_sq = std::numeric_limits<float>::max();
};
const Span<bke::pbvh::BMeshNode> nodes = pbvh.nodes<bke::pbvh::BMeshNode>();
const NearestData nearest = threading::parallel_reduce(
nodes.index_range(),
nodes_in_sphere.index_range(),
1,
NearestData(),
[&](const IndexRange range, NearestData nearest) {
for (const int i : range) {
for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(nodes[i])) {
nodes_in_sphere.slice(range).foreach_index([&](const int i) {
for (BMVert *vert :
BKE_pbvh_bmesh_node_unique_verts(const_cast<bke::pbvh::BMeshNode *>(&nodes[i])))
{
if (BM_elem_flag_test(vert, BM_ELEM_HIDDEN)) {
continue;
}
@@ -966,7 +974,7 @@ std::optional<BMVert *> nearest_vert_calc_bmesh(const bke::pbvh::Tree &pbvh,
nearest = {vert, distance_sq};
}
}
}
});
return nearest;
},
[](const NearestData a, const NearestData b) {
@@ -1160,61 +1168,61 @@ namespace undo {
static void restore_mask_from_undo_step(Object &object)
{
SculptSession &ss = *object.sculpt;
Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory);
switch (ss.pbvh->type()) {
case bke::pbvh::Type::Mesh: {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
Mesh &mesh = *static_cast<Mesh *>(object.data);
bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
bke::SpanAttributeWriter<float> mask = attributes.lookup_or_add_for_write_span<float>(
".sculpt_mask", bke::AttrDomain::Point);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (bke::pbvh::Node *node : nodes.as_span().slice(range)) {
if (const undo::Node *unode = undo::get_node(node, undo::Type::Mask)) {
const Span<int> verts = bke::pbvh::node_unique_verts(*node);
array_utils::scatter(unode->mask.as_span(), verts, mask.span);
BKE_pbvh_node_mark_update_mask(*node);
}
node_mask.foreach_index(GrainSize(1), [&](const int i) {
if (const undo::Node *unode = undo::get_node(&nodes[i], undo::Type::Mask)) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
array_utils::scatter(unode->mask.as_span(), verts, mask.span);
BKE_pbvh_node_mark_update_mask(nodes[i]);
}
});
mask.finish();
break;
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
const int offset = CustomData_get_offset_named(&ss.bm->vdata, CD_PROP_FLOAT, ".sculpt_mask");
if (offset != -1) {
for (bke::pbvh::Node *node : nodes) {
if (undo::get_node(node, undo::Type::Mask)) {
for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(node)) {
node_mask.foreach_index([&](const int i) {
if (undo::get_node(&nodes[i], undo::Type::Mask)) {
for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(&nodes[i])) {
const float orig_mask = BM_log_original_mask(ss.bm_log, vert);
BM_ELEM_CD_SET_FLOAT(vert, offset, orig_mask);
}
BKE_pbvh_node_mark_update_mask(*node);
BKE_pbvh_node_mark_update_mask(nodes[i]);
}
}
});
}
break;
}
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
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<CCGElem *> grids = subdiv_ccg.grids;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (bke::pbvh::Node *node : nodes.as_span().slice(range)) {
if (const undo::Node *unode = undo::get_node(node, undo::Type::Mask)) {
int index = 0;
for (const int grid : unode->grids) {
CCGElem *elem = grids[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) = unode->mask[index];
}
index++;
node_mask.foreach_index(GrainSize(1), [&](const int i) {
if (const undo::Node *unode = undo::get_node(&nodes[i], undo::Type::Mask)) {
int index = 0;
for (const int grid : unode->grids) {
CCGElem *elem = grids[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) = unode->mask[index];
}
index++;
}
BKE_pbvh_node_mark_update_mask(*node);
}
BKE_pbvh_node_mark_update_mask(nodes[i]);
}
});
break;
@@ -1225,7 +1233,9 @@ static void restore_mask_from_undo_step(Object &object)
static void restore_color_from_undo_step(Object &object)
{
SculptSession &ss = *object.sculpt;
Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh);
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory);
BLI_assert(ss.pbvh->type() == bke::pbvh::Type::Mesh);
Mesh &mesh = *static_cast<Mesh *>(object.data);
@@ -1233,19 +1243,17 @@ static void restore_color_from_undo_step(Object &object)
const Span<int> corner_verts = mesh.corner_verts();
const GroupedSpan<int> vert_to_face_map = ss.vert_to_face_map;
bke::GSpanAttributeWriter color_attribute = color::active_color_attribute_for_write(mesh);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (bke::pbvh::Node *node : nodes.as_span().slice(range)) {
if (const undo::Node *unode = undo::get_node(node, undo::Type::Color)) {
const Span<int> verts = bke::pbvh::node_unique_verts(*node);
for (const int i : verts.index_range()) {
color::color_vert_set(faces,
corner_verts,
vert_to_face_map,
color_attribute.domain,
verts[i],
unode->col[i],
color_attribute.span);
}
node_mask.foreach_index(GrainSize(1), [&](const int i) {
if (const undo::Node *unode = undo::get_node(&nodes[i], undo::Type::Color)) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
for (const int i : verts.index_range()) {
color::color_vert_set(faces,
corner_verts,
vert_to_face_map,
color_attribute.domain,
verts[i],
unode->col[i],
color_attribute.span);
}
}
});
@@ -1255,20 +1263,33 @@ static void restore_color_from_undo_step(Object &object)
static void restore_face_set_from_undo_step(Object &object)
{
SculptSession &ss = *object.sculpt;
Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory);
switch (ss.pbvh->type()) {
case bke::pbvh::Type::Mesh:
case bke::pbvh::Type::Grids: {
case bke::pbvh::Type::Mesh: {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
bke::SpanAttributeWriter<int> attribute = face_set::ensure_face_sets_mesh(object);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (bke::pbvh::Node *node : nodes.as_span().slice(range)) {
if (const undo::Node *unode = undo::get_node(node, undo::Type::FaceSet)) {
const Span<int> faces = unode->face_indices;
const Span<int> face_sets = unode->face_sets;
blender::array_utils::scatter(face_sets, faces, attribute.span);
BKE_pbvh_node_mark_update_face_sets(*node);
}
node_mask.foreach_index(GrainSize(1), [&](const int i) {
if (const undo::Node *unode = undo::get_node(&nodes[i], undo::Type::FaceSet)) {
const Span<int> faces = unode->face_indices;
const Span<int> face_sets = unode->face_sets;
blender::array_utils::scatter(face_sets, faces, attribute.span);
BKE_pbvh_node_mark_update_face_sets(nodes[i]);
}
});
attribute.finish();
break;
}
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
bke::SpanAttributeWriter<int> attribute = face_set::ensure_face_sets_mesh(object);
node_mask.foreach_index(GrainSize(1), [&](const int i) {
if (const undo::Node *unode = undo::get_node(&nodes[i], undo::Type::FaceSet)) {
const Span<int> faces = unode->face_indices;
const Span<int> face_sets = unode->face_sets;
blender::array_utils::scatter(face_sets, faces, attribute.span);
BKE_pbvh_node_mark_update_face_sets(nodes[i]);
}
});
attribute.finish();
@@ -1282,10 +1303,12 @@ static void restore_face_set_from_undo_step(Object &object)
void restore_position_from_undo_step(const Depsgraph &depsgraph, Object &object)
{
SculptSession &ss = *object.sculpt;
Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory);
switch (ss.pbvh->type()) {
case bke::pbvh::Type::Mesh: {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
Mesh &mesh = *static_cast<Mesh *>(object.data);
MutableSpan positions_eval = bke::pbvh::vert_positions_eval_for_write(depsgraph, object);
MutableSpan positions_orig = mesh.vert_positions_for_write();
@@ -1298,11 +1321,11 @@ void restore_position_from_undo_step(const Depsgraph &depsgraph, Object &object)
const bool need_translations = !ss.deform_imats.is_empty() || active_key;
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (bke::pbvh::Node *node : nodes.as_span().slice(range)) {
if (const undo::Node *unode = undo::get_node(node, undo::Type::Position)) {
const Span<int> verts = bke::pbvh::node_unique_verts(*node);
node_mask.slice(range).foreach_index([&](const int i) {
if (const undo::Node *unode = undo::get_node(&nodes[i], undo::Type::Position)) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
const Span<float3> undo_positions = unode->position.as_span().take_front(verts.size());
if (need_translations) {
tls.translations.resize(verts.size());
@@ -1336,48 +1359,46 @@ void restore_position_from_undo_step(const Depsgraph &depsgraph, Object &object)
object, mesh, *active_key, verts, tls.translations, positions_orig);
}
BKE_pbvh_node_mark_positions_update(*node);
BKE_pbvh_node_mark_positions_update(nodes[i]);
}
}
});
});
break;
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
if (!undo::get_bmesh_log_entry()) {
return;
}
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (bke::pbvh::Node *node : nodes.as_span().slice(range)) {
for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(node)) {
if (const float *orig_co = BM_log_find_original_vert_co(ss.bm_log, vert)) {
copy_v3_v3(vert->co, orig_co);
}
node_mask.foreach_index(GrainSize(1), [&](const int i) {
for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(&nodes[i])) {
if (const float *orig_co = BM_log_find_original_vert_co(ss.bm_log, vert)) {
copy_v3_v3(vert->co, orig_co);
}
BKE_pbvh_node_mark_positions_update(*node);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
break;
}
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
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<CCGElem *> grids = subdiv_ccg.grids;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (bke::pbvh::Node *node : nodes.as_span().slice(range)) {
if (const undo::Node *unode = undo::get_node(node, undo::Type::Position)) {
int index = 0;
for (const int grid : unode->grids) {
CCGElem *elem = grids[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) = unode->position[index];
}
index++;
node_mask.foreach_index(GrainSize(1), [&](const int i) {
if (const undo::Node *unode = undo::get_node(&nodes[i], undo::Type::Position)) {
int index = 0;
for (const int grid : unode->grids) {
CCGElem *elem = grids[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) = unode->position[index];
}
index++;
}
BKE_pbvh_node_mark_positions_update(*node);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
}
});
break;
@@ -1654,7 +1675,7 @@ static void calc_area_normal_and_center_node_mesh(const Object &object,
const Brush &brush,
const bool use_area_nos,
const bool use_area_cos,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
SampleLocalData &tls,
AreaNormalCenterData &anctd)
{
@@ -1737,7 +1758,7 @@ static void calc_area_normal_and_center_node_grids(const Object &object,
const Brush &brush,
const bool use_area_nos,
const bool use_area_cos,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
SampleLocalData &tls,
AreaNormalCenterData &anctd)
{
@@ -2009,7 +2030,7 @@ static AreaNormalCenterData calc_area_normal_and_center_reduce(const AreaNormalC
void calc_area_center(const Depsgraph &depsgraph,
const Brush &brush,
const Object &ob,
Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
float r_area_co[3])
{
const SculptSession &ss = *ob.sculpt;
@@ -2025,13 +2046,14 @@ void calc_area_center(const Depsgraph &depsgraph,
const bke::AttributeAccessor attributes = mesh.attributes();
const VArraySpan hide_vert = *attributes.lookup<bool>(".hide_vert", bke::AttrDomain::Point);
const Span<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
anctd = threading::parallel_reduce(
nodes.index_range(),
node_mask.index_range(),
1,
AreaNormalCenterData{},
[&](const IndexRange range, AreaNormalCenterData anctd) {
SampleLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_area_normal_and_center_node_mesh(ob,
vert_positions,
vert_normals,
@@ -2039,10 +2061,10 @@ void calc_area_center(const Depsgraph &depsgraph,
brush,
false,
true,
*nodes[i],
nodes[i],
tls,
anctd);
}
});
return anctd;
},
calc_area_normal_and_center_reduce);
@@ -2051,39 +2073,33 @@ void calc_area_center(const Depsgraph &depsgraph,
case bke::pbvh::Type::BMesh: {
const bool has_bm_orco = ss.bm && dyntopo::stroke_is_dyntopo(ss, brush);
const Span<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
anctd = threading::parallel_reduce(
nodes.index_range(),
node_mask.index_range(),
1,
AreaNormalCenterData{},
[&](const IndexRange range, AreaNormalCenterData anctd) {
SampleLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_area_normal_and_center_node_bmesh(
ob,
brush,
false,
true,
has_bm_orco,
static_cast<const blender::bke::pbvh::BMeshNode &>(*nodes[i]),
tls,
anctd);
}
ob, brush, false, true, has_bm_orco, nodes[i], tls, anctd);
});
return anctd;
},
calc_area_normal_and_center_reduce);
break;
}
case bke::pbvh::Type::Grids: {
const Span<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
anctd = threading::parallel_reduce(
nodes.index_range(),
node_mask.index_range(),
1,
AreaNormalCenterData{},
[&](const IndexRange range, AreaNormalCenterData anctd) {
SampleLocalData &tls = all_tls.local();
for (const int i : range) {
calc_area_normal_and_center_node_grids(
ob, brush, false, true, *nodes[i], tls, anctd);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_area_normal_and_center_node_grids(ob, brush, false, true, nodes[i], tls, anctd);
});
return anctd;
},
calc_area_normal_and_center_reduce);
@@ -2114,8 +2130,8 @@ void calc_area_center(const Depsgraph &depsgraph,
std::optional<float3> calc_area_normal(const Depsgraph &depsgraph,
const Brush &brush,
Object &ob,
Span<bke::pbvh::Node *> nodes)
const Object &ob,
const IndexMask &node_mask)
{
SculptSession &ss = *ob.sculpt;
@@ -2129,13 +2145,14 @@ std::optional<float3> calc_area_normal(const Depsgraph &depsgraph,
const bke::AttributeAccessor attributes = mesh.attributes();
const VArraySpan hide_vert = *attributes.lookup<bool>(".hide_vert", bke::AttrDomain::Point);
const Span<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
anctd = threading::parallel_reduce(
nodes.index_range(),
node_mask.index_range(),
1,
AreaNormalCenterData{},
[&](const IndexRange range, AreaNormalCenterData anctd) {
SampleLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_area_normal_and_center_node_mesh(ob,
vert_positions,
vert_normals,
@@ -2143,10 +2160,10 @@ std::optional<float3> calc_area_normal(const Depsgraph &depsgraph,
brush,
true,
false,
*nodes[i],
nodes[i],
tls,
anctd);
}
});
return anctd;
},
calc_area_normal_and_center_reduce);
@@ -2155,39 +2172,40 @@ std::optional<float3> calc_area_normal(const Depsgraph &depsgraph,
case bke::pbvh::Type::BMesh: {
const bool has_bm_orco = ss.bm && dyntopo::stroke_is_dyntopo(ss, brush);
const Span<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
anctd = threading::parallel_reduce(
nodes.index_range(),
node_mask.index_range(),
1,
AreaNormalCenterData{},
[&](const IndexRange range, AreaNormalCenterData anctd) {
SampleLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_area_normal_and_center_node_bmesh(
ob,
brush,
true,
false,
has_bm_orco,
static_cast<const blender::bke::pbvh::BMeshNode &>(*nodes[i]),
static_cast<const blender::bke::pbvh::BMeshNode &>(nodes[i]),
tls,
anctd);
}
});
return anctd;
},
calc_area_normal_and_center_reduce);
break;
}
case bke::pbvh::Type::Grids: {
const Span<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
anctd = threading::parallel_reduce(
nodes.index_range(),
node_mask.index_range(),
1,
AreaNormalCenterData{},
[&](const IndexRange range, AreaNormalCenterData anctd) {
SampleLocalData &tls = all_tls.local();
for (const int i : range) {
calc_area_normal_and_center_node_grids(
ob, brush, true, false, *nodes[i], tls, anctd);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_area_normal_and_center_node_grids(ob, brush, true, false, nodes[i], tls, anctd);
});
return anctd;
},
calc_area_normal_and_center_reduce);
@@ -2208,7 +2226,7 @@ std::optional<float3> calc_area_normal(const Depsgraph &depsgraph,
void calc_area_normal_and_center(const Depsgraph &depsgraph,
const Brush &brush,
const Object &ob,
Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
float r_area_no[3],
float r_area_co[3])
{
@@ -2225,13 +2243,14 @@ void calc_area_normal_and_center(const Depsgraph &depsgraph,
const bke::AttributeAccessor attributes = mesh.attributes();
const VArraySpan hide_vert = *attributes.lookup<bool>(".hide_vert", bke::AttrDomain::Point);
const Span<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
anctd = threading::parallel_reduce(
nodes.index_range(),
node_mask.index_range(),
1,
AreaNormalCenterData{},
[&](const IndexRange range, AreaNormalCenterData anctd) {
SampleLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_area_normal_and_center_node_mesh(ob,
vert_positions,
vert_normals,
@@ -2239,10 +2258,10 @@ void calc_area_normal_and_center(const Depsgraph &depsgraph,
brush,
true,
true,
*nodes[i],
nodes[i],
tls,
anctd);
}
});
return anctd;
},
calc_area_normal_and_center_reduce);
@@ -2251,37 +2270,32 @@ void calc_area_normal_and_center(const Depsgraph &depsgraph,
case bke::pbvh::Type::BMesh: {
const bool has_bm_orco = ss.bm && dyntopo::stroke_is_dyntopo(ss, brush);
const Span<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
anctd = threading::parallel_reduce(
nodes.index_range(),
node_mask.index_range(),
1,
AreaNormalCenterData{},
[&](const IndexRange range, AreaNormalCenterData anctd) {
SampleLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_area_normal_and_center_node_bmesh(
ob,
brush,
true,
true,
has_bm_orco,
static_cast<const blender::bke::pbvh::BMeshNode &>(*nodes[i]),
tls,
anctd);
}
ob, brush, true, true, has_bm_orco, nodes[i], tls, anctd);
});
return anctd;
},
calc_area_normal_and_center_reduce);
break;
}
case bke::pbvh::Type::Grids: {
const Span<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
anctd = threading::parallel_reduce(
nodes.index_range(),
node_mask.index_range(),
1,
AreaNormalCenterData{},
[&](const IndexRange range, AreaNormalCenterData anctd) {
SampleLocalData &tls = all_tls.local();
for (const int i : range) {
calc_area_normal_and_center_node_grids(ob, brush, true, true, *nodes[i], tls, anctd);
calc_area_normal_and_center_node_grids(ob, brush, true, true, nodes[i], tls, anctd);
}
return anctd;
},
@@ -2616,87 +2630,69 @@ bool node_in_cylinder(const DistRayAABB_Precalc &ray_dist_precalc,
return dist_sq < radius_sq || true;
}
static Vector<bke::pbvh::Node *> pbvh_gather_cursor_update(Object &ob, bool use_original)
static IndexMask pbvh_gather_cursor_update(Object &ob, bool use_original, IndexMaskMemory &memory)
{
SculptSession &ss = *ob.sculpt;
const float3 center = ss.cache ? ss.cache->location : ss.cursor_location;
return bke::pbvh::search_gather(*ss.pbvh, [&](bke::pbvh::Node &node) {
return bke::pbvh::search_nodes(*ss.pbvh, memory, [&](const bke::pbvh::Node &node) {
return node_in_sphere(node, center, ss.cursor_radius, use_original);
});
}
/** \return All nodes that are potentially within the cursor or brush's area of influence. */
static Vector<bke::pbvh::Node *> pbvh_gather_generic(
Object &ob, const Brush &brush, bool use_original, float radius_scale, PBVHNodeFlags flag)
static IndexMask pbvh_gather_generic(
Object &ob, const Brush &brush, bool use_original, float radius_scale, IndexMaskMemory &memory)
{
SculptSession &ss = *ob.sculpt;
PBVHNodeFlags leaf_flag = PBVH_Leaf;
if (flag & PBVH_TexLeaf) {
leaf_flag = PBVH_TexLeaf;
}
const float3 center = ss.cache->location;
const float radius_sq = math::square(ss.cache->radius * radius_scale);
const bool ignore_ineffective = brush.sculpt_tool != SCULPT_TOOL_MASK;
switch (brush.falloff_shape) {
case PAINT_FALLOFF_SHAPE_SPHERE: {
return bke::pbvh::search_gather(
*ss.pbvh,
[&](bke::pbvh::Node &node) {
if (ignore_ineffective && node_fully_masked_or_hidden(node)) {
return false;
}
return node_in_sphere(node, center, radius_sq, use_original);
},
leaf_flag);
return bke::pbvh::search_nodes(*ss.pbvh, memory, [&](const bke::pbvh::Node &node) {
if (ignore_ineffective && node_fully_masked_or_hidden(node)) {
return false;
}
return node_in_sphere(node, center, radius_sq, use_original);
});
}
case PAINT_FALLOFF_SHAPE_TUBE: {
const DistRayAABB_Precalc ray_dist_precalc = dist_squared_ray_to_aabb_v3_precalc(
center, ss.cache->view_normal);
return bke::pbvh::search_gather(
*ss.pbvh,
[&](bke::pbvh::Node &node) {
if (ignore_ineffective && node_fully_masked_or_hidden(node)) {
return false;
}
return node_in_cylinder(ray_dist_precalc, node, radius_sq, use_original);
},
leaf_flag);
return bke::pbvh::search_nodes(*ss.pbvh, memory, [&](const bke::pbvh::Node &node) {
if (ignore_ineffective && node_fully_masked_or_hidden(node)) {
return false;
}
return node_in_cylinder(ray_dist_precalc, node, radius_sq, use_original);
});
}
}
return {};
}
static Vector<bke::pbvh::Node *> pbvh_gather_generic(Object &ob,
const Brush &brush,
const bool use_original,
const float radius_scale)
static IndexMask pbvh_gather_texpaint(Object &ob,
const Brush &brush,
const bool use_original,
const float radius_scale,
IndexMaskMemory &memory)
{
return pbvh_gather_generic(ob, brush, use_original, radius_scale, PBVH_Leaf);
}
static Vector<bke::pbvh::Node *> pbvh_gather_texpaint(Object &ob,
const Brush &brush,
const bool use_original,
const float radius_scale)
{
return pbvh_gather_generic(ob, brush, use_original, radius_scale, PBVH_TexLeaf);
return pbvh_gather_generic(ob, brush, use_original, radius_scale, memory);
}
/* Calculate primary direction of movement for many brushes. */
static float3 calc_sculpt_normal(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &ob,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
const SculptSession &ss = *ob.sculpt;
switch (brush.sculpt_plane) {
case SCULPT_DISP_DIR_AREA:
return calc_area_normal(depsgraph, brush, ob, nodes).value_or(float3(0));
return calc_area_normal(depsgraph, brush, ob, node_mask).value_or(float3(0));
case SCULPT_DISP_DIR_VIEW:
return ss.cache->true_view_normal;
case SCULPT_DISP_DIR_X:
@@ -2713,7 +2709,7 @@ static float3 calc_sculpt_normal(const Depsgraph &depsgraph,
static void update_sculpt_normal(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &ob,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
StrokeCache &cache = *ob.sculpt->cache;
@@ -2727,7 +2723,7 @@ static void update_sculpt_normal(const Depsgraph &depsgraph,
if (cache.mirror_symmetry_pass == 0 && cache.radial_symmetry_pass == 0 &&
(SCULPT_stroke_is_first_brush_step_of_symmetry_pass(cache) || update_normal))
{
cache.sculpt_normal = calc_sculpt_normal(depsgraph, sd, ob, nodes);
cache.sculpt_normal = calc_sculpt_normal(depsgraph, sd, ob, node_mask);
if (brush.falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) {
project_plane_v3_v3v3(cache.sculpt_normal, cache.sculpt_normal, cache.view_normal);
normalize_v3(cache.sculpt_normal);
@@ -3064,7 +3060,7 @@ namespace blender::ed::sculpt_paint {
void calc_brush_plane(const Depsgraph &depsgraph,
const Brush &brush,
Object &ob,
Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
float3 &r_area_no,
float3 &r_area_co)
{
@@ -3095,7 +3091,7 @@ void calc_brush_plane(const Depsgraph &depsgraph,
break;
case SCULPT_DISP_DIR_AREA:
calc_area_normal_and_center(depsgraph, brush, ob, nodes, r_area_no, r_area_co);
calc_area_normal_and_center(depsgraph, brush, ob, node_mask, r_area_no, r_area_co);
if (brush.falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) {
project_plane_v3_v3v3(r_area_no, r_area_no, ss.cache->view_normal);
normalize_v3(r_area_no);
@@ -3109,7 +3105,7 @@ void calc_brush_plane(const Depsgraph &depsgraph,
/* For flatten center. */
/* Flatten center has not been calculated yet if we are not using the area normal. */
if (brush.sculpt_plane != SCULPT_DISP_DIR_AREA) {
calc_area_center(depsgraph, brush, ob, nodes, r_area_co);
calc_area_center(depsgraph, brush, ob, node_mask, r_area_co);
}
/* For area normal. */
@@ -3229,13 +3225,15 @@ static void dynamic_topology_update(const Depsgraph &depsgraph,
/* Build a list of all nodes that are potentially within the brush's area of influence. */
const bool use_original = tool_needs_original(brush.sculpt_tool) ? true : !ss.cache->accum;
const float radius_scale = 1.25f;
Vector<bke::pbvh::Node *> nodes = pbvh_gather_generic(ob, brush, use_original, radius_scale);
/* Only act if some verts are inside the brush area. */
if (nodes.is_empty()) {
IndexMaskMemory memory;
const IndexMask node_mask = pbvh_gather_generic(ob, brush, use_original, radius_scale, memory);
if (node_mask.is_empty()) {
return;
}
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
/* Free index based vertex info as it will become invalid after modifying the topology during the
* stroke. */
ss.vertex_info.boundary.clear();
@@ -3253,18 +3251,17 @@ static void dynamic_topology_update(const Depsgraph &depsgraph,
}
}
for (bke::pbvh::Node *node : nodes) {
node_mask.foreach_index([&](const int i) {
undo::push_node(depsgraph,
ob,
node,
&nodes[i],
brush.sculpt_tool == SCULPT_TOOL_MASK ? undo::Type::Mask :
undo::Type::Position);
BKE_pbvh_node_mark_update(*node);
BKE_pbvh_node_mark_update(nodes[i]);
BKE_pbvh_node_mark_topology_update(*node);
BKE_pbvh_bmesh_node_save_orig(
ss.bm, ss.bm_log, static_cast<blender::bke::pbvh::BMeshNode *>(node), false);
}
BKE_pbvh_node_mark_topology_update(nodes[i]);
BKE_pbvh_bmesh_node_save_orig(ss.bm, ss.bm_log, &nodes[i], false);
});
float max_edge_len;
if (sd.flags & (SCULPT_DYNTOPO_DETAIL_CONSTANT | SCULPT_DYNTOPO_DETAIL_MANUAL)) {
@@ -3299,15 +3296,32 @@ static void dynamic_topology_update(const Depsgraph &depsgraph,
static void push_undo_nodes(const Depsgraph &depsgraph,
Object &ob,
const Brush &brush,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
SculptSession &ss = *ob.sculpt;
bool need_coords = ss.cache->supports_gravity;
if (brush.sculpt_tool == SCULPT_TOOL_DRAW_FACE_SETS) {
for (bke::pbvh::Node *node : nodes) {
BKE_pbvh_node_mark_update_face_sets(*node);
switch (ss.pbvh->type()) {
case bke::pbvh::Type::Mesh: {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
node_mask.foreach_index(
[&](const int i) { BKE_pbvh_node_mark_update_face_sets(nodes[i]); });
break;
}
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
node_mask.foreach_index(
[&](const int i) { BKE_pbvh_node_mark_update_face_sets(nodes[i]); });
break;
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
node_mask.foreach_index(
[&](const int i) { BKE_pbvh_node_mark_update_face_sets(nodes[i]); });
break;
}
}
/* Draw face sets in smooth mode moves the vertices. */
@@ -3315,13 +3329,27 @@ static void push_undo_nodes(const Depsgraph &depsgraph,
need_coords = true;
}
else {
undo::push_nodes(depsgraph, ob, nodes, undo::Type::FaceSet);
undo::push_nodes(depsgraph, ob, node_mask, undo::Type::FaceSet);
}
}
else if (brush.sculpt_tool == SCULPT_TOOL_MASK) {
undo::push_nodes(depsgraph, ob, nodes, undo::Type::Mask);
for (bke::pbvh::Node *node : nodes) {
BKE_pbvh_node_mark_update_mask(*node);
undo::push_nodes(depsgraph, ob, node_mask, undo::Type::Mask);
switch (ss.pbvh->type()) {
case bke::pbvh::Type::Mesh: {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_mask(nodes[i]); });
break;
}
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_mask(nodes[i]); });
break;
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_mask(nodes[i]); });
break;
}
}
}
else if (SCULPT_tool_is_paint(brush.sculpt_tool)) {
@@ -3331,9 +3359,23 @@ static void push_undo_nodes(const Depsgraph &depsgraph,
BKE_pbvh_ensure_node_face_corners(*ss.pbvh, mesh.corner_tris());
}
}
undo::push_nodes(depsgraph, ob, nodes, undo::Type::Color);
for (bke::pbvh::Node *node : nodes) {
BKE_pbvh_node_mark_update_color(*node);
undo::push_nodes(depsgraph, ob, node_mask, undo::Type::Color);
switch (ss.pbvh->type()) {
case bke::pbvh::Type::Mesh: {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_color(nodes[i]); });
break;
}
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_color(nodes[i]); });
break;
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_color(nodes[i]); });
break;
}
}
}
else {
@@ -3341,9 +3383,26 @@ static void push_undo_nodes(const Depsgraph &depsgraph,
}
if (need_coords) {
undo::push_nodes(depsgraph, ob, nodes, undo::Type::Position);
for (bke::pbvh::Node *node : nodes) {
BKE_pbvh_node_mark_positions_update(*node);
undo::push_nodes(depsgraph, ob, node_mask, undo::Type::Position);
switch (ss.pbvh->type()) {
case bke::pbvh::Type::Mesh: {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
node_mask.foreach_index(
[&](const int i) { BKE_pbvh_node_mark_positions_update(nodes[i]); });
break;
}
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
node_mask.foreach_index(
[&](const int i) { BKE_pbvh_node_mark_positions_update(nodes[i]); });
break;
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
node_mask.foreach_index(
[&](const int i) { BKE_pbvh_node_mark_positions_update(nodes[i]); });
break;
}
}
}
}
@@ -3357,7 +3416,8 @@ static void do_brush_action(const Depsgraph &depsgraph,
PaintModeSettings &paint_mode_settings)
{
SculptSession &ss = *ob.sculpt;
Vector<bke::pbvh::Node *> nodes, texnodes;
IndexMaskMemory memory;
IndexMask node_mask, texnode_mask;
const bool use_original = tool_needs_original(brush.sculpt_tool) ? true : !ss.cache->accum;
const bool use_pixels = sculpt_needs_pbvh_pixels(paint_mode_settings, brush, ob);
@@ -3365,9 +3425,9 @@ static void do_brush_action(const Depsgraph &depsgraph,
if (sculpt_needs_pbvh_pixels(paint_mode_settings, brush, ob)) {
sculpt_pbvh_update_pixels(depsgraph, paint_mode_settings, ob);
texnodes = pbvh_gather_texpaint(ob, brush, use_original, 1.0f);
texnode_mask = pbvh_gather_texpaint(ob, brush, use_original, 1.0f, memory);
if (texnodes.is_empty()) {
if (texnode_mask.is_empty()) {
return;
}
}
@@ -3376,10 +3436,10 @@ static void do_brush_action(const Depsgraph &depsgraph,
if (SCULPT_tool_needs_all_pbvh_nodes(brush)) {
/* These brushes need to update all nodes as they are not constrained by the brush radius */
nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh);
node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory);
}
else if (brush.sculpt_tool == SCULPT_TOOL_CLOTH) {
nodes = cloth::brush_affected_nodes_gather(ss, brush);
node_mask = cloth::brush_affected_nodes_gather(ss, brush, memory);
}
else {
float radius_scale = 1.0f;
@@ -3394,7 +3454,7 @@ static void do_brush_action(const Depsgraph &depsgraph,
if (brush.sculpt_tool == SCULPT_TOOL_DRAW && brush.flag & BRUSH_ORIGINAL_NORMAL) {
radius_scale = 2.0f;
}
nodes = pbvh_gather_generic(ob, brush, use_original, radius_scale);
node_mask = pbvh_gather_generic(ob, brush, use_original, radius_scale, memory);
}
/* Draw Face Sets in draw mode makes a single undo push, in alt-smooth mode deforms the
@@ -3416,7 +3476,7 @@ static void do_brush_action(const Depsgraph &depsgraph,
/* For anchored brushes with spherical falloff, we start off with zero radius, thus we have no
* bke::pbvh::Tree nodes on the first brush step. */
if (!nodes.is_empty() ||
if (!node_mask.is_empty() ||
((brush.falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE) && (brush.flag & BRUSH_ANCHORED)))
{
if (SCULPT_stroke_is_first_brush_step(*ss.cache)) {
@@ -3437,17 +3497,17 @@ static void do_brush_action(const Depsgraph &depsgraph,
}
/* Only act if some verts are inside the brush area. */
if (nodes.is_empty()) {
if (node_mask.is_empty()) {
return;
}
float location[3];
if (!use_pixels) {
push_undo_nodes(depsgraph, ob, brush, nodes);
push_undo_nodes(depsgraph, ob, brush, node_mask);
}
if (sculpt_brush_needs_normal(ss, sd, brush)) {
update_sculpt_normal(depsgraph, sd, ob, nodes);
update_sculpt_normal(depsgraph, sd, ob, node_mask);
}
update_brush_local_mat(sd, ob);
@@ -3463,7 +3523,7 @@ static void do_brush_action(const Depsgraph &depsgraph,
}
cloth::brush_store_simulation_state(depsgraph, ob, *ss.cache->cloth_sim);
cloth::ensure_nodes_constraints(
sd, ob, nodes, *ss.cache->cloth_sim, ss.cache->location, FLT_MAX);
sd, ob, node_mask, *ss.cache->cloth_sim, ss.cache->location, FLT_MAX);
}
bool invert = ss.cache->pen_flip || ss.cache->invert;
@@ -3477,10 +3537,10 @@ static void do_brush_action(const Depsgraph &depsgraph,
const bool use_vector_displacement = (brush.flag2 & BRUSH_USE_COLOR_AS_DISPLACEMENT &&
(brush.mtex.brush_map_mode == MTEX_MAP_MODE_AREA));
if (use_vector_displacement) {
do_draw_vector_displacement_brush(depsgraph, sd, ob, nodes);
do_draw_vector_displacement_brush(depsgraph, sd, ob, node_mask);
}
else {
do_draw_brush(depsgraph, sd, ob, nodes);
do_draw_brush(depsgraph, sd, ob, node_mask);
}
break;
}
@@ -3492,129 +3552,130 @@ static void do_brush_action(const Depsgraph &depsgraph,
* enhance brush in the middle of the stroke. */
if (ss.cache->bstrength < 0.0f) {
/* Invert mode, intensify details. */
do_enhance_details_brush(depsgraph, sd, ob, nodes);
do_enhance_details_brush(depsgraph, sd, ob, node_mask);
}
else {
do_smooth_brush(depsgraph, sd, ob, nodes, std::clamp(ss.cache->bstrength, 0.0f, 1.0f));
do_smooth_brush(
depsgraph, sd, ob, node_mask, std::clamp(ss.cache->bstrength, 0.0f, 1.0f));
}
}
else if (brush.smooth_deform_type == BRUSH_SMOOTH_DEFORM_SURFACE) {
do_surface_smooth_brush(depsgraph, sd, ob, nodes);
do_surface_smooth_brush(depsgraph, sd, ob, node_mask);
}
break;
case SCULPT_TOOL_CREASE:
do_crease_brush(depsgraph, scene, sd, ob, nodes);
do_crease_brush(depsgraph, scene, sd, ob, node_mask);
break;
case SCULPT_TOOL_BLOB:
do_blob_brush(depsgraph, scene, sd, ob, nodes);
do_blob_brush(depsgraph, scene, sd, ob, node_mask);
break;
case SCULPT_TOOL_PINCH:
do_pinch_brush(depsgraph, sd, ob, nodes);
do_pinch_brush(depsgraph, sd, ob, node_mask);
break;
case SCULPT_TOOL_INFLATE:
do_inflate_brush(depsgraph, sd, ob, nodes);
do_inflate_brush(depsgraph, sd, ob, node_mask);
break;
case SCULPT_TOOL_GRAB:
do_grab_brush(depsgraph, sd, ob, nodes);
do_grab_brush(depsgraph, sd, ob, node_mask);
break;
case SCULPT_TOOL_ROTATE:
do_rotate_brush(depsgraph, sd, ob, nodes);
do_rotate_brush(depsgraph, sd, ob, node_mask);
break;
case SCULPT_TOOL_SNAKE_HOOK:
do_snake_hook_brush(depsgraph, sd, ob, nodes);
do_snake_hook_brush(depsgraph, sd, ob, node_mask);
break;
case SCULPT_TOOL_NUDGE:
do_nudge_brush(depsgraph, sd, ob, nodes);
do_nudge_brush(depsgraph, sd, ob, node_mask);
break;
case SCULPT_TOOL_THUMB:
do_thumb_brush(depsgraph, sd, ob, nodes);
do_thumb_brush(depsgraph, sd, ob, node_mask);
break;
case SCULPT_TOOL_LAYER:
do_layer_brush(depsgraph, sd, ob, nodes);
do_layer_brush(depsgraph, sd, ob, node_mask);
break;
case SCULPT_TOOL_FLATTEN:
do_flatten_brush(depsgraph, sd, ob, nodes);
do_flatten_brush(depsgraph, sd, ob, node_mask);
break;
case SCULPT_TOOL_CLAY:
do_clay_brush(depsgraph, sd, ob, nodes);
do_clay_brush(depsgraph, sd, ob, node_mask);
break;
case SCULPT_TOOL_CLAY_STRIPS:
do_clay_strips_brush(depsgraph, sd, ob, nodes);
do_clay_strips_brush(depsgraph, sd, ob, node_mask);
break;
case SCULPT_TOOL_MULTIPLANE_SCRAPE:
do_multiplane_scrape_brush(depsgraph, sd, ob, nodes);
do_multiplane_scrape_brush(depsgraph, sd, ob, node_mask);
break;
case SCULPT_TOOL_CLAY_THUMB:
do_clay_thumb_brush(depsgraph, sd, ob, nodes);
do_clay_thumb_brush(depsgraph, sd, ob, node_mask);
break;
case SCULPT_TOOL_FILL:
if (invert && brush.flag & BRUSH_INVERT_TO_SCRAPE_FILL) {
do_scrape_brush(depsgraph, sd, ob, nodes);
do_scrape_brush(depsgraph, sd, ob, node_mask);
}
else {
do_fill_brush(depsgraph, sd, ob, nodes);
do_fill_brush(depsgraph, sd, ob, node_mask);
}
break;
case SCULPT_TOOL_SCRAPE:
if (invert && brush.flag & BRUSH_INVERT_TO_SCRAPE_FILL) {
do_fill_brush(depsgraph, sd, ob, nodes);
do_fill_brush(depsgraph, sd, ob, node_mask);
}
else {
do_scrape_brush(depsgraph, sd, ob, nodes);
do_scrape_brush(depsgraph, sd, ob, node_mask);
}
break;
case SCULPT_TOOL_MASK:
switch ((BrushMaskTool)brush.mask_tool) {
case BRUSH_MASK_DRAW:
do_mask_brush(depsgraph, sd, ob, nodes);
do_mask_brush(depsgraph, sd, ob, node_mask);
break;
case BRUSH_MASK_SMOOTH:
do_smooth_mask_brush(depsgraph, sd, ob, nodes, ss.cache->bstrength);
do_smooth_mask_brush(depsgraph, sd, ob, node_mask, ss.cache->bstrength);
break;
}
break;
case SCULPT_TOOL_POSE:
pose::do_pose_brush(depsgraph, sd, ob, nodes);
pose::do_pose_brush(depsgraph, sd, ob, node_mask);
break;
case SCULPT_TOOL_DRAW_SHARP:
do_draw_sharp_brush(depsgraph, sd, ob, nodes);
do_draw_sharp_brush(depsgraph, sd, ob, node_mask);
break;
case SCULPT_TOOL_ELASTIC_DEFORM:
do_elastic_deform_brush(depsgraph, sd, ob, nodes);
do_elastic_deform_brush(depsgraph, sd, ob, node_mask);
break;
case SCULPT_TOOL_SLIDE_RELAX:
if (ss.cache->alt_smooth) {
do_topology_relax_brush(depsgraph, sd, ob, nodes);
do_topology_relax_brush(depsgraph, sd, ob, node_mask);
}
else {
do_topology_slide_brush(depsgraph, sd, ob, nodes);
do_topology_slide_brush(depsgraph, sd, ob, node_mask);
}
break;
case SCULPT_TOOL_BOUNDARY:
boundary::do_boundary_brush(depsgraph, sd, ob, nodes);
boundary::do_boundary_brush(depsgraph, sd, ob, node_mask);
break;
case SCULPT_TOOL_CLOTH:
cloth::do_cloth_brush(depsgraph, sd, ob, nodes);
cloth::do_cloth_brush(depsgraph, sd, ob, node_mask);
break;
case SCULPT_TOOL_DRAW_FACE_SETS:
if (!ss.cache->alt_smooth) {
do_draw_face_sets_brush(depsgraph, sd, ob, nodes);
do_draw_face_sets_brush(depsgraph, sd, ob, node_mask);
}
else {
do_relax_face_sets_brush(depsgraph, sd, ob, nodes);
do_relax_face_sets_brush(depsgraph, sd, ob, node_mask);
}
break;
case SCULPT_TOOL_DISPLACEMENT_ERASER:
do_displacement_eraser_brush(depsgraph, sd, ob, nodes);
do_displacement_eraser_brush(depsgraph, sd, ob, node_mask);
break;
case SCULPT_TOOL_DISPLACEMENT_SMEAR:
do_displacement_smear_brush(depsgraph, sd, ob, nodes);
do_displacement_smear_brush(depsgraph, sd, ob, node_mask);
break;
case SCULPT_TOOL_PAINT:
color::do_paint_brush(depsgraph, paint_mode_settings, sd, ob, nodes, texnodes);
color::do_paint_brush(depsgraph, paint_mode_settings, sd, ob, node_mask, texnode_mask);
break;
case SCULPT_TOOL_SMEAR:
color::do_smear_brush(depsgraph, sd, ob, nodes);
color::do_smear_brush(depsgraph, sd, ob, node_mask);
break;
}
@@ -3623,15 +3684,15 @@ static void do_brush_action(const Depsgraph &depsgraph,
{
if (brush.flag & BRUSH_INVERSE_SMOOTH_PRESSURE) {
do_smooth_brush(
depsgraph, sd, ob, nodes, brush.autosmooth_factor * (1.0f - ss.cache->pressure));
depsgraph, sd, ob, node_mask, brush.autosmooth_factor * (1.0f - ss.cache->pressure));
}
else {
do_smooth_brush(depsgraph, sd, ob, nodes, brush.autosmooth_factor);
do_smooth_brush(depsgraph, sd, ob, node_mask, brush.autosmooth_factor);
}
}
if (brush_uses_topology_rake(ss, brush)) {
do_bmesh_topology_rake_brush(depsgraph, sd, ob, nodes, brush.topology_rake_factor);
do_bmesh_topology_rake_brush(depsgraph, sd, ob, node_mask, brush.topology_rake_factor);
}
if (!auto_mask::tool_can_reuse_automask(brush.sculpt_tool) ||
@@ -3646,13 +3707,13 @@ static void do_brush_action(const Depsgraph &depsgraph,
!ELEM(
brush.sculpt_tool, SCULPT_TOOL_CLOTH, SCULPT_TOOL_DRAW_FACE_SETS, SCULPT_TOOL_BOUNDARY))
{
do_gravity_brush(depsgraph, sd, ob, nodes);
do_gravity_brush(depsgraph, sd, ob, node_mask);
}
if (brush.deform_target == BRUSH_DEFORM_TARGET_CLOTH_SIM) {
if (SCULPT_stroke_is_main_symmetry_pass(*ss.cache)) {
cloth::sim_activate_nodes(*ss.cache->cloth_sim, nodes);
cloth::do_simulation_step(depsgraph, sd, ob, *ss.cache->cloth_sim, nodes);
cloth::sim_activate_nodes(ob, *ss.cache->cloth_sim, node_mask);
cloth::do_simulation_step(depsgraph, sd, ob, *ss.cache->cloth_sim, node_mask);
}
}
@@ -4935,16 +4996,18 @@ bool SCULPT_cursor_geometry_info_update(bContext *C,
}
ss.cursor_radius = radius;
Vector<bke::pbvh::Node *> nodes = pbvh_gather_cursor_update(ob, original);
IndexMaskMemory memory;
const IndexMask node_mask = pbvh_gather_cursor_update(ob, original, memory);
/* In case there are no nodes under the cursor, return the face normal. */
if (nodes.is_empty()) {
if (node_mask.is_empty()) {
copy_v3_v3(out->normal, srd.face_normal);
return true;
}
/* Calculate the sampled normal. */
if (const std::optional<float3> sampled_normal = calc_area_normal(*depsgraph, brush, ob, nodes))
if (const std::optional<float3> sampled_normal = calc_area_normal(
*depsgraph, brush, ob, node_mask))
{
copy_v3_v3(out->normal, *sampled_normal);
copy_v3_v3(ss.cursor_sampled_normal, *sampled_normal);
@@ -5789,7 +5852,7 @@ static void fake_neighbor_search_mesh(const SculptSession &ss,
const float3 &location,
const float max_distance_sq,
const int island_id,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
NearestVertData &nvtd)
{
for (const int vert : bke::pbvh::node_unique_verts(node)) {
@@ -5817,7 +5880,7 @@ static void fake_neighbor_search_grids(const SculptSession &ss,
const float3 &location,
const float max_distance_sq,
const int island_id,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
NearestVertData &nvtd)
{
for (const int grid : bke::pbvh::node_grid_indices(node)) {
@@ -5846,10 +5909,12 @@ static void fake_neighbor_search_bmesh(const SculptSession &ss,
const float3 &location,
const float max_distance_sq,
const int island_id,
bke::pbvh::Node &node,
const bke::pbvh::BMeshNode &node,
NearestVertData &nvtd)
{
for (const BMVert *bm_vert : BKE_pbvh_bmesh_node_unique_verts(&node)) {
for (const BMVert *bm_vert :
BKE_pbvh_bmesh_node_unique_verts(const_cast<bke::pbvh::BMeshNode *>(&node)))
{
if (BM_elem_flag_test(bm_vert, BM_ELEM_HIDDEN)) {
continue;
}
@@ -5890,28 +5955,31 @@ static void fake_neighbor_search(const Depsgraph &depsgraph,
}
const int island_id = islands::vert_id_get(ss, vert);
const float3 &location = vert_positions[vert];
Vector<bke::pbvh::Node *> nodes = bke::pbvh::search_gather(
*ss.pbvh, [&](bke::pbvh::Node &node) {
IndexMaskMemory memory;
const IndexMask nodes_in_sphere = bke::pbvh::search_nodes(
*ss.pbvh, memory, [&](const bke::pbvh::Node &node) {
return node_in_sphere(node, location, max_distance_sq, false);
});
if (nodes.is_empty()) {
if (nodes_in_sphere.is_empty()) {
continue;
}
const Span<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
const NearestVertData nvtd = threading::parallel_reduce(
nodes.index_range(),
nodes_in_sphere.index_range(),
1,
NearestVertData(),
[&](const IndexRange range, NearestVertData nvtd) {
for (const int i : range) {
nodes_in_sphere.slice(range).foreach_index([&](const int i) {
fake_neighbor_search_mesh(ss,
vert_positions,
hide_vert,
location,
max_distance_sq,
island_id,
*nodes[i],
nodes[i],
nvtd);
}
});
return nvtd;
},
NearestVertData::join);
@@ -5935,19 +6003,21 @@ static void fake_neighbor_search(const Depsgraph &depsgraph,
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);
Vector<bke::pbvh::Node *> nodes = bke::pbvh::search_gather(
*ss.pbvh, [&](bke::pbvh::Node &node) {
IndexMaskMemory memory;
const IndexMask nodes_in_sphere = bke::pbvh::search_nodes(
*ss.pbvh, memory, [&](const bke::pbvh::Node &node) {
return node_in_sphere(node, location, max_distance_sq, false);
});
if (nodes.is_empty()) {
if (nodes_in_sphere.is_empty()) {
continue;
}
const Span<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
const NearestVertData nvtd = threading::parallel_reduce(
nodes.index_range(),
nodes_in_sphere.index_range(),
1,
NearestVertData(),
[&](const IndexRange range, NearestVertData nvtd) {
for (const int i : range) {
nodes_in_sphere.slice(range).foreach_index([&](const int i) {
fake_neighbor_search_grids(ss,
key,
elems,
@@ -5955,9 +6025,9 @@ static void fake_neighbor_search(const Depsgraph &depsgraph,
location,
max_distance_sq,
island_id,
*nodes[i],
nodes[i],
nvtd);
}
});
return nvtd;
},
NearestVertData::join);
@@ -5977,22 +6047,24 @@ static void fake_neighbor_search(const Depsgraph &depsgraph,
}
const int island_id = islands::vert_id_get(ss, vert);
const float3 &location = BM_vert_at_index(&const_cast<BMesh &>(bm), vert)->co;
Vector<bke::pbvh::Node *> nodes = bke::pbvh::search_gather(
*ss.pbvh, [&](bke::pbvh::Node &node) {
IndexMaskMemory memory;
const IndexMask nodes_in_sphere = bke::pbvh::search_nodes(
*ss.pbvh, memory, [&](const bke::pbvh::Node &node) {
return node_in_sphere(node, location, max_distance_sq, false);
});
if (nodes.is_empty()) {
if (nodes_in_sphere.is_empty()) {
continue;
}
const Span<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
const NearestVertData nvtd = threading::parallel_reduce(
nodes.index_range(),
nodes_in_sphere.index_range(),
1,
NearestVertData(),
[&](const IndexRange range, NearestVertData nvtd) {
for (const int i : range) {
nodes_in_sphere.slice(range).foreach_index([&](const int i) {
fake_neighbor_search_bmesh(
ss, location, max_distance_sq, island_id, *nodes[i], nvtd);
}
ss, location, max_distance_sq, island_id, nodes[i], nvtd);
});
return nvtd;
},
NearestVertData::join);
@@ -6248,23 +6320,23 @@ static SculptTopologyIslandCache calc_topology_islands_grids(const Object &objec
static SculptTopologyIslandCache calc_topology_islands_bmesh(const Object &object)
{
const SculptSession &ss = *object.sculpt;
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
BMesh &bm = *ss.bm;
BM_mesh_elem_index_ensure(&bm, BM_VERT);
bke::pbvh::Tree &pbvh = *object.sculpt->pbvh;
const Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(pbvh);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
AtomicDisjointSet disjoint_set(bm.totvert);
threading::parallel_for(nodes.index_range(), 1024, [&](const IndexRange range) {
for (bke::pbvh::Node *node : nodes.as_span().slice(range)) {
for (const BMFace *face : BKE_pbvh_bmesh_node_faces(node)) {
if (BM_elem_flag_test(face, BM_ELEM_HIDDEN)) {
continue;
}
disjoint_set.join(BM_elem_index_get(face->l_first->v),
BM_elem_index_get(face->l_first->next->v));
disjoint_set.join(BM_elem_index_get(face->l_first->v),
BM_elem_index_get(face->l_first->next->next->v));
node_mask.foreach_index(GrainSize(1), [&](const int i) {
for (const BMFace *face : BKE_pbvh_bmesh_node_faces(&nodes[i])) {
if (BM_elem_flag_test(face, BM_ELEM_HIDDEN)) {
continue;
}
disjoint_set.join(BM_elem_index_get(face->l_first->v),
BM_elem_index_get(face->l_first->next->v));
disjoint_set.join(BM_elem_index_get(face->l_first->v),
BM_elem_index_get(face->l_first->next->next->v));
}
});
@@ -7320,33 +7392,38 @@ void transform_positions(const float4x4 &transform, const MutableSpan<float3> po
}
}
OffsetIndices<int> create_node_vert_offsets(Span<bke::pbvh::Node *> nodes, Array<int> &node_data)
{
node_data.reinitialize(nodes.size() + 1);
for (const int i : nodes.index_range()) {
node_data[i] = bke::pbvh::node_unique_verts(*nodes[i]).size();
}
return offset_indices::accumulate_counts_to_offsets(node_data);
}
OffsetIndices<int> create_node_vert_offsets(Span<bke::pbvh::Node *> nodes,
const CCGKey &key,
OffsetIndices<int> create_node_vert_offsets(const Span<bke::pbvh::MeshNode> nodes,
const IndexMask &nodes_mask,
Array<int> &node_data)
{
node_data.reinitialize(nodes.size() + 1);
for (const int i : nodes.index_range()) {
node_data[i] = bke::pbvh::node_grid_indices(*nodes[i]).size() * key.grid_area;
}
nodes_mask.foreach_index([&](const int i, const int pos) {
node_data[pos] = bke::pbvh::node_unique_verts(nodes[i]).size();
});
return offset_indices::accumulate_counts_to_offsets(node_data);
}
OffsetIndices<int> create_node_vert_offsets_bmesh(Span<bke::pbvh::Node *> nodes,
OffsetIndices<int> create_node_vert_offsets(const CCGKey &key,
const Span<bke::pbvh::GridsNode> nodes,
const IndexMask &nodes_mask,
Array<int> &node_data)
{
node_data.reinitialize(nodes.size() + 1);
nodes_mask.foreach_index([&](const int i, const int pos) {
node_data[pos] = bke::pbvh::node_grid_indices(nodes[i]).size() * key.grid_area;
});
return offset_indices::accumulate_counts_to_offsets(node_data);
}
OffsetIndices<int> create_node_vert_offsets_bmesh(const Span<bke::pbvh::BMeshNode> nodes,
const IndexMask &nodes_mask,
Array<int> &node_data)
{
node_data.reinitialize(nodes.size() + 1);
for (const int i : nodes.index_range()) {
node_data[i] = BKE_pbvh_bmesh_node_unique_verts(nodes[i]).size();
}
nodes_mask.foreach_index([&](const int i, const int pos) {
node_data[pos] =
BKE_pbvh_bmesh_node_unique_verts(const_cast<bke::pbvh::BMeshNode *>(&nodes[i])).size();
});
return offset_indices::accumulate_counts_to_offsets(node_data);
}

View File

@@ -615,7 +615,7 @@ static float factor_get(const Depsgraph &depsgraph,
void calc_vert_factors(const Depsgraph &depsgraph,
const Object &object,
const Cache &cache,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
const Span<int> verts,
const MutableSpan<float> factors)
{
@@ -641,7 +641,7 @@ void calc_face_factors(const Depsgraph &depsgraph,
const OffsetIndices<int> faces,
const Span<int> corner_verts,
const Cache &cache,
const bke::pbvh::Node & /*node*/,
const bke::pbvh::MeshNode & /*node*/,
const Span<int> face_indices,
const MutableSpan<float> factors)
{
@@ -658,7 +658,7 @@ void calc_face_factors(const Depsgraph &depsgraph,
void calc_grids_factors(const Depsgraph &depsgraph,
const Object &object,
const Cache &cache,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
const Span<int> grids,
const MutableSpan<float> factors)
{
@@ -691,7 +691,7 @@ void calc_grids_factors(const Depsgraph &depsgraph,
void calc_vert_factors(const Depsgraph &depsgraph,
const Object &object,
const Cache &cache,
const bke::pbvh::Node & /*node*/,
const bke::pbvh::BMeshNode & /*node*/,
const Set<BMVert *, 0> &verts,
const MutableSpan<float> factors)
{

View File

@@ -1121,7 +1121,7 @@ static void calc_bend_mesh(const Depsgraph &depsgraph,
const Span<float> vert_factors,
const Span<float3> vert_pivot_positions,
const Span<float3> vert_pivot_axes,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
LocalDataMesh &tls,
const float3 symmetry_pivot,
const float strength,
@@ -1181,7 +1181,7 @@ static void calc_bend_grids(const Depsgraph &depsgraph,
const Span<float> vert_factors,
const Span<float3> vert_pivot_positions,
const Span<float3> vert_pivot_axes,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
LocalDataGrids &tls,
const float3 symmetry_pivot,
const float strength,
@@ -1246,7 +1246,7 @@ static void calc_bend_bmesh(const Depsgraph &depsgraph,
const Span<float> vert_factors,
const Span<float3> vert_pivot_positions,
const Span<float3> vert_pivot_axes,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
LocalDataBMesh &tls,
const float3 symmetry_pivot,
const float strength,
@@ -1304,7 +1304,7 @@ static void calc_bend_bmesh(const Depsgraph &depsgraph,
static void do_bend_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
const Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
const SculptBoundary &boundary,
const float strength,
const eBrushDeformTarget deform_target)
@@ -1317,9 +1317,10 @@ static void do_bend_brush(const Depsgraph &depsgraph,
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::EnumerableThreadSpecific<LocalDataMesh> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalDataMesh &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_bend_mesh(depsgraph,
sd,
object,
@@ -1328,23 +1329,24 @@ static void do_bend_brush(const Depsgraph &depsgraph,
boundary.edit_info.strength_factor,
boundary.bend.pivot_positions,
boundary.bend.pivot_rotation_axis,
*nodes[i],
nodes[i],
tls,
boundary.initial_vert_position,
strength,
deform_target,
positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
threading::EnumerableThreadSpecific<LocalDataGrids> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalDataGrids &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_bend_grids(depsgraph,
sd,
object,
@@ -1353,20 +1355,21 @@ static void do_bend_brush(const Depsgraph &depsgraph,
boundary.edit_info.strength_factor,
boundary.bend.pivot_positions,
boundary.bend.pivot_rotation_axis,
*nodes[i],
nodes[i],
tls,
boundary.initial_vert_position,
strength,
deform_target);
}
});
});
break;
}
case bke::pbvh::Type::BMesh: {
threading::EnumerableThreadSpecific<LocalDataBMesh> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalDataBMesh &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_bend_bmesh(depsgraph,
sd,
object,
@@ -1374,12 +1377,12 @@ static void do_bend_brush(const Depsgraph &depsgraph,
boundary.edit_info.strength_factor,
boundary.bend.pivot_positions,
boundary.bend.pivot_rotation_axis,
*nodes[i],
nodes[i],
tls,
boundary.initial_vert_position,
strength,
deform_target);
}
});
});
break;
}
@@ -1413,7 +1416,7 @@ static void calc_slide_mesh(const Depsgraph &depsgraph,
const Span<int> vert_propagation_steps,
const Span<float> vert_factors,
const Span<float3> vert_slide_directions,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
LocalDataMesh &tls,
const float3 symmetry_pivot,
const float strength,
@@ -1472,7 +1475,7 @@ static void calc_slide_grids(const Depsgraph &depsgraph,
const Span<int> vert_propagation_steps,
const Span<float> vert_factors,
const Span<float3> vert_slide_directions,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
LocalDataGrids &tls,
const float3 symmetry_pivot,
const float strength,
@@ -1535,7 +1538,7 @@ static void calc_slide_bmesh(const Depsgraph &depsgraph,
const Span<int> vert_propagation_steps,
const Span<float> vert_factors,
const Span<float3> vert_slide_directions,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
LocalDataBMesh &tls,
const float3 symmetry_pivot,
const float strength,
@@ -1592,7 +1595,7 @@ static void calc_slide_bmesh(const Depsgraph &depsgraph,
static void do_slide_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
const Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
const SculptBoundary &boundary,
const float strength,
const eBrushDeformTarget deform_target)
@@ -1605,9 +1608,10 @@ static void do_slide_brush(const Depsgraph &depsgraph,
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::EnumerableThreadSpecific<LocalDataMesh> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalDataMesh &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_slide_mesh(depsgraph,
sd,
object,
@@ -1615,23 +1619,24 @@ static void do_slide_brush(const Depsgraph &depsgraph,
boundary.edit_info.propagation_steps_num,
boundary.edit_info.strength_factor,
boundary.slide.directions,
*nodes[i],
nodes[i],
tls,
boundary.initial_vert_position,
strength,
deform_target,
positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
threading::EnumerableThreadSpecific<LocalDataGrids> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalDataGrids &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_slide_grids(depsgraph,
sd,
object,
@@ -1639,32 +1644,33 @@ static void do_slide_brush(const Depsgraph &depsgraph,
boundary.edit_info.propagation_steps_num,
boundary.edit_info.strength_factor,
boundary.slide.directions,
*nodes[i],
nodes[i],
tls,
boundary.initial_vert_position,
strength,
deform_target);
}
});
});
break;
}
case bke::pbvh::Type::BMesh: {
threading::EnumerableThreadSpecific<LocalDataBMesh> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalDataBMesh &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_slide_bmesh(depsgraph,
sd,
object,
boundary.edit_info.propagation_steps_num,
boundary.edit_info.strength_factor,
boundary.slide.directions,
*nodes[i],
nodes[i],
tls,
boundary.initial_vert_position,
strength,
deform_target);
}
});
});
break;
}
@@ -1697,7 +1703,7 @@ static void calc_inflate_mesh(const Depsgraph &depsgraph,
const Span<float3> positions_eval,
const Span<int> vert_propagation_steps,
const Span<float> vert_factors,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
LocalDataMesh &tls,
const float3 symmetry_pivot,
const float strength,
@@ -1751,7 +1757,7 @@ static void calc_inflate_grids(const Depsgraph &depsgraph,
SubdivCCG &subdiv_ccg,
const Span<int> vert_propagation_steps,
const Span<float> vert_factors,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
LocalDataGrids &tls,
const float3 symmetry_pivot,
const float strength,
@@ -1809,7 +1815,7 @@ static void calc_inflate_bmesh(const Depsgraph &depsgraph,
Object &object,
const Span<int> vert_propagation_steps,
const Span<float> vert_factors,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
LocalDataBMesh &tls,
const float3 symmetry_pivot,
const float strength,
@@ -1863,7 +1869,7 @@ static void calc_inflate_bmesh(const Depsgraph &depsgraph,
static void do_inflate_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
const Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
const SculptBoundary &boundary,
const float strength,
const eBrushDeformTarget deform_target)
@@ -1876,63 +1882,66 @@ static void do_inflate_brush(const Depsgraph &depsgraph,
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::EnumerableThreadSpecific<LocalDataMesh> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalDataMesh &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_inflate_mesh(depsgraph,
sd,
object,
positions_eval,
boundary.edit_info.propagation_steps_num,
boundary.edit_info.strength_factor,
*nodes[i],
nodes[i],
tls,
boundary.initial_vert_position,
strength,
deform_target,
positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
threading::EnumerableThreadSpecific<LocalDataGrids> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalDataGrids &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_inflate_grids(depsgraph,
sd,
object,
subdiv_ccg,
boundary.edit_info.propagation_steps_num,
boundary.edit_info.strength_factor,
*nodes[i],
nodes[i],
tls,
boundary.initial_vert_position,
strength,
deform_target);
}
});
});
break;
}
case bke::pbvh::Type::BMesh: {
threading::EnumerableThreadSpecific<LocalDataBMesh> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalDataBMesh &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_inflate_bmesh(depsgraph,
sd,
object,
boundary.edit_info.propagation_steps_num,
boundary.edit_info.strength_factor,
*nodes[i],
nodes[i],
tls,
boundary.initial_vert_position,
strength,
deform_target);
}
});
});
break;
}
@@ -1964,7 +1973,7 @@ static void calc_grab_mesh(const Depsgraph &depsgraph,
const Span<float3> positions_eval,
const Span<int> vert_propagation_steps,
const Span<float> vert_factors,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
LocalDataMesh &tls,
const float3 grab_delta_symmetry,
const float3 symmetry_pivot,
@@ -2019,7 +2028,7 @@ static void calc_grab_grids(const Depsgraph &depsgraph,
SubdivCCG &subdiv_ccg,
const Span<int> vert_propagation_steps,
const Span<float> vert_factors,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
LocalDataGrids &tls,
const float3 grab_delta_symmetry,
const float3 symmetry_pivot,
@@ -2078,7 +2087,7 @@ static void calc_grab_bmesh(const Depsgraph &depsgraph,
Object &object,
const Span<int> vert_propagation_steps,
const Span<float> vert_factors,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
LocalDataBMesh &tls,
const float3 grab_delta_symmetry,
const float3 symmetry_pivot,
@@ -2133,7 +2142,7 @@ static void calc_grab_bmesh(const Depsgraph &depsgraph,
static void do_grab_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
const Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
const SculptBoundary &boundary,
const float strength,
const eBrushDeformTarget deform_target)
@@ -2146,66 +2155,69 @@ static void do_grab_brush(const Depsgraph &depsgraph,
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::EnumerableThreadSpecific<LocalDataMesh> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalDataMesh &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_grab_mesh(depsgraph,
sd,
object,
positions_eval,
boundary.edit_info.propagation_steps_num,
boundary.edit_info.strength_factor,
*nodes[i],
nodes[i],
tls,
ss.cache->grab_delta_symmetry,
boundary.initial_vert_position,
strength,
deform_target,
positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
threading::EnumerableThreadSpecific<LocalDataGrids> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalDataGrids &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_grab_grids(depsgraph,
sd,
object,
subdiv_ccg,
boundary.edit_info.propagation_steps_num,
boundary.edit_info.strength_factor,
*nodes[i],
nodes[i],
tls,
ss.cache->grab_delta_symmetry,
boundary.initial_vert_position,
strength,
deform_target);
}
});
});
break;
}
case bke::pbvh::Type::BMesh: {
threading::EnumerableThreadSpecific<LocalDataBMesh> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalDataBMesh &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_grab_bmesh(depsgraph,
sd,
object,
boundary.edit_info.propagation_steps_num,
boundary.edit_info.strength_factor,
*nodes[i],
nodes[i],
tls,
ss.cache->grab_delta_symmetry,
boundary.initial_vert_position,
strength,
deform_target);
}
});
});
break;
}
@@ -2238,7 +2250,7 @@ static void calc_twist_mesh(const Depsgraph &depsgraph,
const Span<float3> positions_eval,
const Span<int> vert_propagation_steps,
const Span<float> vert_factors,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
LocalDataMesh &tls,
const float3 twist_pivot_position,
const float3 twist_axis,
@@ -2297,7 +2309,7 @@ static void calc_twist_grids(const Depsgraph &depsgraph,
const Span<float> vert_factors,
const float3 twist_pivot_position,
const float3 twist_axis,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
LocalDataGrids &tls,
const float3 symmetry_pivot,
const float strength,
@@ -2358,7 +2370,7 @@ static void calc_twist_bmesh(const Depsgraph &depsgraph,
const Span<float> vert_factors,
const float3 twist_pivot_position,
const float3 twist_axis,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
LocalDataBMesh &tls,
const float3 symmetry_pivot,
const float strength,
@@ -2412,7 +2424,7 @@ static void calc_twist_bmesh(const Depsgraph &depsgraph,
static void do_twist_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
const Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
const SculptBoundary &boundary,
const float strength,
const eBrushDeformTarget deform_target)
@@ -2425,16 +2437,17 @@ static void do_twist_brush(const Depsgraph &depsgraph,
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::EnumerableThreadSpecific<LocalDataMesh> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalDataMesh &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_twist_mesh(depsgraph,
sd,
object,
positions_eval,
boundary.edit_info.propagation_steps_num,
boundary.edit_info.strength_factor,
*nodes[i],
nodes[i],
tls,
boundary.twist.pivot_position,
boundary.twist.rotation_axis,
@@ -2442,17 +2455,18 @@ static void do_twist_brush(const Depsgraph &depsgraph,
strength,
deform_target,
positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
threading::EnumerableThreadSpecific<LocalDataGrids> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalDataGrids &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_twist_grids(depsgraph,
sd,
object,
@@ -2461,20 +2475,21 @@ static void do_twist_brush(const Depsgraph &depsgraph,
boundary.edit_info.strength_factor,
boundary.twist.pivot_position,
boundary.twist.rotation_axis,
*nodes[i],
nodes[i],
tls,
boundary.initial_vert_position,
strength,
deform_target);
}
});
});
break;
}
case bke::pbvh::Type::BMesh: {
threading::EnumerableThreadSpecific<LocalDataBMesh> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalDataBMesh &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_twist_bmesh(depsgraph,
sd,
object,
@@ -2482,12 +2497,12 @@ static void do_twist_brush(const Depsgraph &depsgraph,
boundary.edit_info.strength_factor,
boundary.twist.pivot_position,
boundary.twist.rotation_axis,
*nodes[i],
nodes[i],
tls,
boundary.initial_vert_position,
strength,
deform_target);
}
});
});
break;
}
@@ -2611,7 +2626,7 @@ static void calc_smooth_mesh(const Depsgraph &depsgraph,
const Span<bool> hide_poly,
const Span<int> vert_propagation_steps,
const Span<float> vert_factors,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
LocalDataMesh &tls,
const float3 symmetry_pivot,
const float strength,
@@ -2677,7 +2692,7 @@ static void calc_smooth_grids(const Sculpt &sd,
SubdivCCG &subdiv_ccg,
const Span<int> vert_propagation_steps,
const Span<float> vert_factors,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
LocalDataGrids &tls,
const float3 symmetry_pivot,
const float strength,
@@ -2746,7 +2761,7 @@ static void calc_smooth_bmesh(const Sculpt &sd,
Object &object,
const Span<int> vert_propagation_steps,
const Span<float> vert_factors,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
LocalDataBMesh &tls,
const float3 symmetry_pivot,
const float strength,
@@ -2807,7 +2822,7 @@ static void calc_smooth_bmesh(const Sculpt &sd,
static void do_smooth_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
const Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
const SculptBoundary &boundary,
const float strength,
const eBrushDeformTarget deform_target)
@@ -2825,9 +2840,10 @@ static void do_smooth_brush(const Depsgraph &depsgraph,
const VArraySpan hide_poly = *attributes.lookup<bool>(".hide_poly", bke::AttrDomain::Face);
threading::EnumerableThreadSpecific<LocalDataMesh> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalDataMesh &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_smooth_mesh(depsgraph,
sd,
object,
@@ -2838,52 +2854,54 @@ static void do_smooth_brush(const Depsgraph &depsgraph,
hide_poly,
boundary.edit_info.propagation_steps_num,
boundary.edit_info.strength_factor,
*nodes[i],
nodes[i],
tls,
boundary.initial_vert_position,
strength,
deform_target,
positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
threading::EnumerableThreadSpecific<LocalDataGrids> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalDataGrids &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_smooth_grids(sd,
object,
subdiv_ccg,
boundary.edit_info.propagation_steps_num,
boundary.edit_info.strength_factor,
*nodes[i],
nodes[i],
tls,
boundary.initial_vert_position,
strength,
deform_target);
}
});
});
break;
}
case bke::pbvh::Type::BMesh: {
threading::EnumerableThreadSpecific<LocalDataBMesh> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalDataBMesh &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_smooth_bmesh(sd,
object,
boundary.edit_info.propagation_steps_num,
boundary.edit_info.strength_factor,
*nodes[i],
nodes[i],
tls,
boundary.initial_vert_position,
strength,
deform_target);
}
});
});
break;
}
@@ -3327,7 +3345,7 @@ static float get_mesh_strength(const SculptSession &ss, const Brush &brush)
void do_boundary_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &ob,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
SculptSession &ss = *ob.sculpt;
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
@@ -3362,7 +3380,7 @@ void do_boundary_brush(const Depsgraph &depsgraph,
do_bend_brush(depsgraph,
sd,
ob,
nodes,
node_mask,
*ss.cache->boundaries[symm_area],
strength,
eBrushDeformTarget(brush.deform_target));
@@ -3371,7 +3389,7 @@ void do_boundary_brush(const Depsgraph &depsgraph,
do_slide_brush(depsgraph,
sd,
ob,
nodes,
node_mask,
*ss.cache->boundaries[symm_area],
strength,
eBrushDeformTarget(brush.deform_target));
@@ -3380,7 +3398,7 @@ void do_boundary_brush(const Depsgraph &depsgraph,
do_inflate_brush(depsgraph,
sd,
ob,
nodes,
node_mask,
*ss.cache->boundaries[symm_area],
strength,
eBrushDeformTarget(brush.deform_target));
@@ -3389,7 +3407,7 @@ void do_boundary_brush(const Depsgraph &depsgraph,
do_grab_brush(depsgraph,
sd,
ob,
nodes,
node_mask,
*ss.cache->boundaries[symm_area],
strength,
eBrushDeformTarget(brush.deform_target));
@@ -3398,7 +3416,7 @@ void do_boundary_brush(const Depsgraph &depsgraph,
do_twist_brush(depsgraph,
sd,
ob,
nodes,
node_mask,
*ss.cache->boundaries[symm_area],
strength,
eBrushDeformTarget(brush.deform_target));
@@ -3407,7 +3425,7 @@ void do_boundary_brush(const Depsgraph &depsgraph,
do_smooth_brush(depsgraph,
sd,
ob,
nodes,
node_mask,
*ss.cache->boundaries[symm_area],
strength,
eBrushDeformTarget(brush.deform_target));

View File

@@ -174,7 +174,9 @@ static float3 cloth_brush_simulation_location_get(const SculptSession &ss, const
return ss.cache->location;
}
Vector<bke::pbvh::Node *> brush_affected_nodes_gather(SculptSession &ss, const Brush &brush)
IndexMask brush_affected_nodes_gather(SculptSession &ss,
const Brush &brush,
IndexMaskMemory &memory)
{
BLI_assert(ss.cache);
BLI_assert(brush.sculpt_tool == SCULPT_TOOL_CLOTH);
@@ -183,15 +185,15 @@ Vector<bke::pbvh::Node *> brush_affected_nodes_gather(SculptSession &ss, const B
case BRUSH_CLOTH_SIMULATION_AREA_LOCAL: {
const float radius_squared = math::square(ss.cache->initial_radius *
(1.0 + brush.cloth_sim_limit));
return bke::pbvh::search_gather(*ss.pbvh, [&](bke::pbvh::Node &node) {
return bke::pbvh::search_nodes(*ss.pbvh, memory, [&](const bke::pbvh::Node &node) {
return node_in_sphere(node, ss.cache->initial_location, radius_squared, false);
});
}
case BRUSH_CLOTH_SIMULATION_AREA_GLOBAL:
return bke::pbvh::all_leaf_nodes(*ss.pbvh);
return bke::pbvh::all_leaf_nodes(*ss.pbvh, memory);
case BRUSH_CLOTH_SIMULATION_AREA_DYNAMIC: {
const float radius_squared = math::square(ss.cache->radius * (1.0 + brush.cloth_sim_limit));
return bke::pbvh::search_gather(*ss.pbvh, [&](bke::pbvh::Node &node) {
return bke::pbvh::search_nodes(*ss.pbvh, memory, [&](const bke::pbvh::Node &node) {
return node_in_sphere(node, ss.cache->location, radius_squared, false);
});
}
@@ -475,7 +477,7 @@ static void add_constraints_for_verts(const Object &object,
void ensure_nodes_constraints(const Sculpt &sd,
const Object &object,
const Span<bke::pbvh::Node *> all_nodes,
const IndexMask &node_mask,
SimulationData &cloth_sim,
const float3 &initial_location,
const float radius)
@@ -488,20 +490,18 @@ void ensure_nodes_constraints(const Sculpt &sd,
/* Currently all constrains are added to the same global array which can't be accessed from
* different threads. */
Vector<bke::pbvh::Node *> nodes;
for (bke::pbvh::Node *node : all_nodes) {
const int node_index = cloth_sim.node_state_index.lookup(node);
if (cloth_sim.node_state[node_index] == SCULPT_CLOTH_NODE_UNINITIALIZED) {
/* The simulation already contains constraints for this node. */
nodes.append(node);
}
}
IndexMaskMemory memory;
Set<OrderedEdge> created_length_constraints;
Vector<int> vert_indices;
Vector<Vector<int>> vert_neighbors;
switch (ss.pbvh->type()) {
case bke::pbvh::Type::Mesh: {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
const IndexMask uninitialized_nodes = IndexMask::from_predicate(
node_mask, GrainSize(1024), memory, [&](const int i) {
const int node_index = cloth_sim.node_state_index.lookup(&nodes[i]);
return cloth_sim.node_state[node_index] == SCULPT_CLOTH_NODE_UNINITIALIZED;
});
const Mesh &mesh = *static_cast<const Mesh *>(object.data);
const OffsetIndices faces = mesh.faces();
const Span<int> corner_verts = mesh.corner_verts();
@@ -523,8 +523,8 @@ void ensure_nodes_constraints(const Sculpt &sd,
else {
init_positions = persistent_position;
}
for (const int i : nodes.index_range()) {
const Span<int> verts = hide::node_visible_verts(*nodes[i], hide_vert, vert_indices);
uninitialized_nodes.foreach_index([&](const int i) {
const Span<int> verts = hide::node_visible_verts(nodes[i], hide_vert, vert_indices);
vert_neighbors.resize(verts.size());
calc_vert_neighbors(
faces, corner_verts, ss.vert_to_face_map, hide_poly, verts, vert_neighbors);
@@ -533,21 +533,27 @@ void ensure_nodes_constraints(const Sculpt &sd,
initial_location,
radius,
init_positions,
cloth_sim.node_state_index.lookup(nodes[i]),
cloth_sim.node_state_index.lookup(&nodes[i]),
verts,
vert_neighbors,
cloth_sim,
created_length_constraints);
}
});
break;
}
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
const IndexMask uninitialized_nodes = IndexMask::from_predicate(
node_mask, GrainSize(1024), memory, [&](const int i) {
const int node_index = cloth_sim.node_state_index.lookup(&nodes[i]);
return cloth_sim.node_state[node_index] == SCULPT_CLOTH_NODE_UNINITIALIZED;
});
const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden;
for (const int i : nodes.index_range()) {
uninitialized_nodes.foreach_index([&](const int i) {
const Span<int> verts = calc_visible_vert_indices_grids(
key, grid_hidden, bke::pbvh::node_grid_indices(*nodes[i]), vert_indices);
key, grid_hidden, bke::pbvh::node_grid_indices(nodes[i]), vert_indices);
vert_neighbors.resize(verts.size());
calc_vert_neighbor_indices_grids(subdiv_ccg, verts, vert_neighbors);
add_constraints_for_verts(object,
@@ -555,20 +561,26 @@ void ensure_nodes_constraints(const Sculpt &sd,
initial_location,
radius,
cloth_sim.init_pos,
cloth_sim.node_state_index.lookup(nodes[i]),
cloth_sim.node_state_index.lookup(&nodes[i]),
verts,
vert_neighbors,
cloth_sim,
created_length_constraints);
}
});
break;
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
const IndexMask uninitialized_nodes = IndexMask::from_predicate(
node_mask, GrainSize(1024), memory, [&](const int i) {
const int node_index = cloth_sim.node_state_index.lookup(&nodes[i]);
return cloth_sim.node_state[node_index] == SCULPT_CLOTH_NODE_UNINITIALIZED;
});
BMesh &bm = *ss.bm;
BM_mesh_elem_index_ensure(&bm, BM_VERT);
BM_mesh_elem_table_ensure(&bm, BM_VERT);
for (const int i : nodes.index_range()) {
const Set<BMVert *, 0> &bm_verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]);
uninitialized_nodes.foreach_index([&](const int i) {
const Set<BMVert *, 0> &bm_verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]);
const Span<int> verts = calc_visible_vert_indices_bmesh(bm_verts, vert_indices);
vert_neighbors.resize(verts.size());
calc_vert_neighbor_indices_bmesh(bm, verts, vert_neighbors);
@@ -577,12 +589,12 @@ void ensure_nodes_constraints(const Sculpt &sd,
initial_location,
radius,
cloth_sim.init_pos,
cloth_sim.node_state_index.lookup(nodes[i]),
cloth_sim.node_state_index.lookup(&nodes[i]),
verts,
vert_neighbors,
cloth_sim,
created_length_constraints);
}
});
break;
}
}
@@ -718,7 +730,7 @@ static void calc_forces_mesh(const Depsgraph &depsgraph,
const std::optional<FalloffPlane> &falloff_plane,
const Span<float3> positions_eval,
const Span<float3> vert_normals,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
LocalData &tls)
{
SculptSession &ss = *ob.sculpt;
@@ -825,7 +837,7 @@ static void calc_forces_grids(const Depsgraph &depsgraph,
const float3 &sim_location,
const float3 &gravity,
const std::optional<FalloffPlane> &falloff_plane,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
LocalData &tls)
{
SculptSession &ss = *ob.sculpt;
@@ -935,7 +947,7 @@ static void calc_forces_bmesh(const Depsgraph &depsgraph,
const float3 &sim_location,
const float3 &gravity,
const std::optional<FalloffPlane> &falloff_plane,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
LocalData &tls)
{
SculptSession &ss = *ob.sculpt;
@@ -985,7 +997,7 @@ static void calc_forces_bmesh(const Depsgraph &depsgraph,
calc_brush_strength_factors(cache, brush, distances, factors);
const auto_mask::Cache *automask = auto_mask::active_cache_get(ss);
auto_mask::calc_vert_factors(depsgraph, ob, automask, node, verts, factors);
auto_mask::calc_vert_factors(depsgraph, ob, automask, node, bm_verts, factors);
calc_brush_texture_factors(ss, brush, current_positions, factors);
@@ -1213,8 +1225,8 @@ static void calc_constraint_factors(const Depsgraph &depsgraph,
{
const SculptSession &ss = *object.sculpt;
const bke::pbvh::Tree &pbvh = *ss.pbvh;
const Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(
const_cast<bke::pbvh::Tree &>(pbvh));
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
const auto_mask::Cache *automasking = auto_mask::active_cache_get(ss);
@@ -1226,36 +1238,38 @@ static void calc_constraint_factors(const Depsgraph &depsgraph,
switch (ss.pbvh->type()) {
case bke::pbvh::Type::Mesh: {
const Mesh &mesh = *static_cast<const Mesh *>(object.data);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
const Span<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> verts = bke::pbvh::node_unique_verts(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
tls.factors.resize(verts.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(mesh, verts, factors);
auto_mask::calc_vert_factors(depsgraph, object, automasking, *nodes[i], verts, factors);
auto_mask::calc_vert_factors(depsgraph, object, automasking, nodes[i], verts, factors);
if (ss.cache) {
const MutableSpan positions = gather_data_mesh(init_positions, verts, tls.positions);
calc_brush_simulation_falloff(
*brush, ss.cache->radius, sim_location, positions, factors);
}
scatter_data_mesh(factors.as_span(), verts, cloth_factors);
}
});
});
break;
}
case bke::pbvh::Type::Grids: {
const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
const Span<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> grids = bke::pbvh::node_grid_indices(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
const int grid_verts_num = grids.size() * key.grid_area;
tls.factors.resize(grid_verts_num);
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
auto_mask::calc_grids_factors(depsgraph, object, automasking, *nodes[i], grids, factors);
auto_mask::calc_grids_factors(depsgraph, object, automasking, nodes[i], grids, factors);
if (ss.cache) {
const Span<float3> positions = gather_data_grids(
subdiv_ccg, init_positions, grids, tls.positions);
@@ -1263,20 +1277,22 @@ static void calc_constraint_factors(const Depsgraph &depsgraph,
*brush, ss.cache->radius, sim_location, positions, factors);
}
scatter_data_grids(subdiv_ccg, factors.as_span(), grids, cloth_factors);
}
});
});
break;
}
case bke::pbvh::Type::BMesh: {
const BMesh &bm = *ss.bm;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
const Span<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(
const_cast<bke::pbvh::BMeshNode *>(&nodes[i]));
tls.factors.resize(verts.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(bm, verts, factors);
auto_mask::calc_vert_factors(depsgraph, object, automasking, *nodes[i], verts, factors);
auto_mask::calc_vert_factors(depsgraph, object, automasking, nodes[i], verts, factors);
if (ss.cache) {
const MutableSpan<float3> positions = gather_data_vert_bmesh(
init_positions, verts, tls.positions);
@@ -1284,7 +1300,7 @@ static void calc_constraint_factors(const Depsgraph &depsgraph,
*brush, ss.cache->radius, sim_location, positions, factors);
}
scatter_data_vert_bmesh(factors.as_span(), verts, cloth_factors);
}
});
});
break;
}
@@ -1366,7 +1382,7 @@ void do_simulation_step(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
SimulationData &cloth_sim,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
SculptSession &ss = *object.sculpt;
const bke::pbvh::Tree &pbvh = *ss.pbvh;
@@ -1375,34 +1391,31 @@ void do_simulation_step(const Depsgraph &depsgraph,
/* Update the constraints. */
cloth_brush_satisfy_constraints(depsgraph, object, brush, cloth_sim);
Vector<bke::pbvh::Node *> active_nodes;
for (bke::pbvh::Node *node : nodes) {
const int node_index = cloth_sim.node_state_index.lookup(node);
if (cloth_sim.node_state[node_index] == SCULPT_CLOTH_NODE_ACTIVE) {
active_nodes.append(node);
/* Nodes need to be enabled again to continue. */
cloth_sim.node_state[node_index] = SCULPT_CLOTH_NODE_INACTIVE;
}
}
const float3 sim_location = cloth_brush_simulation_location_get(ss, brush);
IndexMaskMemory memory;
threading::EnumerableThreadSpecific<LocalData> all_tls;
switch (pbvh.type()) {
case bke::pbvh::Type::Mesh: {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
const IndexMask active_nodes = IndexMask::from_predicate(
node_mask, GrainSize(1024), memory, [&](const int i) {
const int node_index = cloth_sim.node_state_index.lookup(&nodes[i]);
return cloth_sim.node_state[node_index] == SCULPT_CLOTH_NODE_ACTIVE;
});
Mesh &mesh = *static_cast<Mesh *>(object.data);
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object);
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::parallel_for(active_nodes.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> verts = bke::pbvh::node_unique_verts(*nodes[i]);
active_nodes.slice(range).foreach_index([&](const int i) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
tls.factors.resize(verts.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(mesh, verts, factors);
const auto_mask::Cache *automasking = auto_mask::active_cache_get(ss);
auto_mask::calc_vert_factors(depsgraph, object, automasking, *nodes[i], verts, factors);
auto_mask::calc_vert_factors(depsgraph, object, automasking, nodes[i], verts, factors);
solve_verts_simulation(object, brush, sim_location, verts, factors, tls, cloth_sim);
@@ -1413,25 +1426,34 @@ void do_simulation_step(const Depsgraph &depsgraph,
}
write_translations(
depsgraph, sd, object, positions_eval, verts, translations, positions_orig);
}
cloth_sim.node_state[cloth_sim.node_state_index.lookup(&nodes[i])] =
SCULPT_CLOTH_NODE_INACTIVE;
});
});
break;
}
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
const IndexMask active_nodes = IndexMask::from_predicate(
node_mask, GrainSize(1024), memory, [&](const int i) {
const int node_index = cloth_sim.node_state_index.lookup(&nodes[i]);
return cloth_sim.node_state[node_index] == SCULPT_CLOTH_NODE_ACTIVE;
});
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
const Span<CCGElem *> elems = subdiv_ccg.grids;
threading::parallel_for(active_nodes.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> grids = bke::pbvh::node_grid_indices(*nodes[i]);
active_nodes.slice(range).foreach_index([&](const int i) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
const int grid_verts_num = grids.size() * key.grid_area;
tls.factors.resize(grid_verts_num);
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
const auto_mask::Cache *automasking = auto_mask::active_cache_get(ss);
auto_mask::calc_grids_factors(depsgraph, object, automasking, *nodes[i], grids, factors);
auto_mask::calc_grids_factors(depsgraph, object, automasking, nodes[i], grids, factors);
const Span<int> verts = calc_vert_indices_grids(key, grids, tls.vert_indices);
solve_verts_simulation(object, brush, sim_location, verts, factors, tls, cloth_sim);
@@ -1445,22 +1467,31 @@ void do_simulation_step(const Depsgraph &depsgraph,
CCG_elem_offset_co(key, elem, offset) = cloth_sim.pos[grid_vert_index];
}
}
}
cloth_sim.node_state[cloth_sim.node_state_index.lookup(&nodes[i])] =
SCULPT_CLOTH_NODE_INACTIVE;
});
});
break;
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
const IndexMask active_nodes = IndexMask::from_predicate(
node_mask, GrainSize(1024), memory, [&](const int i) {
const int node_index = cloth_sim.node_state_index.lookup(&nodes[i]);
return cloth_sim.node_state[node_index] == SCULPT_CLOTH_NODE_ACTIVE;
});
BMesh &bm = *ss.bm;
threading::parallel_for(active_nodes.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]);
active_nodes.slice(range).foreach_index([&](const int i) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]);
tls.factors.resize(verts.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(bm, verts, factors);
const auto_mask::Cache *automasking = auto_mask::active_cache_get(ss);
auto_mask::calc_vert_factors(depsgraph, object, automasking, *nodes[i], verts, factors);
auto_mask::calc_vert_factors(depsgraph, object, automasking, nodes[i], verts, factors);
const Span<int> vert_indices = calc_vert_indices_bmesh(verts, tls.vert_indices);
solve_verts_simulation(
@@ -1469,7 +1500,10 @@ void do_simulation_step(const Depsgraph &depsgraph,
for (BMVert *vert : verts) {
copy_v3_v3(vert->co, cloth_sim.pos[BM_elem_index_get(vert)]);
}
}
cloth_sim.node_state[cloth_sim.node_state_index.lookup(&nodes[i])] =
SCULPT_CLOTH_NODE_INACTIVE;
});
});
break;
}
@@ -1479,7 +1513,7 @@ void do_simulation_step(const Depsgraph &depsgraph,
static void cloth_brush_apply_brush_foces(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &ob,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
SculptSession &ss = *ob.sculpt;
StrokeCache &cache = *ss.cache;
@@ -1504,7 +1538,7 @@ static void cloth_brush_apply_brush_foces(const Depsgraph &depsgraph,
if (brush.cloth_deform_type == BRUSH_CLOTH_DEFORM_PINCH_PERPENDICULAR ||
brush.cloth_force_falloff_type == BRUSH_CLOTH_FORCE_FALLOFF_PLANE)
{
calc_brush_plane(depsgraph, brush, ob, nodes, area_no, area_co);
calc_brush_plane(depsgraph, brush, ob, node_mask, area_no, area_co);
/* Initialize stroke local space matrix. */
mat.x_axis() = math::cross(area_no, cache.grab_delta_symmetry);
@@ -1545,9 +1579,10 @@ static void cloth_brush_apply_brush_foces(const Depsgraph &depsgraph,
case bke::pbvh::Type::Mesh: {
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, ob);
const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, ob);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_forces_mesh(depsgraph,
ob,
brush,
@@ -1558,16 +1593,17 @@ static void cloth_brush_apply_brush_foces(const Depsgraph &depsgraph,
falloff_plane,
positions_eval,
vert_normals,
*nodes[i],
nodes[i],
tls);
}
});
});
break;
}
case bke::pbvh::Type::Grids: {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_forces_grids(depsgraph,
ob,
brush,
@@ -1576,16 +1612,17 @@ static void cloth_brush_apply_brush_foces(const Depsgraph &depsgraph,
sim_location,
gravity,
falloff_plane,
*nodes[i],
nodes[i],
tls);
}
});
});
break;
}
case bke::pbvh::Type::BMesh: {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
calc_forces_bmesh(depsgraph,
ob,
brush,
@@ -1594,9 +1631,9 @@ static void cloth_brush_apply_brush_foces(const Depsgraph &depsgraph,
sim_location,
gravity,
falloff_plane,
*nodes[i],
nodes[i],
tls);
}
});
});
break;
}
@@ -1607,12 +1644,35 @@ static void cloth_brush_apply_brush_foces(const Depsgraph &depsgraph,
* them. */
static void cloth_sim_initialize_default_node_state(SculptSession &ss, SimulationData &cloth_sim)
{
Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory);
cloth_sim.node_state = Array<NodeSimState>(node_mask.size());
cloth_sim.node_state = Array<NodeSimState>(nodes.size());
for (const int i : nodes.index_range()) {
cloth_sim.node_state[i] = SCULPT_CLOTH_NODE_UNINITIALIZED;
cloth_sim.node_state_index.add(nodes[i], i);
switch (ss.pbvh->type()) {
case bke::pbvh::Type::Mesh: {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
node_mask.foreach_index([&](const int i) {
cloth_sim.node_state[i] = SCULPT_CLOTH_NODE_UNINITIALIZED;
cloth_sim.node_state_index.add(&nodes[i], i);
});
break;
}
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
node_mask.foreach_index([&](const int i) {
cloth_sim.node_state[i] = SCULPT_CLOTH_NODE_UNINITIALIZED;
cloth_sim.node_state_index.add(&nodes[i], i);
});
break;
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
node_mask.foreach_index([&](const int i) {
cloth_sim.node_state[i] = SCULPT_CLOTH_NODE_UNINITIALIZED;
cloth_sim.node_state_index.add(&nodes[i], i);
});
break;
}
}
}
@@ -1621,21 +1681,23 @@ static void copy_positions_to_array(const Depsgraph &depsgraph,
MutableSpan<float3> positions)
{
const SculptSession &ss = *object.sculpt;
bke::pbvh::Tree &pbvh = *ss.pbvh;
const bke::pbvh::Tree &pbvh = *ss.pbvh;
switch (pbvh.type()) {
case bke::pbvh::Type::Mesh:
positions.copy_from(bke::pbvh::vert_positions_eval(depsgraph, object));
break;
case bke::pbvh::Type::Grids: {
const Span<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
Vector<bke::pbvh::Node *> all_nodes = bke::pbvh::all_leaf_nodes(pbvh);
threading::parallel_for(all_nodes.index_range(), 8, [&](const IndexRange range) {
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
threading::parallel_for(node_mask.index_range(), 8, [&](const IndexRange range) {
Vector<float3> node_positions;
for (const int i : range) {
const Span<int> grids = bke::pbvh::node_grid_indices(*all_nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
gather_grids_positions(subdiv_ccg, grids, node_positions);
scatter_data_grids(subdiv_ccg, node_positions.as_span(), grids, positions);
}
});
});
break;
}
@@ -1650,25 +1712,27 @@ static void copy_normals_to_array(const Depsgraph &depsgraph,
MutableSpan<float3> normals)
{
const SculptSession &ss = *object.sculpt;
bke::pbvh::Tree &pbvh = *ss.pbvh;
const bke::pbvh::Tree &pbvh = *ss.pbvh;
switch (pbvh.type()) {
case bke::pbvh::Type::Mesh:
normals.copy_from(bke::pbvh::vert_normals_eval(depsgraph, object));
break;
case bke::pbvh::Type::Grids: {
const Span<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
Vector<bke::pbvh::Node *> all_nodes = bke::pbvh::all_leaf_nodes(pbvh);
threading::parallel_for(all_nodes.index_range(), 8, [&](const IndexRange range) {
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
threading::parallel_for(node_mask.index_range(), 8, [&](const IndexRange range) {
Vector<float3> node_normals;
for (const int i : range) {
const Span<int> grids = bke::pbvh::node_grid_indices(*all_nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
const int grid_verts_num = grids.size() * key.grid_area;
node_normals.resize(grid_verts_num);
gather_grids_normals(subdiv_ccg, grids, node_normals);
scatter_data_grids(subdiv_ccg, node_normals.as_span(), grids, normals);
}
});
});
break;
}
@@ -1734,31 +1798,57 @@ void brush_store_simulation_state(const Depsgraph &depsgraph,
copy_positions_to_array(depsgraph, object, cloth_sim.pos);
}
void sim_activate_nodes(SimulationData &cloth_sim, Span<bke::pbvh::Node *> nodes)
void sim_activate_nodes(const Object &object,
SimulationData &cloth_sim,
const IndexMask &node_mask)
{
const SculptSession &ss = *object.sculpt;
/* Activate the nodes inside the simulation area. */
for (bke::pbvh::Node *node : nodes) {
const int node_index = cloth_sim.node_state_index.lookup(node);
cloth_sim.node_state[node_index] = SCULPT_CLOTH_NODE_ACTIVE;
switch (ss.pbvh->type()) {
case bke::pbvh::Type::Mesh: {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
node_mask.foreach_index([&](const int i) {
const int node_index = cloth_sim.node_state_index.lookup(&nodes[i]);
cloth_sim.node_state[node_index] = SCULPT_CLOTH_NODE_ACTIVE;
});
break;
}
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
node_mask.foreach_index([&](const int i) {
const int node_index = cloth_sim.node_state_index.lookup(&nodes[i]);
cloth_sim.node_state[node_index] = SCULPT_CLOTH_NODE_ACTIVE;
});
break;
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
node_mask.foreach_index([&](const int i) {
const int node_index = cloth_sim.node_state_index.lookup(&nodes[i]);
cloth_sim.node_state[node_index] = SCULPT_CLOTH_NODE_ACTIVE;
});
break;
}
}
}
static void sculpt_cloth_ensure_constraints_in_simulation_area(const Sculpt &sd,
Object &ob,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
SculptSession &ss = *ob.sculpt;
const Brush *brush = BKE_paint_brush_for_read(&sd.paint);
const float radius = ss.cache->initial_radius;
const float limit = radius + (radius * brush->cloth_sim_limit);
const float3 sim_location = cloth_brush_simulation_location_get(ss, brush);
ensure_nodes_constraints(sd, ob, nodes, *ss.cache->cloth_sim, sim_location, limit);
ensure_nodes_constraints(sd, ob, node_mask, *ss.cache->cloth_sim, sim_location, limit);
}
void do_cloth_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &ob,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
SculptSession &ss = *ob.sculpt;
const Brush *brush = BKE_paint_brush_for_read(&sd.paint);
@@ -1789,7 +1879,7 @@ void do_cloth_brush(const Depsgraph &depsgraph,
* as this will cause the ensure constraints function to skip the node in the next symmetry
* passes. It needs to build the constraints here and skip simulating the first step, so all
* passes can add their constraints to all affected nodes. */
sculpt_cloth_ensure_constraints_in_simulation_area(sd, ob, nodes);
sculpt_cloth_ensure_constraints_in_simulation_area(sd, ob, node_mask);
}
/* The first step of a symmetry pass is never simulated as deformation modes need valid delta
* for brush tip alignment. */
@@ -1797,19 +1887,19 @@ void do_cloth_brush(const Depsgraph &depsgraph,
}
/* Ensure the constraints for the nodes. */
sculpt_cloth_ensure_constraints_in_simulation_area(sd, ob, nodes);
sculpt_cloth_ensure_constraints_in_simulation_area(sd, ob, node_mask);
/* Store the initial state in the simulation. */
brush_store_simulation_state(depsgraph, ob, *ss.cache->cloth_sim);
/* Enable the nodes that should be simulated. */
sim_activate_nodes(*ss.cache->cloth_sim, nodes);
sim_activate_nodes(ob, *ss.cache->cloth_sim, node_mask);
/* Apply forces to the vertices. */
cloth_brush_apply_brush_foces(depsgraph, sd, ob, nodes);
cloth_brush_apply_brush_foces(depsgraph, sd, ob, node_mask);
/* Update and write the simulation to the nodes. */
do_simulation_step(depsgraph, sd, ob, *ss.cache->cloth_sim, nodes);
do_simulation_step(depsgraph, sd, ob, *ss.cache->cloth_sim, node_mask);
}
SimulationData::~SimulationData() = default;
@@ -1991,7 +2081,7 @@ static void apply_filter_forces_mesh(const Depsgraph &depsgraph,
const float3 &gravity,
const Span<float3> positions_eval,
const Span<float3> vert_normals,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
Object &object,
FilterLocalData &tls)
{
@@ -2059,7 +2149,7 @@ static void apply_filter_forces_grids(const Depsgraph &depsgraph,
const ClothFilterType filter_type,
const float filter_strength,
const float3 &gravity,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
Object &object,
FilterLocalData &tls)
{
@@ -2130,7 +2220,7 @@ static void apply_filter_forces_bmesh(const Depsgraph &depsgraph,
const ClothFilterType filter_type,
const float filter_strength,
const float3 &gravity,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
Object &object,
FilterLocalData &tls)
{
@@ -2227,7 +2317,7 @@ static int sculpt_cloth_filter_modal(bContext *C, wmOperator *op, const wmEvent
brush_store_simulation_state(*depsgraph, object, *ss.filter_cache->cloth_sim);
const Span<bke::pbvh::Node *> nodes = ss.filter_cache->nodes;
const IndexMask &node_mask = ss.filter_cache->node_mask;
float3 gravity(0.0f);
if (sd.gravity_object) {
@@ -2243,50 +2333,55 @@ static int sculpt_cloth_filter_modal(bContext *C, wmOperator *op, const wmEvent
case bke::pbvh::Type::Mesh: {
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(*depsgraph, object);
const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(*depsgraph, object);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
FilterLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
apply_filter_forces_mesh(*depsgraph,
filter_type,
filter_strength,
gravity,
positions_eval,
vert_normals,
*nodes[i],
nodes[i],
object,
tls);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
FilterLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
apply_filter_forces_grids(
*depsgraph, filter_type, filter_strength, gravity, *nodes[i], object, tls);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
*depsgraph, filter_type, filter_strength, gravity, nodes[i], object, tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
case bke::pbvh::Type::BMesh:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
FilterLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
apply_filter_forces_bmesh(
*depsgraph, filter_type, filter_strength, gravity, *nodes[i], object, tls);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
*depsgraph, filter_type, filter_strength, gravity, nodes[i], object, tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
}
/* Activate all nodes. */
sim_activate_nodes(*ss.filter_cache->cloth_sim, nodes);
sim_activate_nodes(object, *ss.filter_cache->cloth_sim, node_mask);
/* Update and write the simulation to the nodes. */
do_simulation_step(*depsgraph, sd, object, *ss.filter_cache->cloth_sim, nodes);
do_simulation_step(*depsgraph, sd, object, *ss.filter_cache->cloth_sim, node_mask);
flush_update_step(C, UpdateType::Position);
return OPERATOR_RUNNING_MODAL;
@@ -2348,7 +2443,7 @@ static int sculpt_cloth_filter_invoke(bContext *C, wmOperator *op, const wmEvent
float3 origin(0);
ensure_nodes_constraints(
sd, ob, ss.filter_cache->nodes, *ss.filter_cache->cloth_sim, origin, FLT_MAX);
sd, ob, ss.filter_cache->node_mask, *ss.filter_cache->cloth_sim, origin, FLT_MAX);
const bool use_face_sets = RNA_boolean_get(op->ptr, "use_face_sets");
if (use_face_sets) {

View File

@@ -9,6 +9,7 @@
#pragma once
#include "BLI_array.hh"
#include "BLI_index_mask_fwd.hh"
#include "BLI_map.hh"
#include "BLI_math_vector.hh"
#include "BLI_vector.hh"
@@ -113,7 +114,9 @@ std::unique_ptr<SimulationData> brush_simulation_create(const Depsgraph &depsgra
bool use_collisions,
bool needs_deform_coords);
void sim_activate_nodes(SimulationData &cloth_sim, Span<blender::bke::pbvh::Node *> nodes);
void sim_activate_nodes(const Object &object,
SimulationData &cloth_sim,
const IndexMask &node_mask);
void brush_store_simulation_state(const Depsgraph &depsgraph,
const Object &object,
@@ -123,11 +126,11 @@ void do_simulation_step(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &ob,
SimulationData &cloth_sim,
Span<blender::bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
void ensure_nodes_constraints(const Sculpt &sd,
const Object &ob,
Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
SimulationData &cloth_sim,
const float3 &initial_location,
float radius);
@@ -148,8 +151,9 @@ void plane_falloff_preview_draw(uint gpuattr,
const float outline_col[3],
float outline_alpha);
Vector<blender::bke::pbvh::Node *> brush_affected_nodes_gather(SculptSession &ss,
const Brush &brush);
IndexMask brush_affected_nodes_gather(SculptSession &ss,
const Brush &brush,
IndexMaskMemory &memory);
bool is_cloth_deform_brush(const Brush &brush);

View File

@@ -65,10 +65,10 @@ void do_paint_brush(const Depsgraph &depsgraph,
PaintModeSettings &paint_mode_settings,
const Sculpt &sd,
Object &ob,
Span<bke::pbvh::Node *> nodes,
Span<bke::pbvh::Node *> texnodes);
const IndexMask &node_mask,
const IndexMask &texnode_mask);
void do_smear_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &ob,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
} // namespace blender::ed::sculpt_paint::color

View File

@@ -108,15 +108,17 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh);
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory);
if (nodes.is_empty()) {
return OPERATOR_CANCELLED;
}
for (bke::pbvh::Node *node : nodes) {
BKE_pbvh_node_mark_topology_update(*node);
}
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_topology_update(nodes[i]); });
/* Get the bounding box, its center and size. */
const Bounds<float3> bounds = bke::pbvh::bounds_get(*ob.sculpt->pbvh);
const float3 center = math::midpoint(bounds.min, bounds.max);
@@ -145,9 +147,7 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *op)
false,
false))
{
for (bke::pbvh::Node *node : nodes) {
BKE_pbvh_node_mark_topology_update(*node);
}
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_topology_update(nodes[i]); });
}
CLOG_INFO(&LOG, 2, "Detail flood fill took %f seconds.", BLI_time_now_seconds() - start_time);

View File

@@ -1424,27 +1424,45 @@ static void expand_cache_free(SculptSession &ss)
*/
static void restore_face_set_data(Object &object, Cache &expand_cache)
{
SculptSession &ss = *object.sculpt;
bke::SpanAttributeWriter<int> face_sets = face_set::ensure_face_sets_mesh(object);
face_sets.span.copy_from(expand_cache.original_face_sets);
face_sets.finish();
for (bke::pbvh::Node *node : bke::pbvh::all_leaf_nodes(*object.sculpt->pbvh)) {
BKE_pbvh_node_mark_update_face_sets(*node);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory);
switch (ss.pbvh->type()) {
case bke::pbvh::Type::Mesh: {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_face_sets(nodes[i]); });
break;
}
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_face_sets(nodes[i]); });
break;
}
case bke::pbvh::Type::BMesh: {
BLI_assert_unreachable();
break;
}
}
}
static void restore_color_data(Object &ob, Cache &expand_cache)
{
SculptSession &ss = *ob.sculpt;
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
Mesh &mesh = *static_cast<Mesh *>(ob.data);
Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory);
const OffsetIndices<int> faces = mesh.faces();
const Span<int> corner_verts = mesh.corner_verts();
const GroupedSpan<int> vert_to_face_map = ss.vert_to_face_map;
bke::GSpanAttributeWriter color_attribute = color::active_color_attribute_for_write(mesh);
for (bke::pbvh::Node *node : nodes) {
for (const int vert : bke::pbvh::node_unique_verts(*node)) {
node_mask.foreach_index([&](const int i) {
for (const int vert : bke::pbvh::node_unique_verts(nodes[i])) {
color::color_vert_set(faces,
corner_verts,
vert_to_face_map,
@@ -1453,14 +1471,16 @@ static void restore_color_data(Object &ob, Cache &expand_cache)
expand_cache.original_colors[vert],
color_attribute.span);
}
BKE_pbvh_node_mark_redraw(*node);
}
BKE_pbvh_node_mark_redraw(nodes[i]);
});
color_attribute.finish();
}
static void write_mask_data(Object &object, const Span<float> mask)
{
SculptSession &ss = *object.sculpt;
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory);
switch (ss.pbvh->type()) {
case bke::pbvh::Type::Mesh: {
Mesh &mesh = *static_cast<Mesh *>(object.data);
@@ -1469,6 +1489,8 @@ static void write_mask_data(Object &object, const Span<float> mask)
attributes.add<float>(".sculpt_mask",
bke::AttrDomain::Point,
bke::AttributeInitVArray(VArray<float>::ForSpan(mask)));
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_mask(nodes[i]); });
break;
}
case bke::pbvh::Type::BMesh: {
@@ -1479,6 +1501,8 @@ static void write_mask_data(Object &object, const Span<float> mask)
for (const int i : mask.index_range()) {
BM_ELEM_CD_SET_FLOAT(BM_vert_at_index(&bm, i), offset, mask[i]);
}
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_mask(nodes[i]); });
break;
}
case bke::pbvh::Type::Grids: {
@@ -1494,13 +1518,11 @@ static void write_mask_data(Object &object, const Span<float> mask)
index++;
}
}
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_mask(nodes[i]); });
break;
}
}
for (bke::pbvh::Node *node : bke::pbvh::all_leaf_nodes(*ss.pbvh)) {
BKE_pbvh_node_mark_update_mask(*node);
}
}
/* Main function to restore the original state of the data to how it was before starting the expand
@@ -1582,7 +1604,7 @@ static void calc_new_mask_mesh(const SculptSession &ss,
static void update_mask_grids(const SculptSession &ss,
const BitSpan enabled_verts,
bke::pbvh::Node &node,
bke::pbvh::GridsNode &node,
SubdivCCG &subdiv_ccg)
{
const Cache &expand_cache = *ss.expand_cache;
@@ -1638,7 +1660,7 @@ static void update_mask_grids(const SculptSession &ss,
static void update_mask_bmesh(SculptSession &ss,
const BitSpan enabled_verts,
const int mask_offset,
bke::pbvh::Node *node)
bke::pbvh::BMeshNode *node)
{
const Cache &expand_cache = *ss.expand_cache;
@@ -1708,9 +1730,9 @@ static void face_sets_update(Object &object, Cache &expand_cache)
face_sets.finish();
for (bke::pbvh::Node *node : expand_cache.nodes) {
BKE_pbvh_node_mark_update_face_sets(*node);
}
MutableSpan<bke::pbvh::MeshNode> nodes = object.sculpt->pbvh->nodes<bke::pbvh::MeshNode>();
expand_cache.node_mask.foreach_index(
[&](const int i) { BKE_pbvh_node_mark_update_face_sets(nodes[i]); });
}
/**
@@ -1724,7 +1746,7 @@ static void colors_update_task(const Depsgraph &depsgraph,
const GroupedSpan<int> vert_to_face_map,
const Span<bool> hide_vert,
const Span<float> mask,
bke::pbvh::Node *node,
bke::pbvh::MeshNode *node,
bke::GSpanAttributeWriter &color_attribute)
{
const SculptSession &ss = *object.sculpt;
@@ -1868,7 +1890,7 @@ static void update_for_vert(bContext *C, Object &ob, const PBVHVertRef vertex)
face_sets_restore(ob, expand_cache);
}
const Span<bke::pbvh::Node *> nodes = expand_cache.nodes;
const IndexMask &node_mask = expand_cache.node_mask;
const BitVector<> enabled_verts = enabled_state_to_bitmap(depsgraph, ob, expand_cache);
@@ -1878,26 +1900,24 @@ static void update_for_vert(bContext *C, Object &ob, const PBVHVertRef vertex)
case bke::pbvh::Type::Mesh: {
const Span<float3> positions = bke::pbvh::vert_positions_eval(depsgraph, ob);
mask::update_mask_mesh(
depsgraph, ob, nodes, [&](const MutableSpan<float> mask, const Span<int> verts) {
depsgraph, ob, node_mask, [&](const MutableSpan<float> mask, const Span<int> verts) {
calc_new_mask_mesh(ss, positions, enabled_verts, verts, mask);
});
break;
}
case bke::pbvh::Type::Grids: {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (const int i : range) {
update_mask_grids(ss, enabled_verts, *nodes[i], *ss.subdiv_ccg);
}
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
node_mask.foreach_index(GrainSize(1), [&](const int i) {
update_mask_grids(ss, enabled_verts, nodes[i], *ss.subdiv_ccg);
});
break;
}
case bke::pbvh::Type::BMesh: {
const int mask_offset = CustomData_get_offset_named(
&ss.bm->vdata, CD_PROP_FLOAT, ".sculpt_mask");
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (const int i : range) {
update_mask_bmesh(ss, enabled_verts, mask_offset, nodes[i]);
}
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
node_mask.foreach_index(GrainSize(1), [&](const int i) {
update_mask_bmesh(ss, enabled_verts, mask_offset, &nodes[i]);
});
break;
}
@@ -1920,19 +1940,18 @@ static void update_for_vert(bContext *C, Object &ob, const PBVHVertRef vertex)
const VArraySpan mask = *attributes.lookup<float>(".sculpt_mask", bke::AttrDomain::Point);
bke::GSpanAttributeWriter color_attribute = color::active_color_attribute_for_write(mesh);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (const int i : range) {
colors_update_task(depsgraph,
ob,
vert_positions,
faces,
corner_verts,
vert_to_face_map,
hide_vert,
mask,
nodes[i],
color_attribute);
}
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
node_mask.foreach_index(GrainSize(1), [&](const int i) {
colors_update_task(depsgraph,
ob,
vert_positions,
faces,
corner_verts,
vert_to_face_map,
hide_vert,
mask,
&nodes[i],
color_attribute);
});
color_attribute.finish();
flush_update_step(C, UpdateType::Color);
@@ -2017,12 +2036,6 @@ static void finish(bContext *C)
SculptSession &ss = *ob.sculpt;
undo::push_end(ob);
/* Tag all nodes to redraw to avoid artifacts after the fast partial updates. */
Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh);
for (bke::pbvh::Node *node : nodes) {
BKE_pbvh_node_mark_update_mask(*node);
}
switch (ss.expand_cache->target) {
case TargetType::Mask:
flush_update_done(C, ob, UpdateType::Mask);
@@ -2485,20 +2498,21 @@ static void cache_initial_config_set(bContext *C, wmOperator *op, Cache &expand_
static void undo_push(const Depsgraph &depsgraph, Object &ob, Cache &expand_cache)
{
SculptSession &ss = *ob.sculpt;
Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory);
switch (expand_cache.target) {
case TargetType::Mask:
undo::push_nodes(depsgraph, ob, nodes, undo::Type::Mask);
undo::push_nodes(depsgraph, ob, node_mask, undo::Type::Mask);
break;
case TargetType::FaceSets:
undo::push_nodes(depsgraph, ob, nodes, undo::Type::FaceSet);
undo::push_nodes(depsgraph, ob, node_mask, undo::Type::FaceSet);
break;
case TargetType::Colors: {
const Mesh &mesh = *static_cast<const Mesh *>(ob.data);
/* The sculpt undo system needs corner indices for corner domain color attributes. */
BKE_pbvh_ensure_node_face_corners(*ss.pbvh, mesh.corner_tris());
undo::push_nodes(depsgraph, ob, nodes, undo::Type::Color);
undo::push_nodes(depsgraph, ob, node_mask, undo::Type::Color);
break;
}
}
@@ -2619,7 +2633,8 @@ static int sculpt_expand_invoke(bContext *C, wmOperator *op, const wmEvent *even
set_initial_components_for_mouse(C, ob, *ss.expand_cache, mouse);
/* Cache bke::pbvh::Tree nodes. */
ss.expand_cache->nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh);
ss.expand_cache->node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh,
ss.expand_cache->node_mask_memory);
/* Store initial state. */
original_state_store(ob, *ss.expand_cache);

View File

@@ -8,6 +8,7 @@
#pragma once
#include "BLI_array.hh"
#include "BLI_index_mask.hh"
#include "BLI_math_vector.hh"
#include "BLI_set.hh"
@@ -117,7 +118,8 @@ struct Cache {
/* Cached pbvh::Tree nodes. This allows to skip gathering all nodes from the pbvh::Tree each time
* expand needs to update the state of the elements. */
Vector<bke::pbvh::Node *> nodes;
IndexMaskMemory node_mask_memory;
IndexMask node_mask;
/* Expand state options. */

View File

@@ -284,7 +284,7 @@ void filter_verts_with_unique_face_sets_bmesh(const bool unique,
static void face_sets_update(const Depsgraph &depsgraph,
Object &object,
const Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
const FunctionRef<void(Span<int>, MutableSpan<int>)> calc_face_sets)
{
SculptSession &ss = *object.sculpt;
@@ -300,29 +300,50 @@ static void face_sets_update(const Depsgraph &depsgraph,
};
threading::EnumerableThreadSpecific<TLS> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
TLS &tls = all_tls.local();
for (bke::pbvh::Node *node : nodes.slice(range)) {
const Span<int> faces =
pbvh.type() == bke::pbvh::Type::Mesh ?
bke::pbvh::node_face_indices_calc_mesh(
tri_faces, static_cast<bke::pbvh::MeshNode &>(*node), tls.face_indices) :
bke::pbvh::node_face_indices_calc_grids(
*ss.subdiv_ccg, static_cast<bke::pbvh::GridsNode &>(*node), tls.face_indices);
if (pbvh.type() == bke::pbvh::Type::Mesh) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
TLS &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> faces = bke::pbvh::node_face_indices_calc_mesh(
tri_faces, nodes[i], tls.face_indices);
tls.new_face_sets.resize(faces.size());
MutableSpan<int> new_face_sets = tls.new_face_sets;
array_utils::gather(face_sets.span.as_span(), faces, new_face_sets);
calc_face_sets(faces, new_face_sets);
if (array_utils::indexed_data_equal<int>(face_sets.span, faces, new_face_sets)) {
continue;
}
tls.new_face_sets.resize(faces.size());
MutableSpan<int> new_face_sets = tls.new_face_sets;
array_utils::gather(face_sets.span.as_span(), faces, new_face_sets);
calc_face_sets(faces, new_face_sets);
if (array_utils::indexed_data_equal<int>(face_sets.span, faces, new_face_sets)) {
return;
}
undo::push_node(depsgraph, object, node, undo::Type::FaceSet);
array_utils::scatter(new_face_sets.as_span(), faces, face_sets.span);
BKE_pbvh_node_mark_update_face_sets(*node);
}
});
undo::push_node(depsgraph, object, &nodes[i], undo::Type::FaceSet);
array_utils::scatter(new_face_sets.as_span(), faces, face_sets.span);
BKE_pbvh_node_mark_update_face_sets(nodes[i]);
});
});
}
else if (pbvh.type() == bke::pbvh::Type::Grids) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
TLS &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> faces = bke::pbvh::node_face_indices_calc_grids(
*ss.subdiv_ccg, nodes[i], tls.face_indices);
tls.new_face_sets.resize(faces.size());
MutableSpan<int> new_face_sets = tls.new_face_sets;
array_utils::gather(face_sets.span.as_span(), faces, new_face_sets);
calc_face_sets(faces, new_face_sets);
if (array_utils::indexed_data_equal<int>(face_sets.span, faces, new_face_sets)) {
return;
}
undo::push_node(depsgraph, object, &nodes[i], undo::Type::FaceSet);
array_utils::scatter(new_face_sets.as_span(), faces, face_sets.span);
BKE_pbvh_node_mark_update_face_sets(nodes[i]);
});
});
}
face_sets.finish();
}
@@ -334,9 +355,7 @@ enum class CreateMode {
Selection = 3,
};
static void clear_face_sets(const Depsgraph &depsgraph,
Object &object,
const Span<bke::pbvh::Node *> nodes)
static void clear_face_sets(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask)
{
Mesh &mesh = *static_cast<Mesh *>(object.data);
bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
@@ -349,24 +368,41 @@ static void clear_face_sets(const Depsgraph &depsgraph,
const int default_face_set = mesh.face_sets_color_default;
const VArraySpan face_sets = *attributes.lookup<int>(".sculpt_face_set", bke::AttrDomain::Face);
threading::EnumerableThreadSpecific<Vector<int>> all_face_indices;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
Vector<int> &face_indices = all_face_indices.local();
for (bke::pbvh::Node *node : nodes.slice(range)) {
const Span<int> faces =
pbvh.type() == bke::pbvh::Type::Mesh ?
bke::pbvh::node_face_indices_calc_mesh(
tri_faces, static_cast<bke::pbvh::MeshNode &>(*node), face_indices) :
bke::pbvh::node_face_indices_calc_grids(
*ss.subdiv_ccg, static_cast<bke::pbvh::GridsNode &>(*node), face_indices);
if (std::any_of(faces.begin(), faces.end(), [&](const int face) {
return face_sets[face] != default_face_set;
}))
{
undo::push_node(depsgraph, object, node, undo::Type::FaceSet);
BKE_pbvh_node_mark_update_face_sets(*node);
}
}
});
if (pbvh.type() == bke::pbvh::Type::Mesh) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
Vector<int> &face_indices = all_face_indices.local();
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> faces =
bke::pbvh::node_face_indices_calc_mesh(tri_faces, nodes[i], face_indices);
if (std::any_of(faces.begin(), faces.end(), [&](const int face) {
return face_sets[face] != default_face_set;
}))
{
undo::push_node(depsgraph, object, &nodes[i], undo::Type::FaceSet);
BKE_pbvh_node_mark_update_face_sets(nodes[i]);
}
});
});
}
else if (pbvh.type() == bke::pbvh::Type::Grids) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
Vector<int> &face_indices = all_face_indices.local();
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> faces = bke::pbvh::node_face_indices_calc_grids(
*ss.subdiv_ccg, nodes[i], face_indices);
if (std::any_of(faces.begin(), faces.end(), [&](const int face) {
return face_sets[face] != default_face_set;
}))
{
undo::push_node(depsgraph, object, &nodes[i], undo::Type::FaceSet);
BKE_pbvh_node_mark_update_face_sets(nodes[i]);
}
});
});
}
attributes.remove(".sculpt_face_set");
}
@@ -398,7 +434,8 @@ static int create_op_exec(bContext *C, wmOperator *op)
const int next_face_set = find_next_available_id(object);
Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory);
switch (mode) {
case CreateMode::Masked: {
const OffsetIndices faces = mesh.faces();
@@ -408,22 +445,24 @@ static int create_op_exec(bContext *C, wmOperator *op)
const VArraySpan<float> mask = *attributes.lookup<float>(".sculpt_mask",
bke::AttrDomain::Point);
if (!mask.is_empty()) {
face_sets_update(
depsgraph, object, nodes, [&](const Span<int> indices, MutableSpan<int> face_sets) {
for (const int i : indices.index_range()) {
if (!hide_poly.is_empty() && hide_poly[indices[i]]) {
continue;
}
const Span<int> face_verts = corner_verts.slice(faces[indices[i]]);
if (!std::any_of(face_verts.begin(), face_verts.end(), [&](const int vert) {
return mask[vert] > 0.5f;
}))
{
continue;
}
face_sets[i] = next_face_set;
}
});
face_sets_update(depsgraph,
object,
node_mask,
[&](const Span<int> indices, MutableSpan<int> face_sets) {
for (const int i : indices.index_range()) {
if (!hide_poly.is_empty() && hide_poly[indices[i]]) {
continue;
}
const Span<int> face_verts = corner_verts.slice(faces[indices[i]]);
if (!std::any_of(face_verts.begin(),
face_verts.end(),
[&](const int vert) { return mask[vert] > 0.5f; }))
{
continue;
}
face_sets[i] = next_face_set;
}
});
}
break;
}
@@ -436,27 +475,31 @@ static int create_op_exec(bContext *C, wmOperator *op)
/* If all vertices in the sculpt are visible, remove face sets and update the default
* color. This way the new face set will be white, and it is a quick way of disabling all
* face sets and the performance hit of rendering the overlay. */
clear_face_sets(depsgraph, object, nodes);
clear_face_sets(depsgraph, object, node_mask);
break;
case array_utils::BooleanMix::Mixed:
const VArraySpan<bool> hide_poly_span(hide_poly);
face_sets_update(
depsgraph, object, nodes, [&](const Span<int> indices, MutableSpan<int> face_sets) {
for (const int i : indices.index_range()) {
if (!hide_poly_span[indices[i]]) {
face_sets[i] = next_face_set;
}
}
});
face_sets_update(depsgraph,
object,
node_mask,
[&](const Span<int> indices, MutableSpan<int> face_sets) {
for (const int i : indices.index_range()) {
if (!hide_poly_span[indices[i]]) {
face_sets[i] = next_face_set;
}
}
});
break;
}
break;
}
case CreateMode::All: {
face_sets_update(
depsgraph, object, nodes, [&](const Span<int> /*indices*/, MutableSpan<int> face_sets) {
face_sets.fill(next_face_set);
});
face_sets_update(depsgraph,
object,
node_mask,
[&](const Span<int> /*indices*/, MutableSpan<int> face_sets) {
face_sets.fill(next_face_set);
});
break;
}
case CreateMode::Selection: {
@@ -466,7 +509,7 @@ static int create_op_exec(bContext *C, wmOperator *op)
bke::AttrDomain::Face);
face_sets_update(
depsgraph, object, nodes, [&](const Span<int> indices, MutableSpan<int> face_sets) {
depsgraph, object, node_mask, [&](const Span<int> indices, MutableSpan<int> face_sets) {
for (const int i : indices.index_range()) {
if (select_poly[indices[i]]) {
if (!hide_poly.is_empty() && hide_poly[i]) {
@@ -648,14 +691,14 @@ static int init_op_exec(bContext *C, wmOperator *op)
}
bke::pbvh::Tree &pbvh = *ob.sculpt->pbvh;
Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(pbvh);
if (nodes.is_empty()) {
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
if (node_mask.is_empty()) {
return OPERATOR_CANCELLED;
}
undo::push_begin(ob, op);
undo::push_nodes(*depsgraph, ob, nodes, undo::Type::FaceSet);
undo::push_nodes(*depsgraph, ob, node_mask, undo::Type::FaceSet);
const float threshold = RNA_float_get(op->ptr, "threshold");
@@ -744,8 +787,13 @@ static int init_op_exec(bContext *C, wmOperator *op)
undo::push_end(ob);
for (bke::pbvh::Node *node : nodes) {
BKE_pbvh_node_mark_redraw(*node);
if (pbvh.type() == bke::pbvh::Type::Mesh) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_redraw(nodes[i]); });
}
else if (pbvh.type() == bke::pbvh::Type::Grids) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_redraw(nodes[i]); });
}
SCULPT_tag_update_overlays(C);
@@ -828,7 +876,7 @@ enum class VisibilityMode {
static void face_hide_update(const Depsgraph &depsgraph,
Object &object,
const Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
const FunctionRef<void(Span<int>, MutableSpan<bool>)> calc_hide)
{
SculptSession &ss = *object.sculpt;
@@ -846,30 +894,52 @@ static void face_hide_update(const Depsgraph &depsgraph,
bool any_changed = false;
threading::EnumerableThreadSpecific<TLS> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
TLS &tls = all_tls.local();
for (bke::pbvh::Node *node : nodes.slice(range)) {
const Span<int> faces =
pbvh.type() == bke::pbvh::Type::Mesh ?
bke::pbvh::node_face_indices_calc_mesh(
tri_faces, static_cast<bke::pbvh::MeshNode &>(*node), tls.face_indices) :
bke::pbvh::node_face_indices_calc_grids(
*ss.subdiv_ccg, static_cast<bke::pbvh::GridsNode &>(*node), tls.face_indices);
if (pbvh.type() == bke::pbvh::Type::Mesh) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
TLS &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> faces = bke::pbvh::node_face_indices_calc_mesh(
tri_faces, nodes[i], tls.face_indices);
tls.new_hide.resize(faces.size());
MutableSpan<bool> new_hide = tls.new_hide;
array_utils::gather(hide_poly.span.as_span(), faces, new_hide);
calc_hide(faces, new_hide);
if (array_utils::indexed_data_equal<bool>(hide_poly.span, faces, new_hide)) {
continue;
}
tls.new_hide.resize(faces.size());
MutableSpan<bool> new_hide = tls.new_hide;
array_utils::gather(hide_poly.span.as_span(), faces, new_hide);
calc_hide(faces, new_hide);
if (array_utils::indexed_data_equal<bool>(hide_poly.span, faces, new_hide)) {
return;
}
any_changed = true;
undo::push_node(depsgraph, object, node, undo::Type::HideFace);
array_utils::scatter(new_hide.as_span(), faces, hide_poly.span);
BKE_pbvh_node_mark_update_visibility(*node);
}
});
any_changed = true;
undo::push_node(depsgraph, object, &nodes[i], undo::Type::HideFace);
array_utils::scatter(new_hide.as_span(), faces, hide_poly.span);
BKE_pbvh_node_mark_update_visibility(nodes[i]);
});
});
}
else if (pbvh.type() == bke::pbvh::Type::Grids) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
TLS &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> faces = bke::pbvh::node_face_indices_calc_grids(
*ss.subdiv_ccg, nodes[i], tls.face_indices);
tls.new_hide.resize(faces.size());
MutableSpan<bool> new_hide = tls.new_hide;
array_utils::gather(hide_poly.span.as_span(), faces, new_hide);
calc_hide(faces, new_hide);
if (array_utils::indexed_data_equal<bool>(hide_poly.span, faces, new_hide)) {
return;
}
any_changed = true;
undo::push_node(depsgraph, object, &nodes[i], undo::Type::HideFace);
array_utils::scatter(new_hide.as_span(), faces, hide_poly.span);
BKE_pbvh_node_mark_update_visibility(nodes[i]);
});
});
}
hide_poly.finish();
if (any_changed) {
@@ -877,14 +947,14 @@ static void face_hide_update(const Depsgraph &depsgraph,
}
}
static void show_all(Depsgraph &depsgraph, Object &object, const Span<bke::pbvh::Node *> nodes)
static void show_all(Depsgraph &depsgraph, Object &object, const IndexMask &node_mask)
{
switch (object.sculpt->pbvh->type()) {
case bke::pbvh::Type::Mesh:
hide::mesh_show_all(depsgraph, object, nodes);
hide::mesh_show_all(depsgraph, object, node_mask);
break;
case bke::pbvh::Type::Grids:
hide::grids_show_all(depsgraph, object, nodes);
hide::grids_show_all(depsgraph, object, node_mask);
break;
case bke::pbvh::Type::BMesh:
BLI_assert_unreachable();
@@ -912,7 +982,8 @@ static int change_visibility_exec(bContext *C, wmOperator *op)
undo::push_begin(object, op);
bke::pbvh::Tree &pbvh = *object.sculpt->pbvh;
Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(pbvh);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
const bke::AttributeAccessor attributes = mesh->attributes();
const VArraySpan<bool> hide_poly = *attributes.lookup<bool>(".hide_poly", bke::AttrDomain::Face);
@@ -922,11 +993,11 @@ static int change_visibility_exec(bContext *C, wmOperator *op)
switch (mode) {
case VisibilityMode::Toggle: {
if (hide_poly.contains(true) || face_sets.is_empty()) {
show_all(depsgraph, object, nodes);
show_all(depsgraph, object, node_mask);
}
else {
face_hide_update(
depsgraph, object, nodes, [&](const Span<int> faces, MutableSpan<bool> hide) {
depsgraph, object, node_mask, [&](const Span<int> faces, MutableSpan<bool> hide) {
for (const int i : hide.index_range()) {
hide[i] = face_sets[faces[i]] != active_face_set;
}
@@ -936,11 +1007,11 @@ static int change_visibility_exec(bContext *C, wmOperator *op)
}
case VisibilityMode::ShowActive:
if (face_sets.is_empty()) {
show_all(depsgraph, object, nodes);
show_all(depsgraph, object, node_mask);
}
else {
face_hide_update(
depsgraph, object, nodes, [&](const Span<int> faces, MutableSpan<bool> hide) {
depsgraph, object, node_mask, [&](const Span<int> faces, MutableSpan<bool> hide) {
for (const int i : hide.index_range()) {
if (face_sets[faces[i]] == active_face_set) {
hide[i] = false;
@@ -952,13 +1023,13 @@ static int change_visibility_exec(bContext *C, wmOperator *op)
case VisibilityMode::HideActive:
if (face_sets.is_empty()) {
face_hide_update(
depsgraph, object, nodes, [&](const Span<int> /*faces*/, MutableSpan<bool> hide) {
depsgraph, object, node_mask, [&](const Span<int> /*faces*/, MutableSpan<bool> hide) {
hide.fill(true);
});
}
else {
face_hide_update(
depsgraph, object, nodes, [&](const Span<int> faces, MutableSpan<bool> hide) {
depsgraph, object, node_mask, [&](const Span<int> faces, MutableSpan<bool> hide) {
for (const int i : hide.index_range()) {
if (face_sets[faces[i]] == active_face_set) {
hide[i] = true;
@@ -1078,9 +1149,15 @@ static int randomize_colors_exec(bContext *C, wmOperator * /*op*/)
mesh->face_sets_color_seed += 1;
Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(pbvh);
for (bke::pbvh::Node *node : nodes) {
BKE_pbvh_node_mark_redraw(*node);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
if (pbvh.type() == bke::pbvh::Type::Mesh) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_redraw(nodes[i]); });
}
else if (pbvh.type() == bke::pbvh::Type::Grids) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_redraw(nodes[i]); });
}
SCULPT_tag_update_overlays(C);
@@ -1129,9 +1206,10 @@ static void edit_grow_shrink(const Depsgraph &depsgraph,
undo::push_begin(object, op);
const Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory);
face_sets_update(
depsgraph, object, nodes, [&](const Span<int> indices, MutableSpan<int> face_sets) {
depsgraph, object, node_mask, [&](const Span<int> indices, MutableSpan<int> face_sets) {
for (const int i : indices.index_range()) {
const int face = indices[i];
if (!modify_hidden && !hide_poly.is_empty() && hide_poly[face]) {
@@ -1289,14 +1367,15 @@ static void edit_fairing(const Depsgraph &depsgraph,
Vector<float3> translations;
};
Vector<bke::pbvh::Node *> nodes = bke::pbvh::search_gather(const_cast<bke::pbvh::Tree &>(pbvh),
{});
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> verts = bke::pbvh::node_unique_verts(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
tls.translations.resize(verts.size());
const MutableSpan<float3> translations = tls.translations;
for (const int i : verts.index_range()) {
@@ -1304,7 +1383,7 @@ static void edit_fairing(const Depsgraph &depsgraph,
}
scale_translations(translations, strength);
write_translations(depsgraph, sd, ob, positions, verts, translations, positions_orig);
}
});
});
}
@@ -1385,15 +1464,23 @@ static void edit_modify_coordinates(
const Sculpt &sd = *CTX_data_tool_settings(C)->sculpt;
SculptSession &ss = *ob.sculpt;
bke::pbvh::Tree &pbvh = *ss.pbvh;
Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(pbvh);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
const float strength = RNA_float_get(op->ptr, "strength");
undo::push_begin(ob, op);
undo::push_nodes(depsgraph, ob, nodes, undo::Type::Position);
for (bke::pbvh::Node *node : nodes) {
BKE_pbvh_node_mark_positions_update(*node);
undo::push_nodes(depsgraph, ob, node_mask, undo::Type::Position);
if (pbvh.type() == bke::pbvh::Type::Mesh) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_positions_update(nodes[i]); });
}
else if (pbvh.type() == bke::pbvh::Type::Grids) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_positions_update(nodes[i]); });
}
switch (mode) {
case EditMode::FairPositions:
edit_fairing(depsgraph, sd, ob, active_face_set, MESH_FAIRING_DEPTH_POSITION, strength);
@@ -1561,8 +1648,7 @@ static void gesture_begin(bContext &C, wmOperator &op, gesture::GestureData &ges
undo::push_begin(*gesture_data.vc.obact, &op);
}
static void gesture_apply_mesh(gesture::GestureData &gesture_data,
const Span<bke::pbvh::Node *> nodes)
static void gesture_apply_mesh(gesture::GestureData &gesture_data, const IndexMask &node_mask)
{
FaceSetOperation *face_set_operation = (FaceSetOperation *)gesture_data.operation;
const int new_face_set = face_set_operation->new_face_set_id;
@@ -1585,56 +1671,84 @@ static void gesture_apply_mesh(gesture::GestureData &gesture_data,
};
threading::EnumerableThreadSpecific<TLS> all_tls;
threading::parallel_for(gesture_data.nodes.index_range(), 1, [&](const IndexRange range) {
TLS &tls = all_tls.local();
for (bke::pbvh::Node *node : nodes.slice(range)) {
undo::push_node(depsgraph, *gesture_data.vc.obact, node, undo::Type::FaceSet);
const Span<int> node_faces =
pbvh.type() == bke::pbvh::Type::Mesh ?
bke::pbvh::node_face_indices_calc_mesh(
tri_faces, static_cast<bke::pbvh::MeshNode &>(*node), tls.face_indices) :
bke::pbvh::node_face_indices_calc_grids(
*ss.subdiv_ccg, static_cast<bke::pbvh::GridsNode &>(*node), tls.face_indices);
if (pbvh.type() == bke::pbvh::Type::Mesh) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
TLS &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
undo::push_node(depsgraph, *gesture_data.vc.obact, &nodes[i], undo::Type::FaceSet);
const Span<int> node_faces = bke::pbvh::node_face_indices_calc_mesh(
tri_faces, nodes[i], tls.face_indices);
bool any_updated = false;
for (const int face : node_faces) {
if (!hide_poly.is_empty() && hide_poly[face]) {
continue;
bool any_updated = false;
for (const int face : node_faces) {
if (!hide_poly.is_empty() && hide_poly[face]) {
continue;
}
const Span<int> face_verts = corner_verts.slice(faces[face]);
const float3 face_center = bke::mesh::face_center_calc(positions, face_verts);
const float3 face_normal = bke::mesh::face_normal_calc(positions, face_verts);
if (!gesture::is_affected(gesture_data, face_center, face_normal)) {
continue;
}
face_sets.span[face] = new_face_set;
any_updated = true;
}
const Span<int> face_verts = corner_verts.slice(faces[face]);
const float3 face_center = bke::mesh::face_center_calc(positions, face_verts);
const float3 face_normal = bke::mesh::face_normal_calc(positions, face_verts);
if (!gesture::is_affected(gesture_data, face_center, face_normal)) {
continue;
if (any_updated) {
BKE_pbvh_node_mark_update_face_sets(nodes[i]);
}
face_sets.span[face] = new_face_set;
any_updated = true;
}
if (any_updated) {
BKE_pbvh_node_mark_update_face_sets(*node);
}
}
});
});
});
}
else if (pbvh.type() == bke::pbvh::Type::Grids) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
TLS &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
undo::push_node(depsgraph, *gesture_data.vc.obact, &nodes[i], undo::Type::FaceSet);
const Span<int> node_faces = bke::pbvh::node_face_indices_calc_grids(
*ss.subdiv_ccg, nodes[i], tls.face_indices);
bool any_updated = false;
for (const int face : node_faces) {
if (!hide_poly.is_empty() && hide_poly[face]) {
continue;
}
const Span<int> face_verts = corner_verts.slice(faces[face]);
const float3 face_center = bke::mesh::face_center_calc(positions, face_verts);
const float3 face_normal = bke::mesh::face_normal_calc(positions, face_verts);
if (!gesture::is_affected(gesture_data, face_center, face_normal)) {
continue;
}
face_sets.span[face] = new_face_set;
any_updated = true;
}
if (any_updated) {
BKE_pbvh_node_mark_update_face_sets(nodes[i]);
}
});
});
}
face_sets.finish();
}
static void gesture_apply_bmesh(gesture::GestureData &gesture_data,
const Span<bke::pbvh::Node *> nodes)
static void gesture_apply_bmesh(gesture::GestureData &gesture_data, const IndexMask &node_mask)
{
FaceSetOperation *face_set_operation = (FaceSetOperation *)gesture_data.operation;
const Depsgraph &depsgraph = *gesture_data.vc.depsgraph;
const int new_face_set = face_set_operation->new_face_set_id;
SculptSession &ss = *gesture_data.ss;
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
BMesh *bm = ss.bm;
const int offset = CustomData_get_offset_named(&bm->pdata, CD_PROP_INT32, ".sculpt_face_set");
threading::parallel_for(gesture_data.nodes.index_range(), 1, [&](const IndexRange range) {
for (bke::pbvh::Node *node : nodes.slice(range)) {
undo::push_node(depsgraph, *gesture_data.vc.obact, node, undo::Type::FaceSet);
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.slice(range).foreach_index([&](const int i) {
undo::push_node(depsgraph, *gesture_data.vc.obact, &nodes[i], undo::Type::FaceSet);
bool any_updated = false;
for (BMFace *face : BKE_pbvh_bmesh_node_faces(node)) {
for (BMFace *face : BKE_pbvh_bmesh_node_faces(&nodes[i])) {
if (BM_elem_flag_test(face, BM_ELEM_HIDDEN)) {
continue;
}
@@ -1648,9 +1762,9 @@ static void gesture_apply_bmesh(gesture::GestureData &gesture_data,
}
if (any_updated) {
BKE_pbvh_node_mark_update_visibility(*node);
BKE_pbvh_node_mark_update_visibility(nodes[i]);
}
}
});
});
}
@@ -1659,10 +1773,10 @@ static void gesture_apply_for_symmetry_pass(bContext & /*C*/, gesture::GestureDa
switch (gesture_data.ss->pbvh->type()) {
case bke::pbvh::Type::Grids:
case bke::pbvh::Type::Mesh:
gesture_apply_mesh(gesture_data, gesture_data.nodes);
gesture_apply_mesh(gesture_data, gesture_data.node_mask);
break;
case bke::pbvh::Type::BMesh:
gesture_apply_bmesh(gesture_data, gesture_data.nodes);
gesture_apply_bmesh(gesture_data, gesture_data.node_mask);
}
}

View File

@@ -11,6 +11,7 @@
#include <array>
#include "BLI_array.hh"
#include "BLI_index_mask.hh"
#include "BLI_math_matrix.hh"
#include "BLI_math_vector.hh"
#include "BLI_vector.hh"
@@ -76,7 +77,8 @@ struct Cache {
Array<float3> limit_surface_co;
/* unmasked nodes */
Vector<bke::pbvh::Node *> nodes;
IndexMaskMemory node_mask_memory;
IndexMask node_mask;
/* Cloth filter. */
std::unique_ptr<cloth::SimulationData> cloth_sim;

View File

@@ -103,7 +103,7 @@ static void color_filter_task(const Depsgraph &depsgraph,
const FilterType mode,
const float filter_strength,
const float *filter_fill_color,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
LocalData &tls,
bke::GSpanAttributeWriter &color_attribute)
{
@@ -311,7 +311,8 @@ static void color_filter_task(const Depsgraph &depsgraph,
static void sculpt_color_presmooth_init(const Mesh &mesh, SculptSession &ss)
{
const Span<bke::pbvh::Node *> nodes = ss.filter_cache->nodes;
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
const IndexMask &node_mask = ss.filter_cache->node_mask;
const OffsetIndices<int> faces = mesh.faces();
const Span<int> corner_verts = mesh.corner_verts();
const GroupedSpan<int> vert_to_face_map = ss.vert_to_face_map;
@@ -323,13 +324,10 @@ static void sculpt_color_presmooth_init(const Mesh &mesh, SculptSession &ss)
}
const MutableSpan<float4> pre_smoothed_color = ss.filter_cache->pre_smoothed_color;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (const int i : range) {
const Span<int> verts = bke::pbvh::node_unique_verts(*nodes[i]);
for (const int vert : verts) {
pre_smoothed_color[vert] = color_vert_get(
faces, corner_verts, vert_to_face_map, colors, color_attribute.domain, vert);
}
node_mask.foreach_index(GrainSize(1), [&](const int i) {
for (const int vert : bke::pbvh::node_unique_verts(nodes[i])) {
pre_smoothed_color[vert] = color_vert_get(
faces, corner_verts, vert_to_face_map, colors, color_attribute.domain, vert);
}
});
@@ -339,10 +337,10 @@ static void sculpt_color_presmooth_init(const Mesh &mesh, SculptSession &ss)
};
threading::EnumerableThreadSpecific<LocalData> all_tls;
for ([[maybe_unused]] const int iteration : IndexRange(2)) {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> verts = bke::pbvh::node_unique_verts(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
tls.vert_neighbors.resize(verts.size());
calc_vert_neighbors(faces, corner_verts, vert_to_face_map, {}, verts, tls.vert_neighbors);
@@ -357,7 +355,7 @@ static void sculpt_color_presmooth_init(const Mesh &mesh, SculptSession &ss)
pre_smoothed_color[verts[i]] = math::interpolate(
pre_smoothed_color[verts[i]], averaged_colors[i], 0.5f);
}
}
});
});
}
}
@@ -366,6 +364,7 @@ static void sculpt_color_filter_apply(bContext *C, wmOperator *op, Object &ob)
{
const Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(C);
SculptSession &ss = *ob.sculpt;
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
const FilterType mode = FilterType(RNA_enum_get(op->ptr, "type"));
float filter_strength = RNA_float_get(op->ptr, "strength");
@@ -379,7 +378,7 @@ static void sculpt_color_filter_apply(bContext *C, wmOperator *op, Object &ob)
sculpt_color_presmooth_init(mesh, ss);
}
const Span<bke::pbvh::Node *> nodes = ss.filter_cache->nodes;
const IndexMask &node_mask = ss.filter_cache->node_mask;
const OffsetIndices<int> faces = mesh.faces();
const Span<int> corner_verts = mesh.corner_verts();
@@ -387,9 +386,9 @@ static void sculpt_color_filter_apply(bContext *C, wmOperator *op, Object &ob)
bke::GSpanAttributeWriter color_attribute = active_color_attribute_for_write(mesh);
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
color_filter_task(depsgraph,
ob,
faces,
@@ -398,11 +397,11 @@ static void sculpt_color_filter_apply(bContext *C, wmOperator *op, Object &ob)
mode,
filter_strength,
fill_color,
*nodes[i],
nodes[i],
tls,
color_attribute);
BKE_pbvh_node_mark_update_color(*nodes[i]);
}
BKE_pbvh_node_mark_update_color(nodes[i]);
});
});
color_attribute.finish();
flush_update_step(C, UpdateType::Color);

View File

@@ -109,24 +109,25 @@ struct FilterLocalData {
static void apply_new_mask_mesh(const Depsgraph &depsgraph,
Object &object,
const Span<bool> hide_vert,
const Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
const OffsetIndices<int> node_verts,
const Span<float> new_mask,
MutableSpan<float> mask)
{
MutableSpan<bke::pbvh::MeshNode> nodes = object.sculpt->pbvh->nodes<bke::pbvh::MeshNode>();
threading::EnumerableThreadSpecific<Vector<int>> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
Vector<int> &tls = all_tls.local();
for (const int i : range) {
const Span<int> verts = hide::node_visible_verts(*nodes[i], hide_vert, tls);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> verts = hide::node_visible_verts(nodes[i], hide_vert, tls);
const Span<float> new_node_mask = new_mask.slice(node_verts[i]);
if (array_utils::indexed_data_equal<float>(mask, verts, new_node_mask)) {
continue;
return;
}
undo::push_node(depsgraph, object, nodes[i], undo::Type::Mask);
undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask);
scatter_data_mesh(new_node_mask, verts, mask);
BKE_pbvh_node_mark_update_mask(*nodes[i]);
}
BKE_pbvh_node_mark_update_mask(nodes[i]);
});
});
}
@@ -135,7 +136,7 @@ static void smooth_mask_mesh(const OffsetIndices<int> faces,
const GroupedSpan<int> vert_to_face_map,
const Span<bool> hide_poly,
const Span<float> mask,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
FilterLocalData &tls,
MutableSpan<float> new_mask)
{
@@ -153,7 +154,7 @@ static void sharpen_mask_mesh(const OffsetIndices<int> faces,
const GroupedSpan<int> vert_to_face_map,
const Span<bool> hide_poly,
const Span<float> mask,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
FilterLocalData &tls,
MutableSpan<float> new_mask)
{
@@ -177,7 +178,7 @@ static void grow_mask_mesh(const OffsetIndices<int> faces,
const GroupedSpan<int> vert_to_face_map,
const Span<bool> hide_poly,
const Span<float> mask,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
FilterLocalData &tls,
MutableSpan<float> new_mask)
{
@@ -200,7 +201,7 @@ static void shrink_mask_mesh(const OffsetIndices<int> faces,
const GroupedSpan<int> vert_to_face_map,
const Span<bool> hide_poly,
const Span<float> mask,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
FilterLocalData &tls,
MutableSpan<float> new_mask)
{
@@ -221,7 +222,7 @@ static void shrink_mask_mesh(const OffsetIndices<int> faces,
static void increase_contrast_mask_mesh(const Depsgraph &depsgraph,
const Object &object,
const Span<bool> hide_vert,
bke::pbvh::Node &node,
bke::pbvh::MeshNode &node,
FilterLocalData &tls,
MutableSpan<float> mask)
{
@@ -245,7 +246,7 @@ static void increase_contrast_mask_mesh(const Depsgraph &depsgraph,
static void decrease_contrast_mask_mesh(const Depsgraph &depsgraph,
const Object &object,
const Span<bool> hide_vert,
bke::pbvh::Node &node,
bke::pbvh::MeshNode &node,
FilterLocalData &tls,
MutableSpan<float> mask)
{
@@ -287,25 +288,24 @@ BLI_NOINLINE static void copy_old_hidden_mask_grids(const SubdivCCG &subdiv_ccg,
static void apply_new_mask_grids(const Depsgraph &depsgraph,
Object &object,
const Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
const OffsetIndices<int> node_verts,
const Span<float> new_mask)
{
SculptSession &ss = *object.sculpt;
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (const int i : range) {
const Span<int> grids = bke::pbvh::node_grid_indices(*nodes[i]);
const Span<float> new_node_mask = new_mask.slice(node_verts[i]);
if (mask_equals_array_grids(subdiv_ccg.grids, key, grids, new_node_mask)) {
continue;
}
undo::push_node(depsgraph, object, nodes[i], undo::Type::Mask);
scatter_mask_grids(new_node_mask, subdiv_ccg, grids);
BKE_pbvh_node_mark_update_mask(*nodes[i]);
node_mask.foreach_index(GrainSize(1), [&](const int i) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
const Span<float> new_node_mask = new_mask.slice(node_verts[i]);
if (mask_equals_array_grids(subdiv_ccg.grids, 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);
BKE_pbvh_node_mark_update_mask(nodes[i]);
});
/* New mask values need propagation across grid boundaries. */
@@ -313,7 +313,7 @@ static void apply_new_mask_grids(const Depsgraph &depsgraph,
}
static void smooth_mask_grids(const SubdivCCG &subdiv_ccg,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
MutableSpan<float> new_mask)
{
const Span<int> grids = bke::pbvh::node_grid_indices(node);
@@ -322,7 +322,7 @@ static void smooth_mask_grids(const SubdivCCG &subdiv_ccg,
}
static void sharpen_mask_grids(const SubdivCCG &subdiv_ccg,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
FilterLocalData &tls,
MutableSpan<float> new_mask)
{
@@ -343,7 +343,7 @@ static void sharpen_mask_grids(const SubdivCCG &subdiv_ccg,
}
static void grow_mask_grids(const SubdivCCG &subdiv_ccg,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
MutableSpan<float> new_mask)
{
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
@@ -378,7 +378,7 @@ static void grow_mask_grids(const SubdivCCG &subdiv_ccg,
}
static void shrink_mask_grids(const SubdivCCG &subdiv_ccg,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
MutableSpan<float> new_mask)
{
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
@@ -414,7 +414,7 @@ static void shrink_mask_grids(const SubdivCCG &subdiv_ccg,
static void increase_contrast_mask_grids(const Depsgraph &depsgraph,
const Object &object,
bke::pbvh::Node &node,
bke::pbvh::GridsNode &node,
FilterLocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -445,7 +445,7 @@ static void increase_contrast_mask_grids(const Depsgraph &depsgraph,
static void decrease_contrast_mask_grids(const Depsgraph &depsgraph,
const Object &object,
bke::pbvh::Node &node,
bke::pbvh::GridsNode &node,
FilterLocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -490,29 +490,28 @@ BLI_NOINLINE static void copy_old_hidden_mask_bmesh(const int mask_offset,
static void apply_new_mask_bmesh(const Depsgraph &depsgraph,
Object &object,
const int mask_offset,
const Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
const OffsetIndices<int> node_verts,
const Span<float> new_mask)
{
SculptSession &ss = *object.sculpt;
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
BMesh &bm = *ss.bm;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (const int i : range) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]);
const Span<float> new_node_mask = new_mask.slice(node_verts[i]);
if (mask_equals_array_bmesh(mask_offset, verts, new_node_mask)) {
continue;
}
undo::push_node(depsgraph, object, nodes[i], undo::Type::Mask);
scatter_mask_bmesh(new_node_mask, bm, verts);
BKE_pbvh_node_mark_update_mask(*nodes[i]);
node_mask.foreach_index(GrainSize(1), [&](const int i) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]);
const Span<float> new_node_mask = new_mask.slice(node_verts[i]);
if (mask_equals_array_bmesh(mask_offset, verts, new_node_mask)) {
return;
}
undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask);
scatter_mask_bmesh(new_node_mask, bm, verts);
BKE_pbvh_node_mark_update_mask(nodes[i]);
});
}
static void smooth_mask_bmesh(const int mask_offset,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
MutableSpan<float> new_mask)
{
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&node);
@@ -522,7 +521,7 @@ static void smooth_mask_bmesh(const int mask_offset,
static void sharpen_mask_bmesh(const BMesh &bm,
const int mask_offset,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
FilterLocalData &tls,
MutableSpan<float> new_mask)
{
@@ -540,7 +539,7 @@ static void sharpen_mask_bmesh(const BMesh &bm,
}
static void grow_mask_bmesh(const int mask_offset,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
MutableSpan<float> new_mask)
{
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&node);
@@ -560,7 +559,7 @@ static void grow_mask_bmesh(const int mask_offset,
}
static void shrink_mask_bmesh(const int mask_offset,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
MutableSpan<float> new_mask)
{
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&node);
@@ -582,7 +581,7 @@ static void shrink_mask_bmesh(const int mask_offset,
static void increase_contrast_mask_bmesh(const Depsgraph &depsgraph,
Object &object,
const int mask_offset,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
FilterLocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -612,7 +611,7 @@ static void increase_contrast_mask_bmesh(const Depsgraph &depsgraph,
static void decrease_contrast_mask_bmesh(const Depsgraph &depsgraph,
Object &object,
const int mask_offset,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
FilterLocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -660,7 +659,8 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
SculptSession &ss = *ob.sculpt;
bke::pbvh::Tree &pbvh = *ob.sculpt->pbvh;
Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(pbvh);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
undo::push_begin(ob, op);
int iterations = RNA_int_get(op->ptr, "iterations");
@@ -676,6 +676,7 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
threading::EnumerableThreadSpecific<FilterLocalData> all_tls;
switch (pbvh.type()) {
case bke::pbvh::Type::Mesh: {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
Mesh &mesh = *static_cast<Mesh *>(ob.data);
const OffsetIndices<int> faces = mesh.faces();
const Span<int> corner_verts = mesh.corner_verts();
@@ -686,103 +687,98 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
bke::SpanAttributeWriter mask = attributes.lookup_for_write_span<float>(".sculpt_mask");
Array<int> node_vert_offset_data;
OffsetIndices node_offsets = create_node_vert_offsets(nodes, node_vert_offset_data);
OffsetIndices node_offsets = create_node_vert_offsets(
nodes, node_mask, node_vert_offset_data);
Array<float> new_masks(node_offsets.total_size());
for ([[maybe_unused]] const int iteration : IndexRange(iterations)) {
switch (filter_type) {
case FilterType::Smooth: {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
FilterLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
smooth_mask_mesh(faces,
corner_verts,
vert_to_face_map,
hide_poly,
mask.span,
*nodes[i],
nodes[i],
tls,
new_masks.as_mutable_span().slice(node_offsets[i]));
}
});
});
apply_new_mask_mesh(
*depsgraph, ob, hide_vert, nodes, node_offsets, new_masks, mask.span);
*depsgraph, ob, hide_vert, node_mask, node_offsets, new_masks, mask.span);
break;
}
case FilterType::Sharpen: {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
FilterLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
sharpen_mask_mesh(faces,
corner_verts,
vert_to_face_map,
hide_poly,
mask.span,
*nodes[i],
nodes[i],
tls,
new_masks.as_mutable_span().slice(node_offsets[i]));
}
});
});
apply_new_mask_mesh(
*depsgraph, ob, hide_vert, nodes, node_offsets, new_masks, mask.span);
*depsgraph, ob, hide_vert, node_mask, node_offsets, new_masks, mask.span);
break;
}
case FilterType::Grow: {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
FilterLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
grow_mask_mesh(faces,
corner_verts,
vert_to_face_map,
hide_poly,
mask.span,
*nodes[i],
nodes[i],
tls,
new_masks.as_mutable_span().slice(node_offsets[i]));
}
});
});
apply_new_mask_mesh(
*depsgraph, ob, hide_vert, nodes, node_offsets, new_masks, mask.span);
*depsgraph, ob, hide_vert, node_mask, node_offsets, new_masks, mask.span);
break;
}
case FilterType::Shrink: {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
FilterLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
shrink_mask_mesh(faces,
corner_verts,
vert_to_face_map,
hide_poly,
mask.span,
*nodes[i],
nodes[i],
tls,
new_masks.as_mutable_span().slice(node_offsets[i]));
}
});
});
apply_new_mask_mesh(
*depsgraph, ob, hide_vert, nodes, node_offsets, new_masks, mask.span);
*depsgraph, ob, hide_vert, node_mask, node_offsets, new_masks, mask.span);
break;
}
case FilterType::ContrastIncrease: {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
FilterLocalData &tls = all_tls.local();
threading::isolate_task([&]() {
for (const int i : range) {
increase_contrast_mask_mesh(
*depsgraph, ob, hide_vert, *nodes[i], tls, mask.span);
}
node_mask.slice(range).foreach_index([&](const int i) {
increase_contrast_mask_mesh(*depsgraph, ob, hide_vert, nodes[i], tls, mask.span);
});
});
break;
}
case FilterType::ContrastDecrease: {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
FilterLocalData &tls = all_tls.local();
threading::isolate_task([&]() {
for (const int i : range) {
decrease_contrast_mask_mesh(
*depsgraph, ob, hide_vert, *nodes[i], tls, mask.span);
}
node_mask.slice(range).foreach_index([&](const int i) {
decrease_contrast_mask_mesh(*depsgraph, ob, hide_vert, nodes[i], tls, mask.span);
});
});
break;
@@ -793,73 +789,66 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
break;
}
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
Array<int> node_vert_offset_data;
OffsetIndices node_offsets = create_node_vert_offsets(
nodes, BKE_subdiv_ccg_key_top_level(subdiv_ccg), node_vert_offset_data);
BKE_subdiv_ccg_key_top_level(subdiv_ccg), nodes, node_mask, node_vert_offset_data);
Array<float> new_masks(node_offsets.total_size());
for ([[maybe_unused]] const int iteration : IndexRange(iterations)) {
switch (filter_type) {
case FilterType::Smooth: {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (const int i : range) {
smooth_mask_grids(
subdiv_ccg, *nodes[i], new_masks.as_mutable_span().slice(node_offsets[i]));
}
node_mask.foreach_index(GrainSize(1), [&](const int i) {
smooth_mask_grids(
subdiv_ccg, nodes[i], new_masks.as_mutable_span().slice(node_offsets[i]));
});
apply_new_mask_grids(*depsgraph, ob, nodes, node_offsets, new_masks);
apply_new_mask_grids(*depsgraph, ob, node_mask, node_offsets, new_masks);
break;
}
case FilterType::Sharpen: {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
FilterLocalData &tls = all_tls.local();
for (const int i : range) {
sharpen_mask_grids(subdiv_ccg,
*nodes[i],
tls,
new_masks.as_mutable_span().slice(node_offsets[i]));
}
node_mask.slice(range).foreach_index([&](const int i) {
sharpen_mask_grids(
subdiv_ccg, nodes[i], tls, new_masks.as_mutable_span().slice(node_offsets[i]));
});
});
apply_new_mask_grids(*depsgraph, ob, nodes, node_offsets, new_masks);
apply_new_mask_grids(*depsgraph, ob, node_mask, node_offsets, new_masks);
break;
}
case FilterType::Grow: {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (const int i : range) {
grow_mask_grids(
subdiv_ccg, *nodes[i], new_masks.as_mutable_span().slice(node_offsets[i]));
}
node_mask.foreach_index(GrainSize(1), [&](const int i) {
grow_mask_grids(
subdiv_ccg, nodes[i], new_masks.as_mutable_span().slice(node_offsets[i]));
});
apply_new_mask_grids(*depsgraph, ob, nodes, node_offsets, new_masks);
apply_new_mask_grids(*depsgraph, ob, node_mask, node_offsets, new_masks);
break;
}
case FilterType::Shrink: {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (const int i : range) {
shrink_mask_grids(
subdiv_ccg, *nodes[i], new_masks.as_mutable_span().slice(node_offsets[i]));
}
node_mask.foreach_index(GrainSize(1), [&](const int i) {
shrink_mask_grids(
subdiv_ccg, nodes[i], new_masks.as_mutable_span().slice(node_offsets[i]));
});
apply_new_mask_grids(*depsgraph, ob, nodes, node_offsets, new_masks);
apply_new_mask_grids(*depsgraph, ob, node_mask, node_offsets, new_masks);
break;
}
case FilterType::ContrastIncrease: {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
FilterLocalData &tls = all_tls.local();
for (const int i : range) {
increase_contrast_mask_grids(*depsgraph, ob, *nodes[i], tls);
}
node_mask.slice(range).foreach_index([&](const int i) {
increase_contrast_mask_grids(*depsgraph, ob, nodes[i], tls);
});
});
break;
}
case FilterType::ContrastDecrease: {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
FilterLocalData &tls = all_tls.local();
for (const int i : range) {
decrease_contrast_mask_grids(*depsgraph, ob, *nodes[i], tls);
}
node_mask.slice(range).foreach_index([&](const int i) {
decrease_contrast_mask_grids(*depsgraph, ob, nodes[i], tls);
});
});
break;
}
@@ -868,76 +857,72 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
break;
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
BMesh &bm = *ss.bm;
BM_mesh_elem_index_ensure(&bm, BM_VERT);
const int mask_offset = CustomData_get_offset_named(
&bm.vdata, CD_PROP_FLOAT, ".sculpt_mask");
Array<int> node_vert_offset_data;
OffsetIndices node_offsets = create_node_vert_offsets_bmesh(nodes, node_vert_offset_data);
OffsetIndices node_offsets = create_node_vert_offsets_bmesh(
nodes, node_mask, node_vert_offset_data);
Array<float> new_masks(node_offsets.total_size());
for ([[maybe_unused]] const int iteration : IndexRange(iterations)) {
switch (filter_type) {
case FilterType::Smooth: {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (const int i : range) {
smooth_mask_bmesh(
mask_offset, *nodes[i], new_masks.as_mutable_span().slice(node_offsets[i]));
}
node_mask.foreach_index(GrainSize(1), [&](const int i) {
smooth_mask_bmesh(
mask_offset, nodes[i], new_masks.as_mutable_span().slice(node_offsets[i]));
});
apply_new_mask_bmesh(*depsgraph, ob, mask_offset, nodes, node_offsets, new_masks);
apply_new_mask_bmesh(*depsgraph, ob, mask_offset, node_mask, node_offsets, new_masks);
break;
}
case FilterType::Sharpen: {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
FilterLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
sharpen_mask_bmesh(bm,
mask_offset,
*nodes[i],
nodes[i],
tls,
new_masks.as_mutable_span().slice(node_offsets[i]));
}
});
});
apply_new_mask_bmesh(*depsgraph, ob, mask_offset, nodes, node_offsets, new_masks);
apply_new_mask_bmesh(*depsgraph, ob, mask_offset, node_mask, node_offsets, new_masks);
break;
}
case FilterType::Grow: {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (const int i : range) {
grow_mask_bmesh(
mask_offset, *nodes[i], new_masks.as_mutable_span().slice(node_offsets[i]));
}
node_mask.foreach_index(GrainSize(1), [&](const int i) {
grow_mask_bmesh(
mask_offset, nodes[i], new_masks.as_mutable_span().slice(node_offsets[i]));
});
apply_new_mask_bmesh(*depsgraph, ob, mask_offset, nodes, node_offsets, new_masks);
apply_new_mask_bmesh(*depsgraph, ob, mask_offset, node_mask, node_offsets, new_masks);
break;
}
case FilterType::Shrink: {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (const int i : range) {
shrink_mask_bmesh(
mask_offset, *nodes[i], new_masks.as_mutable_span().slice(node_offsets[i]));
}
node_mask.foreach_index(GrainSize(1), [&](const int i) {
shrink_mask_bmesh(
mask_offset, nodes[i], new_masks.as_mutable_span().slice(node_offsets[i]));
});
apply_new_mask_bmesh(*depsgraph, ob, mask_offset, nodes, node_offsets, new_masks);
apply_new_mask_bmesh(*depsgraph, ob, mask_offset, node_mask, node_offsets, new_masks);
break;
}
case FilterType::ContrastIncrease: {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
FilterLocalData &tls = all_tls.local();
for (const int i : range) {
increase_contrast_mask_bmesh(*depsgraph, ob, mask_offset, *nodes[i], tls);
}
node_mask.slice(range).foreach_index([&](const int i) {
increase_contrast_mask_bmesh(*depsgraph, ob, mask_offset, nodes[i], tls);
});
});
break;
}
case FilterType::ContrastDecrease: {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
FilterLocalData &tls = all_tls.local();
for (const int i : range) {
decrease_contrast_mask_bmesh(*depsgraph, ob, mask_offset, *nodes[i], tls);
}
node_mask.slice(range).foreach_index([&](const int i) {
decrease_contrast_mask_bmesh(*depsgraph, ob, mask_offset, nodes[i], tls);
});
});
break;
}

View File

@@ -147,10 +147,12 @@ void cache_init(bContext *C,
BKE_pbvh_ensure_node_face_corners(pbvh, mesh.corner_tris());
}
ss.filter_cache->nodes = bke::pbvh::search_gather(
pbvh, [&](bke::pbvh::Node &node) { return !node_fully_masked_or_hidden(node); });
ss.filter_cache->node_mask = bke::pbvh::search_nodes(
pbvh, ss.filter_cache->node_mask_memory, [&](const bke::pbvh::Node &node) {
return !node_fully_masked_or_hidden(node);
});
undo::push_nodes(*depsgraph, ob, ss.filter_cache->nodes, undo_type);
undo::push_nodes(*depsgraph, ob, ss.filter_cache->node_mask, undo_type);
/* Setup orientation matrices. */
copy_m4_m4(ss.filter_cache->obmat.ptr(), ob.object_to_world().ptr());
@@ -170,12 +172,10 @@ void cache_init(bContext *C,
float3 co;
if (vc.rv3d && SCULPT_stroke_get_location(C, co, mval_fl, false)) {
Vector<bke::pbvh::Node *> nodes;
/* Get radius from brush. */
const Brush *brush = BKE_paint_brush_for_read(&sd.paint);
float radius;
float radius;
if (brush) {
if (BKE_brush_use_locked_size(scene, brush)) {
radius = paint_calc_object_space_radius(
@@ -190,11 +190,14 @@ void cache_init(bContext *C,
}
const float radius_sq = math::square(radius);
nodes = bke::pbvh::search_gather(pbvh, [&](bke::pbvh::Node &node) {
return !node_fully_masked_or_hidden(node) && node_in_sphere(node, co, radius_sq, true);
});
const std::optional<float3> area_normal = calc_area_normal(*depsgraph, *brush, ob, nodes);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::search_nodes(
pbvh, memory, [&](const bke::pbvh::Node &node) {
return !node_fully_masked_or_hidden(node) && node_in_sphere(node, co, radius_sq, true);
});
const std::optional<float3> area_normal = calc_area_normal(*depsgraph, *brush, ob, node_mask);
if (BKE_paint_brush_for_read(&sd.paint) && area_normal) {
ss.filter_cache->initial_normal = *area_normal;
ss.last_normal = ss.filter_cache->initial_normal;
@@ -339,7 +342,7 @@ static void calc_smooth_filter(const Depsgraph &depsgraph,
const Sculpt &sd,
const float strength,
Object &object,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
struct LocalData {
Vector<float> factors;
@@ -357,18 +360,19 @@ static void calc_smooth_filter(const Depsgraph &depsgraph,
const OffsetIndices faces = mesh.faces();
const Span<int> corner_verts = mesh.corner_verts();
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> verts = bke::pbvh::node_unique_verts(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
const Span<float3> positions = gather_data_mesh(positions_eval, verts, tls.positions);
const OrigPositionData orig_data = orig_position_data_get_mesh(object, *nodes[i]);
const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]);
tls.factors.resize(verts.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(mesh, verts, factors);
auto_mask::calc_vert_factors(
depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors);
depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
scale_factors(factors, strength);
clamp_factors(factors, -1.0f, 1.0f);
@@ -396,8 +400,8 @@ static void calc_smooth_filter(const Depsgraph &depsgraph,
write_translations(
depsgraph, sd, object, positions_eval, verts, translations, positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
@@ -408,18 +412,19 @@ static void calc_smooth_filter(const Depsgraph &depsgraph,
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> grids = bke::pbvh::node_grid_indices(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
const OrigPositionData orig_data = orig_position_data_get_grids(object, *nodes[i]);
const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]);
tls.factors.resize(positions.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
auto_mask::calc_grids_factors(
depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], grids, factors);
depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
scale_factors(factors, strength);
clamp_factors(factors, -1.0f, 1.0f);
@@ -438,18 +443,19 @@ static void calc_smooth_filter(const Depsgraph &depsgraph,
clip_and_lock_translations(sd, ss, orig_data.positions, translations);
apply_translations(translations, grids, subdiv_ccg);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::BMesh: {
BMesh &bm = *ss.bm;
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]);
const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
Array<float3> orig_positions(verts.size());
orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, {});
@@ -458,7 +464,7 @@ static void calc_smooth_filter(const Depsgraph &depsgraph,
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(bm, verts, factors);
auto_mask::calc_vert_factors(
depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors);
depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
scale_factors(factors, strength);
clamp_factors(factors, -1.0f, 1.0f);
@@ -476,8 +482,8 @@ static void calc_smooth_filter(const Depsgraph &depsgraph,
clip_and_lock_translations(sd, ss, orig_positions, translations);
apply_translations(translations, verts);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
@@ -488,7 +494,7 @@ static void calc_inflate_filter(const Depsgraph &depsgraph,
const Sculpt &sd,
const float strength,
Object &object,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
struct LocalData {
Vector<float> factors;
@@ -502,18 +508,19 @@ static void calc_inflate_filter(const Depsgraph &depsgraph,
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object);
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> verts = bke::pbvh::node_unique_verts(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
const Span<float3> positions = gather_data_mesh(positions_eval, verts, tls.positions);
const OrigPositionData orig_data = orig_position_data_get_mesh(object, *nodes[i]);
const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]);
tls.factors.resize(verts.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(mesh, verts, factors);
auto_mask::calc_vert_factors(
depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors);
depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
scale_factors(factors, strength);
tls.translations.resize(verts.size());
@@ -526,26 +533,27 @@ static void calc_inflate_filter(const Depsgraph &depsgraph,
write_translations(
depsgraph, sd, object, positions_eval, verts, translations, positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> grids = bke::pbvh::node_grid_indices(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
const OrigPositionData orig_data = orig_position_data_get_grids(object, *nodes[i]);
const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]);
tls.factors.resize(positions.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
auto_mask::calc_grids_factors(
depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], grids, factors);
depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
scale_factors(factors, strength);
tls.translations.resize(positions.size());
@@ -558,18 +566,19 @@ static void calc_inflate_filter(const Depsgraph &depsgraph,
clip_and_lock_translations(sd, ss, orig_data.positions, translations);
apply_translations(translations, grids, subdiv_ccg);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::BMesh: {
BMesh &bm = *ss.bm;
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]);
const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
Array<float3> orig_positions(verts.size());
Array<float3> orig_normals(verts.size());
@@ -579,7 +588,7 @@ static void calc_inflate_filter(const Depsgraph &depsgraph,
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(bm, verts, factors);
auto_mask::calc_vert_factors(
depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors);
depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
scale_factors(factors, strength);
tls.translations.resize(verts.size());
@@ -592,8 +601,8 @@ static void calc_inflate_filter(const Depsgraph &depsgraph,
clip_and_lock_translations(sd, ss, orig_positions, translations);
apply_translations(translations, verts);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
@@ -604,7 +613,7 @@ static void calc_scale_filter(const Depsgraph &depsgraph,
const Sculpt &sd,
const float strength,
Object &object,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
struct LocalData {
Vector<float> factors;
@@ -618,18 +627,19 @@ static void calc_scale_filter(const Depsgraph &depsgraph,
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object);
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> verts = bke::pbvh::node_unique_verts(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
const Span<float3> positions = gather_data_mesh(positions_eval, verts, tls.positions);
const OrigPositionData orig_data = orig_position_data_get_mesh(object, *nodes[i]);
const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]);
tls.factors.resize(verts.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(mesh, verts, factors);
auto_mask::calc_vert_factors(
depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors);
depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
scale_factors(factors, strength);
tls.translations.resize(verts.size());
@@ -642,26 +652,27 @@ static void calc_scale_filter(const Depsgraph &depsgraph,
write_translations(
depsgraph, sd, object, positions_eval, verts, translations, positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> grids = bke::pbvh::node_grid_indices(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
const OrigPositionData orig_data = orig_position_data_get_grids(object, *nodes[i]);
const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]);
tls.factors.resize(positions.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
auto_mask::calc_grids_factors(
depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], grids, factors);
depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
scale_factors(factors, strength);
tls.translations.resize(positions.size());
@@ -674,18 +685,19 @@ static void calc_scale_filter(const Depsgraph &depsgraph,
clip_and_lock_translations(sd, ss, orig_data.positions, translations);
apply_translations(translations, grids, subdiv_ccg);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::BMesh: {
BMesh &bm = *ss.bm;
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]);
const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
Array<float3> orig_positions(verts.size());
orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, {});
@@ -694,7 +706,7 @@ static void calc_scale_filter(const Depsgraph &depsgraph,
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(bm, verts, factors);
auto_mask::calc_vert_factors(
depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors);
depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
scale_factors(factors, strength);
tls.translations.resize(positions.size());
@@ -707,8 +719,8 @@ static void calc_scale_filter(const Depsgraph &depsgraph,
clip_and_lock_translations(sd, ss, orig_positions, translations);
apply_translations(translations, verts);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
@@ -736,7 +748,7 @@ static void calc_sphere_filter(const Depsgraph &depsgraph,
const Sculpt &sd,
const float strength,
Object &object,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
struct LocalData {
Vector<float> factors;
@@ -750,18 +762,19 @@ static void calc_sphere_filter(const Depsgraph &depsgraph,
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object);
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> verts = bke::pbvh::node_unique_verts(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
const Span<float3> positions = gather_data_mesh(positions_eval, verts, tls.positions);
const OrigPositionData orig_data = orig_position_data_get_mesh(object, *nodes[i]);
const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]);
tls.factors.resize(verts.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(mesh, verts, factors);
auto_mask::calc_vert_factors(
depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors);
depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
scale_factors(factors, strength);
tls.translations.resize(verts.size());
@@ -773,26 +786,27 @@ static void calc_sphere_filter(const Depsgraph &depsgraph,
write_translations(
depsgraph, sd, object, positions_eval, verts, translations, positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> grids = bke::pbvh::node_grid_indices(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
const OrigPositionData orig_data = orig_position_data_get_grids(object, *nodes[i]);
const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]);
tls.factors.resize(positions.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
auto_mask::calc_grids_factors(
depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], grids, factors);
depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
scale_factors(factors, strength);
tls.translations.resize(positions.size());
@@ -804,18 +818,19 @@ static void calc_sphere_filter(const Depsgraph &depsgraph,
clip_and_lock_translations(sd, ss, orig_data.positions, translations);
apply_translations(translations, grids, subdiv_ccg);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::BMesh: {
BMesh &bm = *ss.bm;
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]);
const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
Array<float3> orig_positions(verts.size());
orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, {});
@@ -824,7 +839,7 @@ static void calc_sphere_filter(const Depsgraph &depsgraph,
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(bm, verts, factors);
auto_mask::calc_vert_factors(
depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors);
depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
scale_factors(factors, strength);
tls.translations.resize(positions.size());
@@ -836,8 +851,8 @@ static void calc_sphere_filter(const Depsgraph &depsgraph,
clip_and_lock_translations(sd, ss, orig_positions, translations);
apply_translations(translations, verts);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
@@ -860,7 +875,7 @@ static void calc_random_filter(const Depsgraph &depsgraph,
const Sculpt &sd,
const float strength,
Object &object,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
struct LocalData {
Vector<float> factors;
@@ -874,18 +889,19 @@ static void calc_random_filter(const Depsgraph &depsgraph,
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object);
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> verts = bke::pbvh::node_unique_verts(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
const Span<float3> positions = gather_data_mesh(positions_eval, verts, tls.positions);
const OrigPositionData orig_data = orig_position_data_get_mesh(object, *nodes[i]);
const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]);
tls.factors.resize(verts.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(mesh, verts, factors);
auto_mask::calc_vert_factors(
depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors);
depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
scale_factors(factors, strength);
randomize_factors(orig_data.positions, ss.filter_cache->random_seed, factors);
@@ -899,26 +915,27 @@ static void calc_random_filter(const Depsgraph &depsgraph,
write_translations(
depsgraph, sd, object, positions_eval, verts, translations, positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> grids = bke::pbvh::node_grid_indices(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
const OrigPositionData orig_data = orig_position_data_get_grids(object, *nodes[i]);
const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]);
tls.factors.resize(positions.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
auto_mask::calc_grids_factors(
depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], grids, factors);
depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
scale_factors(factors, strength);
randomize_factors(orig_data.positions, ss.filter_cache->random_seed, factors);
@@ -932,18 +949,19 @@ static void calc_random_filter(const Depsgraph &depsgraph,
clip_and_lock_translations(sd, ss, orig_data.positions, translations);
apply_translations(translations, grids, subdiv_ccg);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::BMesh: {
BMesh &bm = *ss.bm;
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]);
const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
Array<float3> orig_positions(verts.size());
Array<float3> orig_normals(verts.size());
@@ -953,7 +971,7 @@ static void calc_random_filter(const Depsgraph &depsgraph,
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(bm, verts, factors);
auto_mask::calc_vert_factors(
depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors);
depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
scale_factors(factors, strength);
randomize_factors(orig_positions, ss.filter_cache->random_seed, factors);
@@ -967,8 +985,8 @@ static void calc_random_filter(const Depsgraph &depsgraph,
clip_and_lock_translations(sd, ss, orig_positions, translations);
apply_translations(translations, verts);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
@@ -979,7 +997,7 @@ static void calc_relax_filter(const Depsgraph &depsgraph,
const Sculpt &sd,
const float strength,
Object &object,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
SculptSession &ss = *object.sculpt;
bke::pbvh::update_normals(depsgraph, object, *ss.pbvh);
@@ -1000,20 +1018,17 @@ static void calc_relax_filter(const Depsgraph &depsgraph,
const bke::AttributeAccessor attributes = mesh.attributes();
const VArraySpan hide_poly = *attributes.lookup<bool>(".hide_poly", bke::AttrDomain::Face);
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int node_index : range) {
const Span<int> verts = bke::pbvh::node_unique_verts(*nodes[node_index]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
tls.factors.resize(verts.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(mesh, verts, factors);
auto_mask::calc_vert_factors(depsgraph,
object,
ss.filter_cache->automasking.get(),
*nodes[node_index],
verts,
factors);
auto_mask::calc_vert_factors(
depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
scale_factors(factors, strength);
clamp_factors(factors, 0.0f, 1.0f);
@@ -1037,8 +1052,8 @@ static void calc_relax_filter(const Depsgraph &depsgraph,
write_translations(
depsgraph, sd, object, positions_eval, verts, translations, positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[node_index]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
@@ -1055,21 +1070,18 @@ static void calc_relax_filter(const Depsgraph &depsgraph,
const GroupedSpan<int> vert_to_face_map = base_mesh.vert_to_face_map();
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int node_index : range) {
const Span<int> grids = bke::pbvh::node_grid_indices(*nodes[node_index]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
tls.factors.resize(positions.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
auto_mask::calc_grids_factors(depsgraph,
object,
ss.filter_cache->automasking.get(),
*nodes[node_index],
grids,
factors);
auto_mask::calc_grids_factors(
depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
scale_factors(factors, strength);
clamp_factors(factors, 0.0f, 1.0f);
@@ -1092,8 +1104,8 @@ static void calc_relax_filter(const Depsgraph &depsgraph,
clip_and_lock_translations(sd, ss, positions, translations);
apply_translations(translations, grids, subdiv_ccg);
BKE_pbvh_node_mark_positions_update(*nodes[node_index]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
@@ -1106,21 +1118,18 @@ static void calc_relax_filter(const Depsgraph &depsgraph,
};
BMesh &bm = *ss.bm;
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int node_index : range) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[node_index]);
node_mask.slice(range).foreach_index([&](const int i) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]);
const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
tls.factors.resize(verts.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(bm, verts, factors);
auto_mask::calc_vert_factors(depsgraph,
object,
ss.filter_cache->automasking.get(),
*nodes[node_index],
verts,
factors);
auto_mask::calc_vert_factors(
depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
scale_factors(factors, strength);
clamp_factors(factors, 0.0f, 1.0f);
@@ -1133,8 +1142,8 @@ static void calc_relax_filter(const Depsgraph &depsgraph,
clip_and_lock_translations(sd, ss, positions, translations);
apply_translations(translations, verts);
BKE_pbvh_node_mark_positions_update(*nodes[node_index]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
@@ -1145,7 +1154,7 @@ static void calc_relax_face_sets_filter(const Depsgraph &depsgraph,
const Sculpt &sd,
const float strength,
Object &object,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
SculptSession &ss = *object.sculpt;
bke::pbvh::update_normals(depsgraph, object, *ss.pbvh);
@@ -1173,16 +1182,17 @@ static void calc_relax_face_sets_filter(const Depsgraph &depsgraph,
const bke::AttributeAccessor attributes = mesh.attributes();
const VArraySpan hide_poly = *attributes.lookup<bool>(".hide_poly", bke::AttrDomain::Face);
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> verts = bke::pbvh::node_unique_verts(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
tls.factors.resize(verts.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(mesh, verts, factors);
auto_mask::calc_vert_factors(
depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors);
depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
scale_factors(factors, strength);
clamp_factors(factors, 0.0f, 1.0f);
@@ -1209,8 +1219,8 @@ static void calc_relax_face_sets_filter(const Depsgraph &depsgraph,
write_translations(
depsgraph, sd, object, positions_eval, verts, translations, positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
@@ -1227,17 +1237,18 @@ static void calc_relax_face_sets_filter(const Depsgraph &depsgraph,
const GroupedSpan<int> vert_to_face_map = base_mesh.vert_to_face_map();
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> grids = bke::pbvh::node_grid_indices(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
tls.factors.resize(positions.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
auto_mask::calc_grids_factors(
depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], grids, factors);
depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
scale_factors(factors, strength);
clamp_factors(factors, 0.0f, 1.0f);
@@ -1269,8 +1280,8 @@ static void calc_relax_face_sets_filter(const Depsgraph &depsgraph,
clip_and_lock_translations(sd, ss, positions, translations);
apply_translations(translations, grids, subdiv_ccg);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
@@ -1283,17 +1294,18 @@ static void calc_relax_face_sets_filter(const Depsgraph &depsgraph,
};
BMesh &bm = *ss.bm;
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]);
const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
tls.factors.resize(verts.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(bm, verts, factors);
auto_mask::calc_vert_factors(
depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors);
depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
scale_factors(factors, strength);
clamp_factors(factors, 0.0f, 1.0f);
@@ -1308,8 +1320,8 @@ static void calc_relax_face_sets_filter(const Depsgraph &depsgraph,
clip_and_lock_translations(sd, ss, positions, translations);
apply_translations(translations, verts);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
@@ -1320,7 +1332,7 @@ static void calc_surface_smooth_filter(const Depsgraph &depsgraph,
const Sculpt &sd,
const float strength,
Object &object,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
struct LocalData {
Vector<float> factors;
@@ -1342,18 +1354,19 @@ static void calc_surface_smooth_filter(const Depsgraph &depsgraph,
const OffsetIndices faces = mesh.faces();
const Span<int> corner_verts = mesh.corner_verts();
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> verts = bke::pbvh::node_unique_verts(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
const Span<float3> positions = gather_data_mesh(positions_eval, verts, tls.positions);
const OrigPositionData orig_data = orig_position_data_get_mesh(object, *nodes[i]);
const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]);
tls.factors.resize(verts.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(mesh, verts, factors);
auto_mask::calc_vert_factors(
depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors);
depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
scale_factors(factors, strength);
clamp_factors(factors, 0.0f, 1.0f);
@@ -1384,19 +1397,19 @@ static void calc_surface_smooth_filter(const Depsgraph &depsgraph,
write_translations(
depsgraph, sd, object, positions_eval, verts, translations, positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> verts = bke::pbvh::node_unique_verts(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
tls.factors.resize(verts.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(mesh, verts, factors);
auto_mask::calc_vert_factors(
depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors);
depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
scale_factors(factors, strength);
clamp_factors(factors, 0.0f, 1.0f);
@@ -1422,26 +1435,27 @@ static void calc_surface_smooth_filter(const Depsgraph &depsgraph,
write_translations(
depsgraph, sd, object, positions_eval, verts, translations, positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> grids = bke::pbvh::node_grid_indices(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
const OrigPositionData orig_data = orig_position_data_get_grids(object, *nodes[i]);
const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]);
tls.factors.resize(positions.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
auto_mask::calc_grids_factors(
depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], grids, factors);
depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
scale_factors(factors, strength);
clamp_factors(factors, 0.0f, 1.0f);
@@ -1467,20 +1481,20 @@ static void calc_surface_smooth_filter(const Depsgraph &depsgraph,
clip_and_lock_translations(sd, ss, orig_data.positions, translations);
apply_translations(translations, grids, subdiv_ccg);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> grids = bke::pbvh::node_grid_indices(*nodes[i]);
const OrigPositionData orig_data = orig_position_data_get_grids(object, *nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]);
tls.factors.resize(orig_data.positions.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
auto_mask::calc_grids_factors(
depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], grids, factors);
depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
scale_factors(factors, strength);
clamp_factors(factors, 0.0f, 1.0f);
@@ -1502,18 +1516,19 @@ static void calc_surface_smooth_filter(const Depsgraph &depsgraph,
clip_and_lock_translations(sd, ss, orig_data.positions, translations);
apply_translations(translations, grids, subdiv_ccg);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::BMesh: {
BMesh &bm = *ss.bm;
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]);
const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
Array<float3> orig_positions(verts.size());
Array<float3> orig_normals(verts.size());
@@ -1523,7 +1538,7 @@ static void calc_surface_smooth_filter(const Depsgraph &depsgraph,
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(bm, verts, factors);
auto_mask::calc_vert_factors(
depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors);
depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
scale_factors(factors, strength);
clamp_factors(factors, 0.0f, 1.0f);
@@ -1545,13 +1560,13 @@ static void calc_surface_smooth_filter(const Depsgraph &depsgraph,
clip_and_lock_translations(sd, ss, orig_positions, translations);
apply_translations(translations, verts);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]);
Array<float3> orig_positions(verts.size());
Array<float3> orig_normals(verts.size());
orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, orig_normals);
@@ -1560,7 +1575,7 @@ static void calc_surface_smooth_filter(const Depsgraph &depsgraph,
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(bm, verts, factors);
auto_mask::calc_vert_factors(
depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors);
depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
scale_factors(factors, strength);
clamp_factors(factors, 0.0f, 1.0f);
@@ -1581,8 +1596,8 @@ static void calc_surface_smooth_filter(const Depsgraph &depsgraph,
clip_and_lock_translations(sd, ss, orig_positions, translations);
apply_translations(translations, verts);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
@@ -1613,7 +1628,7 @@ static void calc_sharpen_filter(const Depsgraph &depsgraph,
const Sculpt &sd,
const float strength,
Object &object,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
struct LocalData {
Vector<float> factors;
@@ -1634,10 +1649,11 @@ static void calc_sharpen_filter(const Depsgraph &depsgraph,
const OffsetIndices faces = mesh.faces();
const Span<int> corner_verts = mesh.corner_verts();
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int node_index : range) {
const Span<int> verts = bke::pbvh::node_unique_verts(*nodes[node_index]);
node_mask.slice(range).foreach_index([&](const int node_index) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[node_index]);
const Span<float3> positions = gather_data_mesh(positions_eval, verts, tls.positions);
tls.factors.resize(verts.size());
@@ -1646,7 +1662,7 @@ static void calc_sharpen_filter(const Depsgraph &depsgraph,
auto_mask::calc_vert_factors(depsgraph,
object,
ss.filter_cache->automasking.get(),
*nodes[node_index],
nodes[node_index],
verts,
factors);
scale_factors(factors, strength);
@@ -1698,8 +1714,8 @@ static void calc_sharpen_filter(const Depsgraph &depsgraph,
write_translations(
depsgraph, sd, object, positions_eval, verts, translations, positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[node_index]);
}
BKE_pbvh_node_mark_positions_update(nodes[node_index]);
});
});
break;
}
@@ -1709,10 +1725,11 @@ static void calc_sharpen_filter(const Depsgraph &depsgraph,
const Span<CCGElem *> elems = subdiv_ccg.grids;
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int node_index : range) {
const Span<int> grids = bke::pbvh::node_grid_indices(*nodes[node_index]);
node_mask.slice(range).foreach_index([&](const int node_index) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[node_index]);
const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
tls.factors.resize(positions.size());
@@ -1721,7 +1738,7 @@ static void calc_sharpen_filter(const Depsgraph &depsgraph,
auto_mask::calc_grids_factors(depsgraph,
object,
ss.filter_cache->automasking.get(),
*nodes[node_index],
nodes[node_index],
grids,
factors);
scale_factors(factors, strength);
@@ -1787,8 +1804,8 @@ static void calc_sharpen_filter(const Depsgraph &depsgraph,
clip_and_lock_translations(sd, ss, positions, translations);
apply_translations(translations, grids, subdiv_ccg);
BKE_pbvh_node_mark_positions_update(*nodes[node_index]);
}
BKE_pbvh_node_mark_positions_update(nodes[node_index]);
});
});
break;
}
@@ -1796,10 +1813,11 @@ static void calc_sharpen_filter(const Depsgraph &depsgraph,
BMesh &bm = *ss.bm;
BM_mesh_elem_index_ensure(&bm, BM_VERT);
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int node_index : range) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[node_index]);
node_mask.slice(range).foreach_index([&](const int node_index) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[node_index]);
const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
tls.factors.resize(verts.size());
@@ -1808,7 +1826,7 @@ static void calc_sharpen_filter(const Depsgraph &depsgraph,
auto_mask::calc_vert_factors(depsgraph,
object,
ss.filter_cache->automasking.get(),
*nodes[node_index],
nodes[node_index],
verts,
factors);
scale_factors(factors, strength);
@@ -1861,8 +1879,8 @@ static void calc_sharpen_filter(const Depsgraph &depsgraph,
clip_and_lock_translations(sd, ss, positions, translations);
apply_translations(translations, verts);
BKE_pbvh_node_mark_positions_update(*nodes[node_index]);
}
BKE_pbvh_node_mark_positions_update(nodes[node_index]);
});
});
break;
}
@@ -1873,7 +1891,7 @@ static void calc_enhance_details_filter(const Depsgraph &depsgraph,
const Sculpt &sd,
const float strength,
Object &object,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
const float final_strength = -std::abs(strength);
struct LocalData {
@@ -1888,18 +1906,19 @@ static void calc_enhance_details_filter(const Depsgraph &depsgraph,
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object);
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> verts = bke::pbvh::node_unique_verts(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
const Span<float3> positions = gather_data_mesh(positions_eval, verts, tls.positions);
const OrigPositionData orig_data = orig_position_data_get_mesh(object, *nodes[i]);
const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]);
tls.factors.resize(verts.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(mesh, verts, factors);
auto_mask::calc_vert_factors(
depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors);
depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
scale_factors(factors, final_strength);
const MutableSpan translations = gather_data_mesh(
@@ -1911,26 +1930,27 @@ static void calc_enhance_details_filter(const Depsgraph &depsgraph,
write_translations(
depsgraph, sd, object, positions_eval, verts, translations, positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> grids = bke::pbvh::node_grid_indices(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
const OrigPositionData orig_data = orig_position_data_get_grids(object, *nodes[i]);
const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]);
tls.factors.resize(positions.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
auto_mask::calc_grids_factors(
depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], grids, factors);
depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
scale_factors(factors, final_strength);
const MutableSpan translations = gather_data_grids(
@@ -1942,18 +1962,19 @@ static void calc_enhance_details_filter(const Depsgraph &depsgraph,
clip_and_lock_translations(sd, ss, orig_data.positions, translations);
apply_translations(translations, grids, subdiv_ccg);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::BMesh: {
BMesh &bm = *ss.bm;
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]);
const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
Array<float3> orig_positions(verts.size());
orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, {});
@@ -1962,7 +1983,7 @@ static void calc_enhance_details_filter(const Depsgraph &depsgraph,
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(bm, verts, factors);
auto_mask::calc_vert_factors(
depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors);
depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
scale_factors(factors, final_strength);
const MutableSpan translations = gather_data_vert_bmesh(
@@ -1974,8 +1995,8 @@ static void calc_enhance_details_filter(const Depsgraph &depsgraph,
clip_and_lock_translations(sd, ss, orig_positions, translations);
apply_translations(translations, verts);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
@@ -1986,7 +2007,7 @@ static void calc_erase_displacement_filter(const Depsgraph &depsgraph,
const Sculpt &sd,
const float strength,
Object &object,
const Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
struct LocalData {
Vector<float> factors;
@@ -1997,18 +2018,19 @@ static void calc_erase_displacement_filter(const Depsgraph &depsgraph,
SculptSession &ss = *object.sculpt;
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> grids = bke::pbvh::node_grid_indices(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
const OrigPositionData orig_data = orig_position_data_get_grids(object, *nodes[i]);
const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]);
tls.factors.resize(positions.size());
const MutableSpan<float> factors = tls.factors;
fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
auto_mask::calc_grids_factors(
depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], grids, factors);
depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
scale_factors(factors, strength);
clamp_factors(factors, -1.0f, 1.0f);
@@ -2024,8 +2046,8 @@ static void calc_erase_displacement_filter(const Depsgraph &depsgraph,
clip_and_lock_translations(sd, ss, orig_data.positions, translations);
apply_translations(translations, grids, subdiv_ccg);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
}
@@ -2067,7 +2089,7 @@ static void mesh_filter_sharpen_init(const Depsgraph &depsgraph,
{
const SculptSession &ss = *object.sculpt;
const bke::pbvh::Tree &pbvh = *ss.pbvh;
const Span<bke::pbvh::Node *> nodes = filter_cache.nodes;
const IndexMask &node_mask = filter_cache.node_mask;
const int totvert = SCULPT_vertex_count_get(object);
filter_cache.sharpen_smooth_ratio = smooth_ratio;
@@ -2078,7 +2100,7 @@ static void mesh_filter_sharpen_init(const Depsgraph &depsgraph,
MutableSpan<float3> detail_directions = filter_cache.detail_directions;
MutableSpan<float> sharpen_factors = filter_cache.sharpen_factor;
calc_smooth_translations(depsgraph, object, filter_cache.nodes, filter_cache.detail_directions);
calc_smooth_translations(depsgraph, object, node_mask, filter_cache.detail_directions);
for (int i = 0; i < totvert; i++) {
sharpen_factors[i] = math::length(detail_directions[i]);
@@ -2111,10 +2133,11 @@ static void mesh_filter_sharpen_init(const Depsgraph &depsgraph,
Mesh &mesh = *static_cast<Mesh *>(object.data);
const OffsetIndices faces = mesh.faces();
const Span<int> corner_verts = mesh.corner_verts();
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> verts = bke::pbvh::node_unique_verts(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
tls.vert_neighbors.resize(verts.size());
const MutableSpan<Vector<int>> neighbors = tls.vert_neighbors;
@@ -2129,17 +2152,18 @@ static void mesh_filter_sharpen_init(const Depsgraph &depsgraph,
smooth::neighbor_data_average_mesh(
sharpen_factors.as_span(), neighbors, tls.smooth_factors.as_mutable_span());
scatter_data_mesh(tls.smooth_factors.as_span(), verts, sharpen_factors);
}
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> grids = bke::pbvh::node_grid_indices(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
const int grid_verts_num = grids.size() * key.grid_area;
tls.smooth_directions.resize(grid_verts_num);
@@ -2156,15 +2180,16 @@ static void mesh_filter_sharpen_init(const Depsgraph &depsgraph,
grids,
tls.smooth_factors.as_mutable_span());
scatter_data_grids(subdiv_ccg, tls.smooth_factors.as_span(), grids, sharpen_factors);
}
});
});
break;
}
case bke::pbvh::Type::BMesh:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]);
node_mask.slice(range).foreach_index([&](const int i) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]);
tls.smooth_directions.resize(verts.size());
smooth::average_data_bmesh(
@@ -2175,7 +2200,7 @@ static void mesh_filter_sharpen_init(const Depsgraph &depsgraph,
smooth::average_data_bmesh(
sharpen_factors.as_span(), verts, tls.smooth_factors.as_mutable_span());
scatter_data_vert_bmesh(tls.smooth_factors.as_span(), verts, sharpen_factors);
}
});
});
break;
}
@@ -2227,40 +2252,40 @@ static void sculpt_mesh_filter_apply(bContext *C, wmOperator *op)
SCULPT_vertex_random_access_ensure(ss);
const Span<bke::pbvh::Node *> nodes = ss.filter_cache->nodes;
const IndexMask &node_mask = ss.filter_cache->node_mask;
switch (filter_type) {
case MeshFilterType::Smooth:
calc_smooth_filter(depsgraph, sd, strength, ob, nodes);
calc_smooth_filter(depsgraph, sd, strength, ob, node_mask);
break;
case MeshFilterType::Scale:
calc_scale_filter(depsgraph, sd, strength, ob, nodes);
calc_scale_filter(depsgraph, sd, strength, ob, node_mask);
break;
case MeshFilterType::Inflate:
calc_inflate_filter(depsgraph, sd, strength, ob, nodes);
calc_inflate_filter(depsgraph, sd, strength, ob, node_mask);
break;
case MeshFilterType::Sphere:
calc_sphere_filter(depsgraph, sd, strength, ob, nodes);
calc_sphere_filter(depsgraph, sd, strength, ob, node_mask);
break;
case MeshFilterType::Random:
calc_random_filter(depsgraph, sd, strength, ob, nodes);
calc_random_filter(depsgraph, sd, strength, ob, node_mask);
break;
case MeshFilterType::Relax:
calc_relax_filter(depsgraph, sd, strength, ob, nodes);
calc_relax_filter(depsgraph, sd, strength, ob, node_mask);
break;
case MeshFilterType::RelaxFaceSets:
calc_relax_face_sets_filter(depsgraph, sd, strength, ob, nodes);
calc_relax_face_sets_filter(depsgraph, sd, strength, ob, node_mask);
break;
case MeshFilterType::SurfaceSmooth:
calc_surface_smooth_filter(depsgraph, sd, strength, ob, nodes);
calc_surface_smooth_filter(depsgraph, sd, strength, ob, node_mask);
break;
case MeshFilterType::Sharpen:
calc_sharpen_filter(depsgraph, sd, strength, ob, nodes);
calc_sharpen_filter(depsgraph, sd, strength, ob, node_mask);
break;
case MeshFilterType::EnhanceDetails:
calc_enhance_details_filter(depsgraph, sd, strength, ob, nodes);
calc_enhance_details_filter(depsgraph, sd, strength, ob, node_mask);
break;
case MeshFilterType::EraseDispacement:
calc_erase_displacement_filter(depsgraph, sd, strength, ob, nodes);
calc_erase_displacement_filter(depsgraph, sd, strength, ob, node_mask);
break;
}
@@ -2445,7 +2470,7 @@ static void sculpt_filter_specific_init(const Depsgraph &depsgraph,
case MeshFilterType::EnhanceDetails: {
ss.filter_cache->detail_directions.reinitialize(SCULPT_vertex_count_get(object));
calc_smooth_translations(
depsgraph, object, ss.filter_cache->nodes, ss.filter_cache->detail_directions);
depsgraph, object, ss.filter_cache->node_mask, ss.filter_cache->detail_directions);
break;
}
case MeshFilterType::EraseDispacement: {

View File

@@ -321,7 +321,7 @@ static void flip_for_symmetry_pass(GestureData &gesture_data, const ePaintSymmet
flip_plane(gesture_data.line.side_plane[1], gesture_data.line.true_side_plane[1], symmpass);
}
static Vector<bke::pbvh::Node *> update_affected_nodes_by_line_plane(GestureData &gesture_data)
static void update_affected_nodes_by_line_plane(GestureData &gesture_data)
{
SculptSession &ss = *gesture_data.ss;
float clip_planes[3][4];
@@ -333,9 +333,10 @@ static Vector<bke::pbvh::Node *> update_affected_nodes_by_line_plane(GestureData
frustum.planes = clip_planes;
frustum.num_planes = gesture_data.line.use_side_planes ? 3 : 1;
return gesture_data.nodes = bke::pbvh::search_gather(*ss.pbvh, [&](bke::pbvh::Node &node) {
return BKE_pbvh_node_frustum_contain_AABB(&node, &frustum);
});
gesture_data.node_mask = bke::pbvh::search_nodes(
*ss.pbvh, gesture_data.node_mask_memory, [&](const bke::pbvh::Node &node) {
return BKE_pbvh_node_frustum_contain_AABB(&node, &frustum);
});
}
static void update_affected_nodes_by_clip_planes(GestureData &gesture_data)
@@ -349,23 +350,24 @@ static void update_affected_nodes_by_clip_planes(GestureData &gesture_data)
frustum.planes = clip_planes;
frustum.num_planes = 4;
gesture_data.nodes = bke::pbvh::search_gather(*ss.pbvh, [&](bke::pbvh::Node &node) {
switch (gesture_data.selection_type) {
case SelectionType::Inside:
return BKE_pbvh_node_frustum_contain_AABB(&node, &frustum);
case SelectionType::Outside:
/* Certain degenerate cases of a lasso shape can cause the resulting
* frustum planes to enclose a node's AABB, therefore we must submit it
* to be more thoroughly evaluated. */
if (gesture_data.shape_type == ShapeType::Lasso) {
return true;
gesture_data.node_mask = bke::pbvh::search_nodes(
*ss.pbvh, gesture_data.node_mask_memory, [&](const bke::pbvh::Node &node) {
switch (gesture_data.selection_type) {
case SelectionType::Inside:
return BKE_pbvh_node_frustum_contain_AABB(&node, &frustum);
case SelectionType::Outside:
/* Certain degenerate cases of a lasso shape can cause the resulting
* frustum planes to enclose a node's AABB, therefore we must submit it
* to be more thoroughly evaluated. */
if (gesture_data.shape_type == ShapeType::Lasso) {
return true;
}
return BKE_pbvh_node_frustum_exclude_AABB(&node, &frustum);
default:
BLI_assert_unreachable();
return true;
}
return BKE_pbvh_node_frustum_exclude_AABB(&node, &frustum);
default:
BLI_assert_unreachable();
return true;
}
});
});
}
static void update_affected_nodes(GestureData &gesture_data)

View File

@@ -10,6 +10,7 @@
#include "BLI_array.hh"
#include "BLI_bit_vector.hh"
#include "BLI_index_mask.hh"
#include "BLI_math_matrix.hh"
#include "BLI_vector.hh"
@@ -111,7 +112,8 @@ struct GestureData {
LineData line;
/* Task Callback Data. */
Vector<bke::pbvh::Node *> nodes;
IndexMaskMemory node_mask_memory;
IndexMask node_mask;
~GestureData();
};

View File

@@ -18,7 +18,7 @@
namespace blender::ed::sculpt_paint::hide {
Span<int> node_visible_verts(const bke::pbvh::Node &node,
Span<int> node_visible_verts(const bke::pbvh::MeshNode &node,
const Span<bool> hide_vert,
Vector<int> &indices)
{

View File

@@ -18,12 +18,12 @@ struct PBVHVertRef;
struct SubdivCCG;
struct SubdivCCGCoord;
namespace blender::bke::pbvh {
class Node;
struct MeshNode;
}
namespace blender::ed::sculpt_paint::hide {
Span<int> node_visible_verts(const bke::pbvh::Node &node,
Span<int> node_visible_verts(const bke::pbvh::MeshNode &node,
Span<bool> hide_vert,
Vector<int> &indices);

View File

@@ -575,14 +575,14 @@ namespace blender::ed::sculpt_paint {
void calc_brush_plane(const Depsgraph &depsgraph,
const Brush &brush,
Object &ob,
Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
float3 &r_area_no,
float3 &r_area_co);
std::optional<float3> calc_area_normal(const Depsgraph &depsgraph,
const Brush &brush,
Object &ob,
Span<bke::pbvh::Node *> nodes);
const Object &ob,
const IndexMask &node_mask);
/**
* This calculates flatten center and area normal together,
@@ -591,13 +591,13 @@ std::optional<float3> calc_area_normal(const Depsgraph &depsgraph,
void calc_area_normal_and_center(const Depsgraph &depsgraph,
const Brush &brush,
const Object &ob,
Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
float r_area_no[3],
float r_area_co[3]);
void calc_area_center(const Depsgraph &depsgraph,
const Brush &brush,
const Object &ob,
Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
float r_area_co[3]);
PBVHVertRef nearest_vert_calc(const Depsgraph &depsgraph,
@@ -696,7 +696,7 @@ namespace blender::ed::sculpt_paint {
void calc_smooth_translations(const Depsgraph &depsgraph,
const Object &object,
Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
MutableSpan<float3> translations);
}
@@ -885,7 +885,7 @@ void SCULPT_do_paint_brush_image(const Depsgraph &depsgraph,
PaintModeSettings &paint_mode_settings,
const Sculpt &sd,
Object &ob,
blender::Span<blender::bke::pbvh::Node *> texnodes);
const blender::IndexMask &node_mask);
bool SCULPT_use_image_paint_brush(PaintModeSettings &settings, Object &ob);
namespace blender::ed::sculpt_paint {

View File

@@ -50,14 +50,14 @@ enum class InitMode {
void write_mask_mesh(const Depsgraph &depsgraph,
Object &object,
const Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
FunctionRef<void(MutableSpan<float>, Span<int>)> write_fn)
{
Mesh &mesh = *static_cast<Mesh *>(object.data);
bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
const VArraySpan hide_vert = *attributes.lookup<bool>(".hide_vert", bke::AttrDomain::Point);
undo::push_nodes(depsgraph, object, nodes, undo::Type::Mask);
undo::push_nodes(depsgraph, object, node_mask, undo::Type::Mask);
bke::SpanAttributeWriter mask = attributes.lookup_or_add_for_write_span<float>(
".sculpt_mask", bke::AttrDomain::Point);
@@ -65,12 +65,13 @@ void write_mask_mesh(const Depsgraph &depsgraph,
return;
}
threading::EnumerableThreadSpecific<Vector<int>> all_index_data;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = object.sculpt->pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
Vector<int> &index_data = all_index_data.local();
for (const int i : range) {
write_fn(mask.span, hide::node_visible_verts(*nodes[i], hide_vert, index_data));
BKE_pbvh_node_mark_redraw(*nodes[i]);
bke::pbvh::node_update_mask_mesh(mask.span, static_cast<bke::pbvh::MeshNode &>(*nodes[i]));
write_fn(mask.span, hide::node_visible_verts(nodes[i], hide_vert, index_data));
BKE_pbvh_node_mark_redraw(nodes[i]);
bke::pbvh::node_update_mask_mesh(mask.span, nodes[i]);
}
});
mask.finish();
@@ -80,26 +81,25 @@ static void init_mask_grids(Main &bmain,
Scene &scene,
Depsgraph &depsgraph,
Object &object,
const Span<bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
FunctionRef<void(const BitGroupVector<> &, int, CCGElem *)> write_fn)
{
MultiresModifierData *mmd = BKE_sculpt_multires_active(&scene, &object);
BKE_sculpt_mask_layers_ensure(&depsgraph, &bmain, &object, mmd);
SculptSession &ss = *object.sculpt;
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
const Span<CCGElem *> grids = subdiv_ccg.grids;
const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden;
undo::push_nodes(depsgraph, object, nodes, undo::Type::Mask);
undo::push_nodes(depsgraph, object, node_mask, undo::Type::Mask);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (const int i : range) {
for (const int grid : bke::pbvh::node_grid_indices(*nodes[i])) {
write_fn(grid_hidden, grid, grids[grid]);
}
BKE_pbvh_node_mark_update_mask(*nodes[i]);
node_mask.foreach_index(GrainSize(1), [&](const int i) {
for (const int grid : bke::pbvh::node_grid_indices(nodes[i])) {
write_fn(grid_hidden, grid, grids[grid]);
}
BKE_pbvh_node_mark_update_mask(nodes[i]);
});
BKE_subdiv_ccg_average_grids(subdiv_ccg);
bke::pbvh::update_mask(object, *ss.pbvh);
@@ -119,8 +119,9 @@ static int sculpt_mask_init_exec(bContext *C, wmOperator *op)
BKE_sculpt_update_object_for_edit(&depsgraph, &ob, false);
bke::pbvh::Tree &pbvh = *ob.sculpt->pbvh;
Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(pbvh);
if (nodes.is_empty()) {
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
if (node_mask.is_empty()) {
return OPERATOR_CANCELLED;
}
@@ -133,14 +134,14 @@ static int sculpt_mask_init_exec(bContext *C, wmOperator *op)
case bke::pbvh::Type::Mesh: {
switch (mode) {
case InitMode::Random:
write_mask_mesh(depsgraph, ob, nodes, [&](MutableSpan<float> mask, Span<int> verts) {
write_mask_mesh(depsgraph, ob, node_mask, [&](MutableSpan<float> mask, Span<int> verts) {
for (const int vert : verts) {
mask[vert] = BLI_hash_int_01(vert + seed);
}
});
break;
case InitMode::FaceSet:
write_mask_mesh(depsgraph, ob, nodes, [&](MutableSpan<float> mask, Span<int> verts) {
write_mask_mesh(depsgraph, ob, node_mask, [&](MutableSpan<float> mask, Span<int> verts) {
for (const int vert : verts) {
const int face_set = face_set::vert_face_set_get(ss, PBVHVertRef{vert});
mask[vert] = BLI_hash_int_01(face_set + seed);
@@ -149,7 +150,7 @@ static int sculpt_mask_init_exec(bContext *C, wmOperator *op)
break;
case InitMode::Island:
islands::ensure_cache(ob);
write_mask_mesh(depsgraph, ob, nodes, [&](MutableSpan<float> mask, Span<int> verts) {
write_mask_mesh(depsgraph, ob, node_mask, [&](MutableSpan<float> mask, Span<int> verts) {
for (const int vert : verts) {
const int island = islands::vert_id_get(ss, vert);
mask[vert] = BLI_hash_int_01(island + seed);
@@ -171,7 +172,7 @@ static int sculpt_mask_init_exec(bContext *C, wmOperator *op)
scene,
depsgraph,
ob,
nodes,
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(
@@ -192,7 +193,7 @@ static int sculpt_mask_init_exec(bContext *C, wmOperator *op)
scene,
depsgraph,
ob,
nodes,
node_mask,
[&](const BitGroupVector<> &grid_hidden, const int grid_index, CCGElem *grid) {
const int face_set = face_sets[grid_to_face[grid_index]];
const float value = BLI_hash_int_01(face_set + seed);
@@ -210,7 +211,7 @@ static int sculpt_mask_init_exec(bContext *C, wmOperator *op)
scene,
depsgraph,
ob,
nodes,
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(
@@ -225,32 +226,30 @@ static int sculpt_mask_init_exec(bContext *C, wmOperator *op)
break;
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
const int offset = CustomData_get_offset_named(&ss.bm->vdata, CD_PROP_FLOAT, ".sculpt_mask");
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (const int i : range) {
for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(nodes[i])) {
if (BM_elem_flag_test(vert, BM_ELEM_HIDDEN)) {
continue;
}
switch (mode) {
case InitMode::Random:
BM_ELEM_CD_SET_FLOAT(
vert, offset, BLI_hash_int_01(BM_elem_index_get(vert) + seed));
break;
case InitMode::FaceSet: {
BM_ELEM_CD_SET_FLOAT(vert, offset, 0.0f);
break;
}
case InitMode::Island:
BM_ELEM_CD_SET_FLOAT(
vert,
offset,
BLI_hash_int_01(islands::vert_id_get(ss, BM_elem_index_get(vert)) + seed));
break;
}
node_mask.foreach_index(GrainSize(1), [&](const int i) {
for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(&nodes[i])) {
if (BM_elem_flag_test(vert, BM_ELEM_HIDDEN)) {
continue;
}
switch (mode) {
case InitMode::Random:
BM_ELEM_CD_SET_FLOAT(vert, offset, BLI_hash_int_01(BM_elem_index_get(vert) + seed));
break;
case InitMode::FaceSet: {
BM_ELEM_CD_SET_FLOAT(vert, offset, 0.0f);
break;
}
case InitMode::Island:
BM_ELEM_CD_SET_FLOAT(
vert,
offset,
BLI_hash_int_01(islands::vert_id_get(ss, BM_elem_index_get(vert)) + seed));
break;
}
BKE_pbvh_node_mark_update_mask(*nodes[i]);
}
BKE_pbvh_node_mark_update_mask(nodes[i]);
});
bke::pbvh::update_mask(ob, *ss.pbvh);
break;

View File

@@ -783,10 +783,11 @@ static void sculpt_mask_by_color_contiguous_mesh(const Depsgraph &depsgraph,
return len <= threshold;
});
Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory);
update_mask_mesh(
depsgraph, object, nodes, [&](MutableSpan<float> node_mask, const Span<int> verts) {
depsgraph, object, node_mask, [&](MutableSpan<float> node_mask, const Span<int> verts) {
for (const int i : verts.index_range()) {
node_mask[i] = sculpt_mask_by_color_final_mask_get(
node_mask[i], new_mask[verts[i]], invert, preserve_mask);
@@ -808,10 +809,11 @@ static void sculpt_mask_by_color_full_mesh(const Depsgraph &depsgraph,
mesh.active_color_attribute, bke::AttrDomain::Point, {});
const float4 active_color = float4(colors[vert]);
Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory);
update_mask_mesh(
depsgraph, object, nodes, [&](MutableSpan<float> node_mask, const Span<int> verts) {
depsgraph, object, node_mask, [&](MutableSpan<float> node_mask, const Span<int> verts) {
for (const int i : verts.index_range()) {
const float current_mask = node_mask[i];
const float new_mask = sculpt_mask_by_color_delta_get(
@@ -967,7 +969,7 @@ static void bake_mask_mesh(const Depsgraph &depsgraph,
const auto_mask::Cache &automasking,
const CavityBakeMixMode mode,
const float factor,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
LocalData &tls,
const MutableSpan<float> mask)
{
@@ -991,7 +993,7 @@ static void bake_mask_mesh(const Depsgraph &depsgraph,
calc_new_masks(mode, node_mask, new_mask);
mix_new_masks(new_mask, factors, node_mask);
array_utils::scatter(node_mask.as_span(), verts, mask);
scatter_data_mesh(node_mask.as_span(), verts, mask);
}
static void bake_mask_grids(const Depsgraph &depsgraph,
@@ -999,7 +1001,7 @@ static void bake_mask_grids(const Depsgraph &depsgraph,
const auto_mask::Cache &automasking,
const CavityBakeMixMode mode,
const float factor,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
LocalData &tls)
{
SculptSession &ss = *object.sculpt;
@@ -1034,7 +1036,7 @@ static void bake_mask_bmesh(const Depsgraph &depsgraph,
const auto_mask::Cache &automasking,
const CavityBakeMixMode mode,
const float factor,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
LocalData &tls)
{
const SculptSession &ss = *object.sculpt;
@@ -1085,7 +1087,8 @@ static int sculpt_bake_cavity_exec(bContext *C, wmOperator *op)
CavityBakeMixMode mode = CavityBakeMixMode(RNA_enum_get(op->ptr, "mix_mode"));
float factor = RNA_float_get(op->ptr, "mix_factor");
Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory);
/* Set up automasking settings. */
Sculpt sd2 = sd;
@@ -1150,7 +1153,7 @@ static int sculpt_bake_cavity_exec(bContext *C, wmOperator *op)
std::unique_ptr<auto_mask::Cache> automasking = auto_mask::cache_init(
*depsgraph, sd2, &brush2, ob);
undo::push_nodes(*depsgraph, ob, nodes, undo::Type::Mask);
undo::push_nodes(*depsgraph, ob, node_mask, undo::Type::Mask);
threading::EnumerableThreadSpecific<LocalData> all_tls;
switch (ss.pbvh->type()) {
@@ -1162,37 +1165,37 @@ static int sculpt_bake_cavity_exec(bContext *C, wmOperator *op)
if (!mask) {
return OPERATOR_CANCELLED;
}
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
threading::isolate_task([&]() {
for (const int i : range) {
bake_mask_mesh(*depsgraph, ob, *automasking, mode, factor, *nodes[i], tls, mask.span);
BKE_pbvh_node_mark_update_mask(*nodes[i]);
bke::pbvh::node_update_mask_mesh(mask.span,
static_cast<bke::pbvh::MeshNode &>(*nodes[i]));
}
node_mask.slice(range).foreach_index([&](const int i) {
bake_mask_mesh(*depsgraph, ob, *automasking, mode, factor, nodes[i], tls, mask.span);
BKE_pbvh_node_mark_update_mask(nodes[i]);
bke::pbvh::node_update_mask_mesh(mask.span, nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
bake_mask_grids(*depsgraph, ob, *automasking, mode, factor, *nodes[i], tls);
BKE_pbvh_node_mark_update_mask(*nodes[i]);
}
node_mask.slice(range).foreach_index([&](const int i) {
bake_mask_grids(*depsgraph, ob, *automasking, mode, factor, nodes[i], tls);
BKE_pbvh_node_mark_update_mask(nodes[i]);
});
});
bke::pbvh::update_mask(ob, *ss.pbvh);
break;
}
case bke::pbvh::Type::BMesh: {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
bake_mask_bmesh(*depsgraph, ob, *automasking, mode, factor, *nodes[i], tls);
BKE_pbvh_node_mark_update_mask(*nodes[i]);
}
node_mask.slice(range).foreach_index([&](const int i) {
bake_mask_bmesh(*depsgraph, ob, *automasking, mode, factor, nodes[i], tls);
BKE_pbvh_node_mark_update_mask(nodes[i]);
});
});
bke::pbvh::update_mask(ob, *ss.pbvh);
break;

View File

@@ -266,7 +266,7 @@ static void do_color_smooth_task(const Depsgraph &depsgraph,
const GroupedSpan<int> vert_to_face_map,
const Span<bool> hide_poly,
const Brush &brush,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
ColorPaintLocalData &tls,
bke::GSpanAttributeWriter &color_attribute)
{
@@ -347,7 +347,7 @@ static void do_paint_brush_task(const Depsgraph &depsgraph,
const Brush &brush,
const float4x4 &mat,
const float4 wet_mix_sampled_color,
bke::pbvh::Node &node,
bke::pbvh::MeshNode &node,
ColorPaintLocalData &tls,
const MutableSpan<float4> mix_colors,
bke::GSpanAttributeWriter &color_attribute)
@@ -491,7 +491,7 @@ static void do_sample_wet_paint_task(const Object &object,
const GSpan color_attribute,
const bke::AttrDomain color_domain,
const Brush &brush,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
ColorPaintLocalData &tls,
SampleWetPaintData &swptd)
{
@@ -524,16 +524,17 @@ void do_paint_brush(const Depsgraph &depsgraph,
PaintModeSettings &paint_mode_settings,
const Sculpt &sd,
Object &ob,
Span<bke::pbvh::Node *> nodes,
Span<bke::pbvh::Node *> texnodes)
const IndexMask &node_mask,
const IndexMask &texnode_mask)
{
if (SCULPT_use_image_paint_brush(paint_mode_settings, ob)) {
SCULPT_do_paint_brush_image(depsgraph, paint_mode_settings, sd, ob, texnodes);
SCULPT_do_paint_brush_image(depsgraph, paint_mode_settings, sd, ob, texnode_mask);
return;
}
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
SculptSession &ss = *ob.sculpt;
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(*ss.cache)) {
if (SCULPT_stroke_is_first_brush_step(*ss.cache)) {
@@ -573,9 +574,9 @@ void do_paint_brush(const Depsgraph &depsgraph,
if (ss.cache->alt_smooth) {
threading::EnumerableThreadSpecific<ColorPaintLocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
ColorPaintLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
do_color_smooth_task(depsgraph,
ob,
vert_positions,
@@ -585,10 +586,10 @@ void do_paint_brush(const Depsgraph &depsgraph,
vert_to_face_map,
hide_poly,
brush,
*nodes[i],
nodes[i],
tls,
color_attribute);
}
});
});
color_attribute.finish();
return;
@@ -601,12 +602,12 @@ void do_paint_brush(const Depsgraph &depsgraph,
if (ss.cache->paint_brush.wet_mix > 0.0f) {
threading::EnumerableThreadSpecific<ColorPaintLocalData> all_tls;
const SampleWetPaintData swptd = threading::parallel_reduce(
nodes.index_range(),
node_mask.index_range(),
1,
SampleWetPaintData{},
[&](const IndexRange range, SampleWetPaintData swptd) {
ColorPaintLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
do_sample_wet_paint_task(ob,
vert_positions,
faces,
@@ -615,10 +616,10 @@ void do_paint_brush(const Depsgraph &depsgraph,
color_attribute.span,
color_attribute.domain,
brush,
*nodes[i],
nodes[i],
tls,
swptd);
}
});
return swptd;
},
[](const SampleWetPaintData &a, const SampleWetPaintData &b) {
@@ -647,9 +648,9 @@ void do_paint_brush(const Depsgraph &depsgraph,
}
threading::EnumerableThreadSpecific<ColorPaintLocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
ColorPaintLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
do_paint_brush_task(depsgraph,
ob,
vert_positions,
@@ -660,11 +661,11 @@ void do_paint_brush(const Depsgraph &depsgraph,
brush,
mat,
wet_color,
*nodes[i],
nodes[i],
tls,
ss.cache->paint_brush.mix_colors,
color_attribute);
}
});
});
color_attribute.finish();
}
@@ -678,7 +679,7 @@ static void do_smear_brush_task(const Depsgraph &depsgraph,
const GroupedSpan<int> vert_to_face_map,
const Span<bool> hide_poly,
const Brush &brush,
bke::pbvh::Node &node,
bke::pbvh::MeshNode &node,
ColorPaintLocalData &tls,
bke::GSpanAttributeWriter &color_attribute)
{
@@ -828,10 +829,11 @@ static void do_smear_brush_task(const Depsgraph &depsgraph,
void do_smear_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &ob,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
SculptSession &ss = *ob.sculpt;
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
Mesh &mesh = *static_cast<Mesh *>(ob.data);
if (ss.cache->bstrength == 0.0f) {
@@ -870,9 +872,9 @@ void do_smear_brush(const Depsgraph &depsgraph,
/* Smooth colors mode. */
if (ss.cache->alt_smooth) {
threading::EnumerableThreadSpecific<ColorPaintLocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
ColorPaintLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
do_color_smooth_task(depsgraph,
ob,
vert_positions,
@@ -882,30 +884,28 @@ void do_smear_brush(const Depsgraph &depsgraph,
vert_to_face_map,
hide_poly,
brush,
*nodes[i],
nodes[i],
tls,
color_attribute);
}
});
});
}
else {
/* Smear mode. */
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (const int i : range) {
for (const int vert : bke::pbvh::node_unique_verts(*nodes[i])) {
ss.cache->paint_brush.prev_colors[vert] = color_vert_get(faces,
corner_verts,
vert_to_face_map,
color_attribute.span,
color_attribute.domain,
vert);
}
node_mask.foreach_index(GrainSize(1), [&](const int i) {
for (const int vert : bke::pbvh::node_unique_verts(nodes[i])) {
ss.cache->paint_brush.prev_colors[vert] = color_vert_get(faces,
corner_verts,
vert_to_face_map,
color_attribute.span,
color_attribute.domain,
vert);
}
});
threading::EnumerableThreadSpecific<ColorPaintLocalData> all_tls;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
ColorPaintLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
do_smear_brush_task(depsgraph,
ob,
vert_positions,
@@ -915,10 +915,10 @@ void do_smear_brush(const Depsgraph &depsgraph,
vert_to_face_map,
hide_poly,
brush,
*nodes[i],
nodes[i],
tls,
color_attribute);
}
});
});
}
color_attribute.finish();

View File

@@ -431,12 +431,12 @@ static void do_push_undo_tile(Image &image, ImageUser &image_user, bke::pbvh::No
/** \name Fix non-manifold edge bleeding.
* \{ */
static Vector<image::TileNumber> collect_dirty_tiles(Span<bke::pbvh::Node *> nodes)
static Vector<image::TileNumber> collect_dirty_tiles(MutableSpan<bke::pbvh::MeshNode> nodes,
const IndexMask &node_mask)
{
Vector<image::TileNumber> dirty_tiles;
for (bke::pbvh::Node *node : nodes) {
bke::pbvh::pixels::collect_dirty_tiles(*node, dirty_tiles);
}
node_mask.foreach_index(
[&](const int i) { bke::pbvh::pixels::collect_dirty_tiles(nodes[i], dirty_tiles); });
return dirty_tiles;
}
static void fix_non_manifold_seam_bleeding(bke::pbvh::Tree &pbvh,
@@ -452,9 +452,10 @@ static void fix_non_manifold_seam_bleeding(bke::pbvh::Tree &pbvh,
static void fix_non_manifold_seam_bleeding(Object &ob,
Image &image,
ImageUser &image_user,
const Span<bke::pbvh::Node *> nodes)
MutableSpan<bke::pbvh::MeshNode> nodes,
const IndexMask &node_mask)
{
Vector<image::TileNumber> dirty_tiles = collect_dirty_tiles(nodes);
Vector<image::TileNumber> dirty_tiles = collect_dirty_tiles(nodes, node_mask);
fix_non_manifold_seam_bleeding(*ob.sculpt->pbvh, image, image_user, dirty_tiles);
}
@@ -499,7 +500,7 @@ void SCULPT_do_paint_brush_image(const Depsgraph &depsgraph,
PaintModeSettings &paint_mode_settings,
const Sculpt &sd,
Object &ob,
const blender::Span<blender::bke::pbvh::Node *> nodes)
const blender::IndexMask &node_mask)
{
using namespace blender;
const Brush *brush = BKE_paint_brush_for_read(&sd.paint);
@@ -509,19 +510,19 @@ void SCULPT_do_paint_brush_image(const Depsgraph &depsgraph,
return;
}
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (const int i : range) {
do_push_undo_tile(*image_data.image, *image_data.image_user, *nodes[i]);
}
});
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (const int i : range) {
do_paint_pixels(depsgraph, ob, *brush, image_data, *nodes[i]);
}
});
fix_non_manifold_seam_bleeding(ob, *image_data.image, *image_data.image_user, nodes);
SculptSession &ss = *ob.sculpt;
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
for (bke::pbvh::Node *node : nodes) {
bke::pbvh::pixels::mark_image_dirty(*node, *image_data.image, *image_data.image_user);
}
node_mask.foreach_index(GrainSize(1), [&](const int i) {
do_push_undo_tile(*image_data.image, *image_data.image_user, nodes[i]);
});
node_mask.foreach_index(GrainSize(1), [&](const int i) {
do_paint_pixels(depsgraph, ob, *brush, image_data, nodes[i]);
});
fix_non_manifold_seam_bleeding(ob, *image_data.image, *image_data.image_user, nodes, node_mask);
node_mask.foreach_index([&](const int i) {
bke::pbvh::pixels::mark_image_dirty(nodes[i], *image_data.image, *image_data.image_user);
});
}

View File

@@ -158,7 +158,7 @@ static void calc_mesh(const Depsgraph &depsgraph,
const Sculpt &sd,
const Brush &brush,
const Span<float3> positions_eval,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
Object &object,
BrushLocalData &tls,
const MutableSpan<float3> positions_orig)
@@ -210,7 +210,7 @@ static void calc_mesh(const Depsgraph &depsgraph,
static void calc_grids(const Depsgraph &depsgraph,
const Sculpt &sd,
const Brush &brush,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
Object &object,
BrushLocalData &tls)
{
@@ -263,7 +263,7 @@ static void calc_grids(const Depsgraph &depsgraph,
static void calc_bmesh(const Depsgraph &depsgraph,
const Sculpt &sd,
const Brush &brush,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
Object &object,
BrushLocalData &tls)
{
@@ -350,7 +350,7 @@ static void grow_factors_mesh(const ePaintSymmetryFlags symm,
const Span<bool> hide_poly,
const Span<int> fake_neighbors,
const Span<float> prev_mask,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
GrowFactorLocalData &tls,
const MutableSpan<float> pose_factor,
PoseGrowFactorData &gftd)
@@ -389,7 +389,7 @@ static void grow_factors_grids(const ePaintSymmetryFlags symm,
const SubdivCCG &subdiv_ccg,
const Span<int> fake_neighbors,
const Span<float> prev_mask,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
const MutableSpan<float> pose_factor,
PoseGrowFactorData &gftd)
{
@@ -441,7 +441,7 @@ static void grow_factors_bmesh(const ePaintSymmetryFlags symm,
const float3 &pose_initial_position,
const Span<int> fake_neighbors,
const Span<float> prev_mask,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
const MutableSpan<float> pose_factor,
PoseGrowFactorData &gftd)
{
@@ -488,7 +488,8 @@ static void grow_pose_factor(const Depsgraph &depsgraph,
bke::pbvh::Tree &pbvh = *ob.sculpt->pbvh;
const ePaintSymmetryFlags symm = SCULPT_mesh_symmetry_xyz_get(ob);
Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(pbvh);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
const Span<int> fake_neighbors = ss.fake_neighbors.fake_neighbor_index;
bool grow_next_iteration = true;
@@ -501,6 +502,7 @@ static void grow_pose_factor(const Depsgraph &depsgraph,
threading::EnumerableThreadSpecific<GrowFactorLocalData> all_tls;
switch (pbvh.type()) {
case bke::pbvh::Type::Mesh: {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
const Mesh &mesh = *static_cast<const Mesh *>(ob.data);
const Span<float3> vert_positions = bke::pbvh::vert_positions_eval(depsgraph, ob);
const OffsetIndices faces = mesh.faces();
@@ -512,12 +514,12 @@ static void grow_pose_factor(const Depsgraph &depsgraph,
const VArraySpan<bool> hide_poly = *attributes.lookup<bool>(".hide_poly",
bke::AttrDomain::Face);
gftd = threading::parallel_reduce(
nodes.index_range(),
node_mask.index_range(),
1,
PoseGrowFactorData{},
[&](const IndexRange range, PoseGrowFactorData gftd) {
GrowFactorLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
grow_factors_mesh(symm,
pose_target,
vert_positions,
@@ -528,48 +530,50 @@ static void grow_pose_factor(const Depsgraph &depsgraph,
hide_poly,
fake_neighbors,
prev_mask,
*nodes[i],
nodes[i],
tls,
pose_factor,
gftd);
}
});
return gftd;
},
PoseGrowFactorData::join);
break;
}
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
gftd = threading::parallel_reduce(
nodes.index_range(),
node_mask.index_range(),
1,
PoseGrowFactorData{},
[&](const IndexRange range, PoseGrowFactorData gftd) {
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
grow_factors_grids(symm,
pose_target,
subdiv_ccg,
fake_neighbors,
prev_mask,
*nodes[i],
nodes[i],
pose_factor,
gftd);
}
});
return gftd;
},
PoseGrowFactorData::join);
break;
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
gftd = threading::parallel_reduce(
nodes.index_range(),
node_mask.index_range(),
1,
PoseGrowFactorData{},
[&](const IndexRange range, PoseGrowFactorData gftd) {
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
grow_factors_bmesh(
symm, pose_target, fake_neighbors, prev_mask, *nodes[i], pose_factor, gftd);
}
symm, pose_target, fake_neighbors, prev_mask, nodes[i], pose_factor, gftd);
});
return gftd;
},
PoseGrowFactorData::join);
@@ -1386,7 +1390,7 @@ static void align_pivot_local_space(float r_mat[4][4],
void do_pose_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &ob,
Span<bke::pbvh::Node *> nodes)
const IndexMask &node_mask)
{
SculptSession &ss = *ob.sculpt;
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
@@ -1470,34 +1474,37 @@ void do_pose_brush(const Depsgraph &depsgraph,
threading::EnumerableThreadSpecific<BrushLocalData> all_tls;
switch (ob.sculpt->pbvh->type()) {
case bke::pbvh::Type::Mesh: {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
Mesh &mesh = *static_cast<Mesh *>(ob.data);
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, ob);
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
BrushLocalData &tls = all_tls.local();
for (const int i : range) {
calc_mesh(depsgraph, sd, brush, positions_eval, *nodes[i], ob, tls, positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
node_mask.slice(range).foreach_index([&](const int i) {
calc_mesh(depsgraph, sd, brush, positions_eval, nodes[i], ob, tls, positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
BrushLocalData &tls = all_tls.local();
for (const int i : range) {
calc_grids(depsgraph, sd, brush, *nodes[i], ob, tls);
}
node_mask.slice(range).foreach_index(
[&](const int i) { calc_grids(depsgraph, sd, brush, nodes[i], ob, tls); });
});
break;
case bke::pbvh::Type::BMesh:
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
BrushLocalData &tls = all_tls.local();
for (const int i : range) {
calc_bmesh(depsgraph, sd, brush, *nodes[i], ob, tls);
}
node_mask.slice(range).foreach_index(
[&](const int i) { calc_bmesh(depsgraph, sd, brush, nodes[i], ob, tls); });
});
break;
}
}
}

View File

@@ -53,7 +53,7 @@ struct IKChain {
void do_pose_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &ob,
Span<bke::pbvh::Node *> nodes);
const IndexMask &node_mask);
/**
* Calculate the pose origin and (Optionally the pose factor)
* that is used when using the pose brush.

View File

@@ -48,7 +48,7 @@ static void apply_projection_mesh(const Depsgraph &depsgraph,
const gesture::GestureData &gesture_data,
const Span<float3> positions_eval,
const Span<float3> vert_normals,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
Object &object,
LocalData &tls,
const MutableSpan<float3> positions_orig)
@@ -75,7 +75,7 @@ static void apply_projection_mesh(const Depsgraph &depsgraph,
static void apply_projection_grids(const Sculpt &sd,
const gesture::GestureData &gesture_data,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
Object &object,
LocalData &tls)
{
@@ -107,7 +107,7 @@ static void apply_projection_grids(const Sculpt &sd,
static void apply_projection_bmesh(const Sculpt &sd,
const gesture::GestureData &gesture_data,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
Object &object,
LocalData &tls)
{
@@ -142,54 +142,57 @@ static void gesture_apply_for_symmetry_pass(bContext &C, gesture::GestureData &g
SculptSession &ss = *object.sculpt;
bke::pbvh::Tree &pbvh = *ss.pbvh;
const Sculpt &sd = *CTX_data_tool_settings(&C)->sculpt;
const Span<bke::pbvh::Node *> nodes = gesture_data.nodes;
const IndexMask &node_mask = gesture_data.node_mask;
threading::EnumerableThreadSpecific<LocalData> all_tls;
switch (gesture_data.shape_type) {
case gesture::ShapeType::Line:
switch (pbvh.type()) {
case bke::pbvh::Type::Mesh: {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
Mesh &mesh = *static_cast<Mesh *>(object.data);
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object);
const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
undo::push_nodes(depsgraph, object, nodes, undo::Type::Position);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
undo::push_nodes(depsgraph, object, node_mask, undo::Type::Position);
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
apply_projection_mesh(depsgraph,
sd,
gesture_data,
positions_eval,
vert_normals,
*nodes[i],
nodes[i],
object,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::BMesh: {
undo::push_nodes(depsgraph, object, nodes, undo::Type::Position);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
undo::push_nodes(depsgraph, object, node_mask, undo::Type::Position);
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
apply_projection_grids(sd, gesture_data, *nodes[i], object, tls);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
node_mask.slice(range).foreach_index([&](const int i) {
apply_projection_grids(sd, gesture_data, nodes[i], object, tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
undo::push_nodes(depsgraph, object, nodes, undo::Type::Position);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
undo::push_nodes(depsgraph, object, node_mask, undo::Type::Position);
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
apply_projection_bmesh(sd, gesture_data, *nodes[i], object, tls);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
node_mask.slice(range).foreach_index([&](const int i) {
apply_projection_bmesh(sd, gesture_data, nodes[i], object, tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}

View File

@@ -737,11 +737,14 @@ void blur_geometry_data_array(const Object &object,
Vector<float> new_factors;
};
const SculptSession &ss = *object.sculpt;
Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory);
threading::EnumerableThreadSpecific<LocalData> all_tls;
switch (ss.pbvh->type()) {
case bke::pbvh::Type::Mesh: {
const Span<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
const Mesh &mesh = *static_cast<const Mesh *>(object.data);
const OffsetIndices faces = mesh.faces();
const Span<int> corner_verts = mesh.corner_verts();
@@ -752,11 +755,11 @@ void blur_geometry_data_array(const Object &object,
const VArraySpan<bool> hide_poly = *attributes.lookup<bool>(".hide_poly",
bke::AttrDomain::Face);
for ([[maybe_unused]] const int _ : IndexRange(iterations)) {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> verts = hide::node_visible_verts(
*nodes[i], hide_vert, tls.vert_indices);
nodes[i], hide_vert, tls.vert_indices);
tls.vert_neighbors.resize(verts.size());
const MutableSpan<Vector<int>> neighbors = tls.vert_neighbors;
@@ -768,20 +771,21 @@ void blur_geometry_data_array(const Object &object,
smooth::neighbor_data_average_mesh(data.as_span(), neighbors, new_factors);
scatter_data_mesh(new_factors.as_span(), verts, data);
}
});
});
}
break;
}
case bke::pbvh::Type::Grids: {
const Span<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden;
for ([[maybe_unused]] const int _ : IndexRange(iterations)) {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int i : range) {
const Span<int> grids = bke::pbvh::node_grid_indices(*nodes[i]);
node_mask.slice(range).foreach_index([&](const int node_index) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[node_index]);
const int grid_verts_num = key.grid_area * grids.size();
tls.new_factors.resize(grid_verts_num);
@@ -800,17 +804,19 @@ void blur_geometry_data_array(const Object &object,
});
}
}
}
});
});
}
break;
}
case bke::pbvh::Type::BMesh: {
const Span<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
for ([[maybe_unused]] const int _ : IndexRange(iterations)) {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
for (const int node_index : range) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[node_index]);
node_mask.slice(range).foreach_index([&](const int node_index) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(
const_cast<bke::pbvh::BMeshNode *>(&nodes[node_index]));
tls.new_factors.resize(verts.size());
const MutableSpan<float> new_factors = tls.new_factors;
@@ -825,7 +831,7 @@ void blur_geometry_data_array(const Object &object,
data[BM_elem_index_get(vert)] = new_factors[i];
i++;
}
}
});
});
}
break;

View File

@@ -192,7 +192,7 @@ static void transform_node_mesh(const Depsgraph &depsgraph,
const Sculpt &sd,
const std::array<float4x4, 8> &transform_mats,
const Span<float3> positions_eval,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
Object &object,
TransformLocalData &tls,
const MutableSpan<float3> positions_orig)
@@ -219,7 +219,7 @@ static void transform_node_mesh(const Depsgraph &depsgraph,
static void transform_node_grids(const Sculpt &sd,
const std::array<float4x4, 8> &transform_mats,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
Object &object,
TransformLocalData &tls)
{
@@ -251,7 +251,7 @@ static void transform_node_grids(const Sculpt &sd,
static void transform_node_bmesh(const Sculpt &sd,
const std::array<float4x4, 8> &transform_mats,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
Object &object,
TransformLocalData &tls)
{
@@ -293,41 +293,44 @@ static void sculpt_transform_all_vertices(const Depsgraph &depsgraph, const Scul
/* Regular transform applies all symmetry passes at once as it is split by symmetry areas
* (each vertex can only be transformed once by the transform matrix of its area). */
bke::pbvh::Tree &pbvh = *ss.pbvh;
const Span<bke::pbvh::Node *> nodes = ss.filter_cache->nodes;
const IndexMask &node_mask = ss.filter_cache->node_mask;
threading::EnumerableThreadSpecific<TransformLocalData> all_tls;
switch (pbvh.type()) {
case bke::pbvh::Type::Mesh: {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
Mesh &mesh = *static_cast<Mesh *>(ob.data);
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, ob);
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
TransformLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
transform_node_mesh(
depsgraph, sd, transform_mats, positions_eval, *nodes[i], ob, tls, positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
depsgraph, sd, transform_mats, positions_eval, nodes[i], ob, tls, positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
TransformLocalData &tls = all_tls.local();
for (const int i : range) {
transform_node_grids(sd, transform_mats, *nodes[i], ob, tls);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
node_mask.slice(range).foreach_index([&](const int i) {
transform_node_grids(sd, transform_mats, nodes[i], ob, tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::BMesh: {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
TransformLocalData &tls = all_tls.local();
for (const int i : range) {
transform_node_bmesh(sd, transform_mats, *nodes[i], ob, tls);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
node_mask.slice(range).foreach_index([&](const int i) {
transform_node_bmesh(sd, transform_mats, nodes[i], ob, tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
@@ -361,7 +364,7 @@ static void elastic_transform_node_mesh(const Depsgraph &depsgraph,
const float4x4 &elastic_transform_mat,
const float3 &elastic_transform_pivot,
const Span<float3> positions_eval,
const bke::pbvh::Node &node,
const bke::pbvh::MeshNode &node,
Object &object,
TransformLocalData &tls,
const MutableSpan<float3> positions_orig)
@@ -391,7 +394,7 @@ static void elastic_transform_node_grids(const Sculpt &sd,
const KelvinletParams &params,
const float4x4 &elastic_transform_mat,
const float3 &elastic_transform_pivot,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
Object &object,
TransformLocalData &tls)
{
@@ -422,7 +425,7 @@ static void elastic_transform_node_bmesh(const Sculpt &sd,
const KelvinletParams &params,
const float4x4 &elastic_transform_mat,
const float3 &elastic_transform_pivot,
bke::pbvh::Node &node,
bke::pbvh::BMeshNode &node,
Object &object,
TransformLocalData &tls)
{
@@ -462,7 +465,7 @@ static void transform_radius_elastic(const Depsgraph &depsgraph,
ss, symm, ss.filter_cache->transform_displacement_mode);
bke::pbvh::Tree &pbvh = *ss.pbvh;
const Span<bke::pbvh::Node *> nodes = ss.filter_cache->nodes;
const IndexMask &node_mask = ss.filter_cache->node_mask;
KelvinletParams params;
/* TODO(pablodp606): These parameters can be exposed if needed as transform strength and volume
@@ -485,46 +488,49 @@ static void transform_radius_elastic(const Depsgraph &depsgraph,
float4x4 elastic_transform_mat = transform_mats[symm_area];
switch (pbvh.type()) {
case bke::pbvh::Type::Mesh: {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
Mesh &mesh = *static_cast<Mesh *>(ob.data);
const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, ob);
MutableSpan<float3> positions_orig = mesh.vert_positions_for_write();
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
TransformLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
elastic_transform_node_mesh(depsgraph,
sd,
params,
elastic_transform_mat,
elastic_transform_pivot,
positions_eval,
*nodes[i],
nodes[i],
ob,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
TransformLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
elastic_transform_node_grids(
sd, params, elastic_transform_mat, elastic_transform_pivot, *nodes[i], ob, tls);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
sd, params, elastic_transform_mat, elastic_transform_pivot, nodes[i], ob, tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
case bke::pbvh::Type::BMesh: {
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
TransformLocalData &tls = all_tls.local();
for (const int i : range) {
node_mask.slice(range).foreach_index([&](const int i) {
elastic_transform_node_bmesh(
sd, params, elastic_transform_mat, elastic_transform_pivot, *nodes[i], ob, tls);
BKE_pbvh_node_mark_positions_update(*nodes[i]);
}
sd, params, elastic_transform_mat, elastic_transform_pivot, nodes[i], ob, tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
});
});
break;
}
@@ -659,8 +665,11 @@ static float3 average_unmasked_position(const Depsgraph &depsgraph,
const SculptSession &ss = *object.sculpt;
bke::pbvh::Tree &pbvh = *ss.pbvh;
Vector<bke::pbvh::Node *> nodes = bke::pbvh::search_gather(
pbvh, [&](bke::pbvh::Node &node) { return !node_fully_masked_or_hidden(node); });
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::search_nodes(
pbvh, memory, [&](const bke::pbvh::Node &node) {
return !node_fully_masked_or_hidden(node);
});
struct LocalData {
Vector<float> factors;
@@ -670,17 +679,18 @@ static float3 average_unmasked_position(const Depsgraph &depsgraph,
threading::EnumerableThreadSpecific<LocalData> all_tls;
switch (pbvh.type()) {
case bke::pbvh::Type::Mesh: {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
const Mesh &mesh = *static_cast<const Mesh *>(object.data);
const Span<float3> vert_positions = bke::pbvh::vert_positions_eval(depsgraph, object);
const AveragePositionAccumulation total = threading::parallel_reduce(
nodes.index_range(),
node_mask.index_range(),
1,
AveragePositionAccumulation{},
[&](const IndexRange range, AveragePositionAccumulation sum) {
LocalData &tls = all_tls.local();
threading::isolate_task([&]() {
for (const bke::pbvh::Node *node : nodes.as_span().slice(range)) {
const Span<int> verts = bke::pbvh::node_unique_verts(*node);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
tls.positions.resize(verts.size());
const MutableSpan<float3> positions = tls.positions;
@@ -692,7 +702,7 @@ static float3 average_unmasked_position(const Depsgraph &depsgraph,
filter_verts_outside_symmetry_area(positions, pivot, symm, factors);
accumulate_weighted_average_position(positions, factors, sum);
}
});
});
return sum;
},
@@ -700,15 +710,16 @@ static float3 average_unmasked_position(const Depsgraph &depsgraph,
return float3(math::safe_divide(total.position, total.weight_total));
}
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
const AveragePositionAccumulation total = threading::parallel_reduce(
nodes.index_range(),
node_mask.index_range(),
1,
AveragePositionAccumulation{},
[&](const IndexRange range, AveragePositionAccumulation sum) {
LocalData &tls = all_tls.local();
for (const bke::pbvh::Node *node : nodes.as_span().slice(range)) {
const Span<int> grids = bke::pbvh::node_grid_indices(*node);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
const MutableSpan positions = gather_grids_positions(
subdiv_ccg, grids, tls.positions);
@@ -718,21 +729,22 @@ static float3 average_unmasked_position(const Depsgraph &depsgraph,
filter_verts_outside_symmetry_area(positions, pivot, symm, factors);
accumulate_weighted_average_position(positions, factors, sum);
}
});
return sum;
},
combine_average_position_accumulation);
return float3(math::safe_divide(total.position, total.weight_total));
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
const AveragePositionAccumulation total = threading::parallel_reduce(
nodes.index_range(),
node_mask.index_range(),
1,
AveragePositionAccumulation{},
[&](const IndexRange range, AveragePositionAccumulation sum) {
LocalData &tls = all_tls.local();
for (bke::pbvh::Node *node : nodes.as_span().slice(range)) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(node);
node_mask.slice(range).foreach_index([&](const int i) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]);
const MutableSpan positions = gather_bmesh_positions(verts, tls.positions);
tls.factors.resize(verts.size());
@@ -741,7 +753,7 @@ static float3 average_unmasked_position(const Depsgraph &depsgraph,
filter_verts_outside_symmetry_area(positions, pivot, symm, factors);
accumulate_weighted_average_position(positions, factors, sum);
}
});
return sum;
},
combine_average_position_accumulation);
@@ -772,8 +784,11 @@ static float3 average_mask_border_position(const Depsgraph &depsgraph,
const SculptSession &ss = *object.sculpt;
bke::pbvh::Tree &pbvh = *ss.pbvh;
Vector<bke::pbvh::Node *> nodes = bke::pbvh::search_gather(
pbvh, [&](bke::pbvh::Node &node) { return !node_fully_masked_or_hidden(node); });
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::search_nodes(
pbvh, memory, [&](const bke::pbvh::Node &node) {
return !node_fully_masked_or_hidden(node);
});
struct LocalData {
Vector<float> factors;
@@ -784,19 +799,20 @@ static float3 average_mask_border_position(const Depsgraph &depsgraph,
threading::EnumerableThreadSpecific<LocalData> all_tls;
switch (pbvh.type()) {
case bke::pbvh::Type::Mesh: {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
const Mesh &mesh = *static_cast<const Mesh *>(object.data);
const Span<float3> vert_positions = bke::pbvh::vert_positions_eval(depsgraph, object);
const bke::AttributeAccessor attributes = mesh.attributes();
const VArraySpan mask_attr = *attributes.lookup_or_default<float>(
".sculpt_mask", bke::AttrDomain::Point, 0.0f);
const AveragePositionAccumulation total = threading::parallel_reduce(
nodes.index_range(),
node_mask.index_range(),
1,
AveragePositionAccumulation{},
[&](const IndexRange range, AveragePositionAccumulation sum) {
LocalData &tls = all_tls.local();
for (const bke::pbvh::Node *node : nodes.as_span().slice(range)) {
const Span<int> verts = bke::pbvh::node_unique_verts(*node);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
MutableSpan positions = gather_data_mesh(vert_positions, verts, tls.positions);
MutableSpan masks = gather_data_mesh(mask_attr, verts, tls.masks);
@@ -808,22 +824,23 @@ static float3 average_mask_border_position(const Depsgraph &depsgraph,
filter_verts_outside_symmetry_area(positions, pivot, symm, factors);
accumulate_weighted_average_position(positions, factors, sum);
}
});
return sum;
},
combine_average_position_accumulation);
return float3(math::safe_divide(total.position, total.weight_total));
}
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
const AveragePositionAccumulation total = threading::parallel_reduce(
nodes.index_range(),
node_mask.index_range(),
1,
AveragePositionAccumulation{},
[&](const IndexRange range, AveragePositionAccumulation sum) {
LocalData &tls = all_tls.local();
for (const bke::pbvh::Node *node : nodes.as_span().slice(range)) {
const Span<int> grids = bke::pbvh::node_grid_indices(*node);
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
const MutableSpan positions = gather_grids_positions(
subdiv_ccg, grids, tls.positions);
@@ -838,21 +855,22 @@ static float3 average_mask_border_position(const Depsgraph &depsgraph,
filter_verts_outside_symmetry_area(positions, pivot, symm, factors);
accumulate_weighted_average_position(positions, factors, sum);
}
});
return sum;
},
combine_average_position_accumulation);
return float3(math::safe_divide(total.position, total.weight_total));
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
const AveragePositionAccumulation total = threading::parallel_reduce(
nodes.index_range(),
node_mask.index_range(),
1,
AveragePositionAccumulation{},
[&](const IndexRange range, AveragePositionAccumulation sum) {
LocalData &tls = all_tls.local();
for (bke::pbvh::Node *node : nodes.as_span().slice(range)) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(node);
node_mask.slice(range).foreach_index([&](const int i) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]);
const MutableSpan positions = gather_bmesh_positions(verts, tls.positions);
tls.masks.resize(verts.size());
@@ -866,7 +884,7 @@ static float3 average_mask_border_position(const Depsgraph &depsgraph,
filter_verts_outside_symmetry_area(positions, pivot, symm, factors);
accumulate_weighted_average_position(positions, factors, sum);
}
});
return sum;
},
combine_average_position_accumulation);

View File

@@ -605,9 +605,10 @@ static void bmesh_restore_generic(StepData &step_data, Object &object, SculptSes
}
if (step_data.type == Type::Mask) {
for (bke::pbvh::Node *node : bke::pbvh::all_leaf_nodes(*ss.pbvh)) {
BKE_pbvh_node_mark_redraw(*node);
}
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory);
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_redraw(nodes[i]); });
}
else {
BKE_sculptsession_free_pbvh(&ss);
@@ -862,7 +863,8 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data)
break;
}
case Type::Position: {
const Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory);
BKE_sculpt_update_object_for_edit(depsgraph, &object, false);
if (!topology_matches(step_data, object)) {
@@ -870,6 +872,7 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data)
}
if (use_multires_undo(step_data, ss)) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
MutableSpan<CCGElem *> grids = subdiv_ccg.grids;
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
@@ -878,25 +881,26 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data)
for (std::unique_ptr<Node> &unode : step_data.nodes) {
restore_position_grids(grids, key, *unode, modified_grids);
}
for (bke::pbvh::Node *node : nodes) {
const Span<int> grids = bke::pbvh::node_grid_indices(*node);
node_mask.foreach_index([&](const int i) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
if (indices_contain_true(modified_grids, grids)) {
BKE_pbvh_node_mark_positions_update(*node);
BKE_pbvh_node_mark_positions_update(nodes[i]);
}
}
});
multires_mark_as_modified(depsgraph, &object, MULTIRES_COORDS_MODIFIED);
}
else {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
if (!restore_active_shape_key(*C, *depsgraph, step_data, object)) {
return;
}
Array<bool> modified_verts(ss.totvert, false);
restore_position_mesh(object, step_data.nodes, modified_verts);
for (bke::pbvh::Node *node : nodes) {
if (indices_contain_true(modified_verts, bke::pbvh::node_verts(*node))) {
BKE_pbvh_node_mark_positions_update(*node);
node_mask.foreach_index([&](const int i) {
if (indices_contain_true(modified_verts, bke::pbvh::node_verts(nodes[i]))) {
BKE_pbvh_node_mark_positions_update(nodes[i]);
}
}
});
}
if (tag_update) {
@@ -909,7 +913,8 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data)
break;
}
case Type::HideVert: {
const Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory);
BKE_sculpt_update_object_for_edit(depsgraph, &object, false);
if (!topology_matches(step_data, object)) {
@@ -917,27 +922,29 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data)
}
if (use_multires_undo(step_data, ss)) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
Array<bool> modified_grids(subdiv_ccg.grids.size(), false);
for (std::unique_ptr<Node> &unode : step_data.nodes) {
restore_vert_visibility_grids(subdiv_ccg, *unode, modified_grids);
}
for (bke::pbvh::Node *node : nodes) {
if (indices_contain_true(modified_grids, bke::pbvh::node_grid_indices(*node))) {
BKE_pbvh_node_mark_update_visibility(*node);
node_mask.foreach_index([&](const int i) {
if (indices_contain_true(modified_grids, bke::pbvh::node_grid_indices(nodes[i]))) {
BKE_pbvh_node_mark_update_visibility(nodes[i]);
}
}
});
}
else {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
Array<bool> modified_verts(ss.totvert, false);
for (std::unique_ptr<Node> &unode : step_data.nodes) {
restore_vert_visibility_mesh(object, *unode, modified_verts);
}
for (bke::pbvh::Node *node : nodes) {
if (indices_contain_true(modified_verts, bke::pbvh::node_verts(*node))) {
BKE_pbvh_node_mark_update_visibility(*node);
node_mask.foreach_index([&](const int i) {
if (indices_contain_true(modified_verts, bke::pbvh::node_verts(nodes[i]))) {
BKE_pbvh_node_mark_update_visibility(nodes[i]);
}
}
});
}
BKE_pbvh_sync_visibility_from_verts(object);
@@ -948,7 +955,8 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data)
break;
}
case Type::HideFace: {
const Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory);
BKE_sculpt_update_object_for_edit(depsgraph, &object, false);
if (!topology_matches(step_data, object)) {
@@ -961,28 +969,30 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data)
}
if (use_multires_undo(step_data, ss)) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
Vector<int> faces_vector;
for (bke::pbvh::Node *node : nodes) {
node_mask.foreach_index([&](const int i) {
faces_vector.clear();
const Span<int> faces = bke::pbvh::node_face_indices_calc_grids(
subdiv_ccg, static_cast<bke::pbvh::GridsNode &>(*node), faces_vector);
subdiv_ccg, nodes[i], faces_vector);
if (indices_contain_true(modified_faces, faces)) {
BKE_pbvh_node_mark_update_visibility(*node);
BKE_pbvh_node_mark_update_visibility(nodes[i]);
}
}
});
}
else {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
const Span<int> tri_faces = mesh.corner_tri_faces();
Vector<int> faces_vector;
for (bke::pbvh::Node *node : nodes) {
node_mask.foreach_index([&](const int i) {
faces_vector.clear();
const Span<int> faces = bke::pbvh::node_face_indices_calc_mesh(
tri_faces, static_cast<bke::pbvh::MeshNode &>(*node), faces_vector);
tri_faces, static_cast<bke::pbvh::MeshNode &>(nodes[i]), faces_vector);
if (indices_contain_true(modified_faces, faces)) {
BKE_pbvh_node_mark_update_visibility(*node);
BKE_pbvh_node_mark_update_visibility(nodes[i]);
}
}
});
}
hide::sync_all_from_faces(object);
@@ -990,7 +1000,8 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data)
break;
}
case Type::Mask: {
const Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory);
BKE_sculpt_update_object_for_edit(depsgraph, &object, false);
if (!topology_matches(step_data, object)) {
@@ -998,33 +1009,36 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data)
}
if (use_multires_undo(step_data, ss)) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
Array<bool> modified_grids(ss.subdiv_ccg->grids.size(), false);
for (std::unique_ptr<Node> &unode : step_data.nodes) {
restore_mask_grids(object, *unode, modified_grids);
}
for (bke::pbvh::Node *node : nodes) {
if (indices_contain_true(modified_grids, bke::pbvh::node_grid_indices(*node))) {
BKE_pbvh_node_mark_update_mask(*node);
node_mask.foreach_index([&](const int i) {
if (indices_contain_true(modified_grids, bke::pbvh::node_grid_indices(nodes[i]))) {
BKE_pbvh_node_mark_update_mask(nodes[i]);
}
}
});
}
else {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
Array<bool> modified_verts(ss.totvert, false);
for (std::unique_ptr<Node> &unode : step_data.nodes) {
restore_mask_mesh(object, *unode, modified_verts);
}
for (bke::pbvh::Node *node : nodes) {
if (indices_contain_true(modified_verts, bke::pbvh::node_verts(*node))) {
BKE_pbvh_node_mark_update_mask(*node);
node_mask.foreach_index([&](const int i) {
if (indices_contain_true(modified_verts, bke::pbvh::node_verts(nodes[i]))) {
BKE_pbvh_node_mark_update_mask(nodes[i]);
}
}
});
}
bke::pbvh::update_mask(object, *ss.pbvh);
break;
}
case Type::FaceSet: {
const Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory);
BKE_sculpt_update_object_for_edit(depsgraph, &object, false);
if (!topology_matches(step_data, object)) {
@@ -1036,46 +1050,50 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data)
restore_face_sets(object, *unode, modified_faces);
}
if (use_multires_undo(step_data, ss)) {
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
Vector<int> faces_vector;
for (bke::pbvh::Node *node : nodes) {
node_mask.foreach_index([&](const int i) {
faces_vector.clear();
const Span<int> faces = bke::pbvh::node_face_indices_calc_grids(
subdiv_ccg, static_cast<bke::pbvh::GridsNode &>(*node), faces_vector);
subdiv_ccg, nodes[i], faces_vector);
if (indices_contain_true(modified_faces, faces)) {
BKE_pbvh_node_mark_update_face_sets(*node);
BKE_pbvh_node_mark_update_face_sets(nodes[i]);
}
}
});
}
else {
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
const Span<int> tri_faces = mesh.corner_tri_faces();
Vector<int> faces_vector;
for (bke::pbvh::Node *node : nodes) {
node_mask.foreach_index([&](const int i) {
faces_vector.clear();
const Span<int> faces = bke::pbvh::node_face_indices_calc_mesh(
tri_faces, static_cast<bke::pbvh::MeshNode &>(*node), faces_vector);
tri_faces, static_cast<bke::pbvh::MeshNode &>(nodes[i]), faces_vector);
if (indices_contain_true(modified_faces, faces)) {
BKE_pbvh_node_mark_update_face_sets(*node);
BKE_pbvh_node_mark_update_face_sets(nodes[i]);
}
}
});
}
break;
}
case Type::Color: {
const Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory);
BKE_sculpt_update_object_for_edit(depsgraph, &object, false);
if (!topology_matches(step_data, object)) {
return;
}
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
Array<bool> modified_verts(ss.totvert, false);
restore_color(object, step_data, modified_verts);
for (bke::pbvh::Node *node : nodes) {
if (indices_contain_true(modified_verts, bke::pbvh::node_verts(*node))) {
BKE_pbvh_node_mark_update_color(*node);
node_mask.foreach_index([&](const int i) {
if (indices_contain_true(modified_verts, bke::pbvh::node_verts(nodes[i]))) {
BKE_pbvh_node_mark_update_color(nodes[i]);
}
}
});
break;
}
case Type::Geometry: {
@@ -1131,7 +1149,7 @@ const Node *get_node(const bke::pbvh::Node *node, const Type type)
}
static void alloc_and_store_hidden(const SculptSession &ss,
const bke::pbvh::Node &node,
const bke::pbvh::GridsNode &node,
Node &unode)
{
if (!ss.subdiv_ccg) {
@@ -1207,7 +1225,7 @@ static void store_hidden(const Object &object, const bke::pbvh::Node &node, Node
return;
}
const Span<int> verts = bke::pbvh::node_verts(node);
const Span<int> verts = bke::pbvh::node_verts(static_cast<const bke::pbvh::MeshNode &>(node));
for (const int i : verts.index_range()) {
unode.vert_hidden[i].set(hide_vert[verts[i]]);
}
@@ -1274,7 +1292,8 @@ static void store_color(const Object &object, const bke::pbvh::Node &node, Node
/* NOTE: even with loop colors we still store (derived)
* vertex colors for original data lookup. */
const Span<int> verts = bke::pbvh::node_unique_verts(node);
const Span<int> verts = bke::pbvh::node_unique_verts(
static_cast<const bke::pbvh::MeshNode &>(node));
unode.col.reinitialize(verts.size());
color::gather_colors_vert(
faces, corner_verts, vert_to_face_map, colors, color_attribute.domain, verts, unode.col);
@@ -1330,14 +1349,15 @@ static void fill_node_data(const Depsgraph &depsgraph,
int verts_num;
if (ss.pbvh->type() == bke::pbvh::Type::Grids) {
unode.grids = bke::pbvh::node_grid_indices(*node);
unode.grids = bke::pbvh::node_grid_indices(static_cast<const bke::pbvh::GridsNode &>(*node));
const int grid_area = ss.subdiv_ccg->grid_size * ss.subdiv_ccg->grid_size;
verts_num = unode.grids.size() * grid_area;
}
else {
unode.vert_indices = bke::pbvh::node_verts(*node);
unode.unique_verts_num = bke::pbvh::node_unique_verts(*node).size();
unode.vert_indices = bke::pbvh::node_verts(static_cast<const bke::pbvh::MeshNode &>(*node));
unode.unique_verts_num =
bke::pbvh::node_unique_verts(static_cast<const bke::pbvh::MeshNode &>(*node)).size();
verts_num = unode.vert_indices.size();
}
@@ -1379,7 +1399,7 @@ static void fill_node_data(const Depsgraph &depsgraph,
}
case Type::HideVert: {
if (ss.pbvh->type() == bke::pbvh::Type::Grids) {
alloc_and_store_hidden(ss, *node, unode);
alloc_and_store_hidden(ss, static_cast<const bke::pbvh::GridsNode &>(*node), unode);
}
else {
unode.vert_hidden.resize(unode.vert_indices.size());
@@ -1423,7 +1443,9 @@ static void fill_node_data(const Depsgraph &depsgraph,
* Dynamic topology stores only one undo node per stroke, regardless of the number of
* bke::pbvh::Tree nodes modified.
*/
BLI_NOINLINE static void bmesh_push(const Object &object, const bke::pbvh::Node *node, Type type)
BLI_NOINLINE static void bmesh_push(const Object &object,
const bke::pbvh::BMeshNode *node,
Type type)
{
StepData *step_data = get_step_data();
const SculptSession &ss = *object.sculpt;
@@ -1465,7 +1487,7 @@ BLI_NOINLINE static void bmesh_push(const Object &object, const bke::pbvh::Node
&ss.bm->vdata, CD_PROP_FLOAT, ".sculpt_mask");
/* The vertices and node aren't changed, though pointers to them are stored in the log. */
bke::pbvh::Node *node_mut = const_cast<bke::pbvh::Node *>(node);
bke::pbvh::BMeshNode *node_mut = const_cast<bke::pbvh::BMeshNode *>(node);
switch (type) {
case Type::None:
@@ -1532,7 +1554,7 @@ void push_node(const Depsgraph &depsgraph,
{
SculptSession &ss = *object.sculpt;
if (ss.bm || ELEM(type, Type::DyntopoBegin, Type::DyntopoEnd)) {
bmesh_push(object, node, type);
bmesh_push(object, static_cast<const bke::pbvh::BMeshNode *>(node), type);
return;
}
@@ -1554,14 +1576,13 @@ void push_node(const Depsgraph &depsgraph,
void push_nodes(const Depsgraph &depsgraph,
Object &object,
const Span<const bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
const Type type)
{
SculptSession &ss = *object.sculpt;
if (ss.bm || ELEM(type, Type::DyntopoBegin, Type::DyntopoEnd)) {
for (const bke::pbvh::Node *node : nodes) {
bmesh_push(object, node, type);
}
const Span<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
node_mask.foreach_index([&](const int i) { bmesh_push(object, &nodes[i], type); });
return;
}
@@ -1570,11 +1591,32 @@ void push_nodes(const Depsgraph &depsgraph,
step_data->type = type;
Vector<std::pair<const bke::pbvh::Node *, Node *>, 32> nodes_to_fill;
for (const bke::pbvh::Node *node : nodes) {
bool newly_added;
Node *unode = ensure_node(*step_data, *node, newly_added);
if (newly_added) {
nodes_to_fill.append({node, unode});
switch (ss.pbvh->type()) {
case bke::pbvh::Type::Mesh: {
const Span<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
node_mask.foreach_index([&](const int i) {
bool newly_added;
Node *unode = ensure_node(*step_data, nodes[i], newly_added);
if (newly_added) {
nodes_to_fill.append({&nodes[i], unode});
}
});
break;
}
case bke::pbvh::Type::Grids: {
const Span<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
node_mask.foreach_index([&](const int i) {
bool newly_added;
Node *unode = ensure_node(*step_data, nodes[i], newly_added);
if (newly_added) {
nodes_to_fill.append({&nodes[i], unode});
}
});
break;
}
case bke::pbvh::Type::BMesh: {
BLI_assert_unreachable();
break;
}
}
@@ -2040,8 +2082,9 @@ static void push_all_grids(const Depsgraph &depsgraph, Object *object)
return;
}
Vector<bke::pbvh::Node *> nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh);
push_nodes(depsgraph, *object, nodes, Type::Position);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory);
push_nodes(depsgraph, *object, node_mask, Type::Position);
}
void push_multires_mesh_begin(bContext *C, const char *str)

View File

@@ -13,6 +13,7 @@
#include "BLI_array.hh"
#include "BLI_bit_group_vector.hh"
#include "BLI_bit_vector.hh"
#include "BLI_index_mask_fwd.hh"
#include "BLI_map.hh"
#include "BLI_math_vector.hh"
#include "BLI_vector.hh"
@@ -174,7 +175,7 @@ void push_node(const Depsgraph &depsgraph,
undo::Type type);
void push_nodes(const Depsgraph &depsgraph,
Object &object,
Span<const bke::pbvh::Node *> nodes,
const IndexMask &node_mask,
undo::Type type);
/**