Blender V4.3
node_geo_uv_pack_islands.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
6
7#include "BKE_mesh.hh"
8
10
12
14{
15 b.add_input<decl::Vector>("UV").hide_value().supports_field();
16 b.add_input<decl::Bool>("Selection")
17 .default_value(true)
18 .hide_value()
19 .supports_field()
20 .description("Faces to consider when packing islands");
21 b.add_input<decl::Float>("Margin").default_value(0.001f).min(0.0f).max(1.0f).description(
22 "Space between islands");
23 b.add_input<decl::Bool>("Rotate").default_value(true).description("Rotate islands for best fit");
24 b.add_output<decl::Vector>("UV").field_source_reference_all();
25}
26
28 const Field<bool> selection_field,
29 const Field<float3> uv_field,
30 const bool rotate,
31 const float margin,
32 const AttrDomain domain)
33{
34 const Span<float3> positions = mesh.vert_positions();
35 const OffsetIndices faces = mesh.faces();
36 const Span<int> corner_verts = mesh.corner_verts();
37
38 const bke::MeshFieldContext face_context{mesh, AttrDomain::Face};
39 FieldEvaluator face_evaluator{face_context, faces.size()};
40 face_evaluator.add(selection_field);
41 face_evaluator.evaluate();
42 const IndexMask selection = face_evaluator.get_evaluated_as_mask(0);
43 if (selection.is_empty()) {
44 return {};
45 }
46
47 const bke::MeshFieldContext corner_context{mesh, AttrDomain::Corner};
48 FieldEvaluator evaluator{corner_context, mesh.corners_num};
49 Array<float3> uv(mesh.corners_num);
50 evaluator.add_with_destination(uv_field, uv.as_mutable_span());
51 evaluator.evaluate();
52
54 selection.foreach_index([&](const int face_index) {
55 const IndexRange face = faces[face_index];
56 Array<geometry::ParamKey, 16> mp_vkeys(face.size());
57 Array<bool, 16> mp_pin(face.size());
58 Array<bool, 16> mp_select(face.size());
59 Array<const float *, 16> mp_co(face.size());
60 Array<float *, 16> mp_uv(face.size());
61 for (const int i : IndexRange(face.size())) {
62 const int corner = face[i];
63 const int vert = corner_verts[corner];
64 mp_vkeys[i] = vert;
65 mp_co[i] = positions[vert];
66 mp_uv[i] = uv[corner];
67 mp_pin[i] = false;
68 mp_select[i] = false;
69 }
71 face_index,
72 face.size(),
73 mp_vkeys.data(),
74 mp_co.data(),
75 mp_uv.data(),
76 nullptr,
77 mp_pin.data(),
78 mp_select.data());
79 });
80 geometry::uv_parametrizer_construct_end(handle, true, true, nullptr);
81
82 geometry::uv_parametrizer_pack(handle, margin, rotate, true);
84 delete (handle);
85
86 return mesh.attributes().adapt_domain<float3>(
87 VArray<float3>::ForContainer(std::move(uv)), AttrDomain::Corner, domain);
88}
89
91 private:
92 const Field<bool> selection_field_;
93 const Field<float3> uv_field_;
94 const bool rotate_;
95 const float margin_;
96
97 public:
98 PackIslandsFieldInput(const Field<bool> selection_field,
99 const Field<float3> uv_field,
100 const bool rotate,
101 const float margin)
102 : bke::MeshFieldInput(CPPType::get<float3>(), "Pack UV Islands Field"),
103 selection_field_(selection_field),
104 uv_field_(uv_field),
105 rotate_(rotate),
106 margin_(margin)
107 {
109 }
110
112 const AttrDomain domain,
113 const IndexMask & /*mask*/) const final
114 {
115 return construct_uv_gvarray(mesh, selection_field_, uv_field_, rotate_, margin_, domain);
116 }
117
118 void for_each_field_input_recursive(FunctionRef<void(const FieldInput &)> fn) const override
119 {
120 selection_field_.node().for_each_field_input_recursive(fn);
121 uv_field_.node().for_each_field_input_recursive(fn);
122 }
123
124 std::optional<AttrDomain> preferred_domain(const Mesh & /*mesh*/) const override
125 {
126 return AttrDomain::Corner;
127 }
128};
129
131{
132 const Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
133 const Field<float3> uv_field = params.extract_input<Field<float3>>("UV");
134 const bool rotate = params.extract_input<bool>("Rotate");
135 const float margin = params.extract_input<float>("Margin");
136 params.set_output("UV",
137 Field<float3>(std::make_shared<PackIslandsFieldInput>(
138 selection_field, uv_field, rotate, margin)));
139}
140
141static void node_register()
142{
143 static blender::bke::bNodeType ntype;
144
145 geo_node_type_base(&ntype, GEO_NODE_UV_PACK_ISLANDS, "Pack UV Islands", NODE_CLASS_CONVERTER);
146 ntype.declare = node_declare;
149}
151
152} // namespace blender::nodes::node_geo_uv_pack_islands_cc
#define NODE_CLASS_CONVERTER
Definition BKE_node.hh:410
#define NOD_REGISTER_NODE(REGISTER_FUNC)
MutableSpan< T > as_mutable_span()
Definition BLI_array.hh:237
const T * data() const
Definition BLI_array.hh:301
static VArray ForContainer(ContainerT container)
int add(GField field, GVArray *varray_ptr)
Definition field.cc:756
virtual void for_each_field_input_recursive(FunctionRef< void(const FieldInput &)> fn) const
Definition field.cc:587
const FieldNode & node() const
Definition FN_field.hh:137
void for_each_field_input_recursive(FunctionRef< void(const FieldInput &)> fn) const override
PackIslandsFieldInput(const Field< bool > selection_field, const Field< float3 > uv_field, const bool rotate, const float margin)
GVArray get_varray_for_context(const Mesh &mesh, const AttrDomain domain, const IndexMask &) const final
std::optional< AttrDomain > preferred_domain(const Mesh &) const override
local_group_size(16, 16) .push_constant(Type b
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void node_register_type(bNodeType *ntype)
Definition node.cc:1708
void uv_parametrizer_construct_end(ParamHandle *phandle, bool fill_holes, bool topology_from_uvs, int *r_count_failed=nullptr)
void uv_parametrizer_flush(ParamHandle *handle)
void uv_parametrizer_pack(ParamHandle *handle, float margin, bool do_rotate, bool ignore_pinned)
void uv_parametrizer_face_add(ParamHandle *handle, const ParamKey key, const int nverts, const ParamKey *vkeys, const float **co, float **uv, const float *weight, const bool *pin, const bool *select)
static void node_geo_exec(GeoNodeExecParams params)
static void node_declare(NodeDeclarationBuilder &b)
static VArray< float3 > construct_uv_gvarray(const Mesh &mesh, const Field< bool > selection_field, const Field< float3 > uv_field, const bool rotate, const float margin, const AttrDomain domain)
void geo_node_type_base(blender::bke::bNodeType *ntype, int type, const char *name, short nclass)
Defines a node type.
Definition BKE_node.hh:218
NodeGeometryExecFunction geometry_node_execute
Definition BKE_node.hh:339
NodeDeclareFunction declare
Definition BKE_node.hh:347