Skip to content

Commit 6f10c98

Browse files
committed
Add an example to demonstrate sampling and point advection using an adaptive grid
Signed-off-by: Dan Bailey <[email protected]>
1 parent d2cf953 commit 6f10c98

File tree

2 files changed

+102
-38
lines changed

2 files changed

+102
-38
lines changed

openvdb/openvdb/tools/Interpolation.h

+68-38
Original file line numberDiff line numberDiff line change
@@ -629,29 +629,35 @@ template<class ValueT, class TreeT, size_t N>
629629
inline void
630630
BoxSampler::getValues(ValueT (&data)[N][N][N], const TreeT& inTree, Coord ijk)
631631
{
632-
data[0][0][0] = inTree.getValue(ijk); // i, j, k
632+
// This algorithm is only defined for sparse grids
633633

634-
ijk[2] += 1;
635-
data[0][0][1] = inTree.getValue(ijk); // i, j, k + 1
634+
if constexpr (TreeTraits<TreeT>::IsSparse) {
635+
data[0][0][0] = inTree.getValue(ijk); // i, j, k
636636

637-
ijk[1] += 1;
638-
data[0][1][1] = inTree.getValue(ijk); // i, j+1, k + 1
637+
ijk[2] += 1;
638+
data[0][0][1] = inTree.getValue(ijk); // i, j, k + 1
639639

640-
ijk[2] -= 1;
641-
data[0][1][0] = inTree.getValue(ijk); // i, j+1, k
640+
ijk[1] += 1;
641+
data[0][1][1] = inTree.getValue(ijk); // i, j+1, k + 1
642642

643-
ijk[0] += 1;
644-
ijk[1] -= 1;
645-
data[1][0][0] = inTree.getValue(ijk); // i+1, j, k
643+
ijk[2] -= 1;
644+
data[0][1][0] = inTree.getValue(ijk); // i, j+1, k
646645

647-
ijk[2] += 1;
648-
data[1][0][1] = inTree.getValue(ijk); // i+1, j, k + 1
646+
ijk[0] += 1;
647+
ijk[1] -= 1;
648+
data[1][0][0] = inTree.getValue(ijk); // i+1, j, k
649649

650-
ijk[1] += 1;
651-
data[1][1][1] = inTree.getValue(ijk); // i+1, j+1, k + 1
650+
ijk[2] += 1;
651+
data[1][0][1] = inTree.getValue(ijk); // i+1, j, k + 1
652652

653-
ijk[2] -= 1;
654-
data[1][1][0] = inTree.getValue(ijk); // i+1, j+1, k
653+
ijk[1] += 1;
654+
data[1][1][1] = inTree.getValue(ijk); // i+1, j+1, k + 1
655+
656+
ijk[2] -= 1;
657+
data[1][1][0] = inTree.getValue(ijk); // i+1, j+1, k
658+
} else {
659+
static_assert(AlwaysFalseValue<TreeT>, "Not Implemented");
660+
}
655661
}
656662

657663
template<class ValueT, class TreeT, size_t N>
@@ -744,39 +750,63 @@ inline bool
744750
BoxSampler::sample(const TreeT& inTree, const Vec3R& inCoord,
745751
typename TreeT::ValueType& result)
746752
{
747-
using ValueT = typename TreeT::ValueType;
748-
749-
const Vec3i inIdx = local_util::floorVec3(inCoord);
750-
const Vec3R uvw = inCoord - inIdx;
751-
752-
// Retrieve the values of the eight voxels surrounding the
753-
// fractional source coordinates.
754-
ValueT data[2][2][2];
755-
756-
const bool hasActiveValues = BoxSampler::probeValues(data, inTree, Coord(inIdx));
757-
758-
result = BoxSampler::trilinearInterpolation(data, uvw);
759-
760-
return hasActiveValues;
753+
if constexpr (TreeTraits<TreeT>::IsSparse) {
754+
using ValueT = typename TreeT::ValueType;
755+
756+
const Vec3i inIdx = local_util::floorVec3(inCoord);
757+
const Vec3R uvw = inCoord - inIdx;
758+
759+
// Retrieve the values of the eight voxels surrounding the
760+
// fractional source coordinates.
761+
ValueT data[2][2][2];
762+
763+
const bool hasActiveValues = BoxSampler::probeValues(data, inTree, Coord(inIdx));
764+
765+
result = BoxSampler::trilinearInterpolation(data, uvw);
766+
767+
return hasActiveValues;
768+
} else if constexpr (TreeTraits<TreeT>::IsAdaptive) {
769+
// As an example, return the background value.
770+
// This is where the logic that could sample against an adaptive tree would live.
771+
// Extract the tree from the Tree or ValueAccessor
772+
auto& tree = TreeAdapter<TreeT>::tree(inTree);
773+
result = tree.background();
774+
return true;
775+
} else {
776+
static_assert(AlwaysFalseValue<TreeT>, "Not Implemented");
777+
}
778+
std::abort(); // unreachable
761779
}
762780

