[Bf-blender-cvs] [4599cea15dc] master: Geometry Nodes: refactor instances component

Jacques Lucke noreply at git.blender.org
Tue May 4 10:18:57 CEST 2021


Commit: 4599cea15dcf7563bfbcb8be148ef5f89cf2dddd
Author: Jacques Lucke
Date:   Tue May 4 10:16:24 2021 +0200
Branches: master
https://developer.blender.org/rB4599cea15dcf7563bfbcb8be148ef5f89cf2dddd

Geometry Nodes: refactor instances component

The main goal of this refactor is to not store Object/Collection
pointers for every individual instance. Instead instances now
store a handle for the referenced data. The actual Object/Collection
pointers are stored in a new `InstanceReference` class.

This refactor also allows for some better optimizations further down
the line, because one does not have to search through all instances
anymore to find what data is instanced.

Furthermore, this refactor makes it easier to support instancing
`GeometrySet` or any other data that has to be owned by the
`InstancesComponent`.

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

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

M	source/blender/blenkernel/BKE_geometry_set.h
M	source/blender/blenkernel/BKE_geometry_set.hh
M	source/blender/blenkernel/intern/geometry_component_instances.cc
M	source/blender/blenkernel/intern/geometry_set_instances.cc
M	source/blender/blenkernel/intern/object_dupli.cc
M	source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
M	source/blender/nodes/geometry/nodes/node_geo_collection_info.cc
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_point_instance.cc
M	source/blender/nodes/geometry/nodes/node_geo_transform.cc

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

diff --git a/source/blender/blenkernel/BKE_geometry_set.h b/source/blender/blenkernel/BKE_geometry_set.h
index cb5526cd690..5f6a9ec7b91 100644
--- a/source/blender/blenkernel/BKE_geometry_set.h
+++ b/source/blender/blenkernel/BKE_geometry_set.h
@@ -43,19 +43,6 @@ void BKE_geometry_set_free(struct GeometrySet *geometry_set);
 
 bool BKE_geometry_set_has_instances(const struct GeometrySet *geometry_set);
 
-typedef enum InstancedDataType {
-  INSTANCE_DATA_TYPE_OBJECT = 0,
-  INSTANCE_DATA_TYPE_COLLECTION = 1,
-} InstancedDataType;
-
-typedef struct InstancedData {
-  InstancedDataType type;
-  union {
-    struct Object *object;
-    struct Collection *collection;
-  } data;
-} InstancedData;
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh
index 2d0f099e5ce..106af8172d1 100644
--- a/source/blender/blenkernel/BKE_geometry_set.hh
+++ b/source/blender/blenkernel/BKE_geometry_set.hh
@@ -30,6 +30,7 @@
 #include "BLI_map.hh"
 #include "BLI_set.hh"
 #include "BLI_user_counter.hh"
+#include "BLI_vector_set.hh"
 
 #include "BKE_attribute_access.hh"
 #include "BKE_geometry_set.h"
@@ -505,12 +506,81 @@ class CurveComponent : public GeometryComponent {
   const blender::bke::ComponentAttributeProviders *get_attribute_providers() const final;
 };
 
