Blender  V3.3
node_geo_uv_pack_islands.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include "GEO_uv_parametrizer.h"
4 
5 #include "DNA_mesh_types.h"
6 #include "DNA_meshdata_types.h"
7 
8 #include "node_geometry_util.hh"
9 
11 
13 {
14  b.add_input<decl::Vector>(N_("UV")).hide_value().supports_field();
15  b.add_input<decl::Bool>(N_("Selection"))
16  .default_value(true)
17  .hide_value()
18  .supports_field()
19  .description(N_("Faces to consider when packing islands"));
20  b.add_input<decl::Float>(N_("Margin"))
21  .default_value(0.001f)
22  .min(0.0f)
23  .max(1.0f)
24  .description(N_("Space between islands"));
25  b.add_input<decl::Bool>(N_("Rotate"))
26  .default_value(true)
27  .description(N_("Rotate islands for best fit"));
28  b.add_output<decl::Vector>(N_("UV")).field_source();
29 }
30 
32  const Field<bool> selection_field,
33  const Field<float3> uv_field,
34  const bool rotate,
35  const float margin,
36  const eAttrDomain domain)
37 {
38  const Mesh *mesh = component.get_for_read();
39  if (mesh == nullptr) {
40  return {};
41  }
42 
43  const int face_num = component.attribute_domain_size(ATTR_DOMAIN_FACE);
45  FieldEvaluator face_evaluator{face_context, face_num};
46  face_evaluator.add(selection_field);
47  face_evaluator.evaluate();
48  const IndexMask selection = face_evaluator.get_evaluated_as_mask(0);
49  if (selection.is_empty()) {
50  return {};
51  }
52 
53  const int corner_num = component.attribute_domain_size(ATTR_DOMAIN_CORNER);
55  FieldEvaluator evaluator{corner_context, corner_num};
56  Array<float3> uv(corner_num);
57  evaluator.add_with_destination(uv_field, uv.as_mutable_span());
58  evaluator.evaluate();
59 
61  for (const int mp_index : selection) {
62  const MPoly &mp = mesh->mpoly[mp_index];
63  Array<ParamKey, 16> mp_vkeys(mp.totloop);
64  Array<bool, 16> mp_pin(mp.totloop);
65  Array<bool, 16> mp_select(mp.totloop);
67  Array<float *, 16> mp_uv(mp.totloop);
68  for (const int i : IndexRange(mp.totloop)) {
69  const MLoop &ml = mesh->mloop[mp.loopstart + i];
70  mp_vkeys[i] = ml.v;
71  mp_co[i] = mesh->mvert[ml.v].co;
72  mp_uv[i] = uv[mp.loopstart + i];
73  mp_pin[i] = false;
74  mp_select[i] = false;
75  }
77  mp_index,
78  mp.totloop,
79  mp_vkeys.data(),
80  mp_co.data(),
81  mp_uv.data(),
82  mp_pin.data(),
83  mp_select.data());
84  }
85  GEO_uv_parametrizer_construct_end(handle, true, true, nullptr);
86 
87  GEO_uv_parametrizer_pack(handle, margin, rotate, true);
90 
91  return component.attributes()->adapt_domain<float3>(
92  VArray<float3>::ForContainer(std::move(uv)), ATTR_DOMAIN_CORNER, domain);
93 }
94 
96  private:
97  const Field<bool> selection_field;
98  const Field<float3> uv_field;
99  const bool rotate;
100  const float margin;
101 
102  public:
103  PackIslandsFieldInput(const Field<bool> selection_field,
104  const Field<float3> uv_field,
105  const bool rotate,
106  const float margin)
107  : GeometryFieldInput(CPPType::get<float3>(), "Pack UV Islands Field"),
108  selection_field(selection_field),
109  uv_field(uv_field),
110  rotate(rotate),
111  margin(margin)
112  {
114  }
115 
117  const eAttrDomain domain,
118  IndexMask UNUSED(mask)) const final
119  {
120  if (component.type() == GEO_COMPONENT_TYPE_MESH) {
121  const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
122  return construct_uv_gvarray(
123  mesh_component, selection_field, uv_field, rotate, margin, domain);
124  }
125  return {};
126  }
127 };
128 
130 {
131  const Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
132  const Field<float3> uv_field = params.extract_input<Field<float3>>("UV");
133  const bool rotate = params.extract_input<bool>("Rotate");
134  const float margin = params.extract_input<float>("Margin");
135  params.set_output("UV",
136  Field<float3>(std::make_shared<PackIslandsFieldInput>(
137  selection_field, uv_field, rotate, margin)));
138 }
139 
140 } // namespace blender::nodes::node_geo_uv_pack_islands_cc
141 
143 {
145 
146  static bNodeType ntype;
147 
151  nodeRegisterType(&ntype);
152 }
eAttrDomain
Definition: BKE_attribute.h:25
@ ATTR_DOMAIN_FACE
Definition: BKE_attribute.h:29
@ ATTR_DOMAIN_CORNER
Definition: BKE_attribute.h:30
@ GEO_COMPONENT_TYPE_MESH
#define NODE_CLASS_CONVERTER
Definition: BKE_node.h:351
#define GEO_NODE_UV_PACK_ISLANDS
Definition: BKE_node.h:1507
void nodeRegisterType(struct bNodeType *ntype)
Definition: node.cc:1357
#define final(a, b, c)
Definition: BLI_hash.h:21
#define UNUSED(x)
static uint8 component(Color32 c, uint i)
Definition: ColorBlock.cpp:108
void GEO_uv_parametrizer_flush(ParamHandle *handle)
ParamHandle * GEO_uv_parametrizer_construct_begin(void)
void GEO_uv_parametrizer_face_add(ParamHandle *handle, const ParamKey key, const int nverts, const ParamKey *vkeys, const float **co, float **uv, const bool *pin, const bool *select)
void GEO_uv_parametrizer_pack(ParamHandle *handle, float margin, bool do_rotate, bool ignore_pinned)
void GEO_uv_parametrizer_construct_end(ParamHandle *handle, bool fill, bool topology_from_uvs, int *count_fail)
void GEO_uv_parametrizer_delete(ParamHandle *handle)
SIMD_FORCE_INLINE btVector3 rotate(const btVector3 &wAxis, const btScalar angle) const
Return a rotated version of this vector.
const T * data() const
Definition: BLI_array.hh:300
MutableSpan< T > as_mutable_span()
Definition: BLI_array.hh:236
bool is_empty() const
static VArray ForContainer(ContainerT container)
int add(GField field, GVArray *varray_ptr)
Definition: field.cc:731
PackIslandsFieldInput(const Field< bool > selection_field, const Field< float3 > uv_field, const bool rotate, const float margin)
GVArray get_varray_for_context(const GeometryComponent &component, const eAttrDomain domain, IndexMask UNUSED(mask)) const final
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
Definition: math_float4.h:513
static void node_geo_exec(GeoNodeExecParams params)
static void node_declare(NodeDeclarationBuilder &b)
static VArray< float3 > construct_uv_gvarray(const MeshComponent &component, const Field< bool > selection_field, const Field< float3 > uv_field, const bool rotate, const float margin, const eAttrDomain domain)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
void register_node_type_geo_uv_pack_islands()
void geo_node_type_base(bNodeType *ntype, int type, const char *name, short nclass)
unsigned int v
float co[3]
struct MVert * mvert
struct MLoop * mloop
struct MPoly * mpoly
Defines a node type.
Definition: BKE_node.h:226
NodeGeometryExecFunction geometry_node_execute
Definition: BKE_node.h:316
NodeDeclareFunction declare
Definition: BKE_node.h:324
#define N_(msgid)