diff options
author | Johnny Matthews <johnny.matthews@gmail.com> | 2021-12-08 19:14:03 +0300 |
---|---|---|
committer | Johnny Matthews <johnny.matthews@gmail.com> | 2021-12-08 19:14:03 +0300 |
commit | 069d63561a4ca07aec94ce003d71bd090ebbb887 (patch) | |
tree | f357c4a81a7d25472f1b1d44f85de6b62d5f5111 /source | |
parent | 72b39d3f920072b6a568c63c26e35d444cfcb6f3 (diff) |
Geometry Nodes: Mesh Island Node
This node is a field input that outputs a separate index for each mesh island.
The indices are based on the order of the lowest-numbered vertex in each island.
Authoring help from @hooglyboogly
Differential Revision: https://developer.blender.org/D13504
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_node.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/node.cc | 1 | ||||
-rw-r--r-- | source/blender/nodes/NOD_geometry.h | 1 | ||||
-rw-r--r-- | source/blender/nodes/NOD_static_types.h | 1 | ||||
-rw-r--r-- | source/blender/nodes/geometry/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/nodes/geometry/nodes/node_geo_input_mesh_island.cc | 101 |
6 files changed, 106 insertions, 0 deletions
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 6126aeae422..14a42dc1c83 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -1717,6 +1717,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree, #define GEO_NODE_INPUT_MESH_VERTEX_NEIGHBORS 1141 #define GEO_NODE_GEOMETRY_TO_INSTANCE 1142 #define GEO_NODE_INPUT_MESH_EDGE_NEIGHBORS 1143 +#define GEO_NODE_INPUT_MESH_ISLAND 1144 /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index 4b4c87de9d4..4be374614bb 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -5811,6 +5811,7 @@ static void registerGeometryNodes() register_node_type_geo_input_mesh_edge_vertices(); register_node_type_geo_input_mesh_face_area(); register_node_type_geo_input_mesh_face_neighbors(); + register_node_type_geo_input_mesh_island(); register_node_type_geo_input_mesh_vertex_neighbors(); register_node_type_geo_input_normal(); register_node_type_geo_input_position(); diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h index 6c0385c455c..027180df6e5 100644 --- a/source/blender/nodes/NOD_geometry.h +++ b/source/blender/nodes/NOD_geometry.h @@ -109,6 +109,7 @@ void register_node_type_geo_input_mesh_edge_neighbors(void); void register_node_type_geo_input_mesh_edge_vertices(void); void register_node_type_geo_input_mesh_face_area(void); void register_node_type_geo_input_mesh_face_neighbors(void); +void register_node_type_geo_input_mesh_island(void); void register_node_type_geo_input_mesh_vertex_neighbors(void); void register_node_type_geo_input_normal(void); void register_node_type_geo_input_position(void); diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 27d7837cb11..c2e1d6dd168 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -362,6 +362,7 @@ DefNode(GeometryNode, GEO_NODE_INPUT_MESH_EDGE_NEIGHBORS, 0, "MESH_EDGE_NEIGHBOR DefNode(GeometryNode, GEO_NODE_INPUT_MESH_EDGE_VERTICES, 0, "MESH_EDGE_VERTICES", InputMeshEdgeVertices, "Edge Vertices", "") DefNode(GeometryNode, GEO_NODE_INPUT_MESH_FACE_AREA, 0, "MESH_FACE_AREA", InputMeshFaceArea, "Face Area", "") DefNode(GeometryNode, GEO_NODE_INPUT_MESH_FACE_NEIGHBORS, 0, "MESH_FACE_NEIGHBORS", InputMeshFaceNeighbors, "Face Neighbors", "") +DefNode(GeometryNode, GEO_NODE_INPUT_MESH_ISLAND, 0, "MESH_ISLAND", InputMeshIsland, "Mesh Island", "") DefNode(GeometryNode, GEO_NODE_INPUT_MESH_VERTEX_NEIGHBORS, 0, "MESH_VERTEX_NEIGHBORS", InputMeshVertexNeighbors, "Vertex Neighbors", "") DefNode(GeometryNode, GEO_NODE_INPUT_NORMAL, 0, "INPUT_NORMAL", InputNormal, "Normal", "") DefNode(GeometryNode, GEO_NODE_INPUT_POSITION, 0, "POSITION", InputPosition, "Position", "") diff --git a/source/blender/nodes/geometry/CMakeLists.txt b/source/blender/nodes/geometry/CMakeLists.txt index 19cc23a2013..a81b8cf1afb 100644 --- a/source/blender/nodes/geometry/CMakeLists.txt +++ b/source/blender/nodes/geometry/CMakeLists.txt @@ -127,6 +127,7 @@ set(SRC nodes/node_geo_input_mesh_edge_vertices.cc nodes/node_geo_input_mesh_face_area.cc nodes/node_geo_input_mesh_face_neighbors.cc + nodes/node_geo_input_mesh_island.cc nodes/node_geo_input_mesh_vertex_neighbors.cc nodes/node_geo_input_normal.cc nodes/node_geo_input_position.cc 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 new file mode 100644 index 00000000000..3c713ef6ca9 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_island.cc @@ -0,0 +1,101 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" + +#include "BKE_mesh.h" + +#include "BLI_disjoint_set.hh" + +#include "node_geometry_util.hh" + +namespace blender::nodes::node_geo_input_mesh_island_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_output<decl::Int>(N_("Index")) + .field_source() + .description(N_("Island indices are based on the order of the lowest-numbered vertex " + "contained in each island")); +} + +class IslandFieldInput final : public GeometryFieldInput { + public: + IslandFieldInput() : GeometryFieldInput(CPPType::get<int>(), "Island Index") + { + 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); + } + + Array<int> output(mesh->totvert); + VectorSet<int> ordered_roots; + for (const int i : IndexRange(mesh->totvert)) { + const int64_t root = islands.find_root(i); + output[i] = ordered_roots.index_of_or_add(root); + } + + return mesh_component.attribute_try_adapt_domain<int>( + VArray<int>::ForContainer(std::move(output)), ATTR_DOMAIN_POINT, domain); + } + + uint64_t hash() const override + { + /* Some random constant hash. */ + return 635467354; + } + + bool is_equal_to(const fn::FieldNode &other) const override + { + return dynamic_cast<const IslandFieldInput *>(&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)); +} + +} // namespace blender::nodes::node_geo_input_mesh_island_cc + +void register_node_type_geo_input_mesh_island() +{ + namespace file_ns = blender::nodes::node_geo_input_mesh_island_cc; + + static bNodeType ntype; + geo_node_type_base(&ntype, GEO_NODE_INPUT_MESH_ISLAND, "Mesh Island", NODE_CLASS_INPUT, 0); + ntype.declare = file_ns::node_declare; + ntype.geometry_node_execute = file_ns::node_geo_exec; + nodeRegisterType(&ntype); +} |