From 87c5423c5e1e7b1907a336ce6b74dfd44bde5526 Mon Sep 17 00:00:00 2001 From: Johnny Matthews Date: Fri, 21 Jan 2022 08:30:02 -0600 Subject: Geometry Nodes: New Output for Number of Mesh Islands Adds a second output to the Mesh Islands node that shows the total number of islands as a field. Differential Revision: https://developer.blender.org/D13700 --- .../geometry/nodes/node_geo_input_mesh_island.cc | 60 +++++++++++++++++++++- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_island.cc b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_island.cc index 629279a44e9..ba4295017bc 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_island.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_island.cc @@ -31,6 +31,9 @@ static void node_declare(NodeDeclarationBuilder &b) .field_source() .description(N_("Island indices are based on the order of the lowest-numbered vertex " "contained in each island")); + b.add_output(N_("Island Count")) + .field_source() + .description(N_("The total number of mesh islands")); } class IslandFieldInput final : public GeometryFieldInput { @@ -81,10 +84,63 @@ class IslandFieldInput final : public GeometryFieldInput { } }; +class IslandCountFieldInput final : public GeometryFieldInput { + public: + IslandCountFieldInput() : GeometryFieldInput(CPPType::get(), "Island Count") + { + category_ = Category::Generated; + } + + GVArray get_varray_for_context(const GeometryComponent &component, + const AttributeDomain domain, + IndexMask UNUSED(mask)) const final + { + if (component.type() != GEO_COMPONENT_TYPE_MESH) { + return {}; + } + const MeshComponent &mesh_component = static_cast(component); + const Mesh *mesh = mesh_component.get_for_read(); + if (mesh == nullptr) { + return {}; + } + + DisjointSet islands(mesh->totvert); + for (const int i : IndexRange(mesh->totedge)) { + islands.join(mesh->medge[i].v1, mesh->medge[i].v2); + } + + Set island_list; + for (const int i_vert : IndexRange(mesh->totvert)) { + const int64_t root = islands.find_root(i_vert); + island_list.add(root); + } + + return VArray::ForSingle(island_list.size(), + mesh_component.attribute_domain_size(domain)); + } + + uint64_t hash() const override + { + /* Some random hash. */ + return 45634572457; + } + + bool is_equal_to(const fn::FieldNode &other) const override + { + return dynamic_cast(&other) != nullptr; + } +}; + static void node_geo_exec(GeoNodeExecParams params) { - Field island_field{std::make_shared()}; - params.set_output("Index", std::move(island_field)); + if (params.output_is_required("Index")) { + Field field{std::make_shared()}; + params.set_output("Index", std::move(field)); + } + if (params.output_is_required("Island Count")) { + Field field{std::make_shared()}; + params.set_output("Island Count", std::move(field)); + } } } // namespace blender::nodes::node_geo_input_mesh_island_cc -- cgit v1.2.3