[Bf-blender-cvs] [cec9331b240] temp-geometry-nodes-instances-api-v2: Geometry Nodes: Point distribute support for instances

Hans Goudey noreply at git.blender.org
Fri Feb 5 04:18:21 CET 2021


Commit: cec9331b240c28e211d750bb029b884723655350
Author: Hans Goudey
Date:   Thu Feb 4 21:18:14 2021 -0600
Branches: temp-geometry-nodes-instances-api-v2
https://developer.blender.org/rBcec9331b240c28e211d750bb029b884723655350

Geometry Nodes: Point distribute support for instances

This completes the work to implement instancing on instances.
The density attribute works, and attributes are interpolated to the
output like before.

The code is much more complicated than before, and harder to understand.
Some cleanup is likely possible to help, but to an extent it is unavoidable.

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

M	source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc

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

diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc
index 7a414ec049b..b71232a1ee2 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc
@@ -59,8 +59,9 @@ static void node_point_distribute_update(bNodeTree *UNUSED(ntree), bNode *node)
 namespace blender::nodes {
 
 struct AttributeInfo {
+  /* The highest complexity data type for all attributes in the input meshes with the name. */
   CustomDataType data_type;
-  AttributeDomain domain;
+  /* The result domain is always "points" since we're creating a point cloud. */
 };
 
 /**
@@ -135,47 +136,67 @@ static int sample_mesh_surface(const Mesh &mesh,
   return points_len;
 }
 
-BLI_NOINLINE static KDTree_3d *build_kdtree(Span<float3> positions)
+BLI_NOINLINE static KDTree_3d *build_kdtree(Span<Vector<float3>> positions_array,
+                                            const int initial_points_len)
 {
-  KDTree_3d *kdtree = BLI_kdtree_3d_new(positions.size());
-  for (const int i : positions.index_range()) {
-    BLI_kdtree_3d_insert(kdtree, i, positions[i]);
+  KDTree_3d *kdtree = BLI_kdtree_3d_new(initial_points_len);
+
+  int i_point = 0;
+  for (const int i_instance : positions_array.index_range()) {
+    Span<float3> positions = positions_array[i_instance];
+    for (const float3 position : positions) {
+      BLI_kdtree_3d_insert(kdtree, i_point, position);
+      i_point++;
+    }
   }
   BLI_kdtree_3d_balance(kdtree);
   return kdtree;
 }
 
 BLI_NOINLINE static void update_elimination_mask_for_close_points(
-    Span<float3> positions, const float minimum_distance, MutableSpan<bool> elimination_mask)
+    Span<Vector<float3>> positions_array,
+    const float minimum_distance,
+    MutableSpan<bool> elimination_mask,
+    const int initial_points_len)
 {
   if (minimum_distance <= 0.0f) {
     return;
   }
 
-  KDTree_3d *kdtree = build_kdtree(positions);
+  KDTree_3d *kdtree = build_kdtree(positions_array, initial_points_len);
 
-  for (const int i : positions.index_range()) {
-    if (elimination_mask[i]) {
-      continue;
-    }
+  /* The elimination mask is a flattened array for every point,
+   * so keep track of the index to it separately. */
+  int i_point = 0;
+  for (Span<float3> positions : positions_array) {
+    for (const float3 position : positions) {
+      if (elimination_mask[i_point]) {
+        i_point++;
+        continue;
+      }
 
-    struct CallbackData {
-      int index;
-      MutableSpan<bool> elimination_mask;
-    } callback_data = {i, elimination_mask};
-
-    BLI_kdtree_3d_range_search_cb(
-        kdtree,
-        positions[i],
-        minimum_distance,
-        [](void *user_data, int index, const float *UNUSED(co), float UNUSED(dist_sq)) {
-          CallbackData &callback_data = *static_cast<CallbackData *>(user_data);
-          if (index != callback_data.index) {
-            callback_data.elimination_mask[index] = true;
-          }
-          return true;
-        },
-        &callback_data);
+      struct CallbackData {
+        int index;
+        MutableSpan<bool> elimination_mask;
+      } callback_data = {i_point, elimination_mask};
+
+      std::cout << "  KDTree nearest point callback: \n";
+      BLI_kdtree_3d_range_search_cb(
+          kdtree,
+          position,
+          minimum_distance,
+          [](void *user_data, int index, const float *UNUSED(co), float UNUSED(dist_sq)) {
+            CallbackData &callback_data = *static_cast<CallbackData *>(user_data);
+            if (index != callback_data.index) {
+              std::cout << "    Eliminating index mask: " << index << "\n";
+              callback_data.elimination_mask[index] = true;
+            }
+            return true;
+          },
+          &callback_data);
+
+      i_point++;
+    }
   }
   BLI_kdtree_3d_free(kdtree);
 }
@@ -284,73 +305,127 @@ BLI_NOINLINE static void interpolate_attribute_corner(const Mesh &mesh,
   }
 }
 
