[Bf-blender-cvs] [120f16fa1f1] master: Geometry Nodes: Duplicate Elements Node This adds a node which copies part of a geometry a dynamic number of times.

Johnny Matthews noreply at git.blender.org
Wed Feb 23 16:12:34 CET 2022


Commit: 120f16fa1f1efd3cbb4da191d2912e0a6ce3ea59
Author: Johnny Matthews
Date:   Wed Feb 23 09:08:16 2022 -0600
Branches: master
https://developer.blender.org/rB120f16fa1f1efd3cbb4da191d2912e0a6ce3ea59

Geometry Nodes: Duplicate Elements Node
This adds a node which copies part of a geometry a dynamic number
of times.

Different parts of the geometry can be copied differing amounts
of times, controlled by the amount input field. Geometry can also
be ignored by use of the selection input.

The output geometry contains only the copies created by the node.
if the amount input is set to zero, the output geometry will be
empty. The duplicate index output is an integer index with the copy
number of each duplicate.

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

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

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_duplicate_elements.cc

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

diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index 21e20c3b734..cea938bf1a4 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -164,6 +164,7 @@ def geometry_node_items(context):
     yield NodeItem("GeometryNodeBoundBox")
     yield NodeItem("GeometryNodeConvexHull")
     yield NodeItem("GeometryNodeDeleteGeometry")
+    yield NodeItem("GeometryNodeDuplicateElements")
     yield NodeItem("GeometryNodeGeometryToInstance")
     yield NodeItem("GeometryNodeMergeByDistance")
     yield NodeItem("GeometryNodeProximity")
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 933585b1f8f..024e98daea5 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -1515,6 +1515,8 @@ struct TexResult;
 #define GEO_NODE_EXTRUDE_MESH 1152
 #define GEO_NODE_MERGE_BY_DISTANCE 1153
 
+#define GEO_NODE_DUPLICATE_ELEMENTS 1160
+
 /** \} */
 
 /* -------------------------------------------------------------------- */
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index ad24b3c0eff..474859128dc 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -4751,6 +4751,7 @@ static void registerGeometryNodes()
   register_node_type_geo_curve_to_points();
   register_node_type_geo_curve_trim();
   register_node_type_geo_delete_geometry();
+  register_node_type_geo_duplicate_elements();
   register_node_type_geo_distribute_points_on_faces();
   register_node_type_geo_dual_mesh();
   register_node_type_geo_edge_split();
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 963a34aa645..18b79a6fc25 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -1610,6 +1610,11 @@ typedef struct NodeGeometryDeleteGeometry {
   int8_t mode;
 } NodeGeometryDeleteGeometry;
 
+typedef struct NodeGeometryDuplicateElements {
+  /* AttributeDomain. */
+  int8_t domain;
+} NodeGeometryDuplicateElements;
+
 typedef struct NodeGeometrySeparateGeometry {
   /* AttributeDomain. */
   int8_t domain;
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 85bf98914eb..387166e77b4 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -11287,6 +11287,27 @@ static void def_geo_delete_geometry(StructRNA *srna)
   RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
 }
 
