Blender V4.3
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
11namespace blender::bke::bake {
12
14 const BakeSocketConfig &config,
15 BakeDataBlockMap *data_block_map)
16{
17 BLI_assert(socket_values.size() == config.types.size());
18 BLI_assert(socket_values.size() == config.geometries_by_attribute.size());
19
20 Array<std::unique_ptr<BakeItem>> bake_items(socket_values.size());
21
22 /* Create geometry bake items first because they are used for field evaluation. */
23 for (const int i : socket_values.index_range()) {
24 const eNodeSocketDatatype socket_type = config.types[i];
25 if (socket_type != SOCK_GEOMETRY) {
26 continue;
27 }
28 void *socket_value = socket_values[i];
29 GeometrySet &geometry = *static_cast<GeometrySet *>(socket_value);
30 bake_items[i] = std::make_unique<GeometryBakeItem>(std::move(geometry));
31 }
32
33 for (const int i : socket_values.index_range()) {
34 const eNodeSocketDatatype socket_type = config.types[i];
35 void *socket_value = socket_values[i];
36 switch (socket_type) {
37 case SOCK_GEOMETRY: {
38 /* Handled already. */
39 break;
40 }
41 case SOCK_STRING: {
42 auto &value_variant = *static_cast<SocketValueVariant *>(socket_value);
43 bake_items[i] = std::make_unique<StringBakeItem>(value_variant.extract<std::string>());
44 break;
45 }
46 case SOCK_FLOAT:
47 case SOCK_VECTOR:
48 case SOCK_INT:
49 case SOCK_BOOLEAN:
50 case SOCK_ROTATION:
51 case SOCK_MATRIX:
52 case SOCK_RGBA: {
53 auto &value_variant = *static_cast<SocketValueVariant *>(socket_value);
54 if (value_variant.is_context_dependent_field()) {
55 const fn::GField &field = value_variant.get<fn::GField>();
56 const AttrDomain domain = config.domains[i];
57 const std::string attribute_name = ".bake_" + std::to_string(i);
58 const Span<int> geometry_indices = config.geometries_by_attribute[i];
59 for (const int geometry_i : geometry_indices) {
60 BLI_assert(config.types[geometry_i] == SOCK_GEOMETRY);
61 GeometrySet &geometry =
62 static_cast<GeometryBakeItem *>(bake_items[geometry_i].get())->geometry;
63 if (geometry.has_pointcloud()) {
64 PointCloudComponent &component =
65 geometry.get_component_for_write<PointCloudComponent>();
66 try_capture_field_on_geometry(component, attribute_name, domain, field);
67 }
68 if (geometry.has_mesh()) {
69 MeshComponent &component = geometry.get_component_for_write<MeshComponent>();
70 try_capture_field_on_geometry(component, attribute_name, domain, field);
71 }
72 if (geometry.has_curves()) {
73 CurveComponent &component = geometry.get_component_for_write<CurveComponent>();
74 try_capture_field_on_geometry(component, attribute_name, domain, field);
75 }
76 if (geometry.has_grease_pencil()) {
77 GreasePencilComponent &component =
78 geometry.get_component_for_write<GreasePencilComponent>();
79 try_capture_field_on_geometry(component, attribute_name, domain, field);
80 }
81 if (geometry.has_instances()) {
82 InstancesComponent &component =
83 geometry.get_component_for_write<InstancesComponent>();
84 try_capture_field_on_geometry(component, attribute_name, domain, field);
85 }
86 }
87 bake_items[i] = std::make_unique<AttributeBakeItem>(attribute_name);
88 }
89#ifdef WITH_OPENVDB
90 else if (value_variant.is_volume_grid()) {
91 bke::GVolumeGrid grid = value_variant.get<bke::GVolumeGrid>();
92 grid.get_for_write().set_name(config.names[i]);
93 bake_items[i] = std::make_unique<VolumeGridBakeItem>(
94 std::make_unique<bke::GVolumeGrid>(std::move(grid)));
95 }
96#endif
97 else {
98 value_variant.convert_to_single();
99 GPointer value = value_variant.get_single_ptr();
100 bake_items[i] = std::make_unique<PrimitiveBakeItem>(*value.type(), value.get());
101 }
102 break;
103 }
104 default:
105 break;
106 }
107 }
108
109 /* Cleanup geometries after fields have been evaluated. */
110 for (const int i : config.types.index_range()) {
111 const eNodeSocketDatatype socket_type = config.types[i];
112 if (socket_type != SOCK_GEOMETRY) {
113 continue;
114 }
115 GeometrySet &geometry = static_cast<GeometryBakeItem *>(bake_items[i].get())->geometry;
116 GeometryBakeItem::prepare_geometry_for_bake(geometry, data_block_map);
117 }
118
119 for (const int i : bake_items.index_range()) {
120 if (std::unique_ptr<BakeItem> &item = bake_items[i]) {
121 item->name = config.names[i];
122 }
123 }
124
125 return bake_items;
126}
127
128[[nodiscard]] static bool copy_bake_item_to_socket_value(
129 const BakeItem &bake_item,
130 const eNodeSocketDatatype socket_type,
131 const FunctionRef<std::shared_ptr<AttributeFieldInput>(const CPPType &type)>
132 make_attribute_field,
133 Map<std::string, std::string> &r_attribute_map,
134 void *r_value)
135{
136 switch (socket_type) {
137 case SOCK_GEOMETRY: {
138 if (const auto *item = dynamic_cast<const GeometryBakeItem *>(&bake_item)) {
139 new (r_value) GeometrySet(item->geometry);
140 return true;
141 }
142 return false;
143 }
144 case SOCK_FLOAT:
145 case SOCK_VECTOR:
146 case SOCK_INT:
147 case SOCK_BOOLEAN:
148 case SOCK_ROTATION:
149 case SOCK_MATRIX:
150 case SOCK_RGBA: {
151 const CPPType &base_type = *socket_type_to_geo_nodes_base_cpp_type(socket_type);
152 if (const auto *item = dynamic_cast<const PrimitiveBakeItem *>(&bake_item)) {
153 if (item->type() == base_type) {
154 auto *value_variant = new (r_value) SocketValueVariant();
155 value_variant->store_single(socket_type, item->value());
156 return true;
157 }
158 return false;
159 }
160 if (const auto *item = dynamic_cast<const AttributeBakeItem *>(&bake_item)) {
161 std::shared_ptr<AttributeFieldInput> attribute_field = make_attribute_field(base_type);
162 r_attribute_map.add(item->name(), attribute_field->attribute_name());
163 fn::GField field{attribute_field};
164 new (r_value) SocketValueVariant(std::move(field));
165 return true;
166 }
167#ifdef WITH_OPENVDB
168 if (const auto *item = dynamic_cast<const VolumeGridBakeItem *>(&bake_item)) {
169 const GVolumeGrid &grid = *item->grid;
170 const VolumeGridType grid_type = grid->grid_type();
171 const std::optional<eNodeSocketDatatype> grid_socket_type = grid_type_to_socket_type(
172 grid_type);
173 if (!grid_socket_type) {
174 return false;
175 }
176 if (grid_socket_type == socket_type) {
177 new (r_value) SocketValueVariant(*item->grid);
178 return true;
179 }
180 return false;
181 }
182#endif
183 return false;
184 }
185 case SOCK_STRING: {
186 if (const auto *item = dynamic_cast<const StringBakeItem *>(&bake_item)) {
187 new (r_value) SocketValueVariant(std::string(item->value()));
188 return true;
189 }
190 return false;
191 }
192 default:
193 return false;
194 }
195 return false;
196}
197
198static void rename_attributes(const Span<GeometrySet *> geometries,
199 const Map<std::string, std::string> &attribute_map)
200{
201 for (GeometrySet *geometry : geometries) {
207 {
208 if (!geometry->has(type)) {
209 continue;
210 }
211 /* Avoid write access on the geometry when unnecessary to avoid copying data-blocks. */
212 const AttributeAccessor attributes_read_only = *geometry->get_component(type)->attributes();
213 if (std::none_of(attribute_map.keys().begin(),
214 attribute_map.keys().end(),
215 [&](const StringRef name) { return attributes_read_only.contains(name); }))
216 {
217 continue;
218 }
219
220 GeometryComponent &component = geometry->get_component_for_write(type);
221 MutableAttributeAccessor attributes = *component.attributes_for_write();
222 for (const MapItem<std::string, std::string> &attribute_item : attribute_map.items()) {
223 attributes.rename(attribute_item.key, attribute_item.value);
224 }
225 }
226 }
227}
228
229static void restore_data_blocks(const Span<GeometrySet *> geometries,
230 BakeDataBlockMap *data_block_map)
231{
232 for (GeometrySet *main_geometry : geometries) {
233 GeometryBakeItem::try_restore_data_blocks(*main_geometry, data_block_map);
234 }
235}
236
237static void default_initialize_socket_value(const eNodeSocketDatatype socket_type, void *r_value)
238{
239 const char *socket_idname = bke::node_static_socket_type(socket_type, 0);
240 const bke::bNodeSocketType *typeinfo = bke::node_socket_type_find(socket_idname);
241 if (typeinfo->geometry_nodes_default_cpp_value) {
243 r_value);
244 }
245 else {
246 typeinfo->geometry_nodes_cpp_type->value_initialize(r_value);
247 }
248}
249
251 const Span<BakeItem *> bake_items,
252 const BakeSocketConfig &config,
253 BakeDataBlockMap *data_block_map,
254 FunctionRef<std::shared_ptr<AttributeFieldInput>(int, const CPPType &)> make_attribute_field,
255 const Span<void *> r_socket_values)
256{
257 Map<std::string, std::string> attribute_map;
258
259 Vector<GeometrySet *> geometries;
260
261 for (const int i : bake_items.index_range()) {
262 const eNodeSocketDatatype socket_type = config.types[i];
263 BakeItem *bake_item = bake_items[i];
264 void *r_socket_value = r_socket_values[i];
265 if (bake_item == nullptr) {
266 default_initialize_socket_value(socket_type, r_socket_value);
267 continue;
268 }
270 *bake_item,
271 socket_type,
272 [&](const CPPType &attr_type) { return make_attribute_field(i, attr_type); },
273 attribute_map,
274 r_socket_value))
275 {
276 default_initialize_socket_value(socket_type, r_socket_value);
277 continue;
278 }
279 if (socket_type == SOCK_GEOMETRY) {
280 auto &item = *static_cast<GeometryBakeItem *>(bake_item);
281 item.geometry.clear();
282 geometries.append(static_cast<GeometrySet *>(r_socket_value));
283 }
284 }
285
286 rename_attributes(geometries, attribute_map);
287 restore_data_blocks(geometries, data_block_map);
288}
289
291 const Span<const BakeItem *> bake_items,
292 const BakeSocketConfig &config,
293 BakeDataBlockMap *data_block_map,
294 FunctionRef<std::shared_ptr<AttributeFieldInput>(int, const CPPType &)> make_attribute_field,
295 const Span<void *> r_socket_values)
296{
297 Map<std::string, std::string> attribute_map;
298 Vector<GeometrySet *> geometries;
299
300 for (const int i : bake_items.index_range()) {
301 const eNodeSocketDatatype socket_type = config.types[i];
302 const BakeItem *bake_item = bake_items[i];
303 void *r_socket_value = r_socket_values[i];
304 if (bake_item == nullptr) {
305 default_initialize_socket_value(socket_type, r_socket_value);
306 continue;
307 }
309 *bake_item,
310 socket_type,
311 [&](const CPPType &attr_type) { return make_attribute_field(i, attr_type); },
312 attribute_map,
313 r_socket_value))
314 {
315 default_initialize_socket_value(socket_type, r_socket_value);
316 continue;
317 }
318 if (socket_type == SOCK_GEOMETRY) {
319 geometries.append(static_cast<GeometrySet *>(r_socket_value));
320 }
321 }
322
323 rename_attributes(geometries, attribute_map);
324 restore_data_blocks(geometries, data_block_map);
325}
326
327} // namespace blender::bke::bake
VolumeGridType
#define BLI_assert(a)
Definition BLI_assert.h:50
eNodeSocketDatatype
@ SOCK_INT
@ SOCK_VECTOR
@ SOCK_BOOLEAN
@ SOCK_MATRIX
@ SOCK_FLOAT
@ SOCK_GEOMETRY
@ SOCK_ROTATION
@ SOCK_STRING
@ SOCK_RGBA
IndexRange index_range() const
Definition BLI_array.hh:349
void copy_construct(const void *src, void *dst) const
void value_initialize(void *ptr) const
SubIterator begin() const
Definition BLI_map.hh:730
SubIterator end() const
Definition BLI_map.hh:740
KeyIterator keys() const
Definition BLI_map.hh:837
bool add(const Key &key, const Value &value)
Definition BLI_map.hh:271
ItemIterator items() const
Definition BLI_map.hh:864
constexpr int64_t size() const
Definition BLI_span.hh:253
constexpr IndexRange index_range() const
Definition BLI_span.hh:402
int64_t size() const
IndexRange index_range() const
virtual std::optional< MutableAttributeAccessor > attributes_for_write()
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:57
static void try_restore_data_blocks(GeometrySet &geometry, BakeDataBlockMap *data_block_map)
Array< std::unique_ptr< BakeItem > > move_socket_values_to_bake_items(Span< void * > socket_values, const BakeSocketConfig &config, BakeDataBlockMap *data_block_map)
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 default_initialize_socket_value(const eNodeSocketDatatype socket_type, void *r_value)
std::optional< eNodeSocketDatatype > grid_type_to_socket_type(VolumeGridType type)
Definition node.cc:4516
bNodeSocketType * node_socket_type_find(const char *idname)
Definition node.cc:1763
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 char * node_static_socket_type(int type, int subtype)
Definition node.cc:2126
const CPPType * socket_type_to_geo_nodes_base_cpp_type(eNodeSocketDatatype type)
Definition node.cc:4438
Defines a socket type.
Definition BKE_node.hh:151
const blender::CPPType * geometry_nodes_cpp_type
Definition BKE_node.hh:195
const void * geometry_nodes_default_cpp_value
Definition BKE_node.hh:199
Vector< Vector< int, 1 > > geometries_by_attribute