+class InstanceReference {
+ public:
+  enum class Type {
+    /**
+     * An empty instance. This allows an `InstanceReference` to be default constructed without
+     * being in an invalid state. There might also be other use cases that we haven't explored much
+     * yet (such as changing the instance later on, and "disabling" some instances).
+     */
+    None,
+    Object,
+    Collection,
+  };
+
+ private:
+  Type type_ = Type::None;
+  /** Depending on the type this is either null, an Object or Collection pointer. */
+  void *data_ = nullptr;
+
+ public:
+  InstanceReference() = default;
+
+  InstanceReference(Object &object) : type_(Type::Object), data_(&object)
+  {
+  }
+
+  InstanceReference(Collection &collection) : type_(Type::Collection), data_(&collection)
+  {
+  }
+
+  Type type() const
+  {
+    return type_;
+  }
+
+  Object &object() const
+  {
+    BLI_assert(type_ == Type::Object);
+    return *(Object *)data_;
+  }
+
+  Collection &collection() const
+  {
+    BLI_assert(type_ == Type::Collection);
+    return *(Collection *)data_;
+  }
+
+  uint64_t hash() const
+  {
+    return blender::get_default_hash(data_);
+  }
+
+  friend bool operator==(const InstanceReference &a, const InstanceReference &b)
+  {
+    return a.data_ == b.data_;
+  }
+};
+
 /** A geometry component that stores instances. */
 class InstancesComponent : public GeometryComponent {
  private:
-  blender::Vector<blender::float4x4> transforms_;
-  blender::Vector<int> ids_;
-  blender::Vector<InstancedData> instanced_data_;
+  /**
+   * Indexed set containing information about the data that is instanced.
+   * Actual instances store an index ("handle") into this set.
+   */
+  blender::VectorSet<InstanceReference> references_;
+
+  /** Index into `references_`. Determines what data is instanced. */
+  blender::Vector<int> instance_reference_handles_;
+  /** Transformation of the instances. */
+  blender::Vector<blender::float4x4> instance_transforms_;
+  /**
+   * IDs of the instances. They are used for consistency over multiple frames for things like
+   * motion blur.
+   */
+  blender::Vector<int> instance_ids_;
 
   /* These almost unique ids are generated based on `ids_`, which might not contain unique ids at
    * all. They are *almost* unique, because under certain very unlikely circumstances, they are not
@@ -525,14 +595,20 @@ class InstancesComponent : public GeometryComponent {
   GeometryComponent *copy() const override;
 
   void clear();
-  void add_instance(Object *object, blender::float4x4 transform, const int id = -1);
-  void add_instance(Collection *collection, blender::float4x4 transform, const int id = -1);
-  void add_instance(InstancedData data, blender::float4x4 transform, const int id = -1);
-
-  blender::Span<InstancedData> instanced_data() const;
-  blender::Span<blender::float4x4> transforms() const;
-  blender::Span<int> ids() const;
-  blender::MutableSpan<blender::float4x4> transforms();
+
+  void reserve(int min_capacity);
+
+  int add_reference(InstanceReference reference);
+  void add_instance(int instance_handle, const blender::float4x4 &transform, const int id = -1);
+
+  blender::Span<InstanceReference> references() const;
+
+  blender::Span<int> instance_reference_handles() const;
+  blender::MutableSpan<blender::float4x4> instance_transforms();
+  blender::Span<blender::float4x4> instance_transforms() const;
+  blender::MutableSpan<int> instance_ids();
+  blender::Span<int> instance_ids() const;
+
   int instances_amount() const;
 
   blender::Span<int> almost_unique_ids() const;
diff --git a/source/blender/blenkernel/intern/geometry_component_instances.cc b/source/blender/blenkernel/intern/geometry_component_instances.cc
index feb30e8575a..55025ed5ac9 100644
--- a/source/blender/blenkernel/intern/geometry_component_instances.cc
+++ b/source/blender/blenkernel/intern/geometry_component_instances.cc
@@ -42,72 +42,86 @@ InstancesComponent::InstancesComponent() : GeometryComponent(GEO_COMPONENT_TYPE_
 GeometryComponent *InstancesComponent::copy() const
 {
   InstancesComponent *new_component = new InstancesComponent();
-  new_component->transforms_ = transforms_;
-  new_component->instanced_data_ = instanced_data_;
-  new_component->ids_ = ids_;
+  new_component->instance_reference_handles_ = instance_reference_handles_;
+  new_component->instance_transforms_ = instance_transforms_;
+  new_component->instance_ids_ = instance_ids_;
+  new_component->references_ = references_;
   return new_component;
 }
 
-void InstancesComponent::clear()
+void InstancesComponent::reserve(int min_capacity)
 {
-  instanced_data_.clear();
-  transforms_.clear();
-  ids_.clear();
+  instance_reference_handles_.reserve(min_capacity);
+  instance_transforms_.reserve(min_capacity);
+  instance_ids_.reserve(min_capacity);
 }
 
-void InstancesComponent::add_instance(Object *object, float4x4 transform, const int id)
+void InstancesComponent::clear()
 {
-  InstancedData data;
-  data.type = INSTANCE_DATA_TYPE_OBJECT;
-  data.data.object = object;
-  this->add_instance(data, transform, id);
+  instance_reference_handles_.clear();
+  instance_transforms_.clear();
+  instance_ids_.clear();
+
+  references_.clear();
 }
 
-void InstancesComponent::add_instance(Collection *collection, float4x4 transform, const int id)
+void InstancesComponent::add_instance(const int instance_handle,
+                                      const float4x4 &transform,
+                                      const int id)
 {
-  InstancedData data;
-  data.type = INSTANCE_DATA_TYPE_COLLECTION;
-  data.data.collection = collection;
-  this->add_instance(data, transform, id);
+  BLI_assert(instance_handle >= 0);
+  BLI_assert(instance_handle < references_.size());
+  instance_reference_handles_.append(instance_handle);
+  instance_transforms_.append(transform);
+  instance_ids_.append(id);
 }
 
-void InstancesComponent::add_instance(InstancedData data, float4x4 transform, const int id)
+blender::Span<int> InstancesComponent::instance_reference_handles() const
 {
-  instanced_data_.append(data);
-  transforms_.append(transform);
-  ids_.append(id);
+  return instance_reference_handles_;
 }
 
-Span<InstancedData> InstancesComponent::instanced_data() const
+blender::MutableSpan<blender::float4x4> InstancesComponent::instance_transforms()
+{
+  return instance_transforms_;
+}
+blender::Span<blender::float4x4> InstancesComponent::instance_transforms() const
 {
-  return instanced_data_;
+  return instance_transforms_;
 }
 
-Span<float4x4> InstancesComponent::transforms() const
+blender::MutableSpan<int> InstancesComponent::instance_ids()
+{
+  return instance_ids_;
+}
+blender::Span<int> InstancesComponent::instance_ids() const
 {
-  return transforms_;
+  return instance_ids_;
 }
 
-Span<int> InstancesComponent::ids() const
+/**
+ * Returns a handle for the given reference.
+ * If the reference exists already, the handle of the existing reference is returned.
+ * Otherwise a new handle is added.
+ */
+int InstancesComponent::add_reference(InstanceReference reference)
 {
-  return ids_;
+  return references_.index_of_or_add_as(reference);
 }
 
-MutableSpan<float4x4> InstancesComponent::transforms()
+blender::Span<InstanceReference> InstancesComponent::references() const
 {
-  return transforms_;
+  return references_;
 }
 
 int InstancesComponent::instances_amount() const
 {
-  const int size = instanced_data_.size();
-  BLI_assert(transforms_.size() == size);
-  return size;
+  return instance_transforms_.size();
 }
 
 bool InstancesComponent::is_empty() const
 {
-  return transforms_.size() == 0;
+  return this->instance_reference_handles_.size() == 0;
 }
 
 bool InstancesComponent::owns_direct_data() const
@@ -178,8 +192,8 @@ static blender::Array<int> generate_unique_instance_ids(Span<int> original_ids)
 blender::Span<int> InstancesComponent::almost_unique_ids() const
 {
   std::lock_guard lock(almost_unique_ids_mutex_);
-  if (almost_unique_ids_.size() != ids_.size()) {
-    almost_unique_ids_ = generate_unique_instance_ids(ids_);
+  if (almost_unique_ids_.size() != instance_ids_.size()) {
+    almost_unique_ids_ = generate_unique_instance_ids(instance_ids_);
   }
   return almost_unique_ids_;
 }
diff --git a/source/blender/blenkernel/intern/geometry_set_instances.cc b/source/blender/blenkernel/intern/geometry_set_instances.cc
index 7e994b32ded..a792e268d5c 100644
--- a/source/blender/blenkernel/intern/geometry_set_instances.cc
+++ b/source/blender/blenkernel/intern/geometry_set_instances.cc
@@ -149,21 +149,28 @@ static void geometry_set_collect_recursive(const GeometrySet &geometry_set,
     const InstancesComponent &instances_component =
         *geometry_set.get_component_for_read<InstancesComponent>();
 
-    Span<float4x4> transforms = instances_component.transforms();
-    Span<InstancedData> instances = instances_component.instanced_data();
-    

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list