Part of #122398. This commit moves the runtime instances type to use `AttributeStorage`. Besides sharing some utility functions with point clouds, a resize method is implemented. Pull Request: https://projects.blender.org/blender/blender/pulls/140991
179 lines
6.3 KiB
C++
179 lines
6.3 KiB
C++
/* SPDX-FileCopyrightText: 2024 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
#include "DNA_pointcloud_types.h"
|
|
|
|
#include "BKE_attribute_legacy_convert.hh"
|
|
#include "BKE_attribute_storage.hh"
|
|
#include "BKE_pointcloud.hh"
|
|
|
|
#include "attribute_access_intern.hh"
|
|
#include "attribute_storage_access.hh"
|
|
|
|
namespace blender::bke {
|
|
|
|
static void tag_position_changed(void *owner)
|
|
{
|
|
PointCloud &points = *static_cast<PointCloud *>(owner);
|
|
points.tag_positions_changed();
|
|
}
|
|
|
|
static void tag_radius_changed(void *owner)
|
|
{
|
|
PointCloud &points = *static_cast<PointCloud *>(owner);
|
|
points.tag_radii_changed();
|
|
}
|
|
|
|
static const auto &changed_tags()
|
|
{
|
|
static Map<StringRef, AttrUpdateOnChange> attributes{{"position", tag_position_changed},
|
|
{"radius", tag_radius_changed}};
|
|
return attributes;
|
|
}
|
|
|
|
static const auto &builtin_attributes()
|
|
{
|
|
static auto attributes = []() {
|
|
Map<StringRef, AttrBuiltinInfo> map;
|
|
|
|
AttrBuiltinInfo position(bke::AttrDomain::Point, bke::AttrType::Float3);
|
|
position.deletable = false;
|
|
map.add_new("position", std::move(position));
|
|
|
|
AttrBuiltinInfo radius(bke::AttrDomain::Point, bke::AttrType::Float);
|
|
map.add_new("radius", std::move(radius));
|
|
|
|
return map;
|
|
}();
|
|
return attributes;
|
|
}
|
|
|
|
static constexpr AttributeAccessorFunctions get_pointcloud_accessor_functions()
|
|
{
|
|
AttributeAccessorFunctions fn{};
|
|
fn.domain_supported = [](const void * /*owner*/, const AttrDomain domain) {
|
|
return domain == AttrDomain::Point;
|
|
};
|
|
fn.domain_size = [](const void *owner, const AttrDomain domain) {
|
|
return domain == AttrDomain::Point ? static_cast<const PointCloud *>(owner)->totpoint : 0;
|
|
};
|
|
fn.builtin_domain_and_type = [](const void * /*owner*/,
|
|
const StringRef name) -> std::optional<AttributeDomainAndType> {
|
|
const AttrBuiltinInfo *info = builtin_attributes().lookup_ptr(name);
|
|
if (!info) {
|
|
return std::nullopt;
|
|
}
|
|
const std::optional<eCustomDataType> cd_type = attr_type_to_custom_data_type(info->type);
|
|
BLI_assert(cd_type.has_value());
|
|
return AttributeDomainAndType{info->domain, *cd_type};
|
|
};
|
|
fn.get_builtin_default = [](const void * /*owner*/, StringRef name) -> GPointer {
|
|
const AttrBuiltinInfo &info = builtin_attributes().lookup(name);
|
|
return info.default_value;
|
|
};
|
|
fn.lookup = [](const void *owner, const StringRef name) -> GAttributeReader {
|
|
const PointCloud &pointcloud = *static_cast<const PointCloud *>(owner);
|
|
const AttributeStorage &storage = pointcloud.attribute_storage.wrap();
|
|
const Attribute *attribute = storage.lookup(name);
|
|
if (!attribute) {
|
|
return {};
|
|
}
|
|
return attribute_to_reader(*attribute, AttrDomain::Point, pointcloud.totpoint);
|
|
};
|
|
fn.adapt_domain = [](const void * /*owner*/,
|
|
const GVArray &varray,
|
|
const AttrDomain from_domain,
|
|
const AttrDomain to_domain) {
|
|
if (from_domain == to_domain && from_domain == AttrDomain::Point) {
|
|
return varray;
|
|
}
|
|
return GVArray{};
|
|
};
|
|
fn.foreach_attribute = [](const void *owner,
|
|
const FunctionRef<void(const AttributeIter &)> fn,
|
|
const AttributeAccessor &accessor) {
|
|
const PointCloud &pointcloud = *static_cast<const PointCloud *>(owner);
|
|
const AttributeStorage &storage = pointcloud.attribute_storage.wrap();
|
|
storage.foreach_with_stop([&](const Attribute &attribute) {
|
|
const auto get_fn = [&]() {
|
|
return attribute_to_reader(attribute, AttrDomain::Point, pointcloud.totpoint);
|
|
};
|
|
const std::optional<eCustomDataType> cd_type = attr_type_to_custom_data_type(
|
|
attribute.data_type());
|
|
BLI_assert(cd_type.has_value());
|
|
AttributeIter iter(attribute.name(), attribute.domain(), *cd_type, get_fn);
|
|
iter.is_builtin = builtin_attributes().contains(attribute.name());
|
|
iter.accessor = &accessor;
|
|
fn(iter);
|
|
return !iter.is_stopped();
|
|
});
|
|
};
|
|
fn.lookup_validator = [](const void * /*owner*/, const StringRef name) -> AttributeValidator {
|
|
const AttrBuiltinInfo *info = builtin_attributes().lookup_ptr(name);
|
|
if (!info) {
|
|
return {};
|
|
}
|
|
return info->validator;
|
|
};
|
|
fn.lookup_for_write = [](void *owner, const StringRef name) -> GAttributeWriter {
|
|
PointCloud &pointcloud = *static_cast<PointCloud *>(owner);
|
|
AttributeStorage &storage = pointcloud.attribute_storage.wrap();
|
|
Attribute *attribute = storage.lookup(name);
|
|
if (!attribute) {
|
|
return {};
|
|
}
|
|
return attribute_to_writer(&pointcloud, changed_tags(), pointcloud.totpoint, *attribute);
|
|
};
|
|
fn.remove = [](void *owner, const StringRef name) -> bool {
|
|
PointCloud &pointcloud = *static_cast<PointCloud *>(owner);
|
|
AttributeStorage &storage = pointcloud.attribute_storage.wrap();
|
|
if (const AttrBuiltinInfo *info = builtin_attributes().lookup_ptr(name)) {
|
|
if (!info->deletable) {
|
|
return false;
|
|
}
|
|
}
|
|
const std::optional<AttrUpdateOnChange> fn = changed_tags().lookup_try(name);
|
|
const bool removed = storage.remove(name);
|
|
if (!removed) {
|
|
return false;
|
|
}
|
|
if (fn) {
|
|
(*fn)(owner);
|
|
}
|
|
return true;
|
|
};
|
|
fn.add = [](void *owner,
|
|
const StringRef name,
|
|
const AttrDomain domain,
|
|
const eCustomDataType data_type,
|
|
const AttributeInit &initializer) {
|
|
PointCloud &pointcloud = *static_cast<PointCloud *>(owner);
|
|
const int domain_size = pointcloud.totpoint;
|
|
AttributeStorage &storage = pointcloud.attribute_storage.wrap();
|
|
const std::optional<AttrType> type = custom_data_type_to_attr_type(data_type);
|
|
BLI_assert(type.has_value());
|
|
if (const AttrBuiltinInfo *info = builtin_attributes().lookup_ptr(name)) {
|
|
if (info->domain != domain || info->type != type) {
|
|
return false;
|
|
}
|
|
}
|
|
if (storage.lookup(name)) {
|
|
return false;
|
|
}
|
|
Attribute::DataVariant data = attribute_init_to_data(*type, domain_size, initializer);
|
|
storage.add(name, domain, *type, std::move(data));
|
|
return true;
|
|
};
|
|
|
|
return fn;
|
|
}
|
|
|
|
const AttributeAccessorFunctions &pointcloud_attribute_accessor_functions()
|
|
{
|
|
static constexpr AttributeAccessorFunctions fn = get_pointcloud_accessor_functions();
|
|
return fn;
|
|
}
|
|
|
|
} // namespace blender::bke
|