Blender  V3.3
node_geo_join_geometry.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
4 
5 #include "node_geometry_util.hh"
6 
8 
10 {
11  b.add_input<decl::Geometry>(N_("Geometry")).multi_input();
12  b.add_output<decl::Geometry>(N_("Geometry"));
13 }
14 
15 template<typename Component>
17 {
18  return components;
19 }
20 
22  Span<const GeometryComponent *> components, Span<StringRef> ignored_attributes)
23 {
25 
26  for (const GeometryComponent *component : components) {
27  component->attributes()->for_all(
28  [&](const bke::AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) {
29  if (attribute_id.is_named() && ignored_attributes.contains(attribute_id.name())) {
30  return true;
31  }
32  info.add_or_modify(
33  attribute_id,
34  [&](AttributeMetaData *meta_data_final) { *meta_data_final = meta_data; },
35  [&](AttributeMetaData *meta_data_final) {
36  meta_data_final->data_type = blender::bke::attribute_data_type_highest_complexity(
37  {meta_data_final->data_type, meta_data.data_type});
39  {meta_data_final->domain, meta_data.domain});
40  });
41  return true;
42  });
43  }
44 
45  return info;
46 }
47 
49  const AttributeIDRef &attribute_id,
50  const eCustomDataType data_type,
51  const eAttrDomain domain,
52  GMutableSpan dst_span)
53 {
54  const CPPType *cpp_type = bke::custom_data_type_to_cpp_type(data_type);
55  BLI_assert(cpp_type != nullptr);
56 
57  int offset = 0;
58  for (const GeometryComponent *component : src_components) {
59  const int domain_num = component->attribute_domain_size(domain);
60  if (domain_num == 0) {
61  continue;
62  }
63  GVArray read_attribute = component->attributes()->lookup_or_default(
64  attribute_id, domain, data_type, nullptr);
65 
66  GVArraySpan src_span{read_attribute};
67  const void *src_buffer = src_span.data();
68  void *dst_buffer = dst_span[offset];
69  cpp_type->copy_assign_n(src_buffer, dst_buffer, domain_num);
70 
71  offset += domain_num;
72  }
73 }
74 
77  Span<StringRef> ignored_attributes = {})
78 {
80  ignored_attributes);
81 
82  for (const Map<AttributeIDRef, AttributeMetaData>::Item item : info.items()) {
83  const AttributeIDRef attribute_id = item.key;
84  const AttributeMetaData &meta_data = item.value;
85 
86  GSpanAttributeWriter write_attribute =
87  result.attributes_for_write()->lookup_or_add_for_write_only_span(
88  attribute_id, meta_data.domain, meta_data.data_type);
89  if (!write_attribute) {
90  continue;
91  }
93  src_components, attribute_id, meta_data.data_type, meta_data.domain, write_attribute.span);
94  write_attribute.finish();
95  }
96 }
97 
99 {
100  InstancesComponent &dst_component = result.get_component_for_write<InstancesComponent>();
101 
102  int tot_instances = 0;
103  for (const InstancesComponent *src_component : src_components) {
104  tot_instances += src_component->instances_num();
105  }
106  dst_component.reserve(tot_instances);
107 
108  for (const InstancesComponent *src_component : src_components) {
109  Span<InstanceReference> src_references = src_component->references();
110  Array<int> handle_map(src_references.size());
111  for (const int src_handle : src_references.index_range()) {
112  handle_map[src_handle] = dst_component.add_reference(src_references[src_handle]);
113  }
114 
115  Span<float4x4> src_transforms = src_component->instance_transforms();
116  Span<int> src_reference_handles = src_component->instance_reference_handles();
117 
118  for (const int i : src_transforms.index_range()) {
119  const int src_handle = src_reference_handles[i];
120  const int dst_handle = handle_map[src_handle];
121  const float4x4 &transform = src_transforms[i];
122  dst_component.add_instance(dst_handle, transform);
123  }
124  }
125  join_attributes(to_base_components(src_components), dst_component, {"position"});
126 }
127 
129 {
130  /* Not yet supported. Joining volume grids with the same name requires resampling of at least one
131  * of the grids. The cell size of the resulting volume has to be determined somehow. */
132  VolumeComponent &dst_component = result.get_component_for_write<VolumeComponent>();
133  UNUSED_VARS(src_components, dst_component);
134 }
135 
136 template<typename Component>
137 static void join_component_type(Span<GeometrySet> src_geometry_sets, GeometrySet &result)
138 {
139  Vector<const Component *> components;
140  for (const GeometrySet &geometry_set : src_geometry_sets) {
141  const Component *component = geometry_set.get_component_for_read<Component>();
142  if (component != nullptr && !component->is_empty()) {
143  components.append(component);
144  }
145  }
146 
147  if (components.size() == 0) {
148  return;
149  }
150  if (components.size() == 1) {
151  result.add(*components[0]);
152  return;
153  }
154 
155  GeometrySet instances_geometry_set;
156  InstancesComponent &instances =
157  instances_geometry_set.get_component_for_write<InstancesComponent>();
158 
159  if constexpr (is_same_any_v<Component, InstancesComponent, VolumeComponent>) {
160  join_components(components, result);
161  }
162  else {
163  for (const Component *component : components) {
164  GeometrySet tmp_geo;
165  tmp_geo.add(*component);
166  const int handle = instances.add_reference(InstanceReference{tmp_geo});
167  instances.add_instance(handle, float4x4::identity());
168  }
169 
171  options.keep_original_ids = true;
172  options.realize_instance_attributes = false;
173  GeometrySet joined_components = geometry::realize_instances(instances_geometry_set, options);
174  result.add(joined_components.get_component_for_write<Component>());
175  }
176 }
177 
179 {
180  Vector<GeometrySet> geometry_sets = params.extract_multi_input<GeometrySet>("Geometry");
181 
182  GeometrySet geometry_set_result;
183  join_component_type<MeshComponent>(geometry_sets, geometry_set_result);
184  join_component_type<PointCloudComponent>(geometry_sets, geometry_set_result);
185  join_component_type<InstancesComponent>(geometry_sets, geometry_set_result);
186  join_component_type<VolumeComponent>(geometry_sets, geometry_set_result);
187  join_component_type<CurveComponent>(geometry_sets, geometry_set_result);
188  join_component_type<GeometryComponentEditData>(geometry_sets, geometry_set_result);
189 
190  params.set_output("Geometry", std::move(geometry_set_result));
191 }
192 } // namespace blender::nodes::node_geo_join_geometry_cc
193 
195 {
196  namespace file_ns = blender::nodes::node_geo_join_geometry_cc;
197 
198  static bNodeType ntype;
199 
203  nodeRegisterType(&ntype);
204 }
eAttrDomain
Definition: BKE_attribute.h:25
#define NODE_CLASS_GEOMETRY
Definition: BKE_node.h:359
void nodeRegisterType(struct bNodeType *ntype)
Definition: node.cc:1357
#define GEO_NODE_JOIN_GEOMETRY
Definition: BKE_node.h:1387
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define UNUSED_VARS(...)
static uint8 component(Color32 c, uint i)
Definition: ColorBlock.cpp:108
eCustomDataType
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
int add_reference(const InstanceReference &reference)
void add_instance(int instance_handle, const blender::float4x4 &transform)
void reserve(int min_capacity)
void copy_assign_n(const void *src, void *dst, int64_t n) const
ItemIterator items() const
Definition: BLI_map.hh:859
auto add_or_modify(const Key &key, const CreateValueF &create_value, const ModifyValueF &modify_value) -> decltype(create_value(nullptr))
Definition: BLI_map.hh:436
constexpr int64_t size() const
Definition: BLI_span.hh:240
constexpr IndexRange index_range() const
Definition: BLI_span.hh:401
constexpr bool contains(const T &value) const
Definition: BLI_span.hh:265
int64_t size() const
Definition: BLI_vector.hh:694
void append(const T &value)
Definition: BLI_vector.hh:433
CCL_NAMESPACE_BEGIN struct Options options
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
static int domain_num(const CurvesGeometry &curves, const eAttrDomain domain)
const blender::CPPType * custom_data_type_to_cpp_type(const eCustomDataType type)
Definition: customdata.cc:5312
eAttrDomain attribute_domain_highest_priority(Span< eAttrDomain > domains)
GeometrySet realize_instances(GeometrySet geometry_set, const RealizeInstancesOptions &options)
static void node_geo_exec(GeoNodeExecParams params)
static void fill_new_attribute(Span< const GeometryComponent * > src_components, const AttributeIDRef &attribute_id, const eCustomDataType data_type, const eAttrDomain domain, GMutableSpan dst_span)
static void join_attributes(Span< const GeometryComponent * > src_components, GeometryComponent &result, Span< StringRef > ignored_attributes={})
static void join_component_type(Span< GeometrySet > src_geometry_sets, GeometrySet &result)
static void join_components(Span< const VolumeComponent * > src_components, GeometrySet &result)
static void node_declare(NodeDeclarationBuilder &b)
static Array< const GeometryComponent * > to_base_components(Span< const Component * > components)
static Map< AttributeIDRef, AttributeMetaData > get_final_attribute_info(Span< const GeometryComponent * > components, Span< StringRef > ignored_attributes)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
void register_node_type_geo_join_geometry()
void geo_node_type_base(bNodeType *ntype, int type, const char *name, short nclass)
GeometryComponent & get_component_for_write(GeometryComponentType component_type)
void add(const GeometryComponent &component)
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)