Blender  V3.3
node_geo_merge_by_distance.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
5 
6 #include "UI_interface.h"
7 #include "UI_resources.h"
8 
9 #include "node_geometry_util.hh"
10 
12 
14 
16 {
17  b.add_input<decl::Geometry>(N_("Geometry"))
19  b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().supports_field();
20  b.add_input<decl::Float>(N_("Distance")).default_value(0.001f).min(0.0f).subtype(PROP_DISTANCE);
21  b.add_output<decl::Geometry>(N_("Geometry"));
22 }
23 
24 static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
25 {
26  uiLayoutSetPropSep(layout, true);
27  uiLayoutSetPropDecorate(layout, false);
28  uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
29 }
30 
32 {
33  NodeGeometryMergeByDistance *data = MEM_cnew<NodeGeometryMergeByDistance>(__func__);
35  node->storage = data;
36 }
37 
39  const float merge_distance,
40  const Field<bool> &selection_field)
41 {
42  const int src_num = src_points.attribute_domain_size(ATTR_DOMAIN_POINT);
44  FieldEvaluator evaluator{context, src_num};
45  evaluator.add(selection_field);
46  evaluator.evaluate();
47 
48  const IndexMask selection = evaluator.get_evaluated_as_mask(0);
49  if (selection.is_empty()) {
50  return nullptr;
51  }
52 
53  return geometry::point_merge_by_distance(*src_points.get_for_read(), merge_distance, selection);
54 }
55 
56 static std::optional<Mesh *> mesh_merge_by_distance_connected(const MeshComponent &mesh_component,
57  const float merge_distance,
58  const Field<bool> &selection_field)
59 {
60  const int src_num = mesh_component.attribute_domain_size(ATTR_DOMAIN_POINT);
61  Array<bool> selection(src_num);
63  FieldEvaluator evaluator{context, src_num};
64  evaluator.add_with_destination(selection_field, selection.as_mutable_span());
65  evaluator.evaluate();
66 
67  const Mesh &mesh = *mesh_component.get_for_read();
68  return geometry::mesh_merge_by_distance_connected(mesh, selection, merge_distance, false);
69 }
70 
71 static std::optional<Mesh *> mesh_merge_by_distance_all(const MeshComponent &mesh_component,
72  const float merge_distance,
73  const Field<bool> &selection_field)
74 {
75  const int src_num = mesh_component.attribute_domain_size(ATTR_DOMAIN_POINT);
77  FieldEvaluator evaluator{context, src_num};
78  evaluator.add(selection_field);
79  evaluator.evaluate();
80 
81  const IndexMask selection = evaluator.get_evaluated_as_mask(0);
82  if (selection.is_empty()) {
83  return std::nullopt;
84  }
85 
86  const Mesh &mesh = *mesh_component.get_for_read();
87  return geometry::mesh_merge_by_distance_all(mesh, selection, merge_distance);
88 }
89 
91 {
92  const NodeGeometryMergeByDistance &storage = node_storage(params.node());
94 
95  GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
96 
97  const Field<bool> selection = params.extract_input<Field<bool>>("Selection");
98  const float merge_distance = params.extract_input<float>("Distance");
99 
100  geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
101  if (geometry_set.has_pointcloud()) {
103  *geometry_set.get_component_for_read<PointCloudComponent>(), merge_distance, selection);
104  if (result) {
105  geometry_set.replace_pointcloud(result);
106  }
107  }
108  if (geometry_set.has_mesh()) {
110  std::optional<Mesh *> result;
111  switch (mode) {
113  result = mesh_merge_by_distance_all(component, merge_distance, selection);
114  break;
116  result = mesh_merge_by_distance_connected(component, merge_distance, selection);
117  break;
118  default:
120  }
121  if (result) {
122  geometry_set.replace_mesh(*result);
123  }
124  }
125  });
126 
127  params.set_output("Geometry", std::move(geometry_set));
128 }
129 
130 } // namespace blender::nodes::node_geo_merge_by_distance_cc
131 
133 {
135 
136  static bNodeType ntype;
137 
140  node_type_storage(&ntype,
141  "NodeGeometryMergeByDistance",
147  nodeRegisterType(&ntype);
148 }
@ ATTR_DOMAIN_POINT
Definition: BKE_attribute.h:27
@ GEO_COMPONENT_TYPE_MESH
@ GEO_COMPONENT_TYPE_POINT_CLOUD
#define GEO_NODE_MERGE_BY_DISTANCE
Definition: BKE_node.h:1494
#define NODE_STORAGE_FUNCS(StorageT)
Definition: BKE_node.h:1563
void node_type_init(struct bNodeType *ntype, void(*initfunc)(struct bNodeTree *ntree, struct bNode *node))
Definition: node.cc:4390
#define NODE_CLASS_GEOMETRY
Definition: BKE_node.h:359
void node_type_storage(struct bNodeType *ntype, const char *storagename, void(*freefunc)(struct bNode *node), void(*copyfunc)(struct bNodeTree *dest_ntree, struct bNode *dest_node, const struct bNode *src_node))
Definition: node.cc:4426
void nodeRegisterType(struct bNodeType *ntype)
Definition: node.cc:1357
#define BLI_assert_unreachable()
Definition: BLI_assert.h:93
#define UNUSED(x)
static uint8 component(Color32 c, uint i)
Definition: ColorBlock.cpp:108
GeometryNodeMergeByDistanceMode
@ GEO_NODE_MERGE_BY_DISTANCE_MODE_ALL
@ GEO_NODE_MERGE_BY_DISTANCE_MODE_CONNECTED
@ PROP_DISTANCE
Definition: RNA_types.h:149
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
int attribute_domain_size(eAttrDomain domain) const
Definition: geometry_set.cc:63
const Mesh * get_for_read() const
const PointCloud * get_for_read() const
MutableSpan< T > as_mutable_span()
Definition: BLI_array.hh:236
bool is_empty() const
OperationNode * node
void * tree
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
std::optional< Mesh * > mesh_merge_by_distance_connected(const Mesh &mesh, Span< bool > selection, float merge_distance, bool only_loose_edges)
std::optional< Mesh * > mesh_merge_by_distance_all(const Mesh &mesh, IndexMask selection, float merge_distance)
PointCloud * point_merge_by_distance(const PointCloud &src_points, const float merge_distance, const IndexMask selection)
static void node_declare(NodeDeclarationBuilder &b)
static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
static void node_geo_exec(GeoNodeExecParams params)
static void node_init(bNodeTree *UNUSED(tree), bNode *node)
static std::optional< Mesh * > mesh_merge_by_distance_connected(const MeshComponent &mesh_component, const float merge_distance, const Field< bool > &selection_field)
static PointCloud * pointcloud_merge_by_distance(const PointCloudComponent &src_points, const float merge_distance, const Field< bool > &selection_field)
static std::optional< Mesh * > mesh_merge_by_distance_all(const MeshComponent &mesh_component, const float merge_distance, const Field< bool > &selection_field)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
static void node_init(const struct bContext *C, bNodeTree *ntree, bNode *node)
Definition: node.cc:1082
void register_node_type_geo_merge_by_distance()
void geo_node_type_base(bNodeType *ntype, int type, const char *name, short nclass)
void node_copy_standard_storage(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, const bNode *src_node)
Definition: node_util.c:55
void node_free_standard_storage(bNode *node)
Definition: node_util.c:43
void replace_mesh(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
const GeometryComponent * get_component_for_read(GeometryComponentType component_type) const
bool has_mesh() const
void replace_pointcloud(PointCloud *pointcloud, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
bool has_pointcloud() const
Defines a node type.
Definition: BKE_node.h:226
NodeGeometryExecFunction geometry_node_execute
Definition: BKE_node.h:316
void(* draw_buttons)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr)
Definition: BKE_node.h:244
NodeDeclareFunction declare
Definition: BKE_node.h:324
#define N_(msgid)
PointerRNA * ptr
Definition: wm_files.c:3480