[Bf-blender-cvs] [793547e7d14] master: Geometry Nodes: initial support for volumes

Jacques Lucke noreply at git.blender.org
Thu Jan 21 10:37:52 CET 2021


Commit: 793547e7d1401ad545e0450b80c7bafd521c60e1
Author: Jacques Lucke
Date:   Thu Jan 21 10:32:42 2021 +0100
Branches: master
https://developer.blender.org/rB793547e7d1401ad545e0450b80c7bafd521c60e1

Geometry Nodes: initial support for volumes

For the most part, this just adds boilerplate code for volume support in geometry nodes:
* Add `VolumeComponent` next to `MeshComponent`, etc.
* Support `VolumeComponent` in depsgraph object iterator.

Furthermore, I added initial volume support in a few nodes:
* The Object Info node outputs an object instance when the input is a volume object
  (that will be the same for mesh objects soonish, to avoid copies).
* Support transforming a `VolumeComponent` in the Transform node.
* Support the `VolumeComponent` in Join Geometry nodes, but only when just one of the
  inputs has a volume component for now.

Right now, there is no way to create a `VolumeComponent`, because the Object Info node
outputs an object instance. The `VolumeComponent` will be necessary for upcoming nodes,
which will generate volumes on the fly.

Viewport selection does not work correctly with `VolumeComponent`s currently. I don't
know why that is. That can be figured out a bit later, once we can actually create
new volumes in geometry nodes.

Ref T84604.

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

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

M	source/blender/blenkernel/BKE_geometry_set.hh
M	source/blender/blenkernel/intern/geometry_set.cc
M	source/blender/blenkernel/intern/volume.cc
M	source/blender/depsgraph/intern/depsgraph_query_iter.cc
M	source/blender/nodes/CMakeLists.txt
M	source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc
M	source/blender/nodes/geometry/nodes/node_geo_object_info.cc
M	source/blender/nodes/geometry/nodes/node_geo_transform.cc

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

diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh
index ad5a5d57045..adc08f699fd 100644
--- a/source/blender/blenkernel/BKE_geometry_set.hh
+++ b/source/blender/blenkernel/BKE_geometry_set.hh
@@ -36,6 +36,7 @@ struct Collection;
 struct Mesh;
 struct Object;
 struct PointCloud;
