[Bf-blender-cvs] [6a7fd511804] temp-geometry-nodes-instances-api-v2: Geometry Nodes: Better support instances in point instance node

Hans Goudey noreply at git.blender.org
Thu Feb 4 06:57:00 CET 2021


Commit: 6a7fd51180417b836917d23f3973f88889fe74cb
Author: Hans Goudey
Date:   Wed Feb 3 23:56:56 2021 -0600
Branches: temp-geometry-nodes-instances-api-v2
https://developer.blender.org/rB6a7fd51180417b836917d23f3973f88889fe74cb

Geometry Nodes: Better support instances in point instance node

This does the elimination by distance in a single step for all instances
instead of treating each input mesh separately.

This needs some cleanup, but the bigger TODO is that attribute interpolation
gets a fair amount more complex with this implementation. Needs more thought.

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

M	source/blender/blenkernel/BKE_geometry_set.hh
M	source/blender/blenkernel/intern/geometry_set.cc
M	source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc

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

diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh
index 0ea43202b4a..771664ef209 100644
--- a/source/blender/blenkernel/BKE_geometry_set.hh
+++ b/source/blender/blenkernel/BKE_geometry_set.hh
@@ -483,6 +483,26 @@ using ForeachGeometryCallbackConst = std::function<void(
 void BKE_foreach_geometry_component_recursive(const GeometrySet &geometry_set,
                                               const ForeachGeometryCallbackConst &callback);
 
-using GeometrySetGroup = std::pair<GeometrySet, blender::Vector<blender::float4x4>>;
-blender::Vector<GeometrySetGroup> BKE_geometry_set_gather_instanced(
+/**
+ * Used to keep track of a group of instances using the same geometry data.
+ *
+ * \note In the future, this can be used to store "geometry set instances".
+ */
+struct GeometryInstanceGroup {
+  /**
+   * The geometry set instanced on each of the transforms. The components are not necessarily
+   * owned here. For example, they may be owned by the instanced object. This cannot be a
+   * reference because not all instanced data will necessarily have a #geometry_set_eval.
+   */
+  GeometrySet geometry_set;
+
+  /**
+   * As an optimization to avoid copying, the same geometry set can be associated with multiple
+   * instances. Each instance is stored as a transform matrix here. Again, these must be owned
+   * because they may be transformed from the original data. TODO: Validate that last statement.
+   */
+  blender::Vector<blender::float4x4> transforms;
+};
+
+blender::Vector<GeometryInstanceGroup> BKE_geometry_set_gather_instanced(
     const GeometrySet &geometry_set);
\ No newline at end of file
diff --git a/source/blender/blenkernel/intern/geometry_set.cc b/source/blender/blenkernel/intern/geometry_set.cc
index b0023e2ad0c..f1f156de531 100644
--- a/source/blender/blenkernel/intern/geometry_set.cc
+++ b/source/blender/blenkernel/intern/geometry_set.cc
@@ -593,14 +593,20 @@ static GeometrySet object_get_geometry_set_for_read(const Object &object)
       mesh_component.copy_vertex_group_names_from_object(object);
     }
   }
-  // else if (object.type == OB_VOLUME) {
-  //   Volume *volume = BKE_modifier_get_volume...
-  // }
+  /* TODO: Cover the case of pointclouds without modifiers,
+   * they may not be covered by the #geometry_set_eval case above. */
+  /* TODO: Add volume support. */
 
   /* Return by value since there is no existing geometry set owned elsewhere to use. */
   return new_geometry_set;
 }
 
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Geometry Set Instances Callback
+ * \{ */
+
 static void foreach_geometry_component_recursive(const GeometrySet &geometry_set,
                                                  const ForeachGeometryCallbackConst &callback,
                                                  const float4x4 &transform);
@@ -664,6 +670,13 @@ static void foreach_geometry_component_recursive(const GeometrySet &geometry_set
   }
 }
 
