diff options
author | Victor-Louis De Gusseme <victorlouis> | 2021-02-27 00:23:09 +0300 |
---|---|---|
committer | Hans Goudey <h.goudey@me.com> | 2021-02-27 00:23:09 +0300 |
commit | f7933d0744df44c132f8b07b2cb2a8dea13fb30b (patch) | |
tree | fa28d36de0a67033569cc02fb0061f70209ead95 /source/blender/nodes | |
parent | e00a87163cfd1b885afb4cb3ddff5f9fe911d2aa (diff) |
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
Diffstat (limited to 'source/blender/nodes')
-rw-r--r-- | source/blender/nodes/geometry/nodes/node_geo_attribute_proximity.cc | 102 |
1 files changed, 70 insertions, 32 deletions
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<float> distance_span, + MutableSpan<float3> location_span, Span<float3> 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<std::string>("Result"); + const std::string distance_attribute_name = params.get_input<std::string>("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<std::string>("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<float>(), - position_attribute->get_span<float3>(), + Span<float3> position_span = position_attribute->get_span<float3>(); + + MutableSpan<float> distance_span = distance_attribute ? + distance_attribute->get_span_for_write_only<float>() : + MutableSpan<float>(); + MutableSpan<float3> location_span = location_attribute ? + location_attribute->get_span_for_write_only<float3>() : + MutableSpan<float3>(); + + 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) |