Differential D16029 Diff 56262 source/blender/nodes/geometry/nodes/node_geo_mesh_topology_offset_corner_in_face.cc
Changeset View
Changeset View
Standalone View
Standalone View
source/blender/nodes/geometry/nodes/node_geo_mesh_topology_offset_corner_in_face.cc
- This file was added.
| /* SPDX-License-Identifier: GPL-2.0-or-later */ | |||||
| #include "BKE_mesh.h" | |||||
| #include "BKE_mesh_mapping.h" | |||||
| #include "BLI_task.hh" | |||||
| #include "node_geometry_util.hh" | |||||
| namespace blender::nodes::node_geo_mesh_topology_offset_corner_in_face_cc { | |||||
| static void node_declare(NodeDeclarationBuilder &b) | |||||
| { | |||||
| b.add_input<decl::Int>(N_("Corner Index")) | |||||
| .implicit_field(implicit_field_inputs::index) | |||||
| .description( | |||||
| N_("The corner to retrieve data from. Defaults to the corner from the context")); | |||||
| b.add_input<decl::Int>(N_("Offset")) | |||||
| .supports_field() | |||||
| .description(N_("The number of corners to move around the face before finding the result, " | |||||
| "circling around the start of the face if necessary")); | |||||
| b.add_output<decl::Int>(N_("Corner Index")) | |||||
| .dependent_field() | |||||
| .description(N_("The index of the offset corner")); | |||||
| } | |||||
| class OffsetCornerInFaceFieldInput final : public bke::MeshFieldInput { | |||||
| const Field<int> corner_index_; | |||||
| const Field<int> offset_; | |||||
| public: | |||||
| OffsetCornerInFaceFieldInput(Field<int> corner_index, Field<int> offset) | |||||
| : bke::MeshFieldInput(CPPType::get<int>(), "Offset Corner in Face"), | |||||
| corner_index_(std::move(corner_index)), | |||||
| offset_(std::move(offset)) | |||||
| { | |||||
| category_ = Category::Generated; | |||||
| } | |||||
| GVArray get_varray_for_context(const Mesh &mesh, | |||||
| const eAttrDomain domain, | |||||
| const IndexMask mask) const final | |||||
| { | |||||
| const IndexRange corner_range(mesh.totloop); | |||||
| const Span<MPoly> polys = mesh.polys(); | |||||
| const bke::MeshFieldContext context{mesh, domain}; | |||||
| fn::FieldEvaluator evaluator{context, &mask}; | |||||
| evaluator.add(corner_index_); | |||||
| evaluator.add(offset_); | |||||
| evaluator.evaluate(); | |||||
| const VArray<int> corner_indices = evaluator.get_evaluated<int>(0); | |||||
| const VArray<int> offsets = evaluator.get_evaluated<int>(1); | |||||
| Array<int> corner_to_poly_map = mesh_topology::build_corner_to_poly_map(polys, mesh.totloop); | |||||
| Array<int> offset_corners(mask.min_array_size()); | |||||
| threading::parallel_for(mask.index_range(), 2048, [&](const IndexRange range) { | |||||
| for (const int selection_i : range) { | |||||
| const int corner_i = corner_indices[selection_i]; | |||||
| const int offset = offsets[selection_i]; | |||||
| if (!corner_range.contains(corner_i)) { | |||||
| offset_corners[selection_i] = 0; | |||||
| continue; | |||||
| } | |||||
| const int poly_i = corner_to_poly_map[corner_i]; | |||||
| const IndexRange poly_range(polys[poly_i].loopstart, polys[poly_i].totloop); | |||||
| offset_corners[selection_i] = apply_offset_in_cyclic_range(poly_range, corner_i, offset); | |||||
| } | |||||
| }); | |||||
| return VArray<int>::ForContainer(std::move(offset_corners)); | |||||
| } | |||||
| uint64_t hash() const final | |||||
| { | |||||
| return get_default_hash(offset_); | |||||
| } | |||||
| bool is_equal_to(const fn::FieldNode &other) const final | |||||
| { | |||||
| if (const OffsetCornerInFaceFieldInput *other_field = | |||||
| dynamic_cast<const OffsetCornerInFaceFieldInput *>(&other)) { | |||||
| return other_field->corner_index_ == corner_index_ && other_field->offset_ == offset_; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| }; | |||||
| static void node_geo_exec(GeoNodeExecParams params) | |||||
| { | |||||
| params.set_output("Corner Index", | |||||
| Field<int>(std::make_shared<OffsetCornerInFaceFieldInput>( | |||||
| params.extract_input<Field<int>>("Corner Index"), | |||||
| params.extract_input<Field<int>>("Offset")))); | |||||
| } | |||||
| } // namespace blender::nodes::node_geo_mesh_topology_offset_corner_in_face_cc | |||||
| void register_node_type_geo_mesh_topology_offset_corner_in_face() | |||||
| { | |||||
| namespace file_ns = blender::nodes::node_geo_mesh_topology_offset_corner_in_face_cc; | |||||
| static bNodeType ntype; | |||||
| geo_node_type_base(&ntype, | |||||
| GEO_NODE_MESH_TOPOLOGY_OFFSET_CORNER_IN_FACE, | |||||
| "Offset Corner in Face", | |||||
| NODE_CLASS_INPUT); | |||||
| ntype.geometry_node_execute = file_ns::node_geo_exec; | |||||
| ntype.declare = file_ns::node_declare; | |||||
| nodeRegisterType(&ntype); | |||||
| } | |||||