20 "Index of nearest element");
21 b.add_output<
decl::Bool>(
"Has Neighbor").field_source_reference_all();
26 KDTree_3d *
tree = BLI_kdtree_3d_new(mask.size());
28 [&](
const int index) { BLI_kdtree_3d_insert(
tree, index, positions[index]); });
29 BLI_kdtree_3d_balance(
tree);
35 return BLI_kdtree_3d_find_nearest_cb_cpp(
39 [index](
const int other,
const float * ,
const float ) {
40 return index == other ? 0 : 1;
49 mask.foreach_index(
GrainSize(1024), [&](
const int index) {
61 : bke::GeometryFieldInput(
CPPType::get<
int>(),
"Index of Nearest"),
62 positions_field_(std::move(positions_field)),
63 group_field_(std::move(group_field))
70 if (!context.attributes()) {
73 const int domain_size = context.attributes()->domain_size(context.domain());
75 evaluator.
add(positions_field_);
76 evaluator.add(group_field_);
79 const VArray<int> group_ids = evaluator.get_evaluated<
int>(1);
83 if (group_ids.is_single()) {
87 BLI_kdtree_3d_free(
tree);
93 const int groups_num = group_indexing.
size();
99 const auto get_group_index = [&](
const int i) {
100 const int group_id = group_ids_span[i];
101 return group_indexing.
index_of(group_id);
105 IndexMask(domain_size), mask_memory, get_group_index, all_indices_by_group_id);
107 if (mask.size() == domain_size) {
108 lookup_indices_by_group_id = all_indices_by_group_id;
113 result.reinitialize(mask.min_array_size());
117 const int avg_tree_size = domain_size / group_indexing.
size();
118 const int grain_size = std::max(8192 / avg_tree_size, 1);
120 for (
const int group_index :
range) {
121 const IndexMask &tree_mask = all_indices_by_group_id[group_index];
122 const IndexMask &lookup_mask = lookup_indices_by_group_id[group_index];
125 BLI_kdtree_3d_free(
tree);
147 return positions_field_ == other_field->positions_field_ &&
148 group_field_ == other_field->group_field_;
165 : bke::GeometryFieldInput(
CPPType::get<bool>(),
"Has Neighbor"),
166 group_field_(std::move(group_field))
173 if (!context.attributes()) {
176 const int domain_size = context.attributes()->domain_size(context.domain());
177 if (domain_size == 1) {
182 evaluator.
add(group_field_);
183 evaluator.evaluate();
184 const VArray<int> group = evaluator.get_evaluated<
int>(0);
186 if (group.is_single()) {
192 mask.foreach_index([&](
const int i) {
194 group_span[i], [](
int *
count) { *
count = 1; }, [](
int *
count) { (*count)++; });
197 mask.foreach_index([&](
const int i) { result[i] = counts.
lookup(group_span[i]) > 1; });
215 return group_field_ == other_field->group_field_;
231 if (
params.output_is_required(
"Index")) {
232 params.set_output(
"Index",
233 Field<int>(std::make_shared<IndexOfNearestFieldInput>(
234 std::move(position_field), group_field)));
237 if (
params.output_is_required(
"Has Neighbor")) {
240 Field<bool>(std::make_shared<HasNeighborFieldInput>(std::move(group_field))));
#define NODE_CLASS_CONVERTER
A KD-tree for nearest neighbor search.
#define NOD_REGISTER_NODE(REGISTER_FUNC)
void reinitialize(const int64_t new_size)
const Value & lookup(const Key &key) const
auto add_or_modify(const Key &key, const CreateValueF &create_value, const ModifyValueF &modify_value) -> decltype(create_value(nullptr))
static VArray ForContainer(ContainerT container)
static VArray ForSingle(T value, const int64_t size)
int64_t index_of(const Key &key) const
int add(GField field, GVArray *varray_ptr)
virtual void for_each_field_input_recursive(FunctionRef< void(const FieldInput &)> fn) const
const FieldNode & node() const
static void from_groups(const IndexMask &universe, IndexMaskMemory &memory, Fn &&get_group_index, MutableSpan< IndexMask > r_masks)
local_group_size(16, 16) .push_constant(Type b
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
std::optional< AttrDomain > try_detect_field_domain(const GeometryComponent &component, const fn::GField &field)
void node_register_type(bNodeType *ntype)
static void find_neighbors(const KDTree_3d &tree, const Span< float3 > positions, const IndexMask &mask, MutableSpan< int > r_indices)
static void node_geo_exec(GeoNodeExecParams params)
static void node_declare(NodeDeclarationBuilder &b)
static void node_register()
static int find_nearest_non_self(const KDTree_3d &tree, const float3 &position, const int index)
static KDTree_3d * build_kdtree(const Span< float3 > positions, const IndexMask &mask)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
uint64_t get_default_hash(const T &v)
void geo_node_type_base(blender::bke::bNodeType *ntype, int type, const char *name, short nclass)
unsigned __int64 uint64_t
NodeGeometryExecFunction geometry_node_execute
NodeDeclareFunction declare