Blender  V3.3
node_geo_instances_to_points.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include "DNA_pointcloud_types.h"
4 
5 #include "BKE_attribute_math.hh"
6 #include "BKE_pointcloud.h"
7 
8 #include "node_geometry_util.hh"
9 
11 
13 {
14  b.add_input<decl::Geometry>(N_("Instances")).only_instances();
15  b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().supports_field();
16  b.add_input<decl::Vector>(N_("Position")).implicit_field();
17  b.add_input<decl::Float>(N_("Radius"))
18  .default_value(0.05f)
19  .min(0.0f)
20  .subtype(PROP_DISTANCE)
21  .supports_field();
22  b.add_output<decl::Geometry>(N_("Points"));
23 }
24 
25 static void convert_instances_to_points(GeometrySet &geometry_set,
26  Field<float3> position_field,
27  Field<float> radius_field,
28  const Field<bool> selection_field)
29 {
30  const InstancesComponent &instances = *geometry_set.get_component_for_read<InstancesComponent>();
31 
32  GeometryComponentFieldContext field_context{instances, ATTR_DOMAIN_INSTANCE};
33  const int domain_size = instances.instances_num();
34 
35  fn::FieldEvaluator evaluator{field_context, domain_size};
36  evaluator.set_selection(std::move(selection_field));
37  evaluator.add(std::move(position_field));
38  evaluator.add(std::move(radius_field));
39  evaluator.evaluate();
40  const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
41  if (selection.is_empty()) {
42  return;
43  }
44  const VArray<float3> &positions = evaluator.get_evaluated<float3>(0);
45  const VArray<float> radii = evaluator.get_evaluated<float>(1);
46 
47  PointCloud *pointcloud = BKE_pointcloud_new_nomain(selection.size());
48  geometry_set.replace_pointcloud(pointcloud);
49 
51  *pointcloud);
52 
53  bke::SpanAttributeWriter<float3> point_positions =
54  point_attributes.lookup_or_add_for_write_only_span<float3>("position", ATTR_DOMAIN_POINT);
56  point_attributes.lookup_or_add_for_write_only_span<float>("radius", ATTR_DOMAIN_POINT);
57 
58  positions.materialize_compressed_to_uninitialized(selection, point_positions.span);
59  radii.materialize_compressed_to_uninitialized(selection, point_radii.span);
60  point_positions.finish();
61  point_radii.finish();
62 
63  Map<AttributeIDRef, AttributeKind> attributes_to_propagate;
66  false,
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 AttributeIDRef &attribute_id = item.key;
74  const AttributeKind attribute_kind = item.value;
75 
76  const GVArray src = instances.attributes()->lookup_or_default(
77  attribute_id, ATTR_DOMAIN_INSTANCE, attribute_kind.data_type);
78  BLI_assert(src);
79  GSpanAttributeWriter dst = point_attributes.lookup_or_add_for_write_only_span(
80  attribute_id, ATTR_DOMAIN_POINT, attribute_kind.data_type);
81  BLI_assert(dst);
82 
83  src.materialize_compressed_to_uninitialized(selection, dst.span.data());
84  dst.finish();
85  }
86 }
87 
89 {
90  GeometrySet geometry_set = params.extract_input<GeometrySet>("Instances");
91 
92  if (geometry_set.has_instances()) {
93  convert_instances_to_points(geometry_set,
94  params.extract_input<Field<float3>>("Position"),
95  params.extract_input<Field<float>>("Radius"),
96  params.extract_input<Field<bool>>("Selection"));
98  params.set_output("Points", std::move(geometry_set));
99  }
100  else {
101  params.set_default_remaining_outputs();
102  }
103 }
104 
105 } // namespace blender::nodes::node_geo_instances_to_points_cc
106 
108 {
110 
111  static bNodeType ntype;
112 
114  &ntype, GEO_NODE_INSTANCES_TO_POINTS, "Instances to Points", NODE_CLASS_GEOMETRY);
117  nodeRegisterType(&ntype);
118 }
@ ATTR_DOMAIN_INSTANCE
Definition: BKE_attribute.h:32
@ ATTR_DOMAIN_POINT
Definition: BKE_attribute.h:27
@ GEO_COMPONENT_TYPE_POINT_CLOUD
@ GEO_COMPONENT_TYPE_INSTANCES
@ GEO_COMPONENT_TYPE_EDIT
#define NODE_CLASS_GEOMETRY
Definition: BKE_node.h:359
#define GEO_NODE_INSTANCES_TO_POINTS
Definition: BKE_node.h:1472
void nodeRegisterType(struct bNodeType *ntype)
Definition: node.cc:1357
General operations for point clouds.
struct PointCloud * BKE_pointcloud_new_nomain(int totpoint)
Definition: pointcloud.cc:243
#define BLI_assert(a)
Definition: BLI_assert.h:46
@ PROP_DISTANCE
Definition: RNA_types.h:149
std::optional< blender::bke::AttributeAccessor > attributes() const final
int64_t size() const
bool is_empty() const
bool remove(const Key &key)
Definition: BLI_map.hh:323
ItemIterator items() const
Definition: BLI_map.hh:859
void set_selection(Field< bool > selection)
Definition: FN_field.hh:366
SyclQueue void void * src
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
MutableAttributeAccessor pointcloud_attributes_for_write(PointCloud &pointcloud)
static void convert_instances_to_points(GeometrySet &geometry_set, Field< float3 > position_field, Field< float > radius_field, const Field< bool > selection_field)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
MutableSpan< float3 > positions
Map< AttributeIDRef, GMutableSpan > point_attributes
MutableSpan< float > radii
void register_node_type_geo_instances_to_points()
void geo_node_type_base(bNodeType *ntype, int type, const char *name, short nclass)
const GeometryComponent * get_component_for_read(GeometryComponentType component_type) const
void gather_attributes_for_propagation(blender::Span< GeometryComponentType > component_types, GeometryComponentType dst_component_type, bool include_instances, blender::Map< blender::bke::AttributeIDRef, blender::bke::AttributeKind > &r_attributes) const
bool has_instances() const
void keep_only(const blender::Span< GeometryComponentType > component_types)
void replace_pointcloud(PointCloud *pointcloud, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
Defines a node type.
Definition: BKE_node.h:226
NodeGeometryExecFunction geometry_node_execute
Definition: BKE_node.h:316
NodeDeclareFunction declare
Definition: BKE_node.h:324
#define N_(msgid)