From f7933d0744df44c132f8b07b2cb2a8dea13fb30b Mon Sep 17 00:00:00 2001 From: Victor-Louis De Gusseme Date: Fri, 26 Feb 2021 15:23:09 -0600 Subject: Geometry Nodes: Add "Location" output to Attribute Proximity node This patch adds an output field to the Attribute Proximity node and renames the existing string socket from "Result" to "Distance". - The "Distance" output contains distance to the closest position on the Target geometry. - The new "Location" output contains the coordinates of the closest position on the Target geometry. A basic use case for this data is a simple shrinkwrap operation. Differential Revision: https://developer.blender.org/D10415 --- .../geometry/nodes/node_geo_attribute_proximity.cc | 102 ++++++++++++++------- 1 file changed, 70 insertions(+), 32 deletions(-) (limited to 'source/blender/nodes') diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_proximity.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_proximity.cc index 51f208ed07d..2ab76540bdf 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_proximity.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_proximity.cc @@ -31,7 +31,8 @@ static bNodeSocketTemplate geo_node_attribute_proximity_in[] = { {SOCK_GEOMETRY, N_("Geometry")}, {SOCK_GEOMETRY, N_("Target")}, - {SOCK_STRING, N_("Result")}, + {SOCK_STRING, N_("Distance")}, + {SOCK_STRING, N_("Location")}, {-1, ""}, }; @@ -60,50 +61,66 @@ static void geo_attribute_proximity_init(bNodeTree *UNUSED(ntree), bNode *node) namespace blender::nodes { static void proximity_calc(MutableSpan distance_span, + MutableSpan location_span, Span positions, BVHTreeFromMesh &tree_data_mesh, BVHTreeFromPointCloud &tree_data_pointcloud, const bool bvh_mesh_success, - const bool bvh_pointcloud_success) + const bool bvh_pointcloud_success, + const bool store_distances, + const bool store_locations) { - /* The pointcloud loop uses the values already in the span, - * which is only set if the mesh BVH is used (because it's first). */ - if (!bvh_mesh_success) { - distance_span.fill(FLT_MAX); - } - IndexRange range = positions.index_range(); parallel_for(range, 512, [&](IndexRange range) { - BVHTreeNearest nearest; + BVHTreeNearest nearest_from_mesh; + BVHTreeNearest nearest_from_pointcloud; + + copy_v3_fl(nearest_from_mesh.co, FLT_MAX); + copy_v3_fl(nearest_from_pointcloud.co, FLT_MAX); + + nearest_from_mesh.index = -1; + nearest_from_pointcloud.index = -1; - if (bvh_mesh_success) { - copy_v3_fl(nearest.co, FLT_MAX); - nearest.index = -1; + for (int i : range) { + /* Use the distance to the last found point as upper bound to speedup the bvh lookup. */ + nearest_from_mesh.dist_sq = len_squared_v3v3(nearest_from_mesh.co, positions[i]); - for (int i : range) { - nearest.dist_sq = len_squared_v3v3(nearest.co, positions[i]); + if (bvh_mesh_success) { BLI_bvhtree_find_nearest(tree_data_mesh.tree, positions[i], - &nearest, + &nearest_from_mesh, tree_data_mesh.nearest_callback, &tree_data_mesh); - distance_span[i] = sqrtf(nearest.dist_sq); } - } - if (bvh_pointcloud_success) { - copy_v3_fl(nearest.co, FLT_MAX); - nearest.index = -1; + /* Use the distance to the closest point in the mesh to speedup the pointcloud bvh lookup. + * This is ok because we only need to find the closest point in the pointcloud if it's closer + * than the mesh. */ + nearest_from_pointcloud.dist_sq = nearest_from_mesh.dist_sq; - for (int i : range) { - /* Use the distance to the last found point as upper bound to speedup the bvh lookup. */ - nearest.dist_sq = len_squared_v3v3(nearest.co, positions[i]); + if (bvh_pointcloud_success) { BLI_bvhtree_find_nearest(tree_data_pointcloud.tree, positions[i], - &nearest, + &nearest_from_pointcloud, tree_data_pointcloud.nearest_callback, &tree_data_pointcloud); - distance_span[i] = std::min(distance_span[i], sqrtf(nearest.dist_sq)); + } + + if (nearest_from_pointcloud.dist_sq < nearest_from_mesh.dist_sq) { + if (store_distances) { + distance_span[i] = sqrtf(nearest_from_pointcloud.dist_sq); + } + if (store_locations) { + location_span[i] = nearest_from_pointcloud.co; + } + } + else { + if (store_distances) { + distance_span[i] = sqrtf(nearest_from_mesh.dist_sq); + } + if (store_locations) { + location_span[i] = nearest_from_mesh.co; + } } } }); @@ -151,14 +168,18 @@ static void attribute_calc_proximity(GeometryComponent &component, /* This node works on the "point" domain, since that is where positions are stored. */ const AttributeDomain result_domain = ATTR_DOMAIN_POINT; - const std::string result_attribute_name = params.get_input("Result"); + const std::string distance_attribute_name = params.get_input("Distance"); OutputAttributePtr distance_attribute = component.attribute_try_get_for_output( - result_attribute_name, result_domain, CD_PROP_FLOAT); + distance_attribute_name, result_domain, CD_PROP_FLOAT); + + const std::string location_attribute_name = params.get_input("Location"); + OutputAttributePtr location_attribute = component.attribute_try_get_for_output( + location_attribute_name, result_domain, CD_PROP_FLOAT3); ReadAttributePtr position_attribute = component.attribute_try_get_for_read("position"); BLI_assert(position_attribute->custom_data_type() == CD_PROP_FLOAT3); - if (!distance_attribute || !position_attribute) { + if (!position_attribute || (!distance_attribute && !location_attribute)) { return; } @@ -183,12 +204,24 @@ static void attribute_calc_proximity(GeometryComponent &component, tree_data_pointcloud); } - proximity_calc(distance_attribute->get_span_for_write_only(), - position_attribute->get_span(), + Span position_span = position_attribute->get_span(); + + MutableSpan distance_span = distance_attribute ? + distance_attribute->get_span_for_write_only() : + MutableSpan(); + MutableSpan location_span = location_attribute ? + location_attribute->get_span_for_write_only() : + MutableSpan(); + + proximity_calc(distance_span, + location_span, + position_span, tree_data_mesh, tree_data_pointcloud, bvh_mesh_success, - bvh_pointcloud_success); + bvh_pointcloud_success, + distance_attribute, /* Boolean. */ + location_attribute); /* Boolean. */ if (bvh_mesh_success) { free_bvhtree_from_mesh(&tree_data_mesh); @@ -197,7 +230,12 @@ static void attribute_calc_proximity(GeometryComponent &component, free_bvhtree_from_pointcloud(&tree_data_pointcloud); } - distance_attribute.apply_span_and_save(); + if (distance_attribute) { + distance_attribute.apply_span_and_save(); + } + if (location_attribute) { + location_attribute.apply_span_and_save(); + } } static void geo_node_attribute_proximity_exec(GeoNodeExecParams params) -- cgit v1.2.3