Cleanup: Use FunctionRef for PBVH callbacks

This commit is contained in:
Hans Goudey
2023-12-16 10:57:42 -05:00
parent 3d82c9c239
commit 488de130b3
5 changed files with 141 additions and 134 deletions

View File

@@ -133,14 +133,6 @@ BLI_INLINE PBVHVertRef BKE_pbvh_index_to_vertex(PBVH *pbvh, int index)
/* Callbacks */
/**
* Returns true if the search should continue from this node, false otherwise.
*/
using BKE_pbvh_HitCallback = void (*)(PBVHNode *node, void *data);
using BKE_pbvh_HitOccludedCallback = void (*)(PBVHNode *node, void *data, float *tmin);
using BKE_pbvh_SearchNearestCallback = void (*)(PBVHNode *node, void *data, float *tmin);
namespace blender::bke::pbvh {
/**
@@ -167,10 +159,9 @@ void free(PBVH *pbvh);
* - Gather nodes in an array (easy to multi-thread) see blender::bke::pbvh::search_gather.
*/
void search_callback(PBVH *pbvh,
FunctionRef<bool(PBVHNode &)> scb,
BKE_pbvh_HitCallback hcb,
void *hit_data);
void search_callback(PBVH &pbvh,
FunctionRef<bool(PBVHNode &)> filter_fn,
FunctionRef<void(PBVHNode &)> hit_fn);
/* Ray-cast
* the hit callback is called for all leaf nodes intersecting the ray;
@@ -178,8 +169,7 @@ void search_callback(PBVH *pbvh,
* hit first */
void raycast(PBVH *pbvh,
BKE_pbvh_HitOccludedCallback cb,
void *data,
FunctionRef<void(PBVHNode &node, float *tmin)> cb,
const float ray_start[3],
const float ray_normal[3],
bool original);
@@ -218,8 +208,7 @@ void clip_ray_ortho(
PBVH *pbvh, bool original, float ray_start[3], float ray_end[3], float ray_normal[3]);
void find_nearest_to_ray(PBVH *pbvh,
BKE_pbvh_HitOccludedCallback cb,
void *data,
const FunctionRef<void(PBVHNode &node, float *tmin)> fn,
const float ray_start[3],
const float ray_normal[3],
bool original);

View File

@@ -905,9 +905,7 @@ void free(PBVH *pbvh)
delete pbvh;
}
} // namespace blender::bke::pbvh
static void pbvh_iter_begin(PBVHIter *iter, PBVH *pbvh, blender::FunctionRef<bool(PBVHNode &)> scb)
static void pbvh_iter_begin(PBVHIter *iter, PBVH *pbvh, FunctionRef<bool(PBVHNode &)> scb)
{
iter->pbvh = pbvh;
iter->scb = scb;
@@ -1047,18 +1045,17 @@ static void node_tree_insert(node_tree *tree, node_tree *new_node)
}
static void traverse_tree(node_tree *tree,
BKE_pbvh_HitOccludedCallback hcb,
void *hit_data,
const FunctionRef<void(PBVHNode &node, float *tmin)> hit_fn,
float *tmin)
{
if (tree->left) {
traverse_tree(tree->left, hcb, hit_data, tmin);
traverse_tree(tree->left, hit_fn, tmin);
}
hcb(tree->data, hit_data, tmin);
hit_fn(*tree->data, tmin);
if (tree->right) {
traverse_tree(tree->right, hcb, hit_data, tmin);
traverse_tree(tree->right, hit_fn, tmin);
}
}
@@ -1074,9 +1071,11 @@ static void free_tree(node_tree *tree)
tree->right = nullptr;
}
free(tree);
::free(tree);
}
} // namespace blender::bke::pbvh
float BKE_pbvh_node_get_tmin(const PBVHNode *node)
{
return node->tmin;
@@ -1084,22 +1083,21 @@ float BKE_pbvh_node_get_tmin(const PBVHNode *node)
namespace blender::bke::pbvh {
void search_callback(PBVH *pbvh,
FunctionRef<bool(PBVHNode &)> scb,
BKE_pbvh_HitCallback hcb,
void *hit_data)
void search_callback(PBVH &pbvh,
FunctionRef<bool(PBVHNode &)> filter_fn,
FunctionRef<void(PBVHNode &)> hit_fn)
{
if (pbvh->nodes.is_empty()) {
if (pbvh.nodes.is_empty()) {
return;
}
PBVHIter iter;
PBVHNode *node;
pbvh_iter_begin(&iter, pbvh, scb);
pbvh_iter_begin(&iter, &pbvh, filter_fn);
while ((node = pbvh_iter_next(&iter, PBVH_Leaf))) {
if (node->flag & PBVH_Leaf) {
hcb(node, hit_data);
hit_fn(*node);
}
}
@@ -1107,9 +1105,8 @@ void search_callback(PBVH *pbvh,
}
static void search_callback_occluded(PBVH *pbvh,
FunctionRef<bool(PBVHNode &)> scb,
BKE_pbvh_HitOccludedCallback hcb,
void *hit_data)
const FunctionRef<bool(PBVHNode &)> scb,
const FunctionRef<void(PBVHNode &node, float *tmin)> hit_fn)
{
if (pbvh->nodes.is_empty()) {
return;
@@ -1142,7 +1139,7 @@ static void search_callback_occluded(PBVH *pbvh,
if (tree) {
float tmin = FLT_MAX;
traverse_tree(tree, hcb, hit_data, &tmin);
traverse_tree(tree, hit_fn, &tmin);
free_tree(tree);
}
}
@@ -1570,6 +1567,7 @@ void update_visibility(PBVH &pbvh)
Bounds<float3> BKE_pbvh_redraw_BB(PBVH *pbvh)
{
using namespace blender;
using namespace blender::bke::pbvh;
if (pbvh->nodes.is_empty()) {
return {};
}
@@ -1916,17 +1914,16 @@ struct RaycastData {
bool original;
};
static bool ray_aabb_intersect(PBVHNode *node, RaycastData *rcd)
static bool ray_aabb_intersect(PBVHNode &node, const RaycastData &rcd)
{
if (rcd->original) {
return isect_ray_aabb_v3(&rcd->ray, node->orig_vb.min, node->orig_vb.max, &node->tmin);
if (rcd.original) {
return isect_ray_aabb_v3(&rcd.ray, node.orig_vb.min, node.orig_vb.max, &node.tmin);
}
return isect_ray_aabb_v3(&rcd->ray, node->vb.min, node->vb.max, &node->tmin);
return isect_ray_aabb_v3(&rcd.ray, node.vb.min, node.vb.max, &node.tmin);
}
void raycast(PBVH *pbvh,
BKE_pbvh_HitOccludedCallback cb,
void *data,
const FunctionRef<void(PBVHNode &node, float *tmin)> hit_fn,
const float ray_start[3],
const float ray_normal[3],
bool original)
@@ -1937,7 +1934,7 @@ void raycast(PBVH *pbvh,
rcd.original = original;
search_callback_occluded(
pbvh, [&](PBVHNode &node) { return ray_aabb_intersect(&node, &rcd); }, cb, data);
pbvh, [&](PBVHNode &node) { return ray_aabb_intersect(node, rcd); }, hit_fn);
}
bool ray_face_intersection_quad(const float ray_start[3],
@@ -2396,8 +2393,7 @@ static bool nearest_to_ray_aabb_dist_sq(PBVHNode *node, FindNearestRayData *rcd)
}
void find_nearest_to_ray(PBVH *pbvh,
BKE_pbvh_SearchNearestCallback cb,
void *data,
const FunctionRef<void(PBVHNode &node, float *tmin)> fn,
const float ray_start[3],
const float ray_normal[3],
bool original)
@@ -2408,7 +2404,7 @@ void find_nearest_to_ray(PBVH *pbvh,
ncd.original = original;
search_callback_occluded(
pbvh, [&](PBVHNode &node) { return nearest_to_ray_aabb_dist_sq(&node, &ncd); }, cb, data);
pbvh, [&](PBVHNode &node) { return nearest_to_ray_aabb_dist_sq(&node, &ncd); }, fn);
}
static bool pbvh_faces_node_nearest_to_ray(PBVH *pbvh,

View File

@@ -4762,84 +4762,84 @@ void SCULPT_stroke_modifiers_check(const bContext *C, Object *ob, const Brush *b
}
}
static void sculpt_raycast_cb(PBVHNode *node, void *data_v, float *tmin)
static void sculpt_raycast_cb(PBVHNode &node, SculptRaycastData &srd, float *tmin)
{
using namespace blender;
using namespace blender::ed::sculpt_paint;
if (BKE_pbvh_node_get_tmin(node) >= *tmin) {
if (BKE_pbvh_node_get_tmin(&node) >= *tmin) {
return;
}
SculptRaycastData *srd = static_cast<SculptRaycastData *>(data_v);
float(*origco)[3] = nullptr;
bool use_origco = false;
if (srd->original && srd->ss->cache) {
if (BKE_pbvh_type(srd->ss->pbvh) == PBVH_BMESH) {
if (srd.original && srd.ss->cache) {
if (BKE_pbvh_type(srd.ss->pbvh) == PBVH_BMESH) {
use_origco = true;
}
else {
/* Intersect with coordinates from before we started stroke. */
undo::Node *unode = undo::get_node(node, undo::Type::Position);
undo::Node *unode = undo::get_node(&node, undo::Type::Position);
origco = (unode) ? reinterpret_cast<float(*)[3]>(unode->position.data()) : nullptr;
use_origco = origco ? true : false;
}
}
if (bke::pbvh::raycast_node(srd->ss->pbvh,
node,
if (bke::pbvh::raycast_node(srd.ss->pbvh,
&node,
origco,
use_origco,
srd->corner_verts,
srd->hide_poly,
srd->ray_start,
srd->ray_normal,
&srd->isect_precalc,
&srd->depth,
&srd->active_vertex,
&srd->active_face_grid_index,
srd->face_normal))
srd.corner_verts,
srd.hide_poly,
srd.ray_start,
srd.ray_normal,
&srd.isect_precalc,
&srd.depth,
&srd.active_vertex,
&srd.active_face_grid_index,
srd.face_normal))
{
srd->hit = true;
*tmin = srd->depth;
srd.hit = true;
*tmin = srd.depth;
}
}
static void sculpt_find_nearest_to_ray_cb(PBVHNode *node, void *data_v, float *tmin)
static void sculpt_find_nearest_to_ray_cb(PBVHNode &node,
SculptFindNearestToRayData &srd,
float *tmin)
{
using namespace blender;
using namespace blender::ed::sculpt_paint;
if (BKE_pbvh_node_get_tmin(node) >= *tmin) {
if (BKE_pbvh_node_get_tmin(&node) >= *tmin) {
return;
}
SculptFindNearestToRayData *srd = static_cast<SculptFindNearestToRayData *>(data_v);
float(*origco)[3] = nullptr;
bool use_origco = false;
if (srd->original && srd->ss->cache) {
if (BKE_pbvh_type(srd->ss->pbvh) == PBVH_BMESH) {
if (srd.original && srd.ss->cache) {
if (BKE_pbvh_type(srd.ss->pbvh) == PBVH_BMESH) {
use_origco = true;
}
else {
/* Intersect with coordinates from before we started stroke. */
undo::Node *unode = undo::get_node(node, undo::Type::Position);
undo::Node *unode = undo::get_node(&node, undo::Type::Position);
origco = (unode) ? reinterpret_cast<float(*)[3]>(unode->position.data()) : nullptr;
use_origco = origco ? true : false;
}
}
if (bke::pbvh::find_nearest_to_ray_node(srd->ss->pbvh,
node,
if (bke::pbvh::find_nearest_to_ray_node(srd.ss->pbvh,
&node,
origco,
use_origco,
srd->corner_verts,
srd->hide_poly,
srd->ray_start,
srd->ray_normal,
&srd->depth,
&srd->dist_sq_to_ray))
srd.corner_verts,
srd.hide_poly,
srd.ray_start,
srd.ray_normal,
&srd.depth,
&srd.dist_sq_to_ray))
{
srd->hit = true;
*tmin = srd->dist_sq_to_ray;
srd.hit = true;
*tmin = srd.dist_sq_to_ray;
}
}
@@ -4935,7 +4935,12 @@ bool SCULPT_cursor_geometry_info_update(bContext *C,
srd.face_normal = face_normal;
isect_ray_tri_watertight_v3_precalc(&srd.isect_precalc, ray_normal);
bke::pbvh::raycast(ss->pbvh, sculpt_raycast_cb, &srd, ray_start, ray_normal, srd.original);
bke::pbvh::raycast(
ss->pbvh,
[&](PBVHNode &node, float *tmin) { sculpt_raycast_cb(node, srd, tmin); },
ray_start,
ray_normal,
srd.original);
/* Cursor is not over the mesh, return default values. */
if (!srd.hit) {
@@ -5082,7 +5087,12 @@ bool SCULPT_stroke_get_location_ex(bContext *C,
srd.face_normal = face_normal;
isect_ray_tri_watertight_v3_precalc(&srd.isect_precalc, ray_normal);
bke::pbvh::raycast(ss->pbvh, sculpt_raycast_cb, &srd, ray_start, ray_normal, srd.original);
bke::pbvh::raycast(
ss->pbvh,
[&](PBVHNode &node, float *tmin) { sculpt_raycast_cb(node, srd, tmin); },
ray_start,
ray_normal,
srd.original);
if (srd.hit) {
hit = true;
copy_v3_v3(out, ray_normal);
@@ -5111,7 +5121,11 @@ bool SCULPT_stroke_get_location_ex(bContext *C,
srd.dist_sq_to_ray = FLT_MAX;
bke::pbvh::find_nearest_to_ray(
ss->pbvh, sculpt_find_nearest_to_ray_cb, &srd, ray_start, ray_normal, srd.original);
ss->pbvh,
[&](PBVHNode &node, float *tmin) { sculpt_find_nearest_to_ray_cb(node, srd, tmin); },
ray_start,
ray_normal,
srd.original);
if (srd.hit && srd.dist_sq_to_ray) {
hit = true;
copy_v3_v3(out, ray_normal);
@@ -6045,7 +6059,12 @@ bool SCULPT_vertex_is_occluded(SculptSession *ss, PBVHVertRef vertex, bool origi
srd.face_normal = face_normal;
isect_ray_tri_watertight_v3_precalc(&srd.isect_precalc, ray_normal);
bke::pbvh::raycast(ss->pbvh, sculpt_raycast_cb, &srd, ray_start, ray_normal, srd.original);
bke::pbvh::raycast(
ss->pbvh,
[&](PBVHNode &node, float *tmin) { sculpt_raycast_cb(node, srd, tmin); },
ray_start,
ray_normal,
srd.original);
return srd.hit;
}

View File

@@ -199,15 +199,14 @@ static void sample_detail_voxel(bContext *C, ViewContext *vc, const int mval[2])
}
}
static void sculpt_raycast_detail_cb(PBVHNode *node, void *data_v, float *tmin)
static void sculpt_raycast_detail_cb(PBVHNode &node, SculptDetailRaycastData &srd, float *tmin)
{
if (BKE_pbvh_node_get_tmin(node) < *tmin) {
SculptDetailRaycastData *srd = static_cast<SculptDetailRaycastData *>(data_v);
if (BKE_pbvh_node_get_tmin(&node) < *tmin) {
if (bke::pbvh::bmesh_node_raycast_detail(
node, srd->ray_start, &srd->isect_precalc, &srd->depth, &srd->edge_length))
&node, srd.ray_start, &srd.isect_precalc, &srd.depth, &srd.edge_length))
{
srd->hit = true;
*tmin = srd->depth;
srd.hit = true;
*tmin = srd.depth;
}
}
}
@@ -232,7 +231,11 @@ static void sample_detail_dyntopo(bContext *C, ViewContext *vc, const int mval[2
isect_ray_tri_watertight_v3_precalc(&srd.isect_precalc, ray_normal);
bke::pbvh::raycast(
ob->sculpt->pbvh, sculpt_raycast_detail_cb, &srd, ray_start, ray_normal, false);
ob->sculpt->pbvh,
[&](PBVHNode &node, float *tmin) { sculpt_raycast_detail_cb(node, srd, tmin); },
ray_start,
ray_normal,
false);
if (srd.hit && srd.edge_length > 0.0f) {
/* Convert edge length to world space detail resolution. */

View File

@@ -290,101 +290,99 @@ struct PartialUpdateData {
Span<bool> modified_face_set_faces;
};
static void update_modified_node_mesh(PBVHNode *node, void *userdata)
static void update_modified_node_mesh(PBVHNode &node, PartialUpdateData &data)
{
PartialUpdateData *data = static_cast<PartialUpdateData *>(userdata);
if (BKE_pbvh_node_has_vert_with_normal_update_tag(data->pbvh, node)) {
BKE_pbvh_node_mark_update(node);
if (BKE_pbvh_node_has_vert_with_normal_update_tag(data.pbvh, &node)) {
BKE_pbvh_node_mark_update(&node);
}
const Span<int> verts = BKE_pbvh_node_get_vert_indices(node);
if (!data->modified_mask_verts.is_empty()) {
const Span<int> verts = BKE_pbvh_node_get_vert_indices(&node);
if (!data.modified_mask_verts.is_empty()) {
for (const int vert : verts) {
if (data->modified_mask_verts[vert]) {
BKE_pbvh_node_mark_update_mask(node);
if (data.modified_mask_verts[vert]) {
BKE_pbvh_node_mark_update_mask(&node);
break;
}
}
}
if (!data->modified_color_verts.is_empty()) {
if (!data.modified_color_verts.is_empty()) {
for (const int vert : verts) {
if (data->modified_color_verts[vert]) {
BKE_pbvh_node_mark_update_color(node);
if (data.modified_color_verts[vert]) {
BKE_pbvh_node_mark_update_color(&node);
break;
}
}
}
if (!data->modified_hidden_verts.is_empty()) {
if (!data.modified_hidden_verts.is_empty()) {
for (const int vert : verts) {
if (data->modified_hidden_verts[vert]) {
BKE_pbvh_node_mark_update_visibility(node);
if (data.modified_hidden_verts[vert]) {
BKE_pbvh_node_mark_update_visibility(&node);
break;
}
}
}
Vector<int> faces;
if (!data->modified_face_set_faces.is_empty()) {
if (!data.modified_face_set_faces.is_empty()) {
if (faces.is_empty()) {
bke::pbvh::node_face_indices_calc_mesh(*data->pbvh, *node, faces);
bke::pbvh::node_face_indices_calc_mesh(*data.pbvh, node, faces);
}
for (const int face : faces) {
if (data->modified_face_set_faces[face]) {
BKE_pbvh_node_mark_update_face_sets(node);
if (data.modified_face_set_faces[face]) {
BKE_pbvh_node_mark_update_face_sets(&node);
break;
}
}
}
if (!data->modified_hidden_faces.is_empty()) {
if (!data.modified_hidden_faces.is_empty()) {
if (faces.is_empty()) {
bke::pbvh::node_face_indices_calc_mesh(*data->pbvh, *node, faces);
bke::pbvh::node_face_indices_calc_mesh(*data.pbvh, node, faces);
}
for (const int face : faces) {
if (data->modified_hidden_faces[face]) {
BKE_pbvh_node_mark_update_visibility(node);
if (data.modified_hidden_faces[face]) {
BKE_pbvh_node_mark_update_visibility(&node);
break;
}
}
}
}
static void update_modified_node_grids(PBVHNode *node, void *userdata)
static void update_modified_node_grids(PBVHNode &node, PartialUpdateData &data)
{
PartialUpdateData *data = static_cast<PartialUpdateData *>(userdata);
const Span<int> grid_indices = BKE_pbvh_node_get_grid_indices(*node);
const Span<int> grid_indices = BKE_pbvh_node_get_grid_indices(node);
if (std::any_of(grid_indices.begin(), grid_indices.end(), [&](const int grid) {
return data->modified_grids[grid];
return data.modified_grids[grid];
}))
{
if (data->changed_position) {
BKE_pbvh_node_mark_update(node);
if (data.changed_position) {
BKE_pbvh_node_mark_update(&node);
}
if (data->changed_mask) {
BKE_pbvh_node_mark_update_mask(node);
if (data.changed_mask) {
BKE_pbvh_node_mark_update_mask(&node);
}
if (data->changed_hide_vert) {
BKE_pbvh_node_mark_update_visibility(node);
if (data.changed_hide_vert) {
BKE_pbvh_node_mark_update_visibility(&node);
}
}
Vector<int> faces;
if (!data->modified_face_set_faces.is_empty()) {
if (!data.modified_face_set_faces.is_empty()) {
if (faces.is_empty()) {
bke::pbvh::node_face_indices_calc_grids(*data->pbvh, *node, faces);
bke::pbvh::node_face_indices_calc_grids(*data.pbvh, node, faces);
}
for (const int face : faces) {
if (data->modified_face_set_faces[face]) {
BKE_pbvh_node_mark_update_face_sets(node);
if (data.modified_face_set_faces[face]) {
BKE_pbvh_node_mark_update_face_sets(&node);
break;
}
}
}
if (!data->modified_hidden_faces.is_empty()) {
if (!data.modified_hidden_faces.is_empty()) {
if (faces.is_empty()) {
bke::pbvh::node_face_indices_calc_grids(*data->pbvh, *node, faces);
bke::pbvh::node_face_indices_calc_grids(*data.pbvh, node, faces);
}
for (const int face : faces) {
if (data->modified_hidden_faces[face]) {
BKE_pbvh_node_mark_update_visibility(node);
if (data.modified_hidden_faces[face]) {
BKE_pbvh_node_mark_update_visibility(&node);
break;
}
}
@@ -1031,10 +1029,12 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, UndoSculpt &usculpt)
data.modified_color_verts = modified_verts_color;
data.modified_face_set_faces = modified_faces_face_set;
if (use_multires_undo) {
bke::pbvh::search_callback(ss->pbvh, {}, update_modified_node_grids, &data);
bke::pbvh::search_callback(
*ss->pbvh, {}, [&](PBVHNode &node) { update_modified_node_grids(node, data); });
}
else {
bke::pbvh::search_callback(ss->pbvh, {}, update_modified_node_mesh, &data);
bke::pbvh::search_callback(
*ss->pbvh, {}, [&](PBVHNode &node) { update_modified_node_mesh(node, data); });
}
if (changed_position) {