Blender V5.0
node_geo_edges_to_face_groups.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 "DNA_mesh_types.h"
6
7#include "BKE_mesh_mapping.hh"
8
10
11#include "node_geometry_util.hh"
12
14
16{
17 b.add_input<decl::Bool>("Boundary Edges")
18 .default_value(true)
19 .hide_value()
20 .supports_field()
21 .description("Edges used to split faces into separate groups");
22 b.add_output<decl::Int>("Face Group ID")
23 .field_source_reference_all()
24 .description("Index of the face group inside each boundary edge region");
25}
26
29{
30 for (const int i : indices.index_range().drop_back(1)) {
31 set.join(indices[i], indices[i + 1]);
32 }
33}
34
36 private:
37 Field<bool> non_boundary_edge_field_;
38
39 public:
41 : bke::MeshFieldInput(CPPType::get<int>(), "Edges to Face Groups"),
42 non_boundary_edge_field_(std::move(selection))
43 {
44 }
45
47 const AttrDomain domain,
48 const IndexMask & /*mask*/) const final
49 {
50 const bke::MeshFieldContext context{mesh, AttrDomain::Edge};
51 fn::FieldEvaluator evaluator{context, mesh.edges_num};
52 evaluator.add(non_boundary_edge_field_);
53 evaluator.evaluate();
54 const IndexMask non_boundary_edges = evaluator.get_evaluated_as_mask(0);
55
56 const OffsetIndices faces = mesh.faces();
57
58 Array<int> edge_to_face_offsets;
59 Array<int> edge_to_face_indices;
61 faces, mesh.corner_edges(), mesh.edges_num, edge_to_face_offsets, edge_to_face_indices);
62
63 AtomicDisjointSet islands(faces.size());
64 non_boundary_edges.foreach_index(
65 GrainSize(2048), [&](const int edge) { join_indices(islands, edge_to_face_map[edge]); });
66
67 Array<int> output(faces.size());
68 islands.calc_reduced_ids(output);
69
70 return mesh.attributes().adapt_domain(
71 VArray<int>::from_container(std::move(output)), AttrDomain::Face, domain);
72 }
73
74 uint64_t hash() const override
75 {
76 return non_boundary_edge_field_.hash();
77 }
78
79 bool is_equal_to(const fn::FieldNode &other) const override
80 {
81 if (const auto *other_field = dynamic_cast<const FaceSetFromBoundariesInput *>(&other)) {
82 return other_field->non_boundary_edge_field_ == non_boundary_edge_field_;
83 }
84 return false;
85 }
86
87 std::optional<AttrDomain> preferred_domain(const Mesh & /*mesh*/) const final
88 {
89 return AttrDomain::Face;
90 }
91};
92
94{
95 Field<bool> boundary_edges = params.extract_input<Field<bool>>("Boundary Edges");
96 Field<bool> non_boundary_edges = fn::invert_boolean_field(std::move(boundary_edges));
97 params.set_output(
98 "Face Group ID",
99 Field<int>(std::make_shared<FaceSetFromBoundariesInput>(std::move(non_boundary_edges))));
100}
101
102static void node_register()
103{
104 static blender::bke::bNodeType ntype;
105
106 geo_node_type_base(&ntype, "GeometryNodeEdgesToFaceGroups", GEO_NODE_EDGES_TO_FACE_GROUPS);
107 ntype.ui_name = "Edges to Face Groups";
108 ntype.ui_description = "Group faces into regions surrounded by the selected boundary edges";
109 ntype.enum_name_legacy = "EDGES_TO_FACE_GROUPS";
110 ntype.nclass = NODE_CLASS_INPUT;
112 ntype.declare = node_declare;
113
115}
117
118} // namespace blender::nodes::node_geo_edges_to_face_groups_cc
#define NODE_CLASS_INPUT
Definition BKE_node.hh:447
#define GEO_NODE_EDGES_TO_FACE_GROUPS
#define final(a, b, c)
Definition BLI_hash.h:19
#define NOD_REGISTER_NODE(REGISTER_FUNC)
unsigned long long int uint64_t
int calc_reduced_ids(MutableSpan< int > result) const
static VArray from_container(ContainerT container)
int add(GField field, GVArray *varray_ptr)
Definition field.cc:751
IndexMask get_evaluated_as_mask(int field_index)
Definition field.cc:804
void foreach_index(Fn &&fn) const
GVArray get_varray_for_context(const Mesh &mesh, const AttrDomain domain, const IndexMask &) const final
static ushort indices[]
#define output
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
static char faces[256]
GroupedSpan< int > build_edge_to_face_map(OffsetIndices< int > faces, Span< int > corner_edges, int edges_num, Array< int > &r_offsets, Array< int > &r_indices)
void node_register_type(bNodeType &ntype)
Definition node.cc:2416
Field< bool > invert_boolean_field(const Field< bool > &field)
Definition field.cc:520
static void join_indices(AtomicDisjointSet &set, const Span< int > indices)
void geo_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
Defines a node type.
Definition BKE_node.hh:238
std::string ui_description
Definition BKE_node.hh:244
NodeGeometryExecFunction geometry_node_execute
Definition BKE_node.hh:354
const char * enum_name_legacy
Definition BKE_node.hh:247
NodeDeclareFunction declare
Definition BKE_node.hh:362
i
Definition text_draw.cc:230