763781

764782
template<class TreeT>
765783
inline typename TreeT::ValueType
766784
BoxSampler::sample(const TreeT& inTree, const Vec3R& inCoord)
767785
{
768-
using ValueT = typename TreeT::ValueType;
786+
if constexpr (TreeTraits<TreeT>::IsSparse) {
769787

770-
const Vec3i inIdx = local_util::floorVec3(inCoord);
771-
const Vec3R uvw = inCoord - inIdx;
788+
using ValueT = typename TreeT::ValueType;
772789

773-
// Retrieve the values of the eight voxels surrounding the
774-
// fractional source coordinates.
775-
ValueT data[2][2][2];
790+
const Vec3i inIdx = local_util::floorVec3(inCoord);
791+
const Vec3R uvw = inCoord - inIdx;
792+
793+
// Retrieve the values of the eight voxels surrounding the
794+
// fractional source coordinates.
795+
ValueT data[2][2][2];
776796

777-
BoxSampler::getValues(data, inTree, Coord(inIdx));
797+
BoxSampler::getValues(data, inTree, Coord(inIdx));
778798

779-
return BoxSampler::trilinearInterpolation(data, uvw);
799+
return BoxSampler::trilinearInterpolation(data, uvw);
800+
} else if constexpr (TreeTraits<TreeT>::IsAdaptive) {
801+
// As an example, return the background value.
802+
// This is where the logic that could sample against an adaptive tree would live.
803+
// Extract the tree from the Tree or ValueAccessor
804+
auto& tree = TreeAdapter<TreeT>::tree(inTree);
805+
return tree.background();
806+
} else {
807+
static_assert(AlwaysFalseValue<TreeT>, "Not Implemented");
808+
}
809+
std::abort(); // unreachable
780810
}
781811

782812

openvdb/openvdb/unittest/TestAdaptive.cc

+34
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// SPDX-License-Identifier: MPL-2.0
33

44
#include <openvdb/openvdb.h>
5+
#include <openvdb/tools/Interpolation.h>
6+
#include <openvdb/tools/PointAdvect.h>
57
#include <openvdb/adaptive/AdaptiveGrid.h>
68

79
#include <gtest/gtest.h>
@@ -23,3 +25,35 @@ TEST_F(TestAdaptive, test)
2325

2426
EXPECT_EQ(adaptiveGrid.background(), 5.0f);
2527
}
28+
29+
TEST_F(TestAdaptive, testSample)
30+
{
31+
const float background = 5.0f;
32+
openvdb::adaptive::AdaptiveGrid<float> adaptiveGrid(background);
33+
34+
float result = openvdb::tools::BoxSampler::sample(adaptiveGrid.tree(), openvdb::Vec3R(1.3, 1.6, 1.8));
35+
36+
EXPECT_EQ(result, background);
37+
}
38+
39+
TEST_F(TestAdaptive, testAdvect)
40+
{
41+
using AdaptiveGridT = openvdb::adaptive::AdaptiveGrid<openvdb::Vec3s>;
42+
using PointAdvectT = openvdb::tools::PointAdvect<AdaptiveGridT>;
43+
using PointListT = PointAdvectT::PointListType;
44+
45+
const openvdb::Vec3s background(0.0f, 1.0f, 0.0f);
46+
AdaptiveGridT adaptiveGrid(background);
47+
48+
openvdb::tools::PointAdvect<AdaptiveGridT> pointAdvect(adaptiveGrid);
49+
50+
PointListT points;
51+
points.push_back(openvdb::Vec3s(0.0f, 0.0f, 0.0f));
52+
points.push_back(openvdb::Vec3s(1.0f, 2.0f, 3.0f));
53+
54+
float dt = 1/24.0f;
55+
pointAdvect.advect(points, dt);
56+
57+
EXPECT_EQ(points[0], openvdb::Vec3s(0.0f, dt, 0.0f));
58+
EXPECT_EQ(points[1], openvdb::Vec3s(1.0f, 2.0f + dt, 3.0f));
59+
}

0 commit comments

Comments
 (0)