Blender V5.0
node_geo_sample_grid_index.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
5#include "DNA_userdef_types.h"
6
8#include "BKE_volume_grid.hh"
10
11#include "NOD_rna_define.hh"
13
15#include "UI_resources.hh"
16
17#include "RNA_enum_types.hh"
18
19#include "node_geometry_util.hh"
20
22
24{
25 const bNode *node = b.node_or_null();
26 if (!node) {
27 return;
28 }
29 const eNodeSocketDatatype data_type = eNodeSocketDatatype(node->custom1);
30
31 b.add_input(data_type, "Grid").hide_value().structure_type(StructureType::Grid);
32 b.add_input<decl::Int>("X").supports_field().structure_type(StructureType::Dynamic);
33 b.add_input<decl::Int>("Y").supports_field().structure_type(StructureType::Dynamic);
34 b.add_input<decl::Int>("Z").supports_field().structure_type(StructureType::Dynamic);
35
36 b.add_output(data_type, "Value").dependent_field({1, 2, 3});
37}
38
39static std::optional<eNodeSocketDatatype> node_type_for_socket_type(const bNodeSocket &socket)
40{
41 switch (socket.type) {
42 case SOCK_FLOAT:
43 return SOCK_FLOAT;
44 case SOCK_BOOLEAN:
45 return SOCK_BOOLEAN;
46 case SOCK_INT:
47 return SOCK_INT;
48 case SOCK_VECTOR:
49 case SOCK_RGBA:
50 return SOCK_VECTOR;
51 default:
52 return std::nullopt;
53 }
54}
55
57{
58 const std::optional<eNodeSocketDatatype> node_type = node_type_for_socket_type(
59 params.other_socket());
60 if (!node_type) {
61 return;
62 }
63 if (params.in_out() == SOCK_IN) {
64 params.add_item(IFACE_("Grid"), [node_type](LinkSearchOpParams &params) {
65 bNode &node = params.add_node("GeometryNodeSampleGridIndex");
66 node.custom1 = *node_type;
67 params.update_and_connect_available_socket(node, "Grid");
68 });
69 const eNodeSocketDatatype other_type = eNodeSocketDatatype(params.other_socket().type);
70 if (params.node_tree().typeinfo->validate_link(other_type, SOCK_INT)) {
71 params.add_item(IFACE_("X"), [](LinkSearchOpParams &params) {
72 bNode &node = params.add_node("GeometryNodeSampleGridIndex");
73 params.update_and_connect_available_socket(node, "X");
74 });
75 params.add_item(IFACE_("Y"), [](LinkSearchOpParams &params) {
76 bNode &node = params.add_node("GeometryNodeSampleGridIndex");
77 params.update_and_connect_available_socket(node, "Y");
78 });
79 params.add_item(IFACE_("Z"), [](LinkSearchOpParams &params) {
80 bNode &node = params.add_node("GeometryNodeSampleGridIndex");
81 params.update_and_connect_available_socket(node, "Z");
82 });
83 }
84 }
85 else {
86 params.add_item(IFACE_("Value"), [node_type](LinkSearchOpParams &params) {
87 bNode &node = params.add_node("GeometryNodeSampleGridIndex");
88 node.custom1 = *node_type;
89 params.update_and_connect_available_socket(node, "Value");
90 });
91 }
92}
93
94static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
95{
96 layout->prop(ptr, "data_type", UI_ITEM_NONE, "", ICON_NONE);
97}
98
99#ifdef WITH_OPENVDB
100
101template<typename T>
102void sample_grid(const bke::OpenvdbGridType<T> &grid,
103 const Span<int> x,
104 const Span<int> y,
105 const Span<int> z,
106 const IndexMask &mask,
107 MutableSpan<T> dst)
108{
109 using GridType = bke::OpenvdbGridType<T>;
110 using GridValueT = typename GridType::ValueType;
111 using AccessorT = typename GridType::ConstUnsafeAccessor;
112 using TraitsT = typename bke::VolumeGridTraits<T>;
113 /* Can use unsafe accessor because we know that the tree topology is not modified while we access
114 * it here. This reduces a significant amount of overhead. */
115 AccessorT accessor = grid.getConstUnsafeAccessor();
116
117 mask.foreach_index([&](const int64_t i) {
118 GridValueT value = accessor.getValue(openvdb::Coord(x[i], y[i], z[i]));
119 dst[i] = TraitsT::to_blender(value);
120 });
121}
122
123template<typename Fn> void convert_to_static_type(const VolumeGridType type, const Fn &fn)
124{
125 switch (type) {
127 fn(bool());
128 break;
130 fn(float());
131 break;
132 case VOLUME_GRID_INT:
133 fn(int());
134 break;
135 case VOLUME_GRID_MASK:
136 fn(bool());
137 break;
139 fn(float3());
140 break;
141 default:
142 break;
143 }
144}
145
146class SampleGridIndexFunction : public mf::MultiFunction {
147 bke::GVolumeGrid grid_;
148 mf::Signature signature_;
149 VolumeGridType grid_type_;
151 bke::VolumeTreeAccessToken tree_token_;
152 const openvdb::GridBase *grid_base_ = nullptr;
153
154 public:
155 SampleGridIndexFunction(bke::GVolumeGrid grid) : grid_(std::move(grid))
156 {
157 BLI_assert(grid_);
158
159 const std::optional<eNodeSocketDatatype> data_type = bke::grid_type_to_socket_type(
160 grid_->grid_type());
161 const CPPType *cpp_type = bke::socket_type_to_geo_nodes_base_cpp_type(*data_type);
162 mf::SignatureBuilder builder{"Sample Grid Index", signature_};
163 builder.single_input<int>("X");
164 builder.single_input<int>("Y");
165 builder.single_input<int>("Z");
166 builder.single_output("Value", *cpp_type);
167 this->set_signature(&signature_);
168
169 grid_base_ = &grid_->grid(tree_token_);
170 grid_type_ = grid_->grid_type();
171 }
172
173 void call(const IndexMask &mask, mf::Params params, mf::Context /*context*/) const final
174 {
175 const VArraySpan<int> x = params.readonly_single_input<int>(0, "X");
176 const VArraySpan<int> y = params.readonly_single_input<int>(1, "Y");
177 const VArraySpan<int> z = params.readonly_single_input<int>(2, "Z");
178 GMutableSpan dst = params.uninitialized_single_output(3, "Value");
179
180 convert_to_static_type(grid_type_, [&](auto dummy) {
181 using T = decltype(dummy);
182 sample_grid<T>(static_cast<const bke::OpenvdbGridType<T> &>(*grid_base_),
183 x,
184 y,
185 z,
186 mask,
187 dst.typed<T>());
188 });
189 }
190};
191
192#endif /* WITH_OPENVDB */
193
195{
196#ifdef WITH_OPENVDB
197 bke::GVolumeGrid grid = params.extract_input<bke::GVolumeGrid>("Grid");
198 if (!grid) {
199 params.set_default_remaining_outputs();
200 return;
201 }
202
203 auto x = params.extract_input<bke::SocketValueVariant>("X");
204 auto y = params.extract_input<bke::SocketValueVariant>("Y");
205 auto z = params.extract_input<bke::SocketValueVariant>("Z");
206
207 std::string error_message;
208 bke::SocketValueVariant output_value;
210 std::make_shared<SampleGridIndexFunction>(std::move(grid)),
211 {&x, &y, &z},
212 {&output_value},
213 params.user_data(),
214 error_message))
215 {
216 params.set_default_remaining_outputs();
217 params.error_message_add(NodeWarningType::Error, std::move(error_message));
218 return;
219 }
220
221 params.set_output("Value", std::move(output_value));
222#else
224#endif
225}
226
227static void node_init(bNodeTree * /*tree*/, bNode *node)
228{
229 node->custom1 = SOCK_FLOAT;
230}
231
232static void node_rna(StructRNA *srna)
233{
235 "data_type",
236 "Data Type",
237 "Node socket data type",
242}
243
244static void node_register()
245{
246 static blender::bke::bNodeType ntype;
247
248 geo_node_type_base(&ntype, "GeometryNodeSampleGridIndex", GEO_NODE_SAMPLE_GRID_INDEX);
249 ntype.ui_name = "Sample Grid Index";
250 ntype.ui_description = "Retrieve volume grid values at specific voxels";
251 ntype.enum_name_legacy = "SAMPLE_GRID_INDEX";
253 ntype.initfunc = node_init;
254 ntype.declare = node_declare;
260
261 node_rna(ntype.rna_ext.srna);
262}
264
265} // namespace blender::nodes::node_geo_sample_grid_index_cc
#define NODE_CLASS_GEOMETRY
Definition BKE_node.hh:461
#define GEO_NODE_SAMPLE_GRID_INDEX
VolumeGridType
@ VOLUME_GRID_VECTOR_FLOAT
@ VOLUME_GRID_MASK
@ VOLUME_GRID_BOOLEAN
@ VOLUME_GRID_INT
@ VOLUME_GRID_FLOAT
#define BLI_assert(a)
Definition BLI_assert.h:46
#define IFACE_(msgid)
@ SOCK_IN
eNodeSocketDatatype
@ SOCK_INT
@ SOCK_VECTOR
@ SOCK_BOOLEAN
@ SOCK_FLOAT
@ SOCK_RGBA
#define NOD_REGISTER_NODE(REGISTER_FUNC)
#define NOD_inline_enum_accessors(member)
#define UI_ITEM_NONE
long long int int64_t
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
Definition btQuadWord.h:117
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
#define T
void convert_to_static_type(const CPPType &cpp_type, const Func &func)
void node_register_type(bNodeType &ntype)
Definition node.cc:2416
static void node_declare(NodeDeclarationBuilder &b)
static void node_geo_exec(GeoNodeExecParams params)
static void node_gather_link_search_ops(GatherLinkSearchOpParams &params)
static void node_layout(uiLayout *layout, bContext *, PointerRNA *ptr)
static std::optional< eNodeSocketDatatype > node_type_for_socket_type(const bNodeSocket &socket)
PropertyRNA * RNA_def_node_enum(StructRNA *srna, const char *identifier, const char *ui_name, const char *ui_description, const EnumPropertyItem *static_items, const EnumRNAAccessors accessors, std::optional< int > default_value, const EnumPropertyItemFunc item_func, const bool allow_animation)
bool execute_multi_function_on_value_variant(const MultiFunction &fn, const std::shared_ptr< MultiFunction > &owned_fn, const Span< SocketValueVariant * > input_values, const Span< SocketValueVariant * > output_values, GeoNodesUserData *user_data, std::string &r_error_message)
const EnumPropertyItem * grid_socket_type_items_filter_fn(bContext *, PointerRNA *, PropertyRNA *, bool *r_free)
void node_geo_exec_with_missing_openvdb(GeoNodeExecParams &params)
VecBase< float, 3 > float3
void geo_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
const EnumPropertyItem rna_enum_node_socket_data_type_items[]
StructRNA * srna
int16_t custom1
Defines a node type.
Definition BKE_node.hh:238
std::string ui_description
Definition BKE_node.hh:244
void(* initfunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:289
NodeGeometryExecFunction geometry_node_execute
Definition BKE_node.hh:354
const char * enum_name_legacy
Definition BKE_node.hh:247
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:259
NodeGatherSocketLinkOperationsFunction gather_link_search_ops
Definition BKE_node.hh:378
NodeDeclareFunction declare
Definition BKE_node.hh:362
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
i
Definition text_draw.cc:230
PointerRNA * ptr
Definition wm_files.cc:4238