[Bf-blender-cvs] [3af597d16b1] master: Geometry Nodes: Add Instances to Points Node

Jarrett Johnson noreply at git.blender.org
Sat Oct 23 07:03:01 CEST 2021


Commit: 3af597d16b1ed2887df23cc621f0bf7f2b6d4091
Author: Jarrett Johnson
Date:   Sat Oct 23 00:01:59 2021 -0500
Branches: master
https://developer.blender.org/rB3af597d16b1ed2887df23cc621f0bf7f2b6d4091

Geometry Nodes: Add Instances to Points Node

This node takes a geometry set with instances as input and outputs
points located on the origins of the top level of instances in the
geometry set (not nested instances). It also has position and radius
inputs to allow overriding the default, and a selection input to only
generate points for some instances.

The use case for this node is a method to use geometry proximity on
instance origins, but in a more generic way that is flexible and useful
in other situations.

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

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

M	release/scripts/startup/nodeitems_builtins.py
M	source/blender/blenkernel/BKE_node.h
M	source/blender/blenkernel/intern/node.cc
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_instances_to_points.cc

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

diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index c568eef1d95..4d227be50ad 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -695,6 +695,7 @@ geometry_node_categories = [
     GeometryNodeCategory("GEO_INPUT", "Input", items=geometry_input_node_items),
     GeometryNodeCategory("GEO_INSTANCE", "Instances", items=[
         NodeItem("GeometryNodeInstanceOnPoints"),
+        NodeItem("GeometryNodeInstancesToPoints"),
         NodeItem("GeometryNodeRealizeInstances"),
         NodeItem("GeometryNodeRotateInstances"),
         NodeItem("GeometryNodeScaleInstances"),
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 7a9c23d3f54..1280b83b765 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -1546,6 +1546,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
 #define GEO_NODE_CURVE_ENDPOINT_SELECTION 1127
 #define GEO_NODE_RAYCAST 1128
 #define GEO_NODE_CURVE_TO_POINTS 1130
+#define GEO_NODE_INSTANCES_TO_POINTS 1131
 
 /** \} */
 
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index e97b309f75b..bd0f0df6e02 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -5814,6 +5814,7 @@ static void registerGeometryNodes()
   register_node_type_geo_input_spline_resolution();
   register_node_type_geo_input_tangent();
   register_node_type_geo_instance_on_points();
+  register_node_type_geo_instances_to_points();
   register_node_type_geo_is_viewport();
   register_node_type_geo_join_geometry();
   register_node_type_geo_material_replace();
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 3e62fcb47f5..6c6ce821d0e 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -240,6 +240,7 @@ set(SRC
   geometry/nodes/node_geo_input_spline_resolution.cc
   geometry/nodes/node_geo_input_tangent.cc
   geometry/nodes/node_geo_instance_on_points.cc
+  geometry/nodes/node_geo_instances_to_points.cc
   geometry/nodes/node_geo_is_viewport.cc
   geometry/nodes/node_geo_join_geometry.cc
   geometry/nodes/node_geo_material_replace.cc
diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h
index 890825fdcc0..a37dcf28757 100644
--- a/source/blender/nodes/NOD_geometry.h
+++ b/source/blender/nodes/NOD_geometry.h
@@ -108,6 +108,7 @@ void register_node_type_geo_input_spline_length(void);
 void register_node_type_geo_input_spline_resolution(void);
 void register_node_type_geo_input_tangent(void);
 void register_node_type_geo_instance_on_points(void);
+void register_node_type_geo_instances_to_points(void);
 void register_node_type_geo_is_viewport(void);
 void register_node_type_geo_join_geometry(void);
 void register_node_type_geo_material_replace(void);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index 843d414f426..e966839ab27 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -368,6 +368,7 @@ DefNode(GeometryNode, GEO_NODE_INPUT_SPLINE_LENGTH, 0, "SPLINE_LENGTH", SplineLe
 DefNode(GeometryNode, GEO_NODE_INPUT_SPLINE_RESOLUTION, 0, "INPUT_SPLINE_RESOLUTION", InputSplineResolution, "Spline Resolution", "")
 DefNode(GeometryNode, GEO_NODE_INPUT_TANGENT, 0, "INPUT_TANGENT", InputTangent, "Curve Tangent", "")
 DefNode(GeometryNode, GEO_NODE_INSTANCE_ON_POINTS, 0, "INSTANCE_ON_POINTS", InstanceOnPoints, "Instance on Points", "")
+DefNode(GeometryNode, GEO_NODE_INSTANCES_TO_POINTS, 0, "INSTANCES_TO_POINTS", InstancesToPoints, "Instances to Points", "")
 DefNode(GeometryNode, GEO_NODE_IS_VIEWPORT, 0, "IS_VIEWPORT", IsViewport, "Is Viewport", "")
 DefNode(GeometryNode, GEO_NODE_JOIN_GEOMETRY, 0, "JOIN_GEOMETRY", JoinGeometry, "Join Geometry", "")
 DefNode(GeometryNode, GEO_NODE_REPLACE_MATERIAL, 0, "REPLACE_MATERIAL", ReplaceMaterial, "Replace Material", "")
diff --git a/source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc b/source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc
new file mode 100644
index 00000000000..7f9308d43ad
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc
@@ -0,0 +1,117 @@
+/*
+ * 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 "BKE_pointcloud.h"
+#include "DNA_pointcloud_types.h"
+
+#include "node_geometry_util.hh"
+
+namespace blender::nodes {
+
+static void geo_node_instances_to_points_declare(NodeDeclarationBuilder &b)
+{
+  b.add_input<decl::Geometry>("Instances");
+  b.add_input<decl::Bool>("Selection").default_value(true).hide_value().supports_field();
+  b.add_input<decl::Vector>("Position").implicit_field();
+  b.add_input<decl::Float>("Radius")
+      .default_value(0.05f)
+      .min(0.0f)
+      .subtype(PROP_DISTANCE)
+      .supports_field();
+  b.add_output<decl::Geometry>("Points");
+}
+
+template<typename T>
+static void copy_attribute_to_points(const VArray<T> &src,
+                                     const IndexMask mask,
+                                     MutableSpan<T> dst)
+{
+  for (const int i : mask.index_range()) {
+    dst[i] = src[mask[i]];
+  }
+}
+
+static void convert_instances_to_points(GeometrySet &geometry_set,
+                                        Field<float3> position_field,
+                                        Field<float> radius_field,
+                                        const Field<bool> selection_field)
+{
+  const InstancesComponent &instances = *geometry_set.get_component_for_read<InstancesComponent>();
+
+  const AttributeDomain attribute_domain = ATTR_DOMAIN_POINT;
+  GeometryComponentFieldContext field_context{instances, attribute_domain};
+  const int domain_size = instances.attribute_domain_size(attribute_domain);
+
+  fn::FieldEvaluator selection_evaluator{field_context, domain_size};
+  selection_evaluator.add(std::move(selection_field));
+  selection_evaluator.evaluate();
+  const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0);
+  if (selection.is_empty()) {
+    return;
+  }
+
+  PointCloud *pointcloud = BKE_pointcloud_new_nomain(selection.size());
+  geometry_set.replace_pointcloud(pointcloud);
+
+  PointCloudComponent &points = geometry_set.get_component_for_write<PointCloudComponent>();
+
+  fn::FieldEvaluator evaluator{field_context, &selection};
+  evaluator.add(std::move(position_field));
+  evaluator.add(std::move(radius_field));
+  evaluator.evaluate();
+  const VArray<float3> &positions = evaluator.get_evaluated<float3>(0);
+  copy_attribute_to_points(positions, selection, {(float3 *)pointcloud->co, pointcloud->totpoint});
+  const VArray<float> &radii = evaluator.get_evaluated<float>(1);
+  copy_attribute_to_points(radii, selection, {pointcloud->radius, pointcloud->totpoint});
+
+  OutputAttribute_Typed<int> id_attribute = points.attribute_try_get_for_output<int>(
+      "id", ATTR_DOMAIN_POINT, 0);
+  MutableSpan<int> ids = id_attribute.as_span();
+  for (const int64_t i : selection) {
+    ids[i] = instances.instance_ids()[i];
+  }
+  id_attribute.save();
+}
+
+static void geo_node_instances_to_points_exec(GeoNodeExecParams params)
+{
+  GeometrySet geometry_set = params.extract_input<GeometrySet>("Instances");
+
+  if (geometry_set.has_instances()) {
+    convert_instances_to_points(geometry_set,
+                                params.extract_input<Field<float3>>("Position"),
+                                params.extract_input<Field<float>>("Radius"),
+                                params.extract_input<Field<bool>>("Selection"));
+    geometry_set.keep_only({GEO_COMPONENT_TYPE_POINT_CLOUD});
+    params.set_output("Points", std::move(geometry_set));
+  }
+  else {
+    params.set_output("Points", GeometrySet());
+  }
+}
+
+}  // namespace blender::nodes
+
+void register_node_type_geo_instances_to_points()
+{
+  static bNodeType ntype;
+
+  geo_node_type_base(
+      &ntype, GEO_NODE_INSTANCES_TO_POINTS, "Instances to Points", NODE_CLASS_GEOMETRY, 0);
+  ntype.declare = blender::nodes::geo_node_instances_to_points_declare;
+  ntype.geometry_node_execute = blender::nodes::geo_node_instances_to_points_exec;
+  nodeRegisterType(&ntype);
+}



More information about the Bf-blender-cvs mailing list