Blender V5.0
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
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
85{
86#ifdef WITH_OPENVDB
87 const Operation operation = Operation(params.node().custom1);
88
89 auto grids = params.extract_input<GeoNodesMultiInput<bke::VolumeGrid<float>>>("Grid 2");
91 switch (operation) {
94 operands.extend(grids.values);
95 break;
97 if (auto grid = params.extract_input<bke::VolumeGrid<float>>("Grid 1")) {
98 operands.append(std::move(grid));
99 }
100 operands.extend(grids.values);
101 break;
102 }
103
104 if (operands.is_empty()) {
105 params.set_default_remaining_outputs();
106 return;
107 }
108
109 bke::VolumeTreeAccessToken result_token;
110 openvdb::FloatGrid &result_grid = operands.first().grid_for_write(result_token);
111 const openvdb::math::Transform &transform = result_grid.transform();
112
113 for (bke::VolumeGrid<float> &volume_grid : operands.as_mutable_span().drop_front(1)) {
114 bke::VolumeTreeAccessToken tree_token;
115 std::shared_ptr<openvdb::FloatGrid> resampled_storage;
116 openvdb::FloatGrid &grid = geometry::resample_sdf_grid_if_necessary(
117 volume_grid, tree_token, transform, resampled_storage);
118
119 try {
120 switch (operation) {
122 openvdb::tools::csgIntersection(result_grid, grid);
123 break;
124 case Operation::Union:
125 openvdb::tools::csgUnion(result_grid, grid);
126 break;
128 openvdb::tools::csgDifference(result_grid, grid);
129 break;
130 }
131 }
132 catch (const openvdb::ValueError & /*ex*/) {
133 /* May happen if a grid is empty. */
134 params.set_default_remaining_outputs();
135 return;
136 }
137 }
138 operands.first()->tag_tree_modified();
139
140 params.set_output("Grid", std::move(operands.first()));
141#else
143#endif
144}
145
146static void node_rna(StructRNA *srna)
147{
148 static const EnumPropertyItem operation_items[] = {
150 "INTERSECT",
151 0,
152 "Intersect",
153 "Keep the part of the grids that is common between all operands"},
154 {int(Operation::Union), "UNION", 0, "Union", "Combine grids in an additive way"},
156 "DIFFERENCE",
157 0,
158 "Difference",
159 "Combine grids in a subtractive way"},
160 {0, nullptr, 0, nullptr, nullptr},
161 };
162
164 "operation",
165 "Operation",
166 "",
167 operation_items,
170}
171
172static void node_register()
173{
174 static blender::bke::bNodeType ntype;
175 geo_node_type_base(&ntype, "GeometryNodeSDFGridBoolean", GEO_NODE_SDF_GRID_BOOLEAN);
176 ntype.ui_name = "SDF Grid Boolean";
177 ntype.ui_description = "Cut, subtract, or join multiple SDF volume grid inputs";
178 ntype.enum_name_legacy = "SDF_GRID_BOOLEAN";
180 ntype.declare = node_declare;
181 ntype.initfunc = node_init;
185 node_rna(ntype.rna_ext.srna);
186}
188
189} // namespace blender::nodes::node_geo_sdf_grid_boolean_cc
#define NODE_CLASS_GEOMETRY
Definition BKE_node.hh:461
#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 make_available(bNode &node) const
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void node_register_type(bNodeType &ntype)
Definition node.cc:2416
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 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)
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
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)
PointerRNA * ptr
Definition wm_files.cc:4238