Blender V4.5
node_geo_sdf_grid_boolean.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#ifdef WITH_OPENVDB
6# include <openvdb/openvdb.h>
7# include <openvdb/tools/Composite.h>
8#endif
9
10#include "BKE_volume_grid.hh"
11
13
14#include "NOD_rna_define.hh"
15
16#include "UI_interface.hh"
17#include "UI_resources.hh"
18
19#include "node_geometry_util.hh"
20
22
23enum class Operation {
25 Union = 1,
27};
28
30{
31 const bNode *node = b.node_or_null();
32
33 auto &first_grid = b.add_input<decl::Float>("Grid 1").hide_value().structure_type(
34 StructureType::Grid);
35
36 if (node) {
37 static const auto make_available = [](bNode &node) {
38 node.custom1 = int16_t(Operation::Difference);
39 };
40 switch (Operation(node->custom1)) {
43 b.add_input<decl::Float>("Grid", "Grid 2")
44 .hide_value()
45 .multi_input()
46 .make_available(make_available)
47 .structure_type(StructureType::Grid);
48 break;
50 b.add_input<decl::Float>("Grid 2")
51 .hide_value()
52 .multi_input()
53 .make_available(make_available)
54 .structure_type(StructureType::Grid);
55 break;
56 }
57 }
58
59 b.add_output<decl::Float>("Grid").hide_value().structure_type(StructureType::Grid);
60
61 if (node) {
62 switch (Operation(node->custom1)) {
65 first_grid.available(false);
66 break;
68 first_grid.available(true);
69 break;
70 }
71 }
72}
73
74static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
75{
76 layout->prop(ptr, "operation", UI_ITEM_NONE, "", ICON_NONE);
77}
78
79static void node_init(bNodeTree * /*tree*/, bNode *node)
80{
81 node->custom1 = int16_t(Operation::Difference);
82}
83
84#ifdef WITH_OPENVDB
85static void get_float_grids(MutableSpan<SocketValueVariant> values,
87{
88 for (SocketValueVariant &input : values) {
89 if (auto grid = input.extract<bke::VolumeGrid<float>>()) {
90 grids.append(std::move(grid));
91 }
92 }
93}
94#endif
95
97{
98#ifdef WITH_OPENVDB
99 const Operation operation = Operation(params.node().custom1);
100
103 switch (operation) {
105 case Operation::Union:
106 get_float_grids(inputs, operands);
107 break;
109 if (auto grid = params.extract_input<bke::VolumeGrid<float>>("Grid 1")) {
110 operands.append(std::move(grid));
111 }
112 get_float_grids(inputs, operands);
113 break;
114 }
115
116 if (operands.is_empty()) {
117 params.set_default_remaining_outputs();
118 return;
119 }
120
121 bke::VolumeTreeAccessToken result_token;
122 openvdb::FloatGrid &result_grid = operands.first().grid_for_write(result_token);
123 const openvdb::math::Transform &transform = result_grid.transform();
124
125 for (bke::VolumeGrid<float> &volume_grid : operands.as_mutable_span().drop_front(1)) {
126 bke::VolumeTreeAccessToken tree_token;
127 std::shared_ptr<openvdb::FloatGrid> resampled_storage;
128 openvdb::FloatGrid &grid = geometry::resample_sdf_grid_if_necessary(
129 volume_grid, tree_token, transform, resampled_storage);
130
131 try {
132 switch (operation) {
134 openvdb::tools::csgIntersection(result_grid, grid);
135 break;
136 case Operation::Union:
137 openvdb::tools::csgUnion(result_grid, grid);
138 break;
140 openvdb::tools::csgDifference(result_grid, grid);
141 break;
142 }
143 }
144 catch (const openvdb::ValueError & /*ex*/) {
145 /* May happen if a grid is empty. */
146 params.set_default_remaining_outputs();
147 return;
148 }
149 }
150
151 params.set_output("Grid", std::move(operands.first()));
152#else
154#endif
155}
156
157static void node_rna(StructRNA *srna)
158{
159 static const EnumPropertyItem operation_items[] = {
161 "INTERSECT",
162 0,
163 "Intersect",
164 "Keep the part of the grids that is common between all operands"},
165 {int(Operation::Union), "UNION", 0, "Union", "Combine grids in an additive way"},
167 "DIFFERENCE",
168 0,
169 "Difference",
170 "Combine grids in a subtractive way"},
171 {0, nullptr, 0, nullptr, nullptr},
172 };
173
175 "operation",
176 "Operation",
177 "",
178 operation_items,
181}
182
183static void node_register()
184{
185 static blender::bke::bNodeType ntype;
186 geo_node_type_base(&ntype, "GeometryNodeSDFGridBoolean", GEO_NODE_SDF_GRID_BOOLEAN);
187 ntype.ui_name = "SDF Grid Boolean";
188 ntype.ui_description = "Cut, subtract, or join multiple SDF volume grid inputs";
189 ntype.enum_name_legacy = "SDF_GRID_BOOLEAN";
191 ntype.declare = node_declare;
192 ntype.initfunc = node_init;
197 node_rna(ntype.rna_ext.srna);
198}
200
201} // namespace blender::nodes::node_geo_sdf_grid_boolean_cc
#define NODE_CLASS_GEOMETRY
Definition BKE_node.hh:447
#define GEO_NODE_SDF_GRID_BOOLEAN
#define NOD_REGISTER_NODE(REGISTER_FUNC)
#define NOD_inline_enum_accessors(member)
#define UI_ITEM_NONE
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
DBVT_INLINE bool Intersect(const btDbvtAabbMm &a, const btDbvtAabbMm &b)
Definition btDbvt.h:621
void append(const T &value)
bool is_empty() const
MutableSpan< T > as_mutable_span()
const T & first() const
void make_available(bNode &node) const
#define input
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void node_register_type(bNodeType &ntype)
Definition node.cc:2748
static void node_init(bNodeTree *, bNode *node)
static void node_geo_exec(GeoNodeExecParams params)
static void node_layout(uiLayout *layout, bContext *, PointerRNA *ptr)
static void node_declare(NodeDeclarationBuilder &b)
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)
void search_link_ops_for_volume_grid_node(GatherLinkSearchOpParams &params)
void node_geo_exec_with_missing_openvdb(GeoNodeExecParams &params)
void geo_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
static blender::bke::bNodeSocketTemplate inputs[]
StructRNA * srna
Definition RNA_types.hh:909
int16_t custom1
Defines a node type.
Definition BKE_node.hh:226
std::string ui_description
Definition BKE_node.hh:232
void(* initfunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:277
NodeGeometryExecFunction geometry_node_execute
Definition BKE_node.hh:347
const char * enum_name_legacy
Definition BKE_node.hh:235
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:247
NodeGatherSocketLinkOperationsFunction gather_link_search_ops
Definition BKE_node.hh:371
NodeDeclareFunction declare
Definition BKE_node.hh:355
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)
PointerRNA * ptr
Definition wm_files.cc:4226