4 # include <openvdb/openvdb.h>
5 # include <openvdb/tools/LevelSetUtil.h>
6 # include <openvdb/tools/ParticlesToLevelSet.h>
24 b.add_input<
decl::Float>(
N_(
"Density")).default_value(1.0f).min(0.0f);
79 using PosType = openvdb::Vec3R;
89 void getPos(
size_t n, openvdb::Vec3R &xyz)
const
94 void getPosRad(
size_t n, openvdb::Vec3R &xyz, openvdb::Real &radius)
const
103 const Span<float>
radii,
111 openvdb::tools::ParticlesToLevelSet op{*new_grid};
116 op.rasterizeSpheres(particles);
121 openvdb::tools::sdfToFogVolume(*new_grid);
125 [&](
const openvdb::FloatGrid::ValueOnIter &iter) {
126 iter.modifyValue([&](float &value) { value *= density; });
131 static float compute_voxel_size(
const GeoNodeExecParams &
params,
138 return params.get_input<
float>(
"Voxel Size");
149 const float voxel_amount =
params.get_input<
float>(
"Voxel Amount");
150 if (voxel_amount <= 1) {
156 const float extended_diagonal = diagonal + 2.0f * radius;
157 const float voxel_size = extended_diagonal / voxel_amount;
161 static void gather_point_data_from_component(GeoNodeExecParams &
params,
163 Vector<float3> &r_positions,
164 Vector<float> &r_radii)
172 Field<float> radius_field =
params.get_input<Field<float>>(
"Radius");
176 r_positions.resize(r_positions.size() +
domain_num);
180 fn::FieldEvaluator evaluator{field_context,
domain_num};
181 evaluator.add_with_destination(radius_field, r_radii.as_mutable_span().take_back(
domain_num));
182 evaluator.evaluate();
185 static void convert_to_grid_index_space(
const float voxel_size,
187 MutableSpan<float>
radii)
189 const float voxel_size_inv = 1.0f / voxel_size;
190 for (
const int i :
positions.index_range()) {
194 radii[i] *= voxel_size_inv;
198 static void initialize_volume_component_from_points(GeoNodeExecParams &
params,
206 if (r_geometry_set.
has(
type)) {
207 gather_point_data_from_component(
212 const float max_radius = *std::max_element(
radii.begin(),
radii.end());
213 const float voxel_size = compute_voxel_size(
params,
positions, max_radius);
214 if (voxel_size == 0.0f ||
positions.is_empty()) {
224 new_grid->transform().postScale(voxel_size);
225 BKE_volume_grid_add_vdb(*volume,
"density", std::move(new_grid));
238 initialize_volume_component_from_points(
params, geometry_set);
240 params.set_output(
"Volume", std::move(geometry_set));
242 params.error_message_add(NodeWarningType::Error,
243 TIP_(
"Disabled, Blender was compiled without OpenVDB"));
244 params.set_default_remaining_outputs();
258 "NodeGeometryPointsToVolume",
@ GEO_COMPONENT_TYPE_MESH
@ GEO_COMPONENT_TYPE_POINT_CLOUD
@ GEO_COMPONENT_TYPE_CURVE
@ GEO_COMPONENT_TYPE_VOLUME
void * BKE_id_new_nomain(short type, const char *name)
void node_type_size(struct bNodeType *ntype, int width, int minwidth, int maxwidth)
void node_type_update(struct bNodeType *ntype, void(*updatefunc)(struct bNodeTree *ntree, struct bNode *node))
#define NODE_STORAGE_FUNCS(StorageT)
void nodeSetSocketAvailability(struct bNodeTree *ntree, struct bNodeSocket *sock, bool is_available)
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)
void minmax_v3v3_v3_array(float r_min[3], float r_max[3], const float(*vec_arr)[3], int var_arr_num)
#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
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
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 make_available(bNode &node) const
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 int domain_num(const CurvesGeometry &curves, const eAttrDomain domain)
T distance(const T &a, const T &b)
static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
static void node_geo_exec(GeoNodeExecParams params)
static void node_init(bNodeTree *UNUSED(ntree), bNode *node)
static void node_update(bNodeTree *ntree, bNode *node)
static void node_declare(NodeDeclarationBuilder &b)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
static const pxr::TfToken density("density", pxr::TfToken::Immortal)
static void node_init(const struct bContext *C, bNodeTree *ntree, bNode *node)
MutableSpan< float3 > positions
MutableSpan< float > radii
void register_node_type_geo_points_to_volume()
void geo_node_type_base(bNodeType *ntype, int type, const char *name, short nclass)
void node_copy_standard_storage(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, const bNode *src_node)
void node_free_standard_storage(bNode *node)
bool has(const GeometryComponentType component_type) const
void keep_only_during_modify(const blender::Span< GeometryComponentType > component_types)
const GeometryComponent * get_component_for_read(GeometryComponentType component_type) const
void replace_volume(Volume *volume, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
void modify_geometry_sets(ForeachSubGeometryCallback callback)
NodeGeometryExecFunction geometry_node_execute
void(* draw_buttons)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr)
NodeDeclareFunction declare