[Bf-blender-cvs] [4593fb52cf8] master: Geometry Nodes: UV Unwrap and Pack Islands Nodes

Aleksi Juvani noreply at git.blender.org
Wed Jun 29 19:34:15 CEST 2022


Commit: 4593fb52cf809de29bffa8f18af9a9a792def30d
Author: Aleksi Juvani
Date:   Wed Jun 29 12:25:20 2022 -0500
Branches: master
https://developer.blender.org/rB4593fb52cf809de29bffa8f18af9a9a792def30d

Geometry Nodes: UV Unwrap and Pack Islands Nodes

This commit adds new Unwrap and Pack Islands nodes, with equivalent
functionality to the existing Unwrap and Pack Islands operators. The
Unwrap node uses generic boolean attributes to determine seams instead
of looking at the seam flags in the mesh geometry.

Unlike the Unwrap operator, the Unwrap node doesn't perform aspect
ratio correction, because this is trivial for the user to implement
with a Vector Math node if it is desired.

The Unwrap node implicitly performs a Pack Islands operation upon
completion, because the results may not be generally useful otherwise.
This matches the behaviour of the Unwrap operator.

The nodes use the existing Vector socket type, and do not introduce a
new 2D Vector type (see T92765).

Differential Revision: https://developer.blender.org/D14389

===================================================================

M	release/scripts/startup/nodeitems_builtins.py
M	source/blender/blenkernel/BKE_node.h
M	source/blender/blenkernel/intern/node.cc
M	source/blender/makesdna/DNA_node_types.h
M	source/blender/makesrna/intern/rna_nodetree.c
M	source/blender/nodes/NOD_geometry.h
M	source/blender/nodes/NOD_static_types.h
M	source/blender/nodes/geometry/CMakeLists.txt
A	source/blender/nodes/geometry/nodes/node_geo_uv_pack_islands.cc
A	source/blender/nodes/geometry/nodes/node_geo_uv_unwrap.cc

===================================================================

diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index 5983596dab1..21bb3d01616 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -157,6 +157,17 @@ def geometry_node_items(context):
     yield NodeItem("GeometryNodeSetPosition")
 
 
+# Custom Menu for UV Nodes.
+def uv_node_items(context):
+    if context is None:
+        return
+    space = context.space_data
+    if not space:
+        return
+    yield NodeItem("GeometryNodeUVUnwrap")
+    yield NodeItem("GeometryNodeUVPackIslands")
+
+
 # Custom Menu for Geometry Node Input Nodes.
 def geometry_input_node_items(context):
     if context is None:
@@ -654,6 +665,7 @@ geometry_node_categories = [
         NodeItem("GeometryNodeCurvePrimitiveBezierSegment"),
     ]),
     GeometryNodeCategory("GEO_GEOMETRY", "Geometry", items=geometry_node_items),
+    GeometryNodeCategory("GEO_UV", "UV", items=uv_node_items),
     GeometryNodeCategory("GEO_INPUT", "Input", items=geometry_input_node_items),
     GeometryNodeCategory("GEO_INSTANCE", "Instances", items=geometry_instance_node_items),
     GeometryNodeCategory("GEO_MATERIAL", "Material", items=geometry_material_node_items),
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index bad3e0005b8..e13ac3180ec 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -1499,6 +1499,8 @@ struct TexResult;
 #define GEO_NODE_POINTS 1162
 #define GEO_NODE_FIELD_ON_DOMAIN 1163
 #define GEO_NODE_MESH_TO_VOLUME 1164
+#define GEO_NODE_UV_UNWRAP 1165
+#define GEO_NODE_UV_PACK_ISLANDS 1166
 
 /** \} */
 
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index 244c9ccd048..5be912ffb2b 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -4841,6 +4841,8 @@ static void registerGeometryNodes()
   register_node_type_geo_viewer();
   register_node_type_geo_volume_cube();
   register_node_type_geo_volume_to_mesh();
+  register_node_type_geo_uv_pack_islands();
+  register_node_type_geo_uv_unwrap();
 }
 
 static void registerFunctionNodes()
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 3f3eb6e0571..76d8207eead 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -1455,6 +1455,11 @@ typedef struct NodeGeometryViewer {
   int8_t data_type;
 } NodeGeometryViewer;
 
