[Bf-blender-cvs] [d2c047999be] virtual-array-attributes: start implementing output attribute

Jacques Lucke noreply at git.blender.org
Thu Apr 15 16:13:11 CEST 2021


Commit: d2c047999be2bbc763ed47e2d13c34db8c589d3a
Author: Jacques Lucke
Date:   Thu Apr 15 13:07:52 2021 +0200
Branches: virtual-array-attributes
https://developer.blender.org/rBd2c047999be2bbc763ed47e2d13c34db8c589d3a

start implementing output attribute

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

M	source/blender/blenkernel/BKE_attribute_access.hh
M	source/blender/blenkernel/BKE_geometry_set.hh
M	source/blender/blenkernel/intern/attribute_access.cc
M	source/blender/nodes/NOD_type_conversions.hh
M	source/blender/nodes/geometry/nodes/node_geo_align_rotation_to_vector.cc
M	source/blender/nodes/geometry/nodes/node_geo_attribute_clamp.cc
M	source/blender/nodes/geometry/nodes/node_geo_attribute_color_ramp.cc
M	source/blender/nodes/geometry/nodes/node_geo_attribute_combine_xyz.cc
M	source/blender/nodes/geometry/nodes/node_geo_attribute_compare.cc
M	source/blender/nodes/geometry/nodes/node_geo_attribute_convert.cc
M	source/blender/nodes/geometry/nodes/node_geo_attribute_fill.cc
M	source/blender/nodes/geometry/nodes/node_geo_attribute_map_range.cc
M	source/blender/nodes/geometry/nodes/node_geo_attribute_math.cc
M	source/blender/nodes/geometry/nodes/node_geo_attribute_mix.cc
M	source/blender/nodes/geometry/nodes/node_geo_attribute_proximity.cc
M	source/blender/nodes/geometry/nodes/node_geo_attribute_sample_texture.cc
M	source/blender/nodes/geometry/nodes/node_geo_attribute_separate_xyz.cc
M	source/blender/nodes/geometry/nodes/node_geo_attribute_vector_math.cc
M	source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc
M	source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc
M	source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc
M	source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc
M	source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc
M	source/blender/nodes/geometry/nodes/node_geo_point_rotate.cc
M	source/blender/nodes/geometry/nodes/node_geo_point_separate.cc
M	source/blender/nodes/geometry/nodes/node_geo_point_translate.cc

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

