Blender V5.0
pointcloud_attributes.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
6
8#include "BKE_pointcloud.hh"
9
12
13namespace blender::bke {
14
15static void tag_position_changed(void *owner)
16{
17 PointCloud &points = *static_cast<PointCloud *>(owner);
18 points.tag_positions_changed();
19}
20
21static void tag_radius_changed(void *owner)
22{
23 PointCloud &points = *static_cast<PointCloud *>(owner);
24 points.tag_radii_changed();
25}
26
27static const auto &changed_tags()
28{
29 static Map<StringRef, AttrUpdateOnChange> attributes{{"position", tag_position_changed},
30 {"radius", tag_radius_changed}};
31 return attributes;
32}
33
34static const auto &builtin_attributes()
35{
36 static auto attributes = []() {
38
40 position.deletable = false;
41 map.add_new("position", std::move(position));
42
44 map.add_new("radius", std::move(radius));
45
46 return map;
47 }();
48 return attributes;
49}
50
52{
54 fn.domain_supported = [](const void * /*owner*/, const AttrDomain domain) {
55 return domain == AttrDomain::Point;
56 };
57 fn.domain_size = [](const void *owner, const AttrDomain domain) {
58 return domain == AttrDomain::Point ? static_cast<const PointCloud *>(owner)->totpoint : 0;
59 };
60 fn.builtin_domain_and_type = [](const void * /*owner*/,
61 const StringRef name) -> std::optional<AttributeDomainAndType> {
62 const AttrBuiltinInfo *info = builtin_attributes().lookup_ptr(name);
63 if (!info) {
64 return std::nullopt;
65 }
66 return AttributeDomainAndType{info->domain, info->type};
67 };
68 fn.get_builtin_default = [](const void * /*owner*/, StringRef name) -> GPointer {
69 const AttrBuiltinInfo &info = builtin_attributes().lookup(name);
70 return info.default_value;
71 };
72 fn.lookup = [](const void *owner, const StringRef name) -> GAttributeReader {
73 const PointCloud &pointcloud = *static_cast<const PointCloud *>(owner);
74 const AttributeStorage &storage = pointcloud.attribute_storage.wrap();
75 const Attribute *attribute = storage.lookup(name);
76 if (!attribute) {
77 return {};
78 }
79 return attribute_to_reader(*attribute, AttrDomain::Point, pointcloud.totpoint);
80 };
81 fn.adapt_domain = [](const void * /*owner*/,
82 const GVArray &varray,
83 const AttrDomain from_domain,
84 const AttrDomain to_domain) {
85 if (from_domain == to_domain && from_domain == AttrDomain::Point) {
86 return varray;
87 }
88 return GVArray{};
89 };
90 fn.foreach_attribute = [](const void *owner,
91 const FunctionRef<void(const AttributeIter &)> fn,
92 const AttributeAccessor &accessor) {
93 const PointCloud &pointcloud = *static_cast<const PointCloud *>(owner);
94 const AttributeStorage &storage = pointcloud.attribute_storage.wrap();
95 storage.foreach_with_stop([&](const Attribute &attribute) {
96 const auto get_fn = [&]() {
97 return attribute_to_reader(attribute, AttrDomain::Point, pointcloud.totpoint);
98 };
99 AttributeIter iter(attribute.name(), attribute.domain(), attribute.data_type(), get_fn);
100 iter.is_builtin = builtin_attributes().contains(attribute.name());
101 iter.accessor = &accessor;
102 fn(iter);
103 return !iter.is_stopped();
104 });
105 };
106 fn.lookup_validator = [](const void * /*owner*/, const StringRef name) -> AttributeValidator {
107 const AttrBuiltinInfo *info = builtin_attributes().lookup_ptr(name);
108 if (!info) {
109 return {};
110 }
111 return info->validator;
112 };
113 fn.lookup_for_write = [](void *owner, const StringRef name) -> GAttributeWriter {
114 PointCloud &pointcloud = *static_cast<PointCloud *>(owner);
115 AttributeStorage &storage = pointcloud.attribute_storage.wrap();
116 Attribute *attribute = storage.lookup(name);
117 if (!attribute) {
118 return {};
119 }
120 return attribute_to_writer(&pointcloud, changed_tags(), pointcloud.totpoint, *attribute);
121 };
122 fn.remove = [](void *owner, const StringRef name) -> bool {
123 PointCloud &pointcloud = *static_cast<PointCloud *>(owner);
124 AttributeStorage &storage = pointcloud.attribute_storage.wrap();
125 if (const AttrBuiltinInfo *info = builtin_attributes().lookup_ptr(name)) {
126 if (!info->deletable) {
127 return false;
128 }
129 }
130 const std::optional<AttrUpdateOnChange> fn = changed_tags().lookup_try(name);
131 const bool removed = storage.remove(name);
132 if (!removed) {
133 return false;
134 }
135 if (fn) {
136 (*fn)(owner);
137 }
138 return true;
139 };
140 fn.add = [](void *owner,
141 const StringRef name,
142 const AttrDomain domain,
143 const bke::AttrType type,
144 const AttributeInit &initializer) {
145 PointCloud &pointcloud = *static_cast<PointCloud *>(owner);
146 const int domain_size = pointcloud.totpoint;
147 AttributeStorage &storage = pointcloud.attribute_storage.wrap();
148 if (const AttrBuiltinInfo *info = builtin_attributes().lookup_ptr(name)) {
149 if (info->domain != domain || info->type != type) {
150 return false;
151 }
152 }
153 if (storage.lookup(name)) {
154 return false;
155 }
156 storage.add(name, domain, type, attribute_init_to_data(type, domain_size, initializer));
157 if (initializer.type != AttributeInit::Type::Construct) {
158 if (const std::optional<AttrUpdateOnChange> fn = changed_tags().lookup_try(name)) {
159 (*fn)(owner);
160 }
161 }
162 return true;
163 };
164
165 return fn;
166}
167
173
174} // namespace blender::bke
General operations for point clouds.
void add_new(const Key &key, const Value &value)
Definition BLI_map.hh:265
const AttributeAccessor * accessor
Attribute & add(std::string name, bke::AttrDomain domain, bke::AttrType data_type, Attribute::DataVariant data)
Attribute * lookup(StringRef name)
void foreach_with_stop(FunctionRef< bool(Attribute &)> fn)
static constexpr AttributeAccessorFunctions get_pointcloud_accessor_functions()
GAttributeReader attribute_to_reader(const Attribute &attribute, const AttrDomain domain, const int64_t domain_size)
Attribute::DataVariant attribute_init_to_data(const bke::AttrType data_type, const int64_t domain_size, const AttributeInit &initializer)
GAttributeWriter attribute_to_writer(void *owner, const Map< StringRef, AttrUpdateOnChange > &changed_tags, const int64_t domain_size, Attribute &attribute)
static const auto & builtin_attributes()
const AttributeAccessorFunctions & pointcloud_attribute_accessor_functions()
static void tag_radius_changed(void *owner)
static const auto & changed_tags()
static void tag_position_changed(void *owner)
const char * name
struct AttributeStorage attribute_storage