+typedef struct NodeGeometryUVUnwrap {
+  /* GeometryNodeUVUnwrapMethod. */
+  uint8_t method;
+} NodeGeometryUVUnwrap;
+
 typedef struct NodeFunctionCompare {
   /* NodeCompareOperation */
   int8_t operation;
@@ -2005,6 +2010,11 @@ typedef enum GeometryNodeMergeByDistanceMode {
   GEO_NODE_MERGE_BY_DISTANCE_MODE_CONNECTED = 1,
 } GeometryNodeMergeByDistanceMode;
 
+typedef enum GeometryNodeUVUnwrapMethod {
+  GEO_NODE_UV_UNWRAP_METHOD_ANGLE_BASED = 0,
+  GEO_NODE_UV_UNWRAP_METHOD_CONFORMAL = 1,
+} GeometryNodeUVUnwrapMethod;
+
 typedef enum GeometryNodeMeshLineMode {
   GEO_NODE_MESH_LINE_MODE_END_POINTS = 0,
   GEO_NODE_MESH_LINE_MODE_OFFSET = 1,
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 0ad109e711f..386ef3f74a3 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -9879,6 +9879,33 @@ static void def_geo_points_to_volume(StructRNA *srna)
   RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
 }
 
+static void def_geo_uv_unwrap(StructRNA *srna)
+{
+  PropertyRNA *prop;
+
+  static EnumPropertyItem rna_node_geometry_uv_unwrap_method_items[] = {
+      {GEO_NODE_UV_UNWRAP_METHOD_ANGLE_BASED,
+       "ANGLE_BASED",
+       0,
+       "Angle Based",
+       "This method gives a good 2D representation of a mesh"},
+      {GEO_NODE_UV_UNWRAP_METHOD_CONFORMAL,
+       "CONFORMAL",
+       0,
+       "Conformal",
+       "Uses LSCM (Least Squares Conformal Mapping). This usually gives a less accurate UV "
+       "mapping than Angle Based, but works better for simpler objects"},
+      {0, NULL, 0, NULL, NULL},
+  };
+
+  RNA_def_struct_sdna_from(srna, "NodeGeometryUVUnwrap", "storage");
+
+  prop = RNA_def_property(srna, "method", PROP_ENUM, PROP_NONE);
+  RNA_def_property_enum_items(prop, rna_node_geometry_uv_unwrap_method_items);
+  RNA_def_property_ui_text(prop, "Method", "");
+  RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+}
+
 static void def_geo_collection_info(StructRNA *srna)
 {
   PropertyRNA *prop;
diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h
index 889ab2a81e4..8f15add33fd 100644
--- a/source/blender/nodes/NOD_geometry.h
+++ b/source/blender/nodes/NOD_geometry.h
@@ -140,6 +140,8 @@ void register_node_type_geo_triangulate(void);
 void register_node_type_geo_viewer(void);
 void register_node_type_geo_volume_cube(void);
 void register_node_type_geo_volume_to_mesh(void);
+void register_node_type_geo_uv_pack_islands(void);
+void register_node_type_geo_uv_unwrap(void);
 
 #ifdef __cplusplus
 }
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index f9925924260..609791ad091 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -402,6 +402,8 @@ DefNode(GeometryNode, GEO_NODE_TRIM_CURVE, def_geo_curve_trim, "TRIM_CURVE", Tri
 DefNode(GeometryNode, GEO_NODE_VIEWER, def_geo_viewer, "VIEWER", Viewer, "Viewer", "")
 DefNode(GeometryNode, GEO_NODE_VOLUME_CUBE, 0, "VOLUME_CUBE", VolumeCube, "Volume Cube", "")
 DefNode(GeometryNode, GEO_NODE_VOLUME_TO_MESH, def_geo_volume_to_mesh, "VOLUME_TO_MESH", VolumeToMesh, "Volume to Mesh", "")
+DefNode(GeometryNode, GEO_NODE_UV_PACK_ISLANDS, 0, "UV_PACK_ISLANDS", UVPackIslands, "Pack UV Islands", "")
+DefNode(GeometryNode, GEO_NODE_UV_UNWRAP, def_geo_uv_unwrap, "UV_UNWRAP", UVUnwrap, "UV Unwrap", "")
 
 /* undefine macros */
 #undef DefNode
diff --git a/source/blender/nodes/geometry/CMakeLists.txt b/source/blender/nodes/geometry/CMakeLists.txt
index 9ef3151ddab..950124f75d0 100644
--- a/source/blender/nodes/geometry/CMakeLists.txt
+++ b/source/blender/nodes/geometry/CMakeLists.txt
@@ -146,6 +146,8 @@ set(SRC
   nodes/node_geo_transform.cc
   nodes/node_geo_translate_instances.cc
   nodes/node_geo_triangulate.cc
+  nodes/node_geo_uv_pack_islands.cc
+  nodes/node_geo_uv_unwrap.cc
   nodes/node_geo_viewer.cc
   nodes/node_geo_volume_cube.cc
   nodes/node_geo_volume_to_mesh.cc
diff --git a/source/blender/nodes/geometry/nodes/node_geo_uv_pack_islands.cc b/source/blender/nodes/geometry/nodes/node_geo_uv_pack_islands.cc
new file mode 100644
index 00000000000..feff6efc3f8
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_uv_pack_islands.cc
@@ -0,0 +1,152 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "GEO_uv_parametrizer.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "node_geometry_util.hh"
+
+namespace blender::nodes::node_geo_uv_pack_islands_cc {
+
+static void node_declare(NodeDeclarationBuilder &b)
+{
+  b.add_input<decl::Vector>(N_("UV")).hide_value().supports_field();
+  b.add_input<decl::Bool>(N_("Selection"))
+      .default_value(true)
+      .hide_value()
+      .supports_field()
+      .description(N_("Faces to consider when packing islands"));
+  b.add_input<decl::Float>(N_("Margin"))
+      .default_value(0.001f)
+      .min(0.0f)
+      .max(1.0f)
+      .description(N_("Space between islands"));
+  b.add_input<decl::Bool>(N_("Rotate"))
+      .default_value(true)
+      .description(N_("Rotate islands for best fit"));
+  b.add_output<decl::Vector>(N_("UV")).field_source();
+}
+
+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)
+{
+  const Mesh *mesh = component.get_for_read();
+  if (mesh == nullptr) {
+    return {};
+  }
+
+  const int face_num = component.attribute_domain_num(ATTR_DOMAIN_FACE);
+  GeometryComponentFieldContext face_context{component, ATTR_DOMAIN_FACE};
+  FieldEvaluator face_evaluator{face_context, face_num};
+  face_evaluator.add(selection_field);
+  face_evaluator.evaluate();
+  const IndexMask selection = face_evaluator.get_evaluated_as_mask(0);
+  if (selection.is_empty()) {
+    return {};
+  }
+
+  const int corner_num = component.attribute_domain_num(ATTR_DOMAIN_CORNER);
+  GeometryComponentFieldContext corner_context{component, ATTR_DOMAIN_CORNER};
+  FieldEvaluator evaluator{corner_context, corner_num};
+  Array<float3> uv(corner_num);
+  evaluator.add_with_destination(uv_field, uv.as_mutable_span());
+  evaluator.evaluate();
+
+  ParamHandle *handle = GEO_uv_parametrizer_construct_begin();
+  for (const int mp_index : selection) {
+    const MPoly &mp = mesh->mpoly[mp_index];
+    Array<ParamKey, 16> mp_vkeys(mp.totloop);
+    Array<bool, 16> mp_pin(mp.totloop);
+    Array<bool, 16> mp_select(mp.totloop);
+    Array<const float *, 16> mp_co(mp.totloop);
+    Array<float *, 16> mp_uv(mp.totloop);
+    for (const int i : IndexRange(mp.totloop)) {
+      const MLoop &ml = mesh->mloop[mp.loopstart + i];
+      mp_vkeys[i] = ml.v;
+      mp_co[i] = mesh->mvert[ml.v].co;
+      mp_uv[i] = uv[mp.loopstart + i];
+      mp_pin[i] = false;
+      mp_select[i] = false;
+    }
+    GEO_uv_parametrizer_face_add(handle,
+                                 mp_index,
+                                 mp.totloop,
+                                 mp_vkeys.data(),
+                                 mp_co.data(),
+                                 mp_uv.data(),
+                                 mp_pin.data(),
+                                 mp_select.data());
+  }
+  GEO_uv_parametrizer_construct_end(handle, true, true, nullptr);

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list