28 .supported_type({GeometryComponent::Type::Mesh, GeometryComponent::Type::PointCloud})
29 .description(
"Geometry to find the closest point on");
34 "Splits the elements of the input geometry into groups which can be sampled "
36 b.add_input<
decl::Vector>(
"Sample Position",
"Source Position")
41 .structure_type(StructureType::Dynamic);
42 b.add_output<
decl::Vector>(
"Position").dependent_field({2, 3}).reference_pass_all();
43 b.add_output<
decl::Float>(
"Distance").dependent_field({2, 3}).reference_pass_all();
45 .dependent_field({2, 3})
47 "Whether the sampling was successful. It can fail when the sampled group is empty");
78 : target_(std::move(target)), type_(type)
80 static const mf::Signature
signature = []() {
82 mf::SignatureBuilder builder{
"Geometry Proximity",
signature};
83 builder.single_input<
float3>(
"Source Position");
84 builder.single_input<
int>(
"Sample ID");
85 builder.single_output<
float3>(
"Position", mf::ParamFlag::SupportsUnusedOutput);
86 builder.single_output<
float>(
"Distance", mf::ParamFlag::SupportsUnusedOutput);
87 builder.single_output<
bool>(
"Is Valid", mf::ParamFlag::SupportsUnusedOutput);
93 const PointCloud &pointcloud = *target_.get_pointcloud();
96 if (target_.has_mesh()) {
97 const Mesh &mesh = *target_.get_mesh();
109 field_evaluator.
add(group_id_field);
115 const int groups_num = group_masks.
size();
118 bvh_trees_.resize(groups_num);
123 for (
const int group_i : range) {
124 const IndexMask &group_mask = group_masks[group_i];
133 [&](
const int group_i) {
return group_masks[group_i].
size(); }, pointcloud.
totpoint));
140 const int domain_size = mesh.
attributes().domain_size(domain);
143 field_evaluator.
add(group_id_field);
149 const int groups_num = group_masks.
size();
152 bvh_trees_.resize(groups_num);
157 for (
const int group_i : range) {
158 const IndexMask &group_mask = group_masks[group_i];
176 [&](
const int group_i) {
return group_masks[group_i].
size(); }, domain_size));
196 0,
"Source Position");
197 const VArray<int> &sample_ids =
params.readonly_single_input<
int>(1,
"Sample ID");
205 mask.foreach_index([&](
const int i) {
206 const float3 sample_position = sample_positions[
i];
207 const int sample_id = sample_ids[
i];
208 const int group_index = group_indices_.index_of_try(sample_id);
209 if (group_index == -1) {
210 if (!positions.is_empty()) {
211 positions[
i] =
float3(0, 0, 0);
213 if (!is_valid_span.is_empty()) {
214 is_valid_span[
i] =
false;
216 if (!distances.is_empty()) {
221 const BVHTrees &trees = bvh_trees_[group_index];
227 if (trees.mesh_bvh.
tree !=
nullptr) {
234 if (trees.pointcloud_bvh.
tree !=
nullptr) {
242 if (!positions.is_empty()) {
243 positions[
i] = nearest.
co;
245 if (!is_valid_span.is_empty()) {
246 is_valid_span[
i] =
true;
248 if (!distances.is_empty()) {
249 distances[
i] = std::sqrt(nearest.
dist_sq);
268 params.set_default_remaining_outputs();
279 std::string error_message;
284 std::make_shared<ProximityFunction>(
285 std::move(target), target_type, std::move(group_id_field)),
286 {&sample_position, &sample_group_id},
291 params.set_default_remaining_outputs();
296 params.set_output(
"Position", std::move(position));
298 params.set_output(
"Is Valid", std::move(is_valid));
308 "Calculate the proximity to the target's points (faster than the other modes)"},
313 "Calculate the proximity to the target's edges"},
318 "Calculate the proximity to the target's faces"},
319 {0,
nullptr, 0,
nullptr,
nullptr},
325 "Element of the target geometry to calculate the distance from",
326 target_element_items,
336 ntype.
ui_name =
"Geometry Proximity";
337 ntype.
ui_description =
"Compute the closest location on the target geometry";
#define NODE_STORAGE_FUNCS(StorageT)
#define NODE_CLASS_GEOMETRY
#define GEO_NODE_PROXIMITY
#define BLI_assert_unreachable()
int BLI_bvhtree_find_nearest(const BVHTree *tree, const float co[3], BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata)
@ NODE_DEFAULT_INPUT_POSITION_FIELD
GeometryNodeProximityTargetType
@ GEO_NODE_PROX_TARGET_EDGES
@ GEO_NODE_PROX_TARGET_POINTS
@ GEO_NODE_PROX_TARGET_FACES
#define NOD_REGISTER_NODE(REGISTER_FUNC)
#define NOD_storage_enum_accessors(member)
static Vector< IndexMask, 4 > from_group_ids(const VArray< int > &group_ids, IndexMaskMemory &memory, VectorSet< int > &r_index_by_group_id)
int add(GField field, GVArray *varray_ptr)
const GVArray & get_evaluated(const int field_index) const
const Signature & signature() const
void set_signature(const Signature *signature)
bool only_realized_data() const
void init_for_pointcloud(const PointCloud &pointcloud, const Field< int > &group_id_field)
~ProximityFunction() override=default
ExecutionHints get_execution_hints() const override
bke::AttrDomain get_domain_on_mesh() const
ProximityFunction(GeometrySet target, GeometryNodeProximityTargetType type, const Field< int > &group_id_field)
void call(const IndexMask &mask, mf::Params params, mf::Context) const override
void init_for_mesh(const Mesh &mesh, const Field< int > &group_id_field)
float distance(VecOp< float, D >, VecOp< float, D >) RET
void * MEM_callocN(size_t len, const char *str)
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
void node_register_type(bNodeType &ntype)
BVHTreeFromMesh bvhtree_from_mesh_edges_init(const Mesh &mesh, const IndexMask &edges_mask)
BVHTreeFromMesh bvhtree_from_mesh_tris_init(const Mesh &mesh, const IndexMask &faces_mask)
BVHTreeFromMesh bvhtree_from_mesh_verts_init(const Mesh &mesh, const IndexMask &verts_mask)
BVHTreeFromPointCloud bvhtree_from_pointcloud_get(const PointCloud &pointcloud, const IndexMask &points_mask)
void node_type_storage(bNodeType &ntype, std::optional< StringRefNull > storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
static void node_geo_exec(GeoNodeExecParams params)
static void node_register()
static void node_declare(NodeDeclarationBuilder &b)
static void node_layout(uiLayout *layout, bContext *, PointerRNA *ptr)
static void node_rna(StructRNA *srna)
static void geo_proximity_init(bNodeTree *, bNode *node)
PropertyRNA * RNA_def_node_enum(StructRNA *srna, const char *identifier, const char *ui_name, const char *ui_description, const EnumPropertyItem *static_items, const EnumRNAAccessors accessors, std::optional< int > default_value, const EnumPropertyItemFunc item_func, const bool allow_animation)
bool execute_multi_function_on_value_variant(const MultiFunction &fn, const std::shared_ptr< MultiFunction > &owned_fn, const Span< SocketValueVariant * > input_values, const Span< SocketValueVariant * > output_values, GeoNodesUserData *user_data, std::string &r_error_message)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
auto individual_task_sizes(Fn &&fn, const std::optional< int64_t > full_size=std::nullopt)
VecBase< float, 3 > float3
void geo_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
void node_free_standard_storage(bNode *node)
void node_copy_standard_storage(bNodeTree *, bNode *dest_node, const bNode *src_node)
BVHTree_NearestPointCallback nearest_callback
BVHTree_NearestPointCallback nearest_callback
bool has_pointcloud() const
void ensure_owns_direct_data()
std::string ui_description
void(* initfunc)(bNodeTree *ntree, bNode *node)
NodeGeometryExecFunction geometry_node_execute
const char * enum_name_legacy
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
NodeDeclareFunction declare
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)