18 # include <openvdb/openvdb.h>
19 # include <openvdb/tools/LevelSetUtil.h>
20 # include <openvdb/tools/ParticlesToLevelSet.h>
33 {
SOCK_FLOAT,
N_(
"Density"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX},
35 {
SOCK_FLOAT,
N_(
"Voxel Amount"), 64.0f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX},
37 {
SOCK_FLOAT,
N_(
"Radius"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX},
62 using PosType = openvdb::Vec3R;
64 Span<float3> positions;
69 return (
size_t)positions.size();
72 void getPos(
size_t n, openvdb::Vec3R &xyz)
const
74 xyz = &positions[n].x;
77 void getPosRad(
size_t n, openvdb::Vec3R &xyz, openvdb::Real &radius)
const
79 xyz = &positions[n].x;
85 static openvdb::FloatGrid::Ptr generate_volume_from_points(
const Span<float3> positions,
86 const Span<float> radii,
91 openvdb::FloatGrid::Ptr new_grid = openvdb::FloatGrid::create(1.0f);
94 openvdb::tools::ParticlesToLevelSet op{*new_grid};
98 ParticleList particles{positions, radii};
99 op.rasterizeSpheres(particles);
104 openvdb::tools::sdfToFogVolume(*new_grid);
108 [&](
const openvdb::FloatGrid::ValueOnIter &iter) {
109 iter.modifyValue([&](float &value) { value *= density; });
114 static float compute_voxel_size(
const GeoNodeExecParams &
params,
115 Span<float3> positions,
122 return params.get_input<
float>(
"Voxel Size");
125 if (positions.is_empty()) {
133 const float voxel_amount =
params.get_input<
float>(
"Voxel Amount");
134 if (voxel_amount <= 1) {
140 const float extended_diagonal = diagonal + 2.0f * radius;
141 const float voxel_size = extended_diagonal / voxel_amount;
145 static void gather_point_data_from_component(
const GeoNodeExecParams &
params,
147 Vector<float3> &r_positions,
148 Vector<float> &r_radii)
155 r_positions.extend(positions.get_span());
156 r_radii.extend(radii.get_span());
159 static void convert_to_grid_index_space(
const float voxel_size,
160 MutableSpan<float3> positions,
161 MutableSpan<float> radii)
163 const float voxel_size_inv = 1.0f / voxel_size;
164 for (
const int i : positions.index_range()) {
165 positions[i] *= voxel_size_inv;
167 positions[i] -=
float3(0.5f);
168 radii[i] *= voxel_size_inv;
172 static void initialize_volume_component_from_points(
const GeometrySet &geometry_set_in,
174 const GeoNodeExecParams &
params)
176 Vector<float3> positions;
180 gather_point_data_from_component(
184 gather_point_data_from_component(
188 const float max_radius = *std::max_element(radii.begin(), radii.end());
189 const float voxel_size = compute_voxel_size(
params, positions, max_radius);
190 if (voxel_size == 0.0f || positions.is_empty()) {
198 openvdb::FloatGrid::Ptr density_grid = openvdb::gridPtrCast<openvdb::FloatGrid>(
199 BKE_volume_grid_openvdb_for_write(volume, c_density_grid,
false));
201 const float density =
params.get_input<
float>(
"Density");
202 convert_to_grid_index_space(voxel_size, positions, radii);
203 openvdb::FloatGrid::Ptr new_grid = generate_volume_from_points(positions, radii, density);
205 density_grid->merge(*new_grid);
206 density_grid->transform().postScale(voxel_size);
209 volume_component.
replace(volume);
222 initialize_volume_component_from_points(geometry_set_in, geometry_set_out,
params);
225 params.set_output(
"Geometry", std::move(geometry_set_out));
239 STRNCPY(radius_attribute_socket_value->
value,
"radius");
248 data->resolution_mode ==
267 "NodeGeometryPointsToVolume",
void * BKE_id_new_nomain(const short type, const char *name)
void nodeSetSocketAvailability(struct bNodeSocket *sock, bool is_available)
void node_type_size(struct bNodeType *ntype, int width, int minwidth, int maxwidth)
void node_type_socket_templates(struct bNodeType *ntype, struct bNodeSocketTemplate *inputs, struct bNodeSocketTemplate *outputs)
void node_type_update(struct bNodeType *ntype, void(*updatefunc)(struct bNodeTree *ntree, struct bNode *node))
void node_type_init(struct bNodeType *ntype, void(*initfunc)(struct bNodeTree *ntree, struct bNode *node))
#define NODE_CLASS_GEOMETRY
void node_type_storage(struct bNodeType *ntype, const char *storagename, void(*freefunc)(struct bNode *node), void(*copyfunc)(struct bNodeTree *dest_ntree, struct bNode *dest_node, const struct bNode *src_node))
struct bNodeSocket * nodeFindSocket(const struct bNode *node, eNodeSocketInOut in_out, const char *identifier)
#define GEO_NODE_POINTS_TO_VOLUME
void nodeRegisterType(struct bNodeType *ntype)
void BKE_volume_init_grids(struct Volume *volume)
struct VolumeGrid * BKE_volume_grid_add(struct Volume *volume, const char *name, VolumeGridType type)
void minmax_v3v3_v3_array(float r_min[3], float r_max[3], const float(*vec_arr)[3], int nbr)
#define STRNCPY(dst, src)
#define INIT_MINMAX(min, max)
static uint8 component(Color32 c, uint i)
@ GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_AMOUNT
@ GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_SIZE
GeometryNodeAttributeInputMode
@ GEO_NODE_ATTRIBUTE_INPUT_FLOAT
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
void replace(Volume *volume, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
void *(* MEM_callocN)(size_t len, const char *str)
TypedReadAttribute< float > FloatReadAttribute
TypedReadAttribute< float3 > Float3ReadAttribute
GeometrySet geometry_set_realize_instances(const GeometrySet &geometry_set)
static void geo_node_points_to_volume_update(bNodeTree *UNUSED(ntree), bNode *node)
void update_attribute_input_socket_availabilities(bNode &node, const StringRef name, const GeometryNodeAttributeInputMode mode, const bool name_is_available)
static void geo_node_points_to_volume_init(bNodeTree *UNUSED(ntree), bNode *node)
static void geo_node_points_to_volume_exec(GeoNodeExecParams params)
static bNodeSocketTemplate geo_node_points_to_volume_out[]
static bNodeSocketTemplate geo_node_points_to_volume_in[]
void register_node_type_geo_points_to_volume()
static void geo_node_points_to_volume_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
void geo_node_type_base(bNodeType *ntype, int type, const char *name, short nclass, short flag)
void node_copy_standard_storage(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, const bNode *src_node)
void node_free_standard_storage(bNode *node)
GeometryComponent & get_component_for_write(GeometryComponentType component_type)
bool has(const GeometryComponentType component_type) const
const GeometryComponent * get_component_for_read(GeometryComponentType component_type) const
Compact definition of a node socket.
NodeGeometryExecFunction geometry_node_execute
void(* draw_buttons)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr)
static float distance(const float3 &a, const float3 &b)