+static void def_geo_duplicate_elements(StructRNA *srna)
+{
+  PropertyRNA *prop;
+
+  static const EnumPropertyItem domain_items[] = {
+      {ATTR_DOMAIN_POINT, "POINT", 0, "Point", ""},
+      {ATTR_DOMAIN_EDGE, "EDGE", 0, "Edge", ""},
+      {ATTR_DOMAIN_FACE, "FACE", 0, "Face", ""},
+      {ATTR_DOMAIN_CURVE, "SPLINE", 0, "Spline", ""},
+      {ATTR_DOMAIN_INSTANCE, "INSTANCE", 0, "Instance", ""},
+      {0, NULL, 0, NULL, NULL},
+  };
+  RNA_def_struct_sdna_from(srna, "NodeGeometryDuplicateElements", "storage");
+
+  prop = RNA_def_property(srna, "domain", PROP_ENUM, PROP_NONE);
+  RNA_def_property_enum_items(prop, domain_items);
+  RNA_def_property_enum_default(prop, ATTR_DOMAIN_POINT);
+  RNA_def_property_ui_text(prop, "Domain", "Which domain to duplicate");
+  RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+}
+
 static void def_geo_string_to_curves(StructRNA *srna)
 {
   static const EnumPropertyItem rna_node_geometry_string_to_curves_overflow_items[] = {
diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h
index 86dde999ffc..0a53d9cc019 100644
--- a/source/blender/nodes/NOD_geometry.h
+++ b/source/blender/nodes/NOD_geometry.h
@@ -82,6 +82,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_trim(void);
 void register_node_type_geo_delete_geometry(void);
+void register_node_type_geo_duplicate_elements(void);
 void register_node_type_geo_distribute_points_on_faces(void);
 void register_node_type_geo_dual_mesh(void);
 void register_node_type_geo_edge_split(void);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index 1f1d7e4dc3a..a3033651a3a 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -338,6 +338,7 @@ DefNode(GeometryNode, GEO_NODE_CURVE_SPLINE_TYPE, def_geo_curve_spline_type, "CU
 DefNode(GeometryNode, GEO_NODE_CURVE_TO_MESH, 0, "CURVE_TO_MESH", CurveToMesh, "Curve to Mesh", "")
 DefNode(GeometryNode, GEO_NODE_CURVE_TO_POINTS, def_geo_curve_to_points, "CURVE_TO_POINTS", CurveToPoints, "Curve to Points", "")
 DefNode(GeometryNode, GEO_NODE_DELETE_GEOMETRY, def_geo_delete_geometry, "DELETE_GEOMETRY", DeleteGeometry, "Delete Geometry", "")
+DefNode(GeometryNode, GEO_NODE_DUPLICATE_ELEMENTS, def_geo_duplicate_elements, "DUPLICATE_ELEMENTS", DuplicateElements, "Duplicate Elements", "")
 DefNode(GeometryNode, GEO_NODE_DISTRIBUTE_POINTS_ON_FACES, def_geo_distribute_points_on_faces, "DISTRIBUTE_POINTS_ON_FACES", DistributePointsOnFaces, "Distribute Points on Faces", "")
 DefNode(GeometryNode, GEO_NODE_ACCUMULATE_FIELD, def_geo_accumulate_field, "ACCUMULATE_FIELD", AccumulateField, "Accumulate Field", "")
 DefNode(GeometryNode, GEO_NODE_DUAL_MESH, 0, "DUAL_MESH", DualMesh, "Dual Mesh", "")
diff --git a/source/blender/nodes/geometry/CMakeLists.txt b/source/blender/nodes/geometry/CMakeLists.txt
index f38562a8926..fbf584e0f4b 100644
--- a/source/blender/nodes/geometry/CMakeLists.txt
+++ b/source/blender/nodes/geometry/CMakeLists.txt
@@ -98,6 +98,7 @@ set(SRC
   nodes/node_geo_curve_to_points.cc
   nodes/node_geo_curve_trim.cc
   nodes/node_geo_delete_geometry.cc
+  nodes/node_geo_duplicate_elements.cc
   nodes/node_geo_distribute_points_on_faces.cc
   nodes/node_geo_dual_mesh.cc
   nodes/node_geo_edge_split.cc
diff --git a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc
new file mode 100644
index 00000000000..4c1d26e1012
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc
@@ -0,0 +1,1098 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "BLI_map.hh"
+#include "BLI_noise.hh"
+#include "BLI_span.hh"
+#include "BLI_task.hh"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_pointcloud_types.h"
+
+#include "BKE_attribute_math.hh"
+#include "BKE_mesh.h"
+#include "BKE_pointcloud.h"
+#include "BKE_spline.hh"
+
+#include "node_geometry_util.hh"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+namespace blender::nodes::node_geo_duplicate_elements_cc {
+
+NODE_STORAGE_FUNCS(NodeGeometryDuplicateElements);
+
+static void node_declare(NodeDeclarationBuilder &b)
+{
+  b.add_input<decl::Geometry>(N_("Geometry"));
+  b.add_input<decl::Bool>(N_("Selection")).hide_value().default_value(true).supports_field();
+  b.add_input<decl::Int>(N_("Amount"))
+      .min(0)
+      .default_value(1)
+      .supports_field()
+      .description(N_("The number of duplicates to create for each element"));
+
+  b.add_output<decl::Geometry>(N_("Geometry"))
+      .description(
+          N_("The duplicated geometry only. The output does not contain the original geometry"));
+  b.add_output<decl::Int>(N_("Duplicate Index"))
+      .field_source()
+      .description(N_("The indices of the duplicates for each element"));
+}
+
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
+{
+  NodeGeometryDuplicateElements *data = MEM_cnew<NodeGeometryDuplicateElements>(__func__);
+  data->domain = ATTR_DOMAIN_POINT;
+  node->storage = data;
+}
+
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+  uiItemR(layout, ptr, "domain", 0, "", ICON_NONE);
+}
+
+struct IndexAttributes {
+  StrongAnonymousAttributeID duplicate_index;
+};
+
+/* --------------------------------------------------------------------
+ * Attribute Copy/Creation Functions.
+ */
+
+static void gather_attributes_without_id(const GeometrySet &geometry_set,
+                                         const GeometryComponentType component_type,
+                                         const Span<std::string> skip_attributes,
+                                         const bool include_instances,
+                                         Map<AttributeIDRef, AttributeKind> &r_gathered_attributes)
+{
+  geometry_set.gather_attributes_for_propagation(
+      {component_type}, component_type, include_instances, r_gathered_attributes);
+  for (const std::string &attribute : skip_attributes) {
+    r_gathered_attributes.remove(attribute);
+  }
+  r_gathered_attributes.remove("id");
+};
+
+static IndexRange range_for_offsets_index(const Span<int> offsets, const int index)
+{
+  return {offsets[index], offsets[index + 1] - offsets[index]};
+}
+
+static Array<int> accumulate_counts_to_offsets(const IndexMask selection,
+                                               const VArray<int> &counts)
+{
+  Array<int> offsets(selection.size() + 1);
+  int dst_points_size = 0;
+  for (const int i_point : selection.index_range()) {
+    offsets[i_point] = dst_points_size;
+    dst_points_size += std::max(counts[selection[i_point]], 0);
+  }
+  offsets.last() = dst_points_size;
+  return offsets;
+}
+
+/* Utility functions for threaded copying of attribute data where possible. */
+template<typename T>
+static void threaded_slice_fill(Span<int> offsets, Span<T> src, MutableSpan<T> dst)
+{
+  BLI_assert(offsets.last() == dst.size());
+  threading::parallel_for(IndexRange(offsets.size() - 1), 512, [&](IndexRange range) {
+    for (const int i : range) {
+      dst.slice(offsets[i], offsets[i + 1] - offsets[i]).fill(src[i]);
+    }
+  });
+}
+
+template<typename T>
+static void threaded_mapped_copy(const Span<int> mapping, const Span<T> src, MutableSpan<T> dst)
+{
+  threading::parallel_for(mapping.index_range(), 512, [&](IndexRange range) {
+    for (const int i : range

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list