Welcome to mirror list, hosted at ThFree Co, Russian Federation.

node_geo_mesh_topology_edges_of_corner.cc « nodes « geometry « nodes « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: e46061e0d653d182c96908af5f8fe3e91832b98f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/* 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_edges_of_corner_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_output<decl::Int>(N_("Next Edge Index"))
      .dependent_field()
      .description(
          N_("The edge after the corner in the face, in the direction of increasing indices"));
  b.add_output<decl::Int>(N_("Previous Edge Index"))
      .dependent_field()
      .description(
          N_("The edge before the corner in the face, in the direction of decreasing indices"));
}

static int get_loop_edge(const MLoop &loop)
{
  return loop.e;
}

class CornerNextEdgeFieldInput final : public bke::MeshFieldInput {
 public:
  CornerNextEdgeFieldInput() : bke::MeshFieldInput(CPPType::get<int>(), "Corner Next Edge")
  {
    category_ = Category::Generated;
  }

  GVArray get_varray_for_context(const Mesh &mesh,
                                 const eAttrDomain domain,
                                 const IndexMask /*mask*/) const final
  {
    if (domain != ATTR_DOMAIN_CORNER) {
      return {};
    }
    return VArray<int>::ForDerivedSpan<MLoop, get_loop_edge>(mesh.loops());
  }

  uint64_t hash() const final
  {
    return 1892753404495;
  }

  bool is_equal_to(const fn::FieldNode &other) const final
  {
    if (dynamic_cast<const CornerNextEdgeFieldInput *>(&other)) {
      return true;
    }
    return false;
  }

  std::optional<eAttrDomain> preferred_domain(const Mesh & /*mesh*/) const final
  {
    return ATTR_DOMAIN_CORNER;
  }
};

class CornerPreviousEdgeFieldInput final : public bke::MeshFieldInput {
 public:
  CornerPreviousEdgeFieldInput() : bke::MeshFieldInput(CPPType::get<int>(), "Corner Previous Edge")
  {
    category_ = Category::Generated;
  }

  GVArray get_varray_for_context(const Mesh &mesh,
                                 const eAttrDomain domain,
                                 const IndexMask /*mask*/) const final
  {
    if (domain != ATTR_DOMAIN_CORNER) {
      return {};
    }
    const Span<MPoly> polys = mesh.polys();
    const Span<MLoop> loops = mesh.loops();
    Array<int> loop_to_poly_map = bke::mesh_topology::build_loop_to_poly_map(polys, mesh.totloop);
    return VArray<int>::ForFunc(
        mesh.totloop,
        [polys, loops, loop_to_poly_map = std::move(loop_to_poly_map)](const int corner_i) {
          const int poly_i = loop_to_poly_map[corner_i];
          const MPoly &poly = polys[poly_i];
          const int corner_i_prev = bke::mesh_topology::previous_poly_loop(poly, corner_i);
          return loops[corner_i_prev].e;
        });
  }

  uint64_t hash() const final
  {
    return 987298345762465;
  }

  bool is_equal_to(const fn::FieldNode &other) const final
  {
    if (dynamic_cast<const CornerPreviousEdgeFieldInput *>(&other)) {
      return true;
    }
    return false;
  }

  std::optional<eAttrDomain> preferred_domain(const Mesh & /*mesh*/) const final
  {
    return ATTR_DOMAIN_CORNER;
  }
};

static void node_geo_exec(GeoNodeExecParams params)
{
  const Field<int> corner_index = params.extract_input<Field<int>>("Corner Index");
  if (params.output_is_required("Next Edge Index")) {
    params.set_output("Next Edge Index",
                      Field<int>(std::make_shared<FieldAtIndexInput>(
                          corner_index,
                          Field<int>(std::make_shared<CornerNextEdgeFieldInput>()),
                          ATTR_DOMAIN_CORNER)));
  }
  if (params.output_is_required("Previous Edge Index")) {
    params.set_output("Previous Edge Index",
                      Field<int>(std::make_shared<FieldAtIndexInput>(
                          corner_index,
                          Field<int>(std::make_shared<CornerPreviousEdgeFieldInput>()),
                          ATTR_DOMAIN_CORNER)));
  }
}

}  // namespace blender::nodes::node_geo_mesh_topology_edges_of_corner_cc

void register_node_type_geo_mesh_topology_edges_of_corner()
{
  namespace file_ns = blender::nodes::node_geo_mesh_topology_edges_of_corner_cc;

  static bNodeType ntype;
  geo_node_type_base(
      &ntype, GEO_NODE_MESH_TOPOLOGY_EDGES_OF_CORNER, "Edges of Corner", NODE_CLASS_INPUT);
  ntype.geometry_node_execute = file_ns::node_geo_exec;
  ntype.declare = file_ns::node_declare;
  nodeRegisterType(&ntype);
}