[Bf-blender-cvs] [7b9319adf90] master: Geometry Nodes: Update bounding box to work on individual instances

Hans Goudey noreply at git.blender.org
Thu Oct 21 18:52:03 CEST 2021


Commit: 7b9319adf90e1742873213abbcd9293c3c4c3749
Author: Hans Goudey
Date:   Thu Oct 21 11:51:56 2021 -0500
Branches: master
https://developer.blender.org/rB7b9319adf90e1742873213abbcd9293c3c4c3749

Geometry Nodes: Update bounding box to work on individual instances

This commit makes the bounding box node work on each unique geometry
(including instances) individually instead of making one large bounding
box for everything. This makes the node much faster, and is often the
desired result anyway. For the old behavior, a realize instances node
can be used in front of this node (versioning adds it automatically).

The min and max outputs now only output the values from the realized
geometry.

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

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

M	source/blender/blenkernel/BKE_blender_version.h
M	source/blender/blenloader/intern/versioning_300.c
M	source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc

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

diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index 899d21683e4..32b607ecf9b 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -39,7 +39,7 @@ extern "C" {
 
 /* Blender file format version. */
 #define BLENDER_FILE_VERSION BLENDER_VERSION
-#define BLENDER_FILE_SUBVERSION 36
+#define BLENDER_FILE_SUBVERSION 37
 
 /* Minimum Blender version that supports reading file written with the current
  * version. Older Blender versions will test this and show a warning if the file
diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c
index 51a3e32f2bb..bdee5194c9a 100644
--- a/source/blender/blenloader/intern/versioning_300.c
+++ b/source/blender/blenloader/intern/versioning_300.c
@@ -754,6 +754,19 @@ void do_versions_after_linking_300(Main *bmain, ReportList *UNUSED(reports))
     }
   }
 
+  if (!MAIN_VERSION_ATLEAST(bmain, 300, 37)) {
+    LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
+      if (ntree->type == NTREE_GEOMETRY) {
+        LISTBASE_FOREACH_MUTABLE (bNode *, node, &ntree->nodes) {
+          if (node->type == GEO_NODE_BOUNDING_BOX) {
+            bNodeSocket *geometry_socket = node->inputs.first;
+            add_realize_instances_before_socket(ntree, node, geometry_socket);
+          }
+        }
+      }
+    }
+  }
+
   /**
    * Versioning code until next subversion bump goes here.
    *
diff --git a/source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc b/source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc
index 8b90595a641..e34b65e6c94 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc
@@ -14,9 +14,6 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
-#include "BKE_spline.hh"
-#include "BKE_volume.h"
-
 #include "node_geometry_util.hh"
 
 namespace blender::nodes {
@@ -29,135 +26,56 @@ static void geo_node_bounding_box_declare(NodeDeclarationBuilder &b)
   b.add_output<decl::Vector>("Max");
 }
 
-using bke::GeometryInstanceGroup;
-
-static void compute_min_max_from_position_and_transform(const GeometryComponent &component,
-                                                        Span<float4x4> transforms,
-                                                        float3 &r_min,
-                                                        float3 &r_max)
-{
-  GVArray_Typed<float3> positions = component.attribute_get_for_read<float3>(
-      "position", ATTR_DOMAIN_POINT, {0, 0, 0});
-
-  for (const float4x4 &transform : transforms) {
-    for (const int i : positions.index_range()) {
-      const float3 position = positions[i];
-      const float3 transformed_position = transform * position;
-      minmax_v3v3_v3(r_min, r_max, transformed_position);
-    }
-  }
-}
-
-static void compute_min_max_from_volume_and_transforms(const VolumeComponent &volume_component,
-                                                       Span<float4x4> transforms,
-                                                       float3 &r_min,
-                                                       float3 &r_max)
-{
-#ifdef WITH_OPENVDB
-  const Volume *volume = volume_component.get_for_read();
-  if (volume == nullptr) {
-    return;
-  }
-  for (const int i : IndexRange(BKE_volume_num_grids(volume))) {
-    const VolumeGrid *volume_grid = BKE_volume_grid_get_for_read(volume, i);
-    openvdb::GridBase::ConstPtr grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid);
-
-    for (const float4x4 &transform : transforms) {
-      openvdb::GridBase::ConstPtr instance_grid = BKE_volume_grid_shallow_transform(grid,
-                                                                                    transform);
-      float3 grid_min = float3(FLT_MAX);
-      float3 grid_max = float3(-FLT_MAX);
-      if (BKE_volume_grid_bounds(instance_grid, grid_min, grid_max)) {
-        DO_MIN(grid_min, r_min);
-        DO_MAX(grid_max, r_max);
-      }
-    }
-  }
-#else
-  UNUSED_VARS(volume_component, transforms, r_min, r_max);
-#endif
-}
-
-static void compute_min_max_from_curve_and_transforms(const CurveComponent &curve_component,
-                                                      Span<float4x4> transforms,
-                                                      float3 &r_min,
-                                                      float3 &r_max)
-{
-  const CurveEval *curve = curve_component.get_for_read();
-  if (curve == nullptr) {
-    return;
-  }
-  for (const SplinePtr &spline : curve->splines()) {
-    Span<float3> positions = spline->evaluated_positions();
-
-    for (const float4x4 &transform : transforms) {
-      for (const int i : positions.index_range()) {
-        const float3 position = positions[i];
-        const float3 transformed_position = transform * position;
-        minmax_v3v3_v3(r_min, r_max, transformed_position);
-      }
-    }
-  }
-}
-
-static void compute_geometry_set_instances_boundbox(const GeometrySet &geometry_set,
-                                                    float3 &r_min,
-                                                    float3 &r_max)
-{
-  Vector<GeometryInstanceGroup> set_groups;
-  bke::geometry_set_gather_instances(geometry_set, set_groups);
-
-  for (const GeometryInstanceGroup &set_group : set_groups) {
-    const GeometrySet &set = set_group.geometry_set;
-    Span<float4x4> transforms = set_group.transforms;
-
-    if (set.has<PointCloudComponent>()) {
-      compute_min_max_from_position_and_transform(
-          *set.get_component_for_read<PointCloudComponent>(), transforms, r_min, r_max);
-    }
-    if (set.has<MeshComponent>()) {
-      compute_min_max_from_position_and_transform(
-          *set.get_component_for_read<MeshComponent>(), transforms, r_min, r_max);
-    }
-    if (set.has<VolumeComponent>()) {
-      compute_min_max_from_volume_and_transforms(
-          *set.get_component_for_read<VolumeComponent>(), transforms, r_min, r_max);
-    }
-    if (set.has<CurveComponent>()) {
-      compute_min_max_from_curve_and_transforms(
-          *set.get_component_for_read<CurveComponent>(), transforms, r_min, r_max);
-    }
-  }
-}
-
 static void geo_node_bounding_box_exec(GeoNodeExecParams params)
 {
   GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
 
+  /* Compute the min and max of all realized geometry for the two
+   * vector outputs, which are only meant to consider real geometry. */
   float3 min = float3(FLT_MAX);
   float3 max = float3(-FLT_MAX);
-
-  if (geometry_set.has_instances()) {
-    compute_geometry_set_instances_boundbox(geometry_set, min, max);
-  }
-  else {
-    geometry_set.compute_boundbox_without_instances(&min, &max);
-  }
-
+  geometry_set.compute_boundbox_without_instances(&min, &max);
   if (min == float3(FLT_MAX)) {
-    params.set_output("Bounding Box", GeometrySet());
     params.set_output("Min", float3(0));
     params.set_output("Max", float3(0));
   }
   else {
-    const float3 scale = max - min;
-    const float3 center = min + scale / 2.0f;
-    Mesh *mesh = create_cuboid_mesh(scale, 2, 2, 2);
-    transform_mesh(*mesh, center, float3(0), float3(1));
-    params.set_output("Bounding Box", GeometrySet::create_with_mesh(mesh));
     params.set_output("Min", min);
     params.set_output("Max", max);
   }
+
+  /* Generate the bounding box meshes inside each unique geometry set (including individually for
+   * every instance). Because geometry components are reference counted anyway, we can just
+   * repurpose the original geometry sets for the output. */
+  if (params.output_is_required("Bounding Box")) {
+    geometry_set.modify_geometry_sets([&](GeometrySet &sub_geometry) {
+      float3 sub_min = float3(FLT_MAX);
+      float3 sub_max = float3(-FLT_MAX);
+
+      /* Reuse the min and max calculation if this is the main "real" geometry set. */
+      if (&sub_geometry == &geometry_set) {
+        sub_min = min;
+        sub_max = max;
+      }
+      else {
+        sub_geometry.compute_boundbox_without_instances(&sub_min, &sub_max);
+      }
+
+      if (sub_min == float3(FLT_MAX)) {
+        sub_geometry.keep_only({GEO_COMPONENT_TYPE_INSTANCES});
+      }
+      else {
+        const float3 scale = sub_max - sub_min;
+        const float3 center = sub_min + scale / 2.0f;
+        Mesh *mesh = create_cuboid_mesh(scale, 2, 2, 2);
+        transform_mesh(*mesh, center, float3(0), float3(1));
+        sub_geometry.replace_mesh(mesh);
+        sub_geometry.keep_only({GEO_COMPONENT_TYPE_MESH, GEO_COMPONENT_TYPE_INSTANCES});
+      }
+    });
+
+    params.set_output("Bounding Box", std::move(geometry_set));
+  }
 }
 
 }  // namespace blender::nodes



More information about the Bf-blender-cvs mailing list