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
This commit is contained in:
Johnny Matthews 2022-01-21 08:30:02 -06:00
parent d68ce0e475
commit 87c5423c5e
1 changed files with 58 additions and 2 deletions

View File

@ -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