+template<typename T>
 BLI_NOINLINE static void interpolate_attribute(const Mesh &mesh,
                                                Span<float3> bary_coords,
                                                Span<int> looptri_indices,
-                                               const StringRef attribute_name,
-                                               const ReadAttribute &attribute_in,
-                                               GeometryComponent &component)
+                                               const AttributeDomain source_domain,
+                                               Span<T> source_span,
+                                               MutableSpan<T> output_span)
 {
-  const CustomDataType data_type = attribute_in.custom_data_type();
-  const AttributeDomain domain = attribute_in.domain();
-  if (!ELEM(domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_CORNER)) {
-    /* Not supported currently. */
-    return;
+  switch (source_domain) {
+    case ATTR_DOMAIN_POINT: {
+      interpolate_attribute_point<T>(mesh, bary_coords, looptri_indices, source_span, output_span);
+      break;
+    }
+    case ATTR_DOMAIN_CORNER: {
+      interpolate_attribute_corner<T>(
+          mesh, bary_coords, looptri_indices, source_span, output_span);
+      break;
+    }
+    default: {
+      /* Not supported currently. */
+      return;
+    }
   }
+}
 
-  OutputAttributePtr attribute_out = component.attribute_try_get_for_output(
-      attribute_name, ATTR_DOMAIN_POINT, data_type);
-  if (!attribute_out) {
-    return;
-  }
+BLI_NOINLINE static void interpolate_existing_attributes(
+    Span<GeometryInstanceGroup> sets,
+    Span<int> group_start_indices,
+    Map<std::string, AttributeInfo> &attributes,
+    GeometryComponent &component,
+    Span<Vector<float3>> bary_coords_array,
+    Span<Vector<int>> looptri_indices_array)
+{
+  for (blender::Map<std::string, AttributeInfo>::Item entry : attributes.items()) {
+    StringRef attribute_name = entry.key;
+    std::cout << "Working on attribute: " << attribute_name << "\n";
+
+    const AttributeInfo attribute_info = entry.value;
+    const CustomDataType output_data_type = attribute_info.data_type;
+    OutputAttributePtr attribute_out = component.attribute_try_get_for_output(
+        attribute_name, ATTR_DOMAIN_POINT, output_data_type);
+    BLI_assert(attribute_out);
+    if (!attribute_out) {
+      continue;
+    }
 
-  attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
-    using T = decltype(dummy);
+    attribute_math::convert_to_static_type(output_data_type, [&](auto dummy) {
+      using T = decltype(dummy);
 
-    Span data_in = attribute_in.get_span<T>();
-    MutableSpan data_out = attribute_out->get_span_for_write_only<T>();
+      MutableSpan<T> out_span = attribute_out->get_span_for_write_only<T>();
 
-    switch (domain) {
-      case ATTR_DOMAIN_POINT: {
-        interpolate_attribute_point<T>(mesh, bary_coords, looptri_indices, data_in, data_out);
-        break;
-      }
-      case ATTR_DOMAIN_CORNER: {
-        interpolate_attribute_corner<T>(mesh, bary_coords, looptri_indices, data_in, data_out);
-        break;
-      }
-      default: {
-        BLI_assert(false);
-        break;
-      }
-    }
-  });
-  attribute_out.apply_span_and_save();
-}
+      int i_set_with_mesh = 0;
+      int i_instance = 0;
+      for (const GeometryInstanceGroup &set_group : sets) {
+        const GeometrySet &set = set_group.geometry_set;
+        std::cout << "  Working on geometry set: " << set << "\n";
+        if (set.has_instances()) {
+          std::cout << "    Set has instances\n";
+        }
+        if (set.has_pointcloud()) {
+          std::cout << "    Set has point cloud\n";
+        }
+        if (set.has_volume()) {
+          std::cout << "    Set has volume\n";
+        }
+        if (!set.has_mesh()) {
+          std::cout << "    Set has no mesh\n";
+          continue;
+        }
+        const MeshComponent &source_component = *set.get_component_for_read<MeshComponent>();
+        const Mesh &mesh = *source_component.get_for_read();
+
+        ReadAttributePtr dummy_attribute = source_component.attribute_try_get_for_read(
+            attribute_name);
+        if (!dummy_attribute) {
+          std::cout << "    Source attribute not found\n";
+          i_instance += set_group.transforms.size();
+          i_set_with_mesh++;
+          continue;
+        }
 
-BLI_NOINLINE static void interpolate_existing_attributes(const MeshComponent &mesh_component,
-                                                         GeometryComponent &component,
-                                                         Span<float3> bary_coords,
-                                                         Span<int> looptri_indices)
-{
-  const Mesh &mesh = *mesh_component.get_for_read();
+        /* Do not interpolate the domain, that is handled by #interpolate_attribute. */
+        const AttributeDomain source_domain = dummy_attribute->domain();
 
-  Set<std::string> attribute_names = mesh_component.attribute_names();
-  for (StringRefNull attribute_name : attribute_names) {
-    if (ELEM(attribute_name, "position", "normal", "id")) {
-      continue;
-    }
+        ReadAttributePtr source_attribute = source_component.attribute_get_for_read(
+            attribute_name, source_domain, output_data_type, nullptr);
+        BLI_assert(source_attribute);
+        Span<T> source_span = source_attribute->get_span<T>();
 
-    ReadAttributePtr attribute_in = mesh_component.attribute_try_get_for_read(attribute_name);
-    interpolate_attribute(
-        mesh, bary_coords, looptri_indices, attribute_name, *attribute_in, component);
+        if (!source_attribute) {
+          std::cout << "    Source attribute read with correct domain not found\n";
+          i_instance += set_group.transforms.size();
+          i_set_with_mesh++;
+          continue;
+        }
+
+        int i_point = group_start_indices[i_set_with_mesh];
+        std::cout << "    Adding attribute from source, starting at " << i_point << "\n";
+        for (const int UNUSED(i_set_instance) : set_group.transforms.index_r

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list