Blender V4.5
bake_items_socket.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
7#include "BKE_node.hh"
9#include "BKE_volume_grid.hh"
10
12
13namespace blender::bke::bake {
14
16 const fn::GField &field,
17 const AttrDomain domain,
18 const StringRef attribute_name)
19{
20 if (geometry.has_pointcloud()) {
21 PointCloudComponent &component = geometry.get_component_for_write<PointCloudComponent>();
22 try_capture_field_on_geometry(component, attribute_name, domain, field);
23 }
24 if (geometry.has_mesh()) {
25 MeshComponent &component = geometry.get_component_for_write<MeshComponent>();
26 try_capture_field_on_geometry(component, attribute_name, domain, field);
27 }
28 if (geometry.has_curves()) {
29 CurveComponent &component = geometry.get_component_for_write<CurveComponent>();
30 try_capture_field_on_geometry(component, attribute_name, domain, field);
31 }
32 if (geometry.has_grease_pencil()) {
33 GreasePencilComponent &component = geometry.get_component_for_write<GreasePencilComponent>();
34 try_capture_field_on_geometry(component, attribute_name, domain, field);
35 }
36 if (geometry.has_instances()) {
37 InstancesComponent &component = geometry.get_component_for_write<InstancesComponent>();
38 try_capture_field_on_geometry(component, attribute_name, domain, field);
39 }
40}
41
42static std::unique_ptr<BakeItem> move_common_socket_value_to_bake_item(
43 const bNodeSocketType &stype,
44 void *socket_value,
45 std::optional<StringRef> name,
46 Vector<GeometryBakeItem *> &r_geometry_bake_items)
47{
48 switch (stype.type) {
49 case SOCK_GEOMETRY: {
50 GeometrySet &geometry = *static_cast<GeometrySet *>(socket_value);
51 auto item = std::make_unique<GeometryBakeItem>(std::move(geometry));
52 r_geometry_bake_items.append(item.get());
53 return item;
54 }
55 case SOCK_STRING: {
56 auto &value_variant = *static_cast<SocketValueVariant *>(socket_value);
57 return std::make_unique<StringBakeItem>(value_variant.extract<std::string>());
58 }
59 case SOCK_FLOAT:
60 case SOCK_VECTOR:
61 case SOCK_INT:
62 case SOCK_BOOLEAN:
63 case SOCK_ROTATION:
64 case SOCK_MATRIX:
65 case SOCK_RGBA: {
66 auto &value_variant = *static_cast<SocketValueVariant *>(socket_value);
67 if (value_variant.is_context_dependent_field()) {
68 /* Not supported here because it's not known which geometry this field belongs to. */
69 return {};
70 }
71#ifdef WITH_OPENVDB
72 if (value_variant.is_volume_grid()) {
73 bke::GVolumeGrid grid = value_variant.get<bke::GVolumeGrid>();
74 if (name) {
75 grid.get_for_write().set_name(*name);
76 }
77 return std::make_unique<VolumeGridBakeItem>(
78 std::make_unique<bke::GVolumeGrid>(std::move(grid)));
79 }
80#else
81 UNUSED_VARS(name);
82#endif
83
84 value_variant.convert_to_single();
85 GPointer value = value_variant.get_single_ptr();
86 return std::make_unique<PrimitiveBakeItem>(*value.type(), value.get());
87 }
88 case SOCK_BUNDLE: {
89 auto &value_variant = *static_cast<SocketValueVariant *>(socket_value);
90 nodes::BundlePtr bundle_ptr = value_variant.extract<nodes::BundlePtr>();
91 auto bundle_bake_item = std::make_unique<BundleBakeItem>();
92 if (bundle_ptr) {
93 const nodes::Bundle &bundle = *bundle_ptr;
94 for (const nodes::Bundle::StoredItem &bundle_item : bundle.items()) {
95 if (std::unique_ptr<BakeItem> bake_item = move_common_socket_value_to_bake_item(
96 *bundle_item.type, bundle_item.value, std::nullopt, r_geometry_bake_items))
97 {
98 bundle_bake_item->items.append(BundleBakeItem::Item{
99 bundle_item.key, bundle_item.type->idname, std::move(bake_item)});
100 }
101 }
102 }
103 return bundle_bake_item;
104 }
105 default:
106 return {};
107 }
108}
109
111 const BakeSocketConfig &config,
112 BakeDataBlockMap *data_block_map)
113{
114 BLI_assert(socket_values.size() == config.types.size());
115 BLI_assert(socket_values.size() == config.geometries_by_attribute.size());
116
117 Array<std::unique_ptr<BakeItem>> bake_items(socket_values.size());
118
119 Vector<GeometryBakeItem *> geometry_bake_items;
120
121 /* Create geometry bake items first because they are used for field evaluation. */
122 for (const int i : socket_values.index_range()) {
123 const eNodeSocketDatatype socket_type = config.types[i];
124 if (socket_type != SOCK_GEOMETRY) {
125 continue;
126 }
127 void *socket_value = socket_values[i];
128 GeometrySet &geometry = *static_cast<GeometrySet *>(socket_value);
129 auto geometry_item = std::make_unique<GeometryBakeItem>(std::move(geometry));
130 geometry_bake_items.append(geometry_item.get());
131 bake_items[i] = std::move(geometry_item);
132 }
133
134 for (const int i : socket_values.index_range()) {
135 const eNodeSocketDatatype socket_type = config.types[i];
136 const bNodeSocketType &stype = *node_socket_type_find_static(socket_type);
137 void *socket_value = socket_values[i];
138 switch (socket_type) {
139 case SOCK_GEOMETRY: {
140 /* Handled already. */
141 break;
142 }
143 case SOCK_STRING: {
145 stype, socket_value, config.names[i], geometry_bake_items);
146 break;
147 }
148 case SOCK_FLOAT:
149 case SOCK_VECTOR:
150 case SOCK_INT:
151 case SOCK_BOOLEAN:
152 case SOCK_ROTATION:
153 case SOCK_MATRIX:
154 case SOCK_RGBA: {
155 auto &value_variant = *static_cast<SocketValueVariant *>(socket_value);
156 if (value_variant.is_context_dependent_field()) {
157 const fn::GField &field = value_variant.get<fn::GField>();
158 const AttrDomain domain = config.domains[i];
159 const std::string attribute_name = ".bake_" + std::to_string(i);
160 const Span<int> geometry_indices = config.geometries_by_attribute[i];
161 for (const int geometry_i : geometry_indices) {
162 BLI_assert(config.types[geometry_i] == SOCK_GEOMETRY);
164 static_cast<GeometryBakeItem *>(bake_items[geometry_i].get())->geometry;
165 capture_field_on_geometry_components(geometry, field, domain, attribute_name);
166 }
167 bake_items[i] = std::make_unique<AttributeBakeItem>(attribute_name);
168 }
169 else {
171 stype, socket_value, config.names[i], geometry_bake_items);
172 }
173 break;
174 }
175 case SOCK_BUNDLE: {
177 stype, socket_value, config.names[i], geometry_bake_items);
178 break;
179 }
180 default:
181 break;
182 }
183 }
184
185 /* Cleanup geometries after fields have been evaluated. */
186 for (GeometryBakeItem *geometry_item : geometry_bake_items) {
187 GeometryBakeItem::prepare_geometry_for_bake(geometry_item->geometry, data_block_map);
188 }
189
190 for (const int i : bake_items.index_range()) {
191 if (std::unique_ptr<BakeItem> &item = bake_items[i]) {
192 item->name = config.names[i];
193 }
194 }
195
196 return bake_items;
197}
198
202[[nodiscard]] static bool copy_bake_item_to_socket_value(
203 const BakeItem &bake_item,
204 const eNodeSocketDatatype socket_type,
205 const FunctionRef<std::shared_ptr<AttributeFieldInput>(const CPPType &type)>
206 make_attribute_field,
207 Map<std::string, std::string> &r_attribute_map,
208 void *r_value)
209{
210 switch (socket_type) {
211 case SOCK_GEOMETRY: {
212 if (const auto *item = dynamic_cast<const GeometryBakeItem *>(&bake_item)) {
213 new (r_value) GeometrySet(item->geometry);
214 return true;
215 }
216 return false;
217 }
218 case SOCK_FLOAT:
219 case SOCK_VECTOR:
220 case SOCK_INT:
221 case SOCK_BOOLEAN:
222 case SOCK_ROTATION:
223 case SOCK_MATRIX:
224 case SOCK_RGBA: {
225 const CPPType &base_type = *socket_type_to_geo_nodes_base_cpp_type(socket_type);
226 if (const auto *item = dynamic_cast<const PrimitiveBakeItem *>(&bake_item)) {
227 if (item->type() == base_type) {
228 auto *value_variant = new (r_value) SocketValueVariant();
229 value_variant->store_single(socket_type, item->value());
230 return true;
231 }
232 return false;
233 }
234 if (const auto *item = dynamic_cast<const AttributeBakeItem *>(&bake_item)) {
235 if (!make_attribute_field) {
236 return false;
237 }
238 std::shared_ptr<AttributeFieldInput> attribute_field = make_attribute_field(base_type);
239 r_attribute_map.add(item->name(), attribute_field->attribute_name());
240 fn::GField field{attribute_field};
241 new (r_value) SocketValueVariant(std::move(field));
242 return true;
243 }
244#ifdef WITH_OPENVDB
245 if (const auto *item = dynamic_cast<const VolumeGridBakeItem *>(&bake_item)) {
246 const GVolumeGrid &grid = *item->grid;
247 const VolumeGridType grid_type = grid->grid_type();
248 const std::optional<eNodeSocketDatatype> grid_socket_type = grid_type_to_socket_type(
249 grid_type);
250 if (!grid_socket_type) {
251 return false;
252 }
253 if (grid_socket_type == socket_type) {
254 new (r_value) SocketValueVariant(*item->grid);
255 return true;
256 }
257 return false;
258 }
259#endif
260 return false;
261 }
262 case SOCK_STRING: {
263 if (const auto *item = dynamic_cast<const StringBakeItem *>(&bake_item)) {
264 new (r_value) SocketValueVariant(std::string(item->value()));
265 return true;
266 }
267 return false;
268 }
269 case SOCK_BUNDLE: {
270 if (const auto *item = dynamic_cast<const BundleBakeItem *>(&bake_item)) {
272 nodes::Bundle &bundle = const_cast<nodes::Bundle &>(*bundle_ptr);
273 for (const BundleBakeItem::Item &item : item->items) {
275 if (!stype) {
276 return false;
277 }
278 if (!stype->geometry_nodes_cpp_type) {
279 return false;
280 }
283 *item.value, stype->type, {}, r_attribute_map, buffer))
284 {
285 return false;
286 }
287 bundle.add(item.key, *stype, buffer);
288 stype->geometry_nodes_cpp_type->destruct(buffer);
289 }
290 new (r_value) SocketValueVariant(std::move(bundle_ptr));
291 return true;
292 }
293 return false;
294 }
295 default:
296 return false;
297 }
298 return false;
299}
300
301static void rename_attributes(const Span<GeometrySet *> geometries,
302 const Map<std::string, std::string> &attribute_map)
303{
304 for (GeometrySet *geometry : geometries) {
310 {
311 if (!geometry->has(type)) {
312 continue;
313 }
314 /* Avoid write access on the geometry when unnecessary to avoid copying data-blocks. */
315 const AttributeAccessor attributes_read_only = *geometry->get_component(type)->attributes();
316 if (std::none_of(attribute_map.keys().begin(),
317 attribute_map.keys().end(),
318 [&](const StringRef name) { return attributes_read_only.contains(name); }))
319 {
320 continue;
321 }
322
323 GeometryComponent &component = geometry->get_component_for_write(type);
324 MutableAttributeAccessor attributes = *component.attributes_for_write();
325 for (const MapItem<std::string, std::string> &attribute_item : attribute_map.items()) {
326 attributes.rename(attribute_item.key, attribute_item.value);
327 }
328 }
329 }
330}
331
332static void restore_data_blocks(const Span<GeometrySet *> geometries,
333 BakeDataBlockMap *data_block_map)
334{
335 for (GeometrySet *main_geometry : geometries) {
336 GeometryBakeItem::try_restore_data_blocks(*main_geometry, data_block_map);
337 }
338}
339
340static void default_initialize_socket_value(const eNodeSocketDatatype socket_type, void *r_value)
341{
342 const bke::bNodeSocketType *typeinfo = bke::node_socket_type_find_static(socket_type);
343 if (typeinfo->geometry_nodes_default_cpp_value) {
345 r_value);
346 }
347 else {
348 typeinfo->geometry_nodes_cpp_type->value_initialize(r_value);
349 }
350}
351
353 const Span<BakeItem *> bake_items,
354 const BakeSocketConfig &config,
355 BakeDataBlockMap *data_block_map,
356 FunctionRef<std::shared_ptr<AttributeFieldInput>(int, const CPPType &)> make_attribute_field,
357 const Span<void *> r_socket_values)
358{
359 Map<std::string, std::string> attribute_map;
360
361 Vector<GeometrySet *> geometries;
362
363 for (const int i : bake_items.index_range()) {
364 const eNodeSocketDatatype socket_type = config.types[i];
365 BakeItem *bake_item = bake_items[i];
366 void *r_socket_value = r_socket_values[i];
367 if (bake_item == nullptr) {
368 default_initialize_socket_value(socket_type, r_socket_value);
369 continue;
370 }
372 *bake_item,
373 socket_type,
374 [&](const CPPType &attr_type) { return make_attribute_field(i, attr_type); },
375 attribute_map,
376 r_socket_value))
377 {
378 default_initialize_socket_value(socket_type, r_socket_value);
379 continue;
380 }
381 if (socket_type == SOCK_GEOMETRY) {
382 auto &item = *static_cast<GeometryBakeItem *>(bake_item);
383 item.geometry.clear();
384 geometries.append(static_cast<GeometrySet *>(r_socket_value));
385 }
386 }
387
388 rename_attributes(geometries, attribute_map);
389 restore_data_blocks(geometries, data_block_map);
390}
391
393 const Span<const BakeItem *> bake_items,
394 const BakeSocketConfig &config,
395 BakeDataBlockMap *data_block_map,
396 FunctionRef<std::shared_ptr<AttributeFieldInput>(int, const CPPType &)> make_attribute_field,
397 const Span<void *> r_socket_values)
398{
399 Map<std::string, std::string> attribute_map;
400 Vector<GeometrySet *> geometries;
401
402 for (const int i : bake_items.index_range()) {
403 const eNodeSocketDatatype socket_type = config.types[i];
404 const BakeItem *bake_item = bake_items[i];
405 void *r_socket_value = r_socket_values[i];
406 if (bake_item == nullptr) {
407 default_initialize_socket_value(socket_type, r_socket_value);
408 continue;
409 }
411 *bake_item,
412 socket_type,
413 [&](const CPPType &attr_type) { return make_attribute_field(i, attr_type); },
414 attribute_map,
415 r_socket_value))
416 {
417 default_initialize_socket_value(socket_type, r_socket_value);
418 continue;
419 }
420 if (socket_type == SOCK_GEOMETRY) {
421 geometries.append(static_cast<GeometrySet *>(r_socket_value));
422 }
423 }
424
425 rename_attributes(geometries, attribute_map);
426 restore_data_blocks(geometries, data_block_map);
427}
428
429} // namespace blender::bke::bake
VolumeGridType
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BUFFER_FOR_CPP_TYPE_VALUE(type, variable_name)
#define UNUSED_VARS(...)
eNodeSocketDatatype
@ SOCK_INT
@ SOCK_VECTOR
@ SOCK_BOOLEAN
@ SOCK_MATRIX
@ SOCK_FLOAT
@ SOCK_BUNDLE
@ SOCK_GEOMETRY
@ SOCK_ROTATION
@ SOCK_STRING
@ SOCK_RGBA
SubIterator begin() const
Definition BLI_map.hh:768
SubIterator end() const
Definition BLI_map.hh:778
int64_t size() const
IndexRange index_range() const
Definition BLI_array.hh:349
void copy_construct(const void *src, void *dst) const
void destruct(void *ptr) const
void value_initialize(void *ptr) const
const CPPType * type() const
const void * get() const
bool add(const Key &key, const Value &value)
Definition BLI_map.hh:295
KeyIterator keys() const &
Definition BLI_map.hh:875
ItemIterator items() const &
Definition BLI_map.hh:902
constexpr int64_t size() const
Definition BLI_span.hh:252
constexpr IndexRange index_range() const
Definition BLI_span.hh:401
void append(const T &value)
virtual std::optional< MutableAttributeAccessor > attributes_for_write()
bool rename(StringRef old_attribute_id, StringRef new_attribute_id)
void store_single(eNodeSocketDatatype socket_type, const void *value)
static void prepare_geometry_for_bake(GeometrySet &geometry, BakeDataBlockMap *data_block_map)
Definition bake_items.cc:56
static void try_restore_data_blocks(GeometrySet &geometry, BakeDataBlockMap *data_block_map)
bool add(const SocketInterfaceKey &key, const bke::bNodeSocketType &type, const void *value)
Span< StoredItem > items() const
Array< std::unique_ptr< BakeItem > > move_socket_values_to_bake_items(Span< void * > socket_values, const BakeSocketConfig &config, BakeDataBlockMap *data_block_map)
static std::unique_ptr< BakeItem > move_common_socket_value_to_bake_item(const bNodeSocketType &stype, void *socket_value, std::optional< StringRef > name, Vector< GeometryBakeItem * > &r_geometry_bake_items)
static void restore_data_blocks(const Span< GeometrySet * > geometries, BakeDataBlockMap *data_block_map)
void copy_bake_items_to_socket_values(Span< const BakeItem * > bake_items, const BakeSocketConfig &config, BakeDataBlockMap *data_block_map, FunctionRef< std::shared_ptr< AttributeFieldInput >(int, const CPPType &)> make_attribute_field, Span< void * > r_socket_values)
void move_bake_items_to_socket_values(Span< BakeItem * > bake_items, const BakeSocketConfig &config, BakeDataBlockMap *data_block_map, FunctionRef< std::shared_ptr< AttributeFieldInput >(int socket_index, const CPPType &)> make_attribute_field, Span< void * > r_socket_values)
static void rename_attributes(const Span< GeometrySet * > geometries, const Map< std::string, std::string > &attribute_map)
static bool copy_bake_item_to_socket_value(const BakeItem &bake_item, const eNodeSocketDatatype socket_type, const FunctionRef< std::shared_ptr< AttributeFieldInput >(const CPPType &type)> make_attribute_field, Map< std::string, std::string > &r_attribute_map, void *r_value)
static void capture_field_on_geometry_components(GeometrySet &geometry, const fn::GField &field, const AttrDomain domain, const StringRef attribute_name)
static void default_initialize_socket_value(const eNodeSocketDatatype socket_type, void *r_value)
std::optional< eNodeSocketDatatype > grid_type_to_socket_type(VolumeGridType type)
Definition node.cc:5503
bool try_capture_field_on_geometry(MutableAttributeAccessor attributes, const fn::FieldContext &field_context, const StringRef attribute_id, AttrDomain domain, const fn::Field< bool > &selection, const fn::GField &field)
const CPPType * socket_type_to_geo_nodes_base_cpp_type(eNodeSocketDatatype type)
Definition node.cc:5413
bNodeSocketType * node_socket_type_find(StringRef idname)
Definition node.cc:2794
bNodeSocketType * node_socket_type_find_static(int type, int subtype=0)
Definition node.cc:2803
ImplicitSharingPtr< Bundle > BundlePtr
Defines a socket type.
Definition BKE_node.hh:152
const blender::CPPType * geometry_nodes_cpp_type
Definition BKE_node.hh:203
const void * geometry_nodes_default_cpp_value
Definition BKE_node.hh:207
eNodeSocketDatatype type
Definition BKE_node.hh:187
Vector< Vector< int, 1 > > geometries_by_attribute
i
Definition text_draw.cc:230