6# include <openvdb/openvdb.h>
7# include <openvdb/tools/Interpolation.h>
8# include <openvdb/tools/PointScatter.h>
44 "When combined with each voxel's value, determines the number of points "
45 "to sample per unit volume");
47 "Seed used by the random number generator to generate random points");
49 .default_value({0.3, 0.3, 0.3})
52 .description(
"Spacing between grid points");
57 .
description(
"Minimum density of a voxel to contain a grid point");
60 const bNode *node =
b.node_or_null();
61 if (node !=
nullptr) {
83class PositionsVDBWrapper {
89 PositionsVDBWrapper(
const PositionsVDBWrapper &wrapper) =
default;
91 void add(
const openvdb::Vec3R &
pos)
99using RNGType = std::mt19937;
101using NonUniformPointScatterVDB =
102 openvdb::tools::NonUniformPointScatter<PositionsVDBWrapper, RNGType>;
104static void point_scatter_density_random(
const openvdb::FloatGrid &grid,
107 Vector<float3> &r_positions)
110 PositionsVDBWrapper vdb_position_wrapper(r_positions);
111 RNGType random_generator(
seed);
112 NonUniformPointScatterVDB point_scatter(vdb_position_wrapper, density, random_generator);
116static void point_scatter_density_grid(
const openvdb::FloatGrid &grid,
118 const float threshold,
119 Vector<float3> &r_positions)
121 const openvdb::Vec3d half_voxel(0.5, 0.5, 0.5);
122 const openvdb::Vec3d voxel_spacing(
double(spacing.
x) / grid.voxelSize().x(),
123 double(spacing.
y) / grid.voxelSize().y(),
124 double(spacing.
z) / grid.voxelSize().z());
127 const double min_spacing = std::min({voxel_spacing.x(), voxel_spacing.y(), voxel_spacing.z()});
128 if (std::abs(min_spacing) < 0.0001) {
133 for (openvdb::FloatGrid::ValueOnCIter cell = grid.cbeginValueOn(); cell; ++cell) {
135 if (cell.getValue() < threshold) {
139 const openvdb::CoordBBox bbox = cell.getBoundingBox();
140 const openvdb::Vec3d box_min = bbox.min().asVec3d() - half_voxel;
141 const openvdb::Vec3d box_max = bbox.max().asVec3d() + half_voxel;
144 double abs_spacing_x = std::abs(voxel_spacing.x());
145 double abs_spacing_y = std::abs(voxel_spacing.y());
146 double abs_spacing_z = std::abs(voxel_spacing.z());
147 const openvdb::Vec3d start(
ceil(box_min.x() / abs_spacing_x) * abs_spacing_x,
148 ceil(box_min.y() / abs_spacing_y) * abs_spacing_y,
149 ceil(box_min.z() / abs_spacing_z) * abs_spacing_z);
152 for (
double x = start.x();
x < box_max.x();
x += abs_spacing_x) {
153 for (
double y = start.y();
y < box_max.y();
y += abs_spacing_y) {
154 for (
double z = start.z();
z < box_max.z();
z += abs_spacing_z) {
156 const openvdb::Vec3d idx_pos(
x,
y,
z);
157 const openvdb::Vec3d local_pos = grid.indexToWorld(idx_pos);
172 params.set_default_remaining_outputs();
176 bke::VolumeTreeAccessToken tree_token;
177 const openvdb::GridBase &base_grid = volume_grid.grid(tree_token);
178 if (!base_grid.isType<openvdb::FloatGrid>()) {
179 params.set_default_remaining_outputs();
182 const openvdb::FloatGrid &grid =
static_cast<const openvdb::FloatGrid &
>(base_grid);
191 density =
params.extract_input<
float>(
"Density");
196 threshold =
params.extract_input<
float>(
"Threshold");
202 point_scatter_density_random(grid, density,
seed, positions);
205 point_scatter_density_grid(grid, spacing, threshold, positions);
210 pointcloud->positions_for_write().copy_from(positions);
227 "Distribute points randomly inside of the volume"},
232 "Distribute the points in a grid pattern inside of the volume"},
233 {0,
nullptr, 0,
nullptr,
nullptr},
238 "Distribution Method",
239 "Method to use for scattering points",
250 ntype.
ui_name =
"Distribute Points in Grid";
#define NODE_CLASS_GEOMETRY
#define GEO_NODE_DISTRIBUTE_POINTS_IN_GRID
General operations for point clouds.
PointCloud * BKE_pointcloud_new_nomain(int totpoint)
#define NOD_REGISTER_NODE(REGISTER_FUNC)
#define NOD_inline_enum_accessors(member)
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
static unsigned long seed
void append(const T &value)
void append(const T &value)
StructureType structure_type
VecBase< float, 3 > float3
static void add(blender::Map< std::string, std::string > &messages, Message &msg)
void node_type_size(bNodeType &ntype, int width, int minwidth, int maxwidth)
void node_register_type(bNodeType &ntype)
void debug_randomize_point_order(PointCloud *pointcloud)
static void node_layout(uiLayout *layout, bContext *, PointerRNA *ptr)
static void node_declare(NodeDeclarationBuilder &b)
static void node_init(bNodeTree *, bNode *node)
static void node_geo_exec(GeoNodeExecParams params)
static void node_register()
static void node_rna(StructRNA *srna)
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 ¶ms)
VecBase< float, 3 > float3
void geo_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
std::string ui_description
void(* initfunc)(bNodeTree *ntree, bNode *node)
NodeGeometryExecFunction geometry_node_execute
const char * enum_name_legacy
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
NodeDeclareFunction declare
static GeometrySet from_pointcloud(PointCloud *pointcloud, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
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)