diff options
Diffstat (limited to 'source/blender/nodes')
-rw-r--r-- | source/blender/nodes/geometry/nodes/node_geo_input_mesh_island.cc | 60 |
1 files 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<decl::Int>(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<int>(), "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<const MeshComponent &>(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<int> 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<int>::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<const IslandCountFieldInput *>(&other) != nullptr; + } +}; + static void node_geo_exec(GeoNodeExecParams params) { - Field<int> island_field{std::make_shared<IslandFieldInput>()}; - params.set_output("Index", std::move(island_field)); + if (params.output_is_required("Index")) { + Field<int> field{std::make_shared<IslandFieldInput>()}; + params.set_output("Index", std::move(field)); + } + if (params.output_is_required("Island Count")) { + Field<int> field{std::make_shared<IslandCountFieldInput>()}; + params.set_output("Island Count", std::move(field)); + } } } // namespace blender::nodes::node_geo_input_mesh_island_cc |