Lagrange
Loading...
Searching...
No Matches
register_grid.h
1/*
2 * Copyright 2026 Adobe. All rights reserved.
3 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License. You may obtain a copy
5 * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 *
7 * Unless required by applicable law or agreed to in writing, software distributed under
8 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 * OF ANY KIND, either express or implied. See the License for the specific language
10 * governing permissions and limitations under the License.
11 */
12
13#pragma once
14
15#include <lagrange/Logger.h>
16#include <lagrange/utils/assert.h>
17#include <lagrange/volume/types.h>
18
19// clang-format off
20#include <lagrange/utils/warnoff.h>
21#include <polyscope/polyscope.h>
22#include <polyscope/volume_grid.h>
23#include <openvdb/tools/FastSweeping.h>
24#include <openvdb/tools/Dense.h>
25#include <openvdb/tools/Interpolation.h>
26#include <tbb/parallel_for.h>
27#include <tbb/blocked_range3d.h>
28#include <tbb/enumerable_thread_specific.h>
29#include <lagrange/utils/warnon.h>
30// clang-format on
31
32using FloatGrid = lagrange::volume::Grid<float>;
33
34void register_grid(std::string_view name, const FloatGrid& grid)
35{
36 auto bbox_index = grid.evalActiveVoxelBoundingBox();
37 la_runtime_assert(!bbox_index.empty(), "Grid has no active voxels.");
38 auto bbox_world = grid.transform().indexToWorld(bbox_index);
39
40 uint32_t dimX = bbox_index.dim().x();
41 uint32_t dimY = bbox_index.dim().y();
42 uint32_t dimZ = bbox_index.dim().z();
43 glm::vec3 bbox_min(
44 static_cast<float>(bbox_world.min().x()),
45 static_cast<float>(bbox_world.min().y()),
46 static_cast<float>(bbox_world.min().z()));
47 glm::vec3 bbox_max(
48 static_cast<float>(bbox_world.max().x()),
49 static_cast<float>(bbox_world.max().y()),
50 static_cast<float>(bbox_world.max().z()));
51
52 // register the grid
53 polyscope::VolumeGrid* ps_grid =
54 polyscope::registerVolumeGrid(std::string(name), {dimX, dimY, dimZ}, bbox_min, bbox_max);
55
56 // add a scalar function on the grid
57 uint32_t num_voxels = dimX * dimY * dimZ;
58 std::vector<float> values(num_voxels, 0.f);
59 auto o = bbox_index.min();
60 struct Data
61 {
62 FloatGrid::ConstAccessor accessor;
63 };
64 tbb::enumerable_thread_specific<Data> data([&]() { return Data{grid.getConstAccessor()}; });
65 using Range3d = tbb::blocked_range3d<int32_t>;
66 const Range3d voxel_range(0, dimZ, 0, dimY, 0, dimX);
67 tbb::parallel_for(voxel_range, [&](const Range3d& range) {
68 auto rz = range.pages();
69 auto ry = range.rows();
70 auto rx = range.cols();
71 auto& accessor = data.local().accessor;
72 for (int32_t k = rz.begin(); k != rz.end(); ++k) {
73 for (int32_t j = ry.begin(); j != ry.end(); ++j) {
74 for (int32_t i = rx.begin(); i != rx.end(); ++i) {
75 openvdb::Vec3R ijk_is(i + o.x(), j + o.y(), k + o.z());
76 float value = openvdb::tools::BoxSampler::sample(accessor, ijk_is);
77 values[k * dimY * dimX + j * dimX + i] = value;
78 }
79 }
80 }
81 });
82 lagrange::logger().info(
83 "Registered {} voxels. Min corner: {}, {}, {}",
84 num_voxels,
85 bbox_min.x,
86 bbox_min.y,
87 bbox_min.z);
88
89 polyscope::VolumeGridNodeScalarQuantity* ps_scalars =
90 ps_grid->addNodeScalarQuantity("values", std::make_tuple(values.data(), num_voxels));
91 ps_scalars->setEnabled(true);
92}
LA_CORE_API spdlog::logger & logger()
Retrieves the current logger.
Definition Logger.cpp:40
#define la_runtime_assert(...)
Runtime assertion check.
Definition assert.h:174
internal::Range< Index > range(Index end)
Returns an iterable object representing the range [0, end).
Definition range.h:176