[Bf-blender-cvs] [ed4222258ea] master: Geometry Nodes: Add Curve Subdivision Node

Hans Goudey noreply at git.blender.org
Thu Jun 17 18:39:46 CEST 2021


Commit: ed4222258ea6fff51c17a2e244b497f03a8e0162
Author: Hans Goudey
Date:   Thu Jun 17 11:39:23 2021 -0500
Branches: master
https://developer.blender.org/rBed4222258ea6fff51c17a2e244b497f03a8e0162

Geometry Nodes: Add Curve Subdivision Node

This node creates splines with more control points in between the
existing control points. The point is to give the splines more
definition for further tweaking like randomization with white noise,
instead of deforming a resampled poly spline with a noise texture.

For poly splines and NURBS, the node simply interpolates new values
between the existing control points. However, for Bezier splines,
the result follows the existing evaluated shape of the curve, changing
the handle positions and handle types to make that possible.

The number of "cuts" can be controlled by an integer input, or an
attribute can be used. Both spline and point domain attributes are
supported, so the number of cuts can vary using the value from the
point at the start of each segment.

Dynamic curve attributes are interpolated to the result with linear
interpolation.

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

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

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/CMakeLists.txt
M	source/blender/nodes/NOD_geometry.h
M	source/blender/nodes/NOD_static_types.h
A	source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc
M	source/blender/nodes/intern/node_geometry_exec.cc

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

diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index fe788c2575d..e27073bca9b 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -501,6 +501,7 @@ geometry_node_categories = [
         NodeItem("ShaderNodeCombineRGB"),
     ]),
     GeometryNodeCategory("GEO_CURVE", "Curve", items=[
+        NodeItem("GeometryNodeCurveSubdivide"),
         NodeItem("GeometryNodeCurveToMesh"),
         NodeItem("GeometryNodeCurveResample"),
         NodeItem("GeometryNodeMeshToCurve"),
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 5c9d7881093..c7ed12452a5 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -1437,6 +1437,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
 #define GEO_NODE_CURVE_TO_POINTS 1057
 #define GEO_NODE_CURVE_REVERSE 1058
 #define GEO_NODE_SEPARATE_COMPONENTS 1059
+#define GEO_NODE_CURVE_SUBDIVIDE 1060
 
 /** \} */
 
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index d8682473124..3e89be37d2f 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -5058,6 +5058,7 @@ static void registerGeometryNodes()
   register_node_type_geo_curve_to_points();
   register_node_type_geo_curve_resample();
   register_node_type_geo_curve_reverse();
+  register_node_type_geo_curve_subdivide();
   register_node_type_geo_delete_geometry();
   register_node_type_geo_edge_split();
   register_node_type_geo_input_material();
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index e6884f45258..2a5b59f03b1 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -1362,6 +1362,11 @@ typedef struct NodeGeometryCurveResample {
   uint8_t mode;
 } NodeGeometryCurveResample;
 
+typedef struct NodeGeometryCurveSubdivide {
+  /* GeometryNodeAttributeInputMode (integer or attribute). */
+  uint8_t cuts_type;
+} NodeGeometryCurveSubdivide;
+
 typedef struct NodeGeometryCurveToPoints {
   /* GeometryNodeCurveSampleMode. */
   uint8_t mode;
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 17ff997e0df..b96400cda91 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -502,13 +502,11 @@ static const EnumPropertyItem rna_node_geometry_attribute_input_type_items_float
     ITEM_FLOAT,
     {0, NULL, 0, NULL, NULL},
 };
-#  if 0 /* UNUSED */
 static const EnumPropertyItem rna_node_geometry_attribute_input_type_items_int[] = {
     ITEM_ATTRIBUTE,
     ITEM_INTEGER,
     {0, NULL, 0, NULL, NULL},
 };
-#  endif
 static const EnumPropertyItem rna_node_geometry_attribute_input_type_items_no_boolean[] = {
     ITEM_ATTRIBUTE,
     ITEM_FLOAT,
@@ -9861,6 +9859,18 @@ static void def_geo_curve_resample(StructRNA *srna)
   RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
 }
 
+static void def_geo_curve_subdivide(StructRNA *srna)
+{
+  PropertyRNA *prop;
+
+  RNA_def_struct_sdna_from(srna, "NodeGeometryCurveSubdivide", "storage");
+
+  prop = RNA_def_property(srna, "cuts_type", PROP_ENUM, PROP_NONE);
+  RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_int);
+  RNA_def_property_ui_text(prop, "Cuts Type", "");
+  RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
+}
+
 static void def_geo_curve_to_points(StructRNA *srna)
 {
   PropertyRNA *prop;
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index edf471d2ad9..d5ed8317bbb 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -168,6 +168,7 @@ set(SRC
   geometry/nodes/node_geo_curve_to_points.cc
   geometry/nodes/node_geo_curve_resample.cc
   geometry/nodes/node_geo_curve_reverse.cc
+  geometry/nodes/node_geo_curve_subdivide.cc
   geometry/nodes/node_geo_delete_geometry.cc
   geometry/nodes/node_geo_edge_split.cc
   geometry/nodes/node_geo_input_material.cc
diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h
index afb797614e4..5bbdf57f1fa 100644
--- a/source/blender/nodes/NOD_geometry.h
+++ b/source/blender/nodes/NOD_geometry.h
@@ -56,6 +56,7 @@ void register_node_type_geo_curve_to_mesh(void);
 void register_node_type_geo_curve_to_points(void);
 void register_node_type_geo_curve_resample(void);
 void register_node_type_geo_curve_reverse(void);
+void register_node_type_geo_curve_subdivide(void);
 void register_node_type_geo_delete_geometry(void);
 void register_node_type_geo_edge_split(void);
 void register_node_type_geo_input_material(void);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index 0a8c912be04..5e66b72cadb 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -292,6 +292,7 @@ DefNode(GeometryNode, GEO_NODE_COLLECTION_INFO, def_geo_collection_info, "COLLEC
 DefNode(GeometryNode, GEO_NODE_CONVEX_HULL, 0, "CONVEX_HULL", ConvexHull, "Convex Hull", "")
 DefNode(GeometryNode, GEO_NODE_CURVE_LENGTH, 0, "CURVE_LENGTH", CurveLength, "Curve Length", "")
 DefNode(GeometryNode, GEO_NODE_CURVE_RESAMPLE, def_geo_curve_resample, "CURVE_RESAMPLE", CurveResample, "Resample Curve", "")
+DefNode(GeometryNode, GEO_NODE_CURVE_SUBDIVIDE, def_geo_curve_subdivide, "CURVE_SUBDIVIDE", CurveSubdivide, "Curve Subdivide", "")
 DefNode(GeometryNode, GEO_NODE_CURVE_TO_MESH, 0, "CURVE_TO_MESH", CurveToMesh, "Curve to Mesh", "")
 DefNode(GeometryNode, GEO_NODE_CURVE_REVERSE, 0, "CURVE_REVERSE", CurveReverse, "Curve Reverse", "")
 DefNode(GeometryNode, GEO_NODE_CURVE_TO_POINTS, def_geo_curve_to_points, "CURVE_TO_POINTS", CurveToPoints, "Curve to Points", "")
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc
new file mode 100644
index 00000000000..fdb01fa07cf
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc
@@ -0,0 +1,407 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "BLI_task.hh"
+#include "BLI_timeit.hh"
+
+#include "BKE_attribute_math.hh"
+#include "BKE_spline.hh"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "node_geometry_util.hh"
+
+using blender::fn::GVArray_For_GSpan;
+using blender::fn::GVArray_For_Span;
+using blender::fn::GVArray_Typed;
+
+static bNodeSocketTemplate geo_node_curve_subdivide_in[] = {
+    {SOCK_GEOMETRY, N_("Geometry")},
+    {SOCK_STRING, N_("Cuts")},
+    {SOCK_INT, N_("Cuts"), 1, 0, 0, 0, 0, 1000},
+    {-1, ""},
+};
+
+static bNodeSocketTemplate geo_node_curve_subdivide_out[] = {
+    {SOCK_GEOMETRY, N_("Geometry")},
+    {-1, ""},
+};
+
+static void geo_node_curve_subdivide_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+  uiLayoutSetPropSep(layout, true);
+  uiLayoutSetPropDecorate(layout, false);
+  uiItemR(layout, ptr, "cuts_type", 0, IFACE_("Cuts"), ICON_NONE);
+}
+
+static void geo_node_curve_subdivide_init(bNodeTree *UNUSED(tree), bNode *node)
+{
+  NodeGeometryCurveSubdivide *data = (NodeGeometryCurveSubdivide *)MEM_callocN(
+      sizeof(NodeGeometryCurveSubdivide), __func__);
+
+  data->cuts_type = GEO_NODE_ATTRIBUTE_INPUT_INTEGER;
+  node->storage = data;
+}
+
+namespace blender::nodes {
+
+static void geo_node_curve_subdivide_update(bNodeTree *UNUSED(ntree), bNode *node)
+{
+  NodeGeometryPointTranslate &node_storage = *(NodeGeometryPointTranslate *)node->storage;
+
+  update_attribute_input_socket_availabilities(
+      *node, "Cuts", (GeometryNodeAttributeInputMode)node_storage.input_type);
+}
+
+static Array<int> get_subdivided_offsets(const Spline &spline,
+                                         const VArray<int> &cuts,
+                                         const int spline_offset)
+{
+  Array<int> offsets(spline.segments_size() + 1);
+  int offset = 0;
+  for (const int i : IndexRange(spline.segments_size())) {
+    offsets[i] = offset;
+    offset = offset + std::max(cuts[spline_offset + i], 0) + 1;
+  }
+  offsets.last() = offset;
+  return offsets;
+}
+
+template<typename T>
+static void subdivide_attribute(Span<T> src,
+                                const Span<int> offsets,
+                                const bool is_cyclic,
+                                MutableSpan<T> dst)
+{
+  const int src_size = src.size();
+  threading::parallel_for(IndexRange(src_size - 1), 1024, [&](IndexRange range) {
+    for (const int i : range) {
+      const int cuts = offsets[i + 1] - offsets[i];
+      dst[offsets[i]] = src[i];
+      const float factor_delta = 1.0f / (cuts + 1.0f);
+      for (const int cut : IndexRange(cuts)) {
+        const float factor = (cut + 1) * factor_delta;
+        dst[offsets[i] + cut] = attribute_math::mix2(factor, src[i], src[i + 1]);
+      }
+    }
+  });
+
+  if (is_cyclic) {
+    const int i = src_size - 1;
+    const int cuts = offsets[i + 1] - offsets[i];
+    dst[offsets[i]] = src.last();
+    const float factor_delta = 1.0f / (cuts + 1.0f);
+    for (const int cut : IndexRange(cuts)) {
+      const float factor = (cut + 1) * factor_delta;
+      dst[offsets[i] + cut] = attribute_math::mix2(factor, src.last(), src.first());
+    }
+  }
+  else {
+    dst.last() = src.last();
+  }
+}
+
+/**
+ * De Casteljau 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list