Read a NanoVDB grid from a file and print out multiple values. /// ///
The first example shows how to convert an OpenVDB level set sphere into a NanoVDB level set, use accessors to print out multiple values from both grids, and save the NanoVDB grid to file. Note that this example depends on both OpenVDB and NanoVDB.
int main()
{
try {
auto srcGrid = openvdb::tools::createLevelSetSphere<openvdb::FloatGrid>(100.0f, openvdb::Vec3f(0.0f), 1.0f);
auto handle = nanovdb::createNanoGrid(*srcGrid);
auto* dstGrid = handle.grid<float>();
if (!dstGrid)
throw std::runtime_error("GridHandle does not contain a grid with value type float");
auto dstAcc = dstGrid->getAccessor();
auto srcAcc = srcGrid->getAccessor();
for (int i = 97; i < 104; ++i) {
printf("(%3i,0,0) OpenVDB cpu: % -4.2f, NanoVDB cpu: % -4.2f\n", i, srcAcc.getValue(openvdb::Coord(i, 0, 0)), dstAcc.getValue(nanovdb::Coord(i, 0, 0)));
}
nanovdb::io::writeGrid("data/sphere.nvdb", handle);
}
catch (const std::exception& e) {
std::cerr << "An exception occurred: \"" << e.what() << "\"" << std::endl;
}
return 0;
}
The second example reads a NanoVDB grid from a file (the one saved in the previous example) and prints out multiple values. Note that this example does not depend on OpenVDB (nor CUDA), only NanoVDB.
int main()
{
try {
auto handle = nanovdb::io::readGrid("data/sphere.nvdb");
auto* grid = handle.grid<float>();
if (!grid)
throw std::runtime_error("File did not contain a grid with value type float");
auto acc = grid->getAccessor();
for (int i = 97; i < 104; ++i) {
printf("(%3i,0,0) NanoVDB cpu: % -4.2f\n", i, acc.getValue(nanovdb::Coord(i, 0, 0)));
}
}
catch (const std::exception& e) {
std::cerr << "An exception occurred: \"" << e.what() << "\"" << std::endl;
}
return 0;
}
The third example reads a NanoVDB grid from a file (the one saved in the first example) and prints out multiple values on both the CPU and GPU. Note that this example does NOT depend on OpenVDB, only NanoVDB and CUDA.
#include <nanovdb/util/cuda/CudaDeviceBuffer.h>
cudaStream_t stream);
int main()
{
try {
auto handle = nanovdb::io::readGrid<nanovdb::CudaDeviceBuffer>("data/sphere.nvdb");
cudaStream_t stream;
cudaStreamCreate(&stream);
handle.deviceUpload(stream, false);
auto* cpuGrid = handle.grid<float>();
auto* deviceGrid = handle.deviceGrid<float>();
if (!deviceGrid || !cpuGrid)
throw std::runtime_error("GridHandle did not contain a grid with value type float");
launch_kernels(deviceGrid, cpuGrid, stream);
cudaStreamDestroy(stream);
}
catch (const std::exception& e) {
std::cerr << "An exception occurred: \"" << e.what() << "\"" << std::endl;
}
return 0;
}
NVCC requires the CUDA kernel to be defined in a separate .cu file:
#include <stdio.h>
{
for (int i = 97; i < 104; ++i) {
printf("(%3i,0,0) NanoVDB cpu: % -4.2f\n", i, cpuAcc.getValue(nanovdb::Coord(i, 0, 0)));
}
}
{
if (threadIdx.x > 6)
return;
int i = 97 + threadIdx.x;
printf("(%3i,0,0) NanoVDB gpu: % -4.2f\n", i, gpuAcc.getValue(nanovdb::Coord(i, 0, 0)));
}
cudaStream_t stream)
{
gpu_kernel<<<1, 64, 0, stream>>>(deviceGrid);
cpu_kernel(cpuGrid);
}