+/**
+ * Execute a callback for every component of a geometry set. This approach is used to avoid
+ * allocating a temporary vector the store the flattened instances before operation.
+ *
+ * \note For convenience (to avoid duplication in the caller),
+ * this also executes the callback for the argument geometry set.
+ */
 void BKE_foreach_geometry_component_recursive(const GeometrySet &geometry_set,
                                               const ForeachGeometryCallbackConst &callback)
 {
@@ -673,18 +686,19 @@ void BKE_foreach_geometry_component_recursive(const GeometrySet &geometry_set,
   foreach_geometry_component_recursive(geometry_set, callback, unit_transform);
 }
 
-/* ============= API 2 =============== */
+/** \} */
 
-using GeometrySetGroup = std::pair<GeometrySet, Vector<float4x4>>;
+/* -------------------------------------------------------------------- */
+/** \name Geometry Set Gather Recursive Instances
+ * \{ */
 
-static void collect_geometry_set_recursive(
-    const GeometrySet &geometry_set,
-    const float4x4 &transform,
-    Vector<std::pair<GeometrySet, Vector<float4x4>>> &r_sets);
+static void collect_geometry_set_recursive(const GeometrySet &geometry_set,
+                                           const float4x4 &transform,
+                                           Vector<GeometryInstanceGroup> &r_sets);
 
 static void collect_collection_geometry_set_recursive(const Collection &collection,
                                                       const float4x4 &transform,
-                                                      Vector<GeometrySetGroup> &r_sets)
+                                                      Vector<GeometryInstanceGroup> &r_sets)
 {
   LISTBASE_FOREACH (const CollectionObject *, collection_object, &collection.gobject) {
     BLI_assert(collection_object->ob != nullptr);
@@ -704,7 +718,7 @@ static void collect_collection_geometry_set_recursive(const Collection &collecti
 
 static void collect_geometry_set_recursive(const GeometrySet &geometry_set,
                                            const float4x4 &transform,
-                                           Vector<GeometrySetGroup> &r_sets)
+                                           Vector<GeometryInstanceGroup> &r_sets)
 {
   r_sets.append({geometry_set, {transform}});
 
@@ -733,9 +747,17 @@ static void collect_geometry_set_recursive(const GeometrySet &geometry_set,
   }
 }
 
-Vector<GeometrySetGroup> BKE_geometry_set_gather_instanced(const GeometrySet &geometry_set)
+/**
+ * Return a vector of geometry sets, including a flattened array of instances. This approach
+ * (as opposed to #BKE_foreach_geometry_component_recursive) can be used where multiple iterations
+ * over the input data are needed, or where it simplifies code enough.
+ *
+ * \note For convenience (to avoid duplication in the caller),
+ * the returned vector also contains the argument geometry set.
+ */
+Vector<GeometryInstanceGroup> BKE_geometry_set_gather_instanced(const GeometrySet &geometry_set)
 {
-  Vector<GeometrySetGroup> result_vector;
+  Vector<GeometryInstanceGroup> result_vector;
 
   float4x4 unit_transform;
   unit_m4(unit_transform.values);
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 e7f20d98d56..7a414ec049b 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc
@@ -57,6 +57,7 @@ static void node_point_distribute_update(bNodeTree *UNUSED(ntree), bNode *node)
 }
 
 namespace blender::nodes {
+
 struct AttributeInfo {
   CustomDataType data_type;
   AttributeDomain domain;
@@ -82,17 +83,18 @@ static Span<MLoopTri> get_mesh_looptris(const Mesh &mesh)
   return {looptris, looptris_len};
 }
 
-static void sample_mesh_surface(const Mesh &mesh,
-                                const float4x4 &transform,
-                                const float base_density,
-                                const FloatReadAttribute *density_factors,
-                                const int seed,
-                                Vector<float3> &r_positions,
-                                Vector<float3> &r_bary_coords,
-                                Vector<int> &r_looptri_indices)
+static int sample_mesh_surface(const Mesh &mesh,
+                               const float4x4 &transform,
+                               const float base_density,
+                               const FloatReadAttribute *density_factors,
+                               const int seed,
+                               Vector<float3> &r_positions,
+                               Vector<float3> &r_bary_coords,
+                               Vector<int> &r_looptri_indices)
 {
   Span<MLoopTri> looptris = get_mesh_looptris(mesh);
 
+  int points_len = 0;
   for (const int looptri_index : looptris.index_range()) {
     const MLoopTri &looptri = looptris[looptri_index];
     const int v0_index = mesh.mloop[looptri.tri[0]].v;
@@ -127,73 +129,54 @@ static void sample_mesh_surface(const Mesh &mesh,
       r_positions.append(point_pos);
       r_bary_coords.append(bary_coord);
       r_looptri_indices.append(looptri_index);
+      points_len++;
     }
   }
+  return points_len;
 }
 
-BLI_NOINLINE static KDTree_3d *build_kdtree(Span<Vector<float3>> all_positions)
+BLI_NOINLINE static KDTree_3d *build_kdtree(Span<float3> positions)
 {
-  for (Vector<float3> positions : all_positions) {
-    for (const float3 position : positions) {
-    }
-  }
   KDTree_3d *kdtree = BLI_kdtree_3d_new(positions.size());
-  int i = 0;
-  for (Vector<float3> positions : all_positions) {
-    for (const float3 position : positions) {
-      BLI_kdtree_3d_insert(kdtree, i, positions[i]);
-      i++;
-    }
+  for (const int i : positions.index_range()) {
+    BLI_kdtree_3d_insert(kdtree, i, positions[i]);
   }
   BLI_kdtree_3d_balance(kdtree);
   return kdtree;
 }
 
 BLI_NOINLINE static void update_elimination_mask_for_close_points(
-    Span<Vector<float3>> positions_per_instance,
-    const float minimum_distance,
-    MutableSpan<bool> elimination_mask_per_instance)
+    Span<float3> positions, const float minimum_distance, MutableSpan<bool> elimination_mask)
 {
   if (minimum_distance <= 0.0f) {
     return;
   }
 
-  for (const int i_set : get_groups.index_range()) {
-    const GeometrySetGroup &set_group = get_groups[i_set];
-    const GeometrySet &set = set_group.first;
-    if (!set.has_mesh()) {
-      continue;
-    }
-    const Mesh &mesh = *set.get_mesh_for_read();
-    for (const float4x4 &transform : set_group.second) {
-    }
-  }
   KDTree_3d *kdtree = build_kdtree(positions);
 
-  for (const int i_instance :)
-    for (const int i : positions.index_range()) {
-      if (elimination_mask[i]) {
-        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 UN

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list