4 # include <openvdb/openvdb.h>
5 # include <openvdb/tools/Dense.h>
6 # include <openvdb/tools/LevelSetUtil.h>
7 # include <openvdb/tools/ParticlesToLevelSet.h>
26 .description(
N_(
"Volume density per voxel"))
30 .description(
N_(
"Value for voxels outside of the cube"));
33 .description(
N_(
"Minimum boundary of volume"))
34 .default_value(
float3(-1.0f));
36 .description(
N_(
"Maximum boundary of volume"))
37 .default_value(
float3(1.0f));
40 .description(
N_(
"Number of voxels in the X axis"))
44 .description(
N_(
"Number of voxels in the Y axis"))
48 .description(
N_(
"Number of voxels in the Z axis"))
55 static float map(
const float x,
61 return (
x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
72 : resolution_(resolution), bounds_min_(bounds_min), bounds_max_(bounds_max)
78 return static_cast<int64_t>(resolution_.x) *
static_cast<int64_t>(resolution_.y) *
79 static_cast<int64_t>(resolution_.z);
88 if (attribute_field_input ==
nullptr) {
99 int64_t index = x_range.start() * resolution_.y * resolution_.z;
100 for (const int64_t x_i : x_range) {
101 const float x = map(x_i, 0.0f, resolution_.x - 1, bounds_min_.x, bounds_max_.x);
102 for (const int64_t y_i : IndexRange(resolution_.y)) {
103 const float y = map(y_i, 0.0f, resolution_.y - 1, bounds_min_.y, bounds_max_.y);
104 for (const int64_t z_i : IndexRange(resolution_.z)) {
105 const float z = map(z_i, 0.0f, resolution_.z - 1, bounds_min_.z, bounds_max_.z);
106 positions[index] = float3(x, y, z);
122 const int3 resolution =
int3(
params.extract_input<
int>(
"Resolution X"),
123 params.extract_input<
int>(
"Resolution Y"),
124 params.extract_input<
int>(
"Resolution Z"));
126 if (resolution.x < 2 || resolution.y < 2 || resolution.z < 2) {
127 params.error_message_add(NodeWarningType::Error,
TIP_(
"Resolution must be greater than 1"));
128 params.set_default_remaining_outputs();
132 if (bounds_min.x == bounds_max.x || bounds_min.y == bounds_max.y ||
133 bounds_min.z == bounds_max.z) {
134 params.error_message_add(NodeWarningType::Error,
135 TIP_(
"Bounding box volume must be greater than 0"));
136 params.set_default_remaining_outputs();
142 params.error_message_add(NodeWarningType::Warning,
143 TIP_(
"Volume scale is lower than permitted by OpenVDB"));
144 params.set_default_remaining_outputs();
148 Field<float> input_field =
params.extract_input<Field<float>>(
"Density");
151 Grid3DFieldContext
context(resolution, bounds_min, bounds_max);
153 Array<float> densities(
context.points_num());
154 evaluator.add_with_destination(std::move(input_field), densities.as_mutable_span());
155 evaluator.evaluate();
158 const float background =
params.extract_input<
float>(
"Background");
160 grid->setGridClass(openvdb::GRID_FOG_VOLUME);
162 openvdb::tools::Dense<float, openvdb::tools::LayoutZYX> dense_grid{
163 openvdb::math::CoordBBox({0, 0, 0}, {resolution.x - 1, resolution.y - 1, resolution.z - 1}),
165 openvdb::tools::copyFromDense(dense_grid, *grid, 0.0f);
167 grid->transform().preTranslate(openvdb::math::Vec3<float>(-0.5f));
168 grid->transform().postScale(openvdb::math::Vec3<double>(scale_fac.x, scale_fac.y, scale_fac.z));
169 grid->transform().postTranslate(
170 openvdb::math::Vec3<float>(bounds_min.x, bounds_min.y, bounds_min.z));
175 BKE_volume_grid_add_vdb(*volume,
"density", std::move(grid));
179 params.set_output(
"Volume", r_geometry_set);
185 params.error_message_add(NodeWarningType::Error,
186 TIP_(
"Disabled, Blender was compiled without OpenVDB"));
187 params.set_default_remaining_outputs();
void * BKE_id_new_nomain(short type, const char *name)
#define GEO_NODE_VOLUME_CUBE
#define NODE_CLASS_GEOMETRY
void nodeRegisterType(struct bNodeType *ntype)
void BKE_volume_init_grids(struct Volume *volume)
bool BKE_volume_grid_determinant_valid(double determinant)
static VArray ForContainer(ContainerT container)
Grid3DFieldContext(const int3 resolution, const float3 bounds_min, const float3 bounds_max)
int64_t points_num() const
GVArray get_varray_for_input(const FieldInput &field_input, const IndexMask UNUSED(mask), ResourceScope &UNUSED(scope)) const
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
std::unique_ptr< IDProperty, IDPropertyDeleter > create(StringRefNull prop_name, int32_t value)
Allocate a new IDProperty of type IDP_INT, set its name and value.
static void node_declare(NodeDeclarationBuilder &b)
static void node_geo_exec(GeoNodeExecParams params)
static float map(const float x, const float in_min, const float in_max, const float out_min, const float out_max)
void parallel_for(IndexRange range, int64_t grain_size, const Function &function)
vec_base< float, 3 > float3
vec_base< double, 3 > double3
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
MutableSpan< float3 > positions
void register_node_type_geo_volume_cube()
void geo_node_type_base(bNodeType *ntype, int type, const char *name, short nclass)
void replace_volume(Volume *volume, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
NodeGeometryExecFunction geometry_node_execute
NodeDeclareFunction declare