/* SPDX-License-Identifier: GPL-2.0-or-later */ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "BKE_mesh.h" #include "node_geometry_util.hh" namespace blender::nodes::node_geo_input_mesh_face_neighbors_cc { static void node_declare(NodeDeclarationBuilder &b) { b.add_output(N_("Vertex Count")) .field_source() .description(N_("Number of edges or points in the face")); b.add_output(N_("Face Count")) .field_source() .description(N_("Number of faces which share an edge with the face")); } static VArray construct_neighbor_count_varray(const Mesh &mesh, const eAttrDomain domain) { const Span polys = mesh.polys(); const Span loops = mesh.loops(); Array edge_count(mesh.totedge, 0); for (const MLoop &loop : loops) { edge_count[loop.e]++; } Array poly_count(polys.size(), 0); for (const int poly_index : polys.index_range()) { const MPoly &poly = polys[poly_index]; for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) { poly_count[poly_index] += edge_count[loop.e] - 1; } } return mesh.attributes().adapt_domain( VArray::ForContainer(std::move(poly_count)), ATTR_DOMAIN_FACE, domain); } class FaceNeighborCountFieldInput final : public bke::MeshFieldInput { public: FaceNeighborCountFieldInput() : bke::MeshFieldInput(CPPType::get(), "Face Neighbor Count Field") { category_ = Category::Generated; } GVArray get_varray_for_context(const Mesh &mesh, const eAttrDomain domain, IndexMask UNUSED(mask)) const final { return construct_neighbor_count_varray(mesh, domain); } uint64_t hash() const override { /* Some random constant hash. */ return 823543774; } bool is_equal_to(const fn::FieldNode &other) const override { return dynamic_cast(&other) != nullptr; } }; static VArray construct_vertex_count_varray(const Mesh &mesh, const eAttrDomain domain) { const Span polys = mesh.polys(); return mesh.attributes().adapt_domain( VArray::ForFunc(polys.size(), [polys](const int i) -> float { return polys[i].totloop; }), ATTR_DOMAIN_FACE, domain); } class FaceVertexCountFieldInput final : public bke::MeshFieldInput { public: FaceVertexCountFieldInput() : bke::MeshFieldInput(CPPType::get(), "Vertex Count Field") { category_ = Category::Generated; } GVArray get_varray_for_context(const Mesh &mesh, const eAttrDomain domain, IndexMask UNUSED(mask)) const final { return construct_vertex_count_varray(mesh, domain); } uint64_t hash() const override { /* Some random constant hash. */ return 236235463634; } bool is_equal_to(const fn::FieldNode &other) const override { return dynamic_cast(&other) != nullptr; } }; static void node_geo_exec(GeoNodeExecParams params) { Field vertex_count_field{std::make_shared()}; Field neighbor_count_field{std::make_shared()}; params.set_output("Vertex Count", std::move(vertex_count_field)); params.set_output("Face Count", std::move(neighbor_count_field)); } } // namespace blender::nodes::node_geo_input_mesh_face_neighbors_cc void register_node_type_geo_input_mesh_face_neighbors() { namespace file_ns = blender::nodes::node_geo_input_mesh_face_neighbors_cc; static bNodeType ntype; geo_node_type_base( &ntype, GEO_NODE_INPUT_MESH_FACE_NEIGHBORS, "Face Neighbors", NODE_CLASS_INPUT); node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); ntype.declare = file_ns::node_declare; ntype.geometry_node_execute = file_ns::node_geo_exec; nodeRegisterType(&ntype); }