+struct Volume;
 
 /* Each geometry component has a specific type. The type determines what kind of data the component
  * stores. Functions modifying a geometry will usually just modify a subset of the component types.
@@ -44,6 +45,7 @@ enum class GeometryComponentType {
   Mesh = 0,
   PointCloud = 1,
   Instances = 2,
+  Volume = 3,
 };
 
 enum class GeometryOwnershipType {
@@ -319,10 +321,13 @@ struct GeometrySet {
   bool has_mesh() const;
   bool has_pointcloud() const;
   bool has_instances() const;
+  bool has_volume() const;
   const Mesh *get_mesh_for_read() const;
   const PointCloud *get_pointcloud_for_read() const;
+  const Volume *get_volume_for_read() const;
   Mesh *get_mesh_for_write();
   PointCloud *get_pointcloud_for_write();
+  Volume *get_volume_for_write();
 
   /* Utility methods for replacement. */
   void replace_mesh(Mesh *mesh, GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
@@ -464,3 +469,25 @@ class InstancesComponent : public GeometryComponent {
 
   static constexpr inline GeometryComponentType static_type = GeometryComponentType::Instances;
 };
+
+/** A geometry component that stores volume grids. */
+class VolumeComponent : public GeometryComponent {
+ private:
+  Volume *volume_ = nullptr;
+  GeometryOwnershipType ownership_ = GeometryOwnershipType::Owned;
+
+ public:
+  VolumeComponent();
+  ~VolumeComponent();
+  GeometryComponent *copy() const override;
+
+  void clear();
+  bool has_volume() const;
+  void replace(Volume *volume, GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
+  Volume *release();
+
+  const Volume *get_for_read() const;
+  Volume *get_for_write();
+
+  static constexpr inline GeometryComponentType static_type = GeometryComponentType::Volume;
+};
diff --git a/source/blender/blenkernel/intern/geometry_set.cc b/source/blender/blenkernel/intern/geometry_set.cc
index 81958b81213..7a3239babd4 100644
--- a/source/blender/blenkernel/intern/geometry_set.cc
+++ b/source/blender/blenkernel/intern/geometry_set.cc
@@ -19,6 +19,7 @@
 #include "BKE_mesh.h"
 #include "BKE_mesh_wrapper.h"
 #include "BKE_pointcloud.h"
+#include "BKE_volume.h"
 
 #include "DNA_object_types.h"
 
@@ -51,6 +52,8 @@ GeometryComponent *GeometryComponent::create(GeometryComponentType component_typ
       return new PointCloudComponent();
     case GeometryComponentType::Instances:
       return new InstancesComponent();
+    case GeometryComponentType::Volume:
+      return new VolumeComponent();
   }
   BLI_assert(false);
   return nullptr;
@@ -201,6 +204,13 @@ const PointCloud *GeometrySet::get_pointcloud_for_read() const
   return (component == nullptr) ? nullptr : component->get_for_read();
 }
 
+/* Returns a read-only volume or null. */
+const Volume *GeometrySet::get_volume_for_read() const
+{
+  const VolumeComponent *component = this->get_component_for_read<VolumeComponent>();
+  return (component == nullptr) ? nullptr : component->get_for_read();
+}
+
 /* Returns true when the geometry set has a point cloud component that has a point cloud. */
 bool GeometrySet::has_pointcloud() const
 {
@@ -215,6 +225,13 @@ bool GeometrySet::has_instances() const
   return component != nullptr && component->instances_amount() >= 1;
 }
 
+/* Returns true when the geometry set has a volume component that has a volume. */
+bool GeometrySet::has_volume() const
+{
+  const VolumeComponent *component = this->get_component_for_read<VolumeComponent>();
+  return component != nullptr && component->has_volume();
+}
+
 /* Create a new geometry set that only contains the given mesh. */
 GeometrySet GeometrySet::create_with_mesh(Mesh *mesh, GeometryOwnershipType ownership)
 {
@@ -262,6 +279,13 @@ PointCloud *GeometrySet::get_pointcloud_for_write()
   return component.get_for_write();
 }
 
+/* Returns a mutable volume or null. No ownership is transferred. */
+Volume *GeometrySet::get_volume_for_write()
+{
+  VolumeComponent &component = this->get_component_for_write<VolumeComponent>();
+  return component.get_for_write();
+}
+
 /** \} */
 
 /* -------------------------------------------------------------------- */
@@ -566,6 +590,85 @@ bool InstancesComponent::is_empty() const
 
 /** \} */
 
+/* -------------------------------------------------------------------- */
+/** \name Volume Component
+ * \{ */
+
+VolumeComponent::VolumeComponent() : GeometryComponent(GeometryComponentType::Volume)
+{
+}
+
+VolumeComponent::~VolumeComponent()
+{
+  this->clear();
+}
+
+GeometryComponent *VolumeComponent::copy() const
+{
+  VolumeComponent *new_component = new VolumeComponent();
+  if (volume_ != nullptr) {
+    new_component->volume_ = BKE_volume_copy_for_eval(volume_, false);
+    new_component->ownership_ = GeometryOwnershipType::Owned;
+  }
+  return new_component;
+}
+
+void VolumeComponent::clear()
+{
+  BLI_assert(this->is_mutable());
+  if (volume_ != nullptr) {
+    if (ownership_ == GeometryOwnershipType::Owned) {
+      BKE_id_free(nullptr, volume_);
+    }
+    volume_ = nullptr;
+  }
+}
+
+bool VolumeComponent::has_volume() const
+{
+  return volume_ != nullptr;
+}
+
+/* Clear the component and replace it with the new volume. */
+void VolumeComponent::replace(Volume *volume, GeometryOwnershipType ownership)
+{
+  BLI_assert(this->is_mutable());
+  this->clear();
+  volume_ = volume;
+  ownership_ = ownership;
+}
+
+/* Return the volume and clear the component. The caller takes over responsibility for freeing the
+ * volume (if the component was responsible before). */
+Volume *VolumeComponent::release()
+{
+  BLI_assert(this->is_mutable());
+  Volume *volume = volume_;
+  volume_ = nullptr;
+  return volume;
+}
+
+/* Get the volume from this component. This method can be used by multiple threads at the same
+ * time. Therefore, the returned volume should not be modified. No ownership is transferred. */
+const Volume *VolumeComponent::get_for_read() const
+{
+  return volume_;
+}
+
+/* Get the volume from this component. This method can only be used when the component is mutable,
+ * i.e. it is not shared. The returned volume can be modified. No ownership is transferred. */
+Volume *VolumeComponent::get_for_write()
+{
+  BLI_assert(this->is_mutable());
+  if (ownership_ == GeometryOwnershipType::ReadOnly) {
+    volume_ = BKE_volume_copy_for_eval(volume_, false);
+    ownership_ = GeometryOwnershipType::Owned;
+  }
+  return volume_;
+}
+
+/** \} */
+
 /* -------------------------------------------------------------------- */
 /** \name C API
  * \{ */
diff --git a/source/blender/blenkernel/intern/volume.cc b/source/blender/blenkernel/intern/volume.cc
index 9e7a3736141..0c64295b55b 100644
--- a/source/blender/blenkernel/intern/volume.cc
+++ b/source/blender/blenkernel/intern/volume.cc
@@ -523,6 +523,8 @@ static void volume_copy_data(Main *UNUSED(bmain),
     volume_dst->runtime.grids = OBJECT_GUARDED_NEW(VolumeGridVector, grids_src);
   }
 #endif
+
+  volume_dst->batch_cache = nullptr;
 }
 
 static void volume_free_data(ID *id)
diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc
index e472d82f2ee..c9780b9b129 100644
--- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc
+++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc
@@ -193,6 +193,30 @@ bool deg_iterator_components_step(BLI_Iterator *iter)
     }
   }
 
+  /* The volume component. */
+  if (data->geometry_component_id == 2) {
+    data->geometry_component_id++;
+
+    /* Don't use a temporary object for this component, when the owner is a volume object. */
+    if (data->geometry_component_owner->type == OB_VOLUME) {
+      iter->current = data->geometry_component_owner;
+      return true;
+    }
+
+    const VolumeComponent *component = geometry_set->get_component_for_read<VolumeComponent>();
+    if (component != nullptr) {
+      const Volume *volume = component->get_for_read();
+
+      Object *temp_object = &data->temp_geometry_component_object;
+      *temp_object = *data->geometry_component_owner;
+      temp_object->type = OB_VOLUME;
+      temp_object->data = (void *)volume;
+      temp_object->runtime.select_id = data->geometry_component_owner->runtime.select_id;
+      iter->current = temp_object;
+      return true;
+    }
+  }
+
   data->geometry_component_owner = nullptr;
   return false;
 }
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index ed4d658eb4f..9057e4c6be8 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -366,4 +366,11 @@ if(WITH_OPENSUBDIV)
   add_definitions(-DWITH_OPENSUBDIV)
 endif()
 
+if(WITH_OPENVDB)
+  list(APPEND INC_SYS
+    ${OPENVDB_INCLUDE_DIRS}
+  )
+  add_definitions(-DWITH_OPENVDB ${OPENVDB_DEFINITIONS})
+endif()
+
 blender_add_lib(bf_nodes "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc
index 75736ae714a..b9c9e5bd02a 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc
@@ -228,6 +228,14 @@ static void join_components(Span<const InstancesComponent *> src_components, Geo
   }
 }
 
+static void join_components(Span<const VolumeComponent *> src_components, GeometrySet &result)
+{
+  /* Not yet supported. Joining volume grids with the same name requires resampling of at least one
+   * of the grids. The cell size of the resulting volume has to be determined somehow. */
+  VolumeComponent &dst_component = result.get_component_for_write<VolumeComponent>();
+  UNUSED_VARS(src_components, dst_component);
+}
+
 template<typename Component>
 static void join_component_type(Span<const GeometrySet *> src_geometry_sets, GeometrySet &result)
 {
@@ -260,6 +268,7 @@ static void geo_node_join_geometry_exec(GeoNod

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list