[Bf-blender-cvs] [9ce950daabb] master: Cleanup: Move geometry component implementations to separate files

Hans Goudey noreply at git.blender.org
Mon Mar 8 17:41:31 CET 2021


Commit: 9ce950daabbf580fc1b8da2c325ba2903e02b62e
Author: Hans Goudey
Date:   Mon Mar 8 11:41:23 2021 -0500
Branches: master
https://developer.blender.org/rB9ce950daabbf580fc1b8da2c325ba2903e02b62e

Cleanup: Move geometry component implementations to separate files

Currently the implementations specific to each geometry type are in
the same file. This makes it difficult to tell which code is generic
for all component types and which is specific to a certain type.
The two files, `attribute_access.cc`, and `geometry_set.cc` are
also getting quite long.

This commit splits up the implementation for every geometry component,
and adds an internal header file for the common parts of the attribute
access code. This was discussed with Jacques Lucke.

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

A	source/blender/blenkernel/intern/attribute_access_intern.hh
A	source/blender/blenkernel/intern/geometry_component_instances.cc
A	source/blender/blenkernel/intern/geometry_component_mesh.cc
A	source/blender/blenkernel/intern/geometry_component_pointcloud.cc
A	source/blender/blenkernel/intern/geometry_component_volume.cc

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

diff --git a/source/blender/blenkernel/intern/attribute_access_intern.hh b/source/blender/blenkernel/intern/attribute_access_intern.hh
new file mode 100644
index 00000000000..299da4c97fe
--- /dev/null
+++ b/source/blender/blenkernel/intern/attribute_access_intern.hh
@@ -0,0 +1,499 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "BLI_map.hh"
+#include "BLI_span.hh"
+#include "BLI_string_ref.hh"
+#include "BLI_vector.hh"
+
+namespace blender::bke {
+
+class ConstantReadAttribute final : public ReadAttribute {
+ private:
+  void *value_;
+
+ public:
+  ConstantReadAttribute(AttributeDomain domain,
+                        const int64_t size,
+                        const CPPType &type,
+                        const void *value)
+      : ReadAttribute(domain, type, size)
+  {
+    value_ = MEM_mallocN_aligned(type.size(), type.alignment(), __func__);
+    type.copy_to_uninitialized(value, value_);
+  }
+
+  ~ConstantReadAttribute() override
+  {
+    this->cpp_type_.destruct(value_);
+    MEM_freeN(value_);
+  }
+
+  void get_internal(const int64_t UNUSED(index), void *r_value) const override
+  {
+    this->cpp_type_.copy_to_uninitialized(value_, r_value);
+  }
+
+  void initialize_span() const override
+  {
+    const int element_size = cpp_type_.size();
+    array_buffer_ = MEM_mallocN_aligned(size_ * element_size, cpp_type_.alignment(), __func__);
+    array_is_temporary_ = true;
+    cpp_type_.fill_uninitialized(value_, array_buffer_, size_);
+  }
+};
+
+template<typename T> class ArrayReadAttribute final : public ReadAttribute {
+ private:
+  Span<T> data_;
+
+ public:
+  ArrayReadAttribute(AttributeDomain domain, Span<T> data)
+      : ReadAttribute(domain, CPPType::get<T>(), data.size()), data_(data)
+  {
+  }
+
+  void get_internal(const int64_t index, void *r_value) const override
+  {
+    new (r_value) T(data_[index]);
+  }
+
+  void initialize_span() const override
+  {
+    /* The data will not be modified, so this const_cast is fine. */
+    array_buffer_ = const_cast<T *>(data_.data());
+    array_is_temporary_ = false;
+  }
+};
+
+template<typename T> class OwnedArrayReadAttribute final : public ReadAttribute {
+ private:
+  Array<T> data_;
+
+ public:
+  OwnedArrayReadAttribute(AttributeDomain domain, Array<T> data)
+      : ReadAttribute(domain, CPPType::get<T>(), data.size()), data_(std::move(data))
+  {
+  }
+
+  void get_internal(const int64_t index, void *r_value) const override
+  {
+    new (r_value) T(data_[index]);
+  }
+
+  void initialize_span() const override
+  {
+    /* The data will not be modified, so this const_cast is fine. */
+    array_buffer_ = const_cast<T *>(data_.data());
+    array_is_temporary_ = false;
+  }
+};
+
+template<typename StructT, typename ElemT, ElemT (*GetFunc)(const StructT &)>
+class DerivedArrayReadAttribute final : public ReadAttribute {
+ private:
+  blender::Span<StructT> data_;
+
+ public:
+  DerivedArrayReadAttribute(AttributeDomain domain, Span<StructT> data)
+      : ReadAttribute(domain, CPPType::get<ElemT>(), data.size()), data_(data)
+  {
+  }
+
+  void get_internal(const int64_t index, void *r_value) const override
+  {
+    const StructT &struct_value = data_[index];
+    const ElemT value = GetFunc(struct_value);
+    new (r_value) ElemT(value);
+  }
+};
+
+template<typename T> class ArrayWriteAttribute final : public WriteAttribute {
+ private:
+  MutableSpan<T> data_;
+
+ public:
+  ArrayWriteAttribute(AttributeDomain domain, MutableSpan<T> data)
+      : WriteAttribute(domain, CPPType::get<T>(), data.size()), data_(data)
+  {
+  }
+
+  void get_internal(const int64_t index, void *r_value) const override
+  {
+    new (r_value) T(data_[index]);
+  }
+
+  void set_internal(const int64_t index, const void *value) override
+  {
+    data_[index] = *reinterpret_cast<const T *>(value);
+  }
+
+  void initialize_span(const bool UNUSED(write_only)) override
+  {
+    array_buffer_ = data_.data();
+    array_is_temporary_ = false;
+  }
+
+  void apply_span_if_necessary() override
+  {
+    /* Do nothing, because the span contains the attribute itself already. */
+  }
+};
+
+template<typename StructT,
+         typename ElemT,
+         ElemT (*GetFunc)(const StructT &),
+         void (*SetFunc)(StructT &, const ElemT &)>
+class DerivedArrayWriteAttribute final : public WriteAttribute {
+ private:
+  blender::MutableSpan<StructT> data_;
+
+ public:
+  DerivedArrayWriteAttribute(AttributeDomain domain, blender::MutableSpan<StructT> data)
+      : WriteAttribute(domain, CPPType::get<ElemT>(), data.size()), data_(data)
+  {
+  }
+
+  void get_internal(const int64_t index, void *r_value) const override
+  {
+    const StructT &struct_value = data_[index];
+    const ElemT value = GetFunc(struct_value);
+    new (r_value) ElemT(value);
+  }
+
+  void set_internal(const int64_t index, const void *value) override
+  {
+    StructT &struct_value = data_[index];
+    const ElemT &typed_value = *reinterpret_cast<const ElemT *>(value);
+    SetFunc(struct_value, typed_value);
+  }
+};
+
+/**
+ * Utility to group together multiple functions that are used to access custom data on geometry
+ * components in a generic way.
+ */
+struct CustomDataAccessInfo {
+  using CustomDataGetter = CustomData *(*)(GeometryComponent &component);
+  using ConstCustomDataGetter = const CustomData *(*)(const GeometryComponent &component);
+  using UpdateCustomDataPointers = void (*)(GeometryComponent &component);
+
+  CustomDataGetter get_custom_data;
+  ConstCustomDataGetter get_const_custom_data;
+  UpdateCustomDataPointers update_custom_data_pointers;
+};
+
+/**
+ * A #BuiltinAttributeProvider is responsible for exactly one attribute on a geometry component.
+ * The attribute is identified by its name and has a fixed domain and type. Builtin attributes do
+ * not follow the same loose rules as other attributes, because they are mapped to internal
+ * "legacy" data structures. For example, some builtin attributes cannot be deleted. */
+class BuiltinAttributeProvider {
+ public:
+  /* Some utility enums to avoid hard to read booleans in function calls. */
+  enum CreatableEnum {
+    Creatable,
+    NonCreatable,
+  };
+  enum WritableEnum {
+    Writable,
+    Readonly,
+  };
+  enum DeletableEnum {
+    Deletable,
+    NonDeletable,
+  };
+
+ protected:
+  const std::string name_;
+  const AttributeDomain domain_;
+  const CustomDataType data_type_;
+  const CreatableEnum createable_;
+  const WritableEnum writable_;
+  const DeletableEnum deletable_;
+
+ public:
+  BuiltinAttributeProvider(std::string name,
+                           const AttributeDomain domain,
+                           const CustomDataType data_type,
+                           const CreatableEnum createable,
+                           const WritableEnum writable,
+                           const DeletableEnum deletable)
+      : name_(std::move(name)),
+        domain_(domain),
+        data_type_(data_type),
+        createable_(createable),
+        writable_(writable),
+        deletable_(deletable)
+  {
+  }
+
+  virtual ReadAttributePtr try_get_for_read(const GeometryComponent &component) const = 0;
+  virtual WriteAttributePtr try_get_for_write(GeometryComponent &component) const = 0;
+  virtual bool try_delete(GeometryComponent &component) const = 0;
+  virtual bool try_create(GeometryComponent &UNUSED(component)) const = 0;
+  virtual bool exists(const GeometryComponent &component) const = 0;
+
+  blender::StringRefNull name() const
+  {
+    return name_;
+  }
+
+  AttributeDomain domain() const
+  {
+    return domain_;
+  }
+
+  CustomDataType data_type() const
+  {
+    return data_type_;
+  }
+};
+
+/**
+ * A #DynamicAttributesProvider manages a set of named attributes on a geometry component. Each
+ * attribute has a name, domain and type.
+ */
+class DynamicAttributesProvider {
+ public:
+  virtual ReadAttributePtr try_get_for_read(const GeometryComponent &component,
+                                            const blender::StringRef attribute_name) const = 0;
+  virtual WriteAttributePtr try_get_for_write(GeometryComponent &component,
+                                              const blender::StringRef attribute_name) const = 0;
+  virtual bool try_delete(GeometryComponent &component,
+                          const blender::StringRef attribute_name) const = 0;
+  virtual bool try_create(GeometryComponent &UNUSED(component),
+                          const blender::StringRef UNUSED(attribute_name),
+                          const AttributeDomain UNUSED(domain),
+                          const CustomDataType UNUSED(data_type)) const
+  {
+    /* Some providers should not create new attributes. */
+    return false;
+  };
+
+  virtual bool foreach_attribute(const GeometryComponent &component,
+                                 const AttributeForeachCallback callback) const = 0;
+  virtual void supported_domains(blender::Vector<AttributeDomain> &r_domains) const = 0;
+};
+
+/**
+ * This is the attribute provider for most user generated attributes.
+ */
+class CustomDataAttributeProvider final : public DynamicAttributesProvider {
+ private:
+  static constexpr uint64_t supported_types_mask = CD_MASK_PROP_FLOAT | CD_MASK_PROP_FLOAT2 |
+                                                   CD_MASK_PROP_FLOAT3 | CD_MASK_PROP_INT32 |
+                                                   CD_MASK_PROP_COLOR | CD_MASK_PROP_BOOL;
+  const AttributeDomain domain_;
+  const CustomDataAccessInfo custom_data_access_;
+
+ public:
+  Cust

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list