Blender V4.3
node_geo_instances_to_points.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BLI_array_utils.hh"
6
8
10#include "BKE_instances.hh"
11#include "BKE_pointcloud.hh"
12
13#include "node_geometry_util.hh"
14
16
18{
19 b.add_input<decl::Geometry>("Instances").only_instances();
20 b.add_input<decl::Bool>("Selection").default_value(true).hide_value().field_on_all();
21 b.add_input<decl::Vector>("Position").implicit_field_on_all(implicit_field_inputs::position);
22 b.add_input<decl::Float>("Radius")
23 .default_value(0.05f)
24 .min(0.0f)
26 .field_on_all();
27 b.add_output<decl::Geometry>("Points").propagate_all();
28}
29
30static void convert_instances_to_points(GeometrySet &geometry_set,
31 Field<float3> position_field,
32 Field<float> radius_field,
33 Field<bool> selection_field,
34 const AttributeFilter &attribute_filter)
35{
36 const bke::Instances &instances = *geometry_set.get_instances();
37
38 const bke::InstancesFieldContext context{instances};
39 fn::FieldEvaluator evaluator{context, instances.instances_num()};
40 evaluator.set_selection(std::move(selection_field));
41 evaluator.add(std::move(position_field));
42 evaluator.add(std::move(radius_field));
43 evaluator.evaluate();
44 const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
45 if (selection.is_empty()) {
46 return;
47 }
48 const VArray<float3> positions = evaluator.get_evaluated<float3>(0);
49 const VArray<float> radii = evaluator.get_evaluated<float>(1);
50
51 PointCloud *pointcloud = BKE_pointcloud_new_nomain(selection.size());
52 geometry_set.replace_pointcloud(pointcloud);
53 array_utils::gather(positions, selection, pointcloud->positions_for_write());
54
55 bke::MutableAttributeAccessor dst_attributes = pointcloud->attributes_for_write();
57 dst_attributes.lookup_or_add_for_write_only_span<float>("radius", AttrDomain::Point);
58 array_utils::gather(radii, selection, point_radii.span);
59 point_radii.finish();
60
61 const bke::AttributeAccessor src_attributes = instances.attributes();
62 Map<StringRef, AttributeKind> attributes_to_propagate;
65 false,
66 attribute_filter,
67 attributes_to_propagate);
68 /* These two attributes are added by the implicit inputs above. */
69 attributes_to_propagate.remove("position");
70 attributes_to_propagate.remove("radius");
71
72 for (const auto item : attributes_to_propagate.items()) {
73 const StringRef id = item.key;
74 const eCustomDataType type = item.value.data_type;
75
76 const GAttributeReader src = src_attributes.lookup(id);
77 if (selection.size() == instances.instances_num() && src.sharing_info && src.varray.is_span())
78 {
80 *src.sharing_info);
81 dst_attributes.add(id, AttrDomain::Point, type, init);
82 }
83 else {
85 id, AttrDomain::Point, type);
86 array_utils::gather(src.varray, selection, dst.span);
87 dst.finish();
88 }
89 }
90}
91
93{
94 GeometrySet geometry_set = params.extract_input<GeometrySet>("Instances");
95
96 if (geometry_set.has_instances()) {
97 convert_instances_to_points(geometry_set,
98 params.extract_input<Field<float3>>("Position"),
99 params.extract_input<Field<float>>("Radius"),
100 params.extract_input<Field<bool>>("Selection"),
101 params.get_attribute_filter("Points"));
103 params.set_output("Points", std::move(geometry_set));
104 }
105 else {
106 params.set_default_remaining_outputs();
107 }
108}
109
110static void node_register()
111{
112 static blender::bke::bNodeType ntype;
113
115 &ntype, GEO_NODE_INSTANCES_TO_POINTS, "Instances to Points", NODE_CLASS_GEOMETRY);
116 ntype.declare = node_declare;
119}
121
122} // namespace blender::nodes::node_geo_instances_to_points_cc
#define NODE_CLASS_GEOMETRY
Definition BKE_node.hh:418
General operations for point clouds.
PointCloud * BKE_pointcloud_new_nomain(int totpoint)
#define NOD_REGISTER_NODE(REGISTER_FUNC)
@ PROP_DISTANCE
Definition RNA_types.hh:159
void init()
const void * data() const
bool remove(const Key &key)
Definition BLI_map.hh:344
ItemIterator items() const
Definition BLI_map.hh:864
GAttributeReader lookup(const StringRef attribute_id) const
bool add(const StringRef attribute_id, const AttrDomain domain, const eCustomDataType data_type, const AttributeInit &initializer)
GSpanAttributeWriter lookup_or_add_for_write_only_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type)
void set_selection(Field< bool > selection)
Definition FN_field.hh:385
local_group_size(16, 16) .push_constant(Type b
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void gather(const GVArray &src, const IndexMask &indices, GMutableSpan dst, int64_t grain_size=4096)
void node_register_type(bNodeType *ntype)
Definition node.cc:1708
void position(const bNode &, void *r_value)
static void convert_instances_to_points(GeometrySet &geometry_set, Field< float3 > position_field, Field< float > radius_field, Field< bool > selection_field, const AttributeFilter &attribute_filter)
void geo_node_type_base(blender::bke::bNodeType *ntype, int type, const char *name, short nclass)
const ImplicitSharingInfo * sharing_info
void keep_only(Span< GeometryComponent::Type > component_types)
void gather_attributes_for_propagation(Span< GeometryComponent::Type > component_types, GeometryComponent::Type dst_component_type, bool include_instances, const AttributeFilter &attribute_filter, Map< StringRef, AttributeKind > &r_attributes) const
void replace_pointcloud(PointCloud *pointcloud, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
const Instances * get_instances() const
Defines a node type.
Definition BKE_node.hh:218
NodeGeometryExecFunction geometry_node_execute
Definition BKE_node.hh:339
NodeDeclareFunction declare
Definition BKE_node.hh:347