diff --git a/source/blender/blenkernel/BKE_attribute_access.hh b/source/blender/blenkernel/BKE_attribute_access.hh
index e70eb8d3997..0dff3cfeda4 100644
--- a/source/blender/blenkernel/BKE_attribute_access.hh
+++ b/source/blender/blenkernel/BKE_attribute_access.hh
@@ -68,12 +68,19 @@ class OutputAttribute {
   AttributeDomain domain_;
   SaveF save_;
   std::optional<fn::GVMutableArray_GSpan> optional_span_varray_;
+  bool ignore_old_values_ = false;
 
  public:
   OutputAttribute() = default;
 
-  OutputAttribute(std::unique_ptr<GVMutableArray> varray, AttributeDomain domain, SaveF save)
-      : varray_(std::move(varray)), domain_(domain), save_(std::move(save))
+  OutputAttribute(std::unique_ptr<GVMutableArray> varray,
+                  AttributeDomain domain,
+                  SaveF save,
+                  const bool ignore_old_values)
+      : varray_(std::move(varray)),
+        domain_(domain),
+        save_(std::move(save)),
+        ignore_old_values_(ignore_old_values)
   {
   }
 
@@ -115,7 +122,8 @@ class OutputAttribute {
   fn::GMutableSpan as_span()
   {
     if (!optional_span_varray_.has_value()) {
-      optional_span_varray_.emplace(*varray_);
+      const bool materialize_old_values = !ignore_old_values_;
+      optional_span_varray_.emplace(*varray_, materialize_old_values);
     }
     fn::GVMutableArray_GSpan &span_varray = *optional_span_varray_;
     return span_varray;
diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh
index b5e1fa3d518..012b0be36a2 100644
--- a/source/blender/blenkernel/BKE_geometry_set.hh
+++ b/source/blender/blenkernel/BKE_geometry_set.hh
@@ -107,6 +107,8 @@ class GeometryComponent {
   /* Can only be used with supported domain types. */
   virtual int attribute_domain_size(const AttributeDomain domain) const;
 
+  bool attribute_is_deletable(const blender::StringRef attribute_name) const;
+
   /* Get read-only access to the highest priority attribute with the given name.
    * Returns null if the attribute does not exist. */
   blender::bke::ReadAttributeLookup attribute_try_get_for_read(
@@ -157,7 +159,7 @@ class GeometryComponent {
       const blender::StringRef attribute_name,
       const AttributeDomain domain,
       const CustomDataType data_type,
-      const void *default_value) const;
+      const void *default_value = nullptr) const;
 
   /* Get a typed read-only attribute for the given domain and type. */
   template<typename T>
@@ -188,13 +190,27 @@ class GeometryComponent {
       const CustomDataType data_type,
       const void *default_value = nullptr);
 
+  blender::bke::OutputAttribute attribute_try_get_for_output_only(
+      const blender::StringRef attribute_name,
+      const AttributeDomain domain,
+      const CustomDataType data_type);
+
   template<typename T>
   blender::bke::OutputAttribute_Typed<T> attribute_try_get_for_output(
+      const blender::StringRef attribute_name, const AttributeDomain domain, const T default_value)
+  {
+    const blender::fn::CPPType &cpp_type = blender::fn::CPPType::get<T>();
+    const CustomDataType data_type = blender::bke::cpp_type_to_custom_data_type(cpp_type);
+    return this->attribute_try_get_for_output(attribute_name, domain, data_type, &default_value);
+  }
+
+  template<typename T>
+  blender::bke::OutputAttribute_Typed<T> attribute_try_get_for_output_only(
       const blender::StringRef attribute_name, const AttributeDomain domain)
   {
     const blender::fn::CPPType &cpp_type = blender::fn::CPPType::get<T>();
     const CustomDataType data_type = blender::bke::cpp_type_to_custom_data_type(cpp_type);
-    return this->attribute_try_get_for_output(attribute_name, domain, data_type, nullptr);
+    return this->attribute_try_get_for_output_only(attribute_name, domain, data_type);
   }
 
  private:
diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc
index fad6f111458..d1322081f58 100644
--- a/source/blender/blenkernel/intern/attribute_access.cc
+++ b/source/blender/blenkernel/intern/attribute_access.cc
@@ -770,6 +770,9 @@ std::unique_ptr<blender::bke::GVArray> GeometryComponent::attribute_get_for_read
     return varray;
   }
   const blender::fn::CPPType *type = blender::bke::custom_data_type_to_cpp_type(data_type);
+  if (default_value == nullptr) {
+    default_value = type->default_value();
+  }
   const int domain_size = this->attribute_domain_size(domain);
   return std::make_unique<blender::fn::GVArray_For_SingleValue>(*type, domain_size, default_value);
 }
@@ -788,3 +791,82 @@ blender::bke::OutputAttribute GeometryComponent::attribute_try_get_for_output(
   /* TODO */
   return {};
 }
+
+class GVMutableAttribute_For_OutputAttribute
+    : public blender::fn::GVMutableArray_For_GMutableSpan {
+ public:
+  GeometryComponent *component;
+  std::string final_name;
+
+  GVMutableAttribute_For_OutputAttribute(GMutableSpan data,
+                                         GeometryComponent &component,
+                                         std::string final_name)
+      : blender::fn::GVMutableArray_For_GMutableSpan(data),
+        component(&component),
+        final_name(std::move(final_name))
+  {
+  }
+
+  ~GVMutableAttribute_For_OutputAttribute() override
+  {
+    type_->destruct_n(data_, size_);
+    MEM_freeN(data_);
+  }
+};
+
+blender::bke::OutputAttribute GeometryComponent::attribute_try_get_for_output_only(
+    const blender::StringRef attribute_name,
+    const AttributeDomain domain,
+    const CustomDataType data_type)
+{
+  using namespace blender;
+  using namespace blender::fn;
+  using namespace blender::bke;
+  const CPPType *cpp_type = custom_data_type_to_cpp_type(data_type);
+  BLI_assert(cpp_type != nullptr);
+
+  WriteAttributeLookup attribute = this->attribute_try_get_for_write(attribute_name);
+  if (attribute) {
+    if (attribute.domain == domain) {
+      if (attribute.varray->type() == *cpp_type) {
+        /* Best case, attribute with correct type and domain exists already. */
+        return OutputAttribute(std::move(attribute.varray), domain, {}, true);
+      }
+      if (!this->attribute_is_deletable(attribute_name)) {
+        /* Can't delete this attribute later on, so adapt the data type. */
+        const nodes::DataTypeConversions &conversions = nodes::get_implicit_type_conversions();
+        std::unique_ptr<GVMutableArray> varray = conversions.try_convert(
+            std::move(attribute.varray), *cpp_type);
+        return OutputAttribute(std::move(varray), domain, {}, true);
+      }
+    }
+  }
+  else if (this->attribute_try_create(attribute_name, domain, data_type)) {
+    /* There is no conflicting attribute, so create it and return the new attribute. */
+    attribute = this->attribute_try_get_for_write(attribute_name);
+    return OutputAttribute(std::move(attribute.varray), domain, {}, true);
+  }
+
+  const int domain_size = this->attribute_domain_size(domain);
+  void *data = MEM_mallocN_aligned(
+      cpp_type->size() * domain_size, cpp_type->alignment(), __func__);
+  cpp_type->construct_default_n(data, domain);
+  std::unique_ptr<GVMutableArray> varray =
+      std::make_unique<GVMutableAttribute_For_OutputAttribute>(
+          GMutableSpan{*cpp_type, data, domain_size}, *this, attribute_name);
+  auto save = [](OutputAttribute &attribute) {
+    GVMutableAttribute_For_OutputAttribute &varray =
+        dynamic_cast<GVMutableAttribute_For_OutputAttribute &>(attribute.varray());
+    varray.component->attribute_try_delete(varray.final_name);
+    varray.component->attribute_try_create(
+        varray.final_name, attribute.domain(), attribute.custom_data_type());
+    WriteAttributeLookup write_attribute = varray.component->attribute_try_get_for_write(
+        varray.final_name);
+    BUFFER_FOR_CPP_TYPE_VALUE(varray.type(), buffer);
+    for (const int i : IndexRange(varray.size())) {
+      varray.get(i, buffer);
+      write_attribute.varray->set_by_relocate(i, buffer);
+    }
+  };
+  return OutputAttribute(std::move(varray), domain, save, true);
+}
diff --git a/source/blender/nodes/NOD_type_conversions.hh b/source/blender/nodes/NOD_type_conversions.hh
index dc24e35d0f7..7b7e63bd1bc 100644
--- a/source/blender/nodes/NOD_type_conversions.hh
+++ b/source/blender/nodes/NOD_type_conversions.hh
@@ -75,6 +75,9 @@ class DataTypeConversions {
 
   std::unique_ptr<fn::GVArray> try_convert(std::unique_ptr<fn::GVArray> varray,
                                            const CPPType &to_type) const;
+
+  std::unique_ptr<fn::GVMutableArray> try_convert(std::unique_ptr<fn::GVMutableArray> varray,
+                                                  const CPPType &to_type) const;
 };
 
 const DataTypeConversions &get_implicit_type_conversions();
diff --git a/source/blender/nodes/geometry/nodes/node_geo_align_rotation_to_vector.cc b/source/blender/nodes/geometry/nodes/node_geo_align_rotation_to_vector.cc
index ffcbae6b5cd..0135b3da90b 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_align_rotation_to_vector.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_align_rotation_to_vector.cc
@@ -145,7 +145,7 @@ static void align_rotations_on_component(GeometryComponent &component,
                                                           node.storage;
 
   OutputAttribute_Typed<float3> rotations = component.attribute_try_get_for_output<float3>(
-      "rotation", ATTR_DOMAIN_POINT);
+      "rotation", ATTR_DOMAIN_POINT, {0, 0, 0});
   if (!rotations) {
     return;
   }
diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_clamp.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_clamp.cc
index 2bd36cfd119..0da3d92dc79 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_attribute_clamp.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_clamp.cc
@@ -160,7 +160,7 @@ static void clamp_attribute(GeometryComponent &component, const GeoNodeExecParam
   std::unique_ptr<GVArray> attribute_input = component.attribute_try_get_for_read(
       attribute_name, domain, data_type);
 
-  OutputAttribute attribute_result = component.attribute_try_get_for_output(
+  OutputAttribute attribute_result = component.attribute_t

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list