Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacques Lucke <jacques@blender.org>2021-02-09 13:44:58 +0300
committerJacques Lucke <jacques@blender.org>2021-02-09 13:45:04 +0300
commit17672efa0e02172b77eed95bfb977c914a5305b9 (patch)
tree12e7f61bd3dd47a9585cc45e473a3f36fcfca041 /source/blender/blenkernel/intern/attribute_access.cc
parent4601e3a5916c7746ad29d20add91651929c6f621 (diff)
Geometry Nodes: initial attribute interpolation between domains
This patch adds support for accessing corner attributes on the point domain. The immediate benefit of this is that now (interpolated) uv coordinates are available on points without having to use the Point Distribute node. This is also very useful for parts of T84297, because once we have vertex colors, those will also be available on points, even though they are stored per corner. Differential Revision: https://developer.blender.org/D10305
Diffstat (limited to 'source/blender/blenkernel/intern/attribute_access.cc')
-rw-r--r--source/blender/blenkernel/intern/attribute_access.cc101
1 files changed, 98 insertions, 3 deletions
diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc
index 772309349ff..cc833e094c8 100644
--- a/source/blender/blenkernel/intern/attribute_access.cc
+++ b/source/blender/blenkernel/intern/attribute_access.cc
@@ -17,6 +17,7 @@
#include <utility>
#include "BKE_attribute_access.hh"
+#include "BKE_attribute_math.hh"
#include "BKE_customdata.h"
#include "BKE_deform.h"
#include "BKE_geometry_set.hh"
@@ -323,6 +324,29 @@ template<typename T> class ArrayReadAttribute final : public ReadAttribute {
}
};
+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 &),
@@ -1344,10 +1368,10 @@ ReadAttributePtr GeometryComponent::attribute_try_get_for_read(
return {};
}
-ReadAttributePtr GeometryComponent::attribute_try_adapt_domain(ReadAttributePtr attribute,
- const AttributeDomain domain) const
+ReadAttributePtr GeometryComponent::attribute_try_adapt_domain(
+ ReadAttributePtr attribute, const AttributeDomain new_domain) const
{
- if (attribute && attribute->domain() == domain) {
+ if (attribute && attribute->domain() == new_domain) {
return attribute;
}
return {};
@@ -1765,4 +1789,75 @@ int MeshComponent::attribute_domain_size(const AttributeDomain domain) const
return 0;
}
+namespace blender::bke {
+
+template<typename T>
+void adapt_mesh_domain_corner_to_point_impl(const Mesh &mesh,
+ const TypedReadAttribute<T> &attribute,
+ MutableSpan<T> r_values)
+{
+ BLI_assert(r_values.size() == mesh.totvert);
+ attribute_math::DefaultMixer<T> mixer(r_values);
+
+ for (const int loop_index : IndexRange(mesh.totloop)) {
+ const T value = attribute[loop_index];
+ const MLoop &loop = mesh.mloop[loop_index];
+ const int point_index = loop.v;
+ mixer.mix_in(point_index, value);
+ }
+ mixer.finalize();
+}
+
+static ReadAttributePtr adapt_mesh_domain_corner_to_point(const Mesh &mesh,
+ ReadAttributePtr attribute)
+{
+ ReadAttributePtr new_attribute;
+ const CustomDataType data_type = attribute->custom_data_type();
+ attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
+ using T = decltype(dummy);
+ if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
+ /* We compute all interpolated values at once, because for this interpolation, one has to
+ * iterate over all loops anyway. */
+ Array<T> values(mesh.totvert);
+ adapt_mesh_domain_corner_to_point_impl<T>(mesh, *attribute, values);
+ new_attribute = std::make_unique<OwnedArrayReadAttribute<T>>(ATTR_DOMAIN_POINT,
+ std::move(values));
+ }
+ });
+ return new_attribute;
+}
+
+} // namespace blender::bke
+
+ReadAttributePtr MeshComponent::attribute_try_adapt_domain(ReadAttributePtr attribute,
+ const AttributeDomain new_domain) const
+{
+ if (!attribute) {
+ return {};
+ }
+ if (attribute->size() == 0) {
+ return {};
+ }
+ const AttributeDomain old_domain = attribute->domain();
+ if (old_domain == new_domain) {
+ return attribute;
+ }
+
+ switch (old_domain) {
+ case ATTR_DOMAIN_CORNER: {
+ switch (new_domain) {
+ case ATTR_DOMAIN_POINT:
+ return blender::bke::adapt_mesh_domain_corner_to_point(*mesh_, std::move(attribute));
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ return {};
+}
+
/** \} */