Blender V4.3
points_to_volume.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BLI_math_matrix.hh"
6
7#include "BKE_volume.hh"
8#include "BKE_volume_grid.hh"
10
12
13#ifdef WITH_OPENVDB
14# include <openvdb/openvdb.h>
15# include <openvdb/tools/LevelSetUtil.h>
16# include <openvdb/tools/ParticlesToLevelSet.h>
17
18namespace blender::geometry {
19
20/* Implements the interface required by #openvdb::tools::ParticlesToLevelSet. */
21class OpenVDBParticleList {
22 public:
23 using PosType = openvdb::Vec3R;
24
25 private:
26 Span<float3> positions_;
27 Span<float> radii_;
28 float voxel_size_inv_;
29
30 public:
31 OpenVDBParticleList(const Span<float3> positions,
32 const Span<float> radii,
33 const float voxel_size)
34 : positions_(positions), radii_(radii), voxel_size_inv_(math::rcp(voxel_size))
35 {
36 BLI_assert(voxel_size > 0.0f);
37 }
38
39 size_t size() const
40 {
41 return size_t(positions_.size());
42 }
43
44 void getPos(size_t n, openvdb::Vec3R &xyz) const
45 {
46 float3 pos = positions_[n] * voxel_size_inv_;
47 /* Better align generated grid with source points. */
48 pos -= float3(0.5f);
49 xyz = &pos.x;
50 }
51
52 void getPosRad(size_t n, openvdb::Vec3R &xyz, openvdb::Real &radius) const
53 {
54 this->getPos(n, xyz);
55 radius = radii_[n] * voxel_size_inv_;
56 }
57};
58
59static openvdb::FloatGrid::Ptr points_to_sdf_grid_impl(const Span<float3> positions,
60 const Span<float> radii,
61 const float voxel_size)
62{
63 /* Create a new grid that will be filled. #ParticlesToLevelSet requires
64 * the background value to be positive */
65 openvdb::FloatGrid::Ptr new_grid = openvdb::FloatGrid::create(1.0f);
66
67 /* Create a narrow-band level set grid based on the positions and radii. */
68 openvdb::tools::ParticlesToLevelSet op{*new_grid};
69 /* Don't ignore particles based on their radius. */
70 op.setRmin(0.0f);
71 op.setRmax(std::numeric_limits<float>::max());
72 OpenVDBParticleList particles{positions, radii, voxel_size};
73 op.rasterizeSpheres(particles);
74 op.finalize();
75
76 new_grid->transform().postScale(voxel_size);
77 new_grid->setGridClass(openvdb::GRID_LEVEL_SET);
78
79 return new_grid;
80}
81
82bke::VolumeGrid<float> points_to_sdf_grid(const Span<float3> positions,
83 const Span<float> radii,
84 const float voxel_size)
85{
86 return bke::VolumeGrid<float>(points_to_sdf_grid_impl(positions, radii, voxel_size));
87}
88
89bke::VolumeGridData *fog_volume_grid_add_from_points(Volume *volume,
90 const StringRefNull name,
91 const Span<float3> positions,
92 const Span<float> radii,
93 const float voxel_size,
94 const float density)
95{
96 openvdb::FloatGrid::Ptr new_grid = points_to_sdf_grid_impl(positions, radii, voxel_size);
97 new_grid->setGridClass(openvdb::GRID_FOG_VOLUME);
98
99 /* Convert the level set to a fog volume. This also sets the background value to zero. Inside the
100 * fog there will be a density of 1. */
101 openvdb::tools::sdfToFogVolume(*new_grid);
102
103 /* Take the desired density into account. */
104 openvdb::tools::foreach (new_grid->beginValueOn(),
105 [&](const openvdb::FloatGrid::ValueOnIter &iter) {
106 iter.modifyValue([&](float &value) { value *= density; });
107 });
108
109 return BKE_volume_grid_add_vdb(*volume, name, std::move(new_grid));
110}
111
112} // namespace blender::geometry
113#endif
Volume data-block.
#define BLI_assert(a)
Definition BLI_assert.h:50
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
ccl_device_inline float3 rcp(const float3 a)