[Bf-blender-cvs] [a108f2462f2] temp-geometry-nodes-instances-api-v2: Rewrite point separate node to support instances (untested)

Hans Goudey noreply at git.blender.org
Mon Feb 15 04:16:28 CET 2021


Commit: a108f2462f214cf7d4c8fda325d3e2ba92666b91
Author: Hans Goudey
Date:   Sun Feb 14 21:12:04 2021 -0600
Branches: temp-geometry-nodes-instances-api-v2
https://developer.blender.org/rBa108f2462f214cf7d4c8fda325d3e2ba92666b91

Rewrite point separate node to support instances (untested)

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

M	source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc
M	source/blender/nodes/geometry/nodes/node_geo_point_separate.cc

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

diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc
index 91b6bbdafc3..dc924ede3a1 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc
@@ -279,8 +279,6 @@ static void geo_node_random_attribute_exec(GeoNodeExecParams params)
 
   geometry_set = geometry_set_realize_instances(geometry_set);
 
-  geometry_set_realize_instances_for_write(geometry_set);
-
   if (geometry_set.has<MeshComponent>()) {
     randomize_attribute_on_component(geometry_set.get_component_for_write<MeshComponent>(),
                                      params,
diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_separate.cc b/source/blender/nodes/geometry/nodes/node_geo_point_separate.cc
index 8bb8c5e980a..dd587b6bea9 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_point_separate.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_point_separate.cc
@@ -14,6 +14,7 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
+#include "BKE_attribute_math.hh"
 #include "BKE_mesh.h"
 #include "BKE_persistent_data_handle.hh"
 #include "BKE_pointcloud.h"
@@ -38,163 +39,240 @@ static bNodeSocketTemplate geo_node_point_instance_out[] = {
 
 namespace blender::nodes {
 
-static void fill_new_attribute_from_input(const ReadAttribute &input_attribute,
-                                          WriteAttribute &out_attribute_a,
-                                          WriteAttribute &out_attribute_b,
-                                          Span<bool> a_or_b)
+static void gather_positions_from_component_instances(const GeometryComponent &component,
+                                                      const StringRef mask_attribute_name,
+                                                      Span<float4x4> transforms,
+                                                      MutableSpan<Vector<float3>> r_positions_a,
+                                                      MutableSpan<Vector<float3>> r_positions_b)
 {
-  fn::GSpan in_span = input_attribute.get_span();
-  int i_a = 0;
-  int i_b = 0;
-  for (int i_in = 0; i_in < in_span.size(); i_in++) {
-    const bool move_to_b = a_or_b[i_in];
-    if (move_to_b) {
-      out_attribute_b.set(i_b, in_span[i_in]);
-      i_b++;
-    }
-    else {
-      out_attribute_a.set(i_a, in_span[i_in]);
-      i_a++;
-    }
+  if (component.attribute_domain_size(ATTR_DOMAIN_POINT) == 0) {
+    return;
   }
-}
 
-/**
- * Move the original attribute values to the two output components.
- *
- * \note This assumes a consistent ordering of indices before and after the split,
- * which is true for points and a simple vertex array.
- */
-static void move_split_attributes(const GeometryComponent &in_component,
-                                  GeometryComponent &out_component_a,
-                                  GeometryComponent &out_component_b,
-                                  Span<bool> a_or_b)
-{
-  Set<std::string> attribute_names = in_component.attribute_names();
+  const BooleanReadAttribute mask_attribute = component.attribute_get_for_read<bool>(
+      mask_attribute_name, ATTR_DOMAIN_POINT, false);
+  const Float3ReadAttribute position_attribute = component.attribute_get_for_read<float3>(
+      "position", ATTR_DOMAIN_POINT, {0.0f, 0.0f, 0.0f});
 
-  for (const std::string &name : attribute_names) {
-    ReadAttributePtr attribute = in_component.attribute_try_get_for_read(name);
-    BLI_assert(attribute);
+  Span<bool> masks = mask_attribute.get_span();
+  Span<float3> component_positions = position_attribute.get_span();
 
-    /* Since this node only creates points and vertices, don't copy other attributes. */
-    if (attribute->domain() != ATTR_DOMAIN_POINT) {
-      continue;
+  for (const int instance_index : transforms.index_range()) {
+    const float4x4 &transform = transforms[instance_index];
+    for (const int i : masks.index_range()) {
+      if (masks[i]) {
+        r_positions_a[instance_index].append(transform * component_positions[i]);
+      }
+      else {
+        r_positions_b[instance_index].append(transform * component_positions[i]);
+      }
     }
+  }
+}
 
-    const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute->cpp_type());
-    const AttributeDomain domain = attribute->domain();
+static void get_positions_from_instances(Span<GeometryInstanceGroup> set_groups,
+                                         const StringRef mask_attribute_name,
+                                         MutableSpan<Vector<float3>> r_positions_a,
+                                         MutableSpan<Vector<float3>> r_positions_b)
+{
+  int instance_index = 0;
+  for (const GeometryInstanceGroup &set_group : set_groups) {
+    const GeometrySet &set = set_group.geometry_set;
 
-    /* Don't try to create the attribute on the new component if it already exists (i.e. has been
-     * initialized by someone else). */
-    if (!out_component_a.attribute_exists(name)) {
-      if (!out_component_a.attribute_try_create(name, domain, data_type)) {
-        continue;
-      }
+    MutableSpan<Vector<float3>> set_instance_positions_a = r_positions_a.slice(
+        instance_index, set_group.transforms.size());
+    MutableSpan<Vector<float3>> set_instance_positions_b = r_positions_b.slice(
+        instance_index, set_group.transforms.size());
+
+    if (set.has<PointCloudComponent>()) {
+      gather_positions_from_component_instances(*set.get_component_for_read<PointCloudComponent>(),
+                                                mask_attribute_name,
+                                                set_group.transforms,
+                                                set_instance_positions_a,
+                                                set_instance_positions_b);
     }
-    if (!out_component_b.attribute_exists(name)) {
-      if (!out_component_b.attribute_try_create(name, domain, data_type)) {
-        continue;
-      }
+    if (set.has<MeshComponent>()) {
+      gather_positions_from_component_instances(*set.get_component_for_read<MeshComponent>(),
+                                                mask_attribute_name,
+                                                set_group.transforms,
+                                                set_instance_positions_a,
+                                                set_instance_positions_b);
     }
 
-    WriteAttributePtr out_attribute_a = out_component_a.attribute_try_get_for_write(name);
-    WriteAttributePtr out_attribute_b = out_component_b.attribute_try_get_for_write(name);
-    if (!out_attribute_a || !out_attribute_b) {
-      BLI_assert(false);
-      continue;
-    }
+    instance_index += set_group.transforms.size();
+  }
+}
 
-    fill_new_attribute_from_input(*attribute, *out_attribute_a, *out_attribute_b, a_or_b);
+static PointCloud *create_point_cloud(Span<Vector<float3>> positions)
+{
+  int points_len = 0;
+  for (const Vector<float3> &instance_positions : positions) {
+    points_len += instance_positions.size();
+  }
+  PointCloud *pointcloud = BKE_pointcloud_new_nomain(points_len);
+  int point_index = 0;
+  for (const Vector<float3> &instance_positions : positions) {
+    memcpy(pointcloud->co + point_index, positions.data(), sizeof(float3) * positions.size());
+    point_index += instance_positions.size();
   }
+
+  return pointcloud;
 }
 
-/**
- * Find total in each new set and find which of the output sets each point will belong to.
- */
-static Array<bool> count_point_splits(const GeometryComponent &component,
-                                      const GeoNodeExecParams &params,
-                                      int *r_a_total,
-                                      int *r_b_total)
+template<typename T>
+static void copy_from_span_and_mask(Span<T> span,
+                                    Span<bool> mask,
+                                    MutableSpan<T> out_span_a,
+                                    MutableSpan<T> out_span_b,
+                                    int &offset_a,
+                                    int &offset_b)
 {
-  const BooleanReadAttribute mask_attribute = params.get_input_attribute<bool>(
-      "Mask", component, ATTR_DOMAIN_POINT, false);
-  Array<bool> masks = mask_attribute.get_span();
-  const int in_total = masks.size();
-
-  *r_b_total = 0;
-  for (const bool mask : masks) {
-    if (mask) {
-      *r_b_total += 1;
+  for (const int i : span.index_range()) {
+    if (mask[i]) {
+      out_span_b[offset_b] = span[i];
+      offset_b++;
+    }
+    else {
+      out_span_a[offset_a] = span[i];
+      offset_a++;
     }
   }
-  *r_a_total = in_total - *r_b_total;
-
-  return masks;
 }
 
-static void separate_mesh(const MeshComponent &in_component,
-                          const GeoNodeExecParams &params,
-                          MeshComponent &out_component_a,
-                          MeshComponent &out_component_b)
+static void copy_attribute_from_component_instances(const GeometryComponent &component,
+                                                    const int instances_len,
+                                                    const StringRef mask_attribute_name,
+                                                    const StringRef attribute_name,
+                                                    const CustomDataType data_type,
+                                                    fn::GMutableSpan out_data_a,
+                                                    fn::GMutableSpan out_data_b,
+                                                    int &offset_a,
+                                                    int &offset_b)
 {
-  const int size = in_component.attribute_domain_size(ATTR_DOMAIN_POINT);
-  if (size == 0) {
+  if (component.attribute_domain_size(ATTR_DOMAIN_POINT) == 0) {
     return;
   }
 
-  int a_total;
-  int b_total;
-  Array<bool> a_or_b = count_point_splits(in_component, params, &a_total, &b_total);
+  const BooleanReadAttribute mask_attribute = component.attribute_get_for_read<bool>(
+      mask_attribute_name, ATTR_DOMAIN_POINT,

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list