OpenVDB 13.0.0

Loading...
Searching...
No Matches
VoxToNanoVDB.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: Apache-2.0
3
4#pragma once
5
6#include <nanovdb/tools/GridBuilder.h>
7#include <nanovdb/tools/CreateNanoGrid.h>
8
9#define OGT_VOX_IMPLEMENTATION
10#include "ogt_vox.h"
11#if defined(_MSC_VER)
12#include <io.h>
13#endif
14
15 namespace detail {
16
17 inline const ogt_vox_scene* load_vox_scene(const char* filename, uint32_t scene_read_flags = 0)
18{
19#if defined(_MSC_VER) && _MSC_VER >= 1400
20 FILE* fp;
21 if (0 != fopen_s(&fp, filename, "rb"))
22 fp = 0;
23#else
24 FILE* fp = fopen(filename, "rb");
25#endif
26 if (!fp)
27 return NULL;
28 fseek(fp, 0, SEEK_END);
29 uint32_t buffer_size = ftell(fp);
30 fseek(fp, 0, SEEK_SET);
31 uint8_t* buffer = new uint8_t[buffer_size];
32 size_t bytes = fread(buffer, buffer_size, 1, fp);
33 fclose(fp);
34 const ogt_vox_scene* scene = ogt_vox_read_scene_with_flags(buffer, buffer_size, scene_read_flags);
35 delete[] buffer; // the buffer can be safely deleted once the scene is instantiated.
36 return scene;
37}
38
39 inline nanovdb::Vec4f matMult4x4(const float* mat, const nanovdb::Vec4f& rhs)
40{
41#define _mat(m, r, c) m[c * 4 + r]
42
43 return nanovdb::Vec4f(_mat(mat, 0, 0) * rhs[0] + _mat(mat, 0, 1) * rhs[1] + _mat(mat, 0, 2) * rhs[2] + _mat(mat, 0, 3) * rhs[3],
44 _mat(mat, 1, 0) * rhs[0] + _mat(mat, 1, 1) * rhs[1] + _mat(mat, 1, 2) * rhs[2] + _mat(mat, 1, 3) * rhs[3],
45 _mat(mat, 2, 0) * rhs[0] + _mat(mat, 2, 1) * rhs[1] + _mat(mat, 2, 2) * rhs[2] + _mat(mat, 2, 3) * rhs[3],
46 _mat(mat, 3, 0) * rhs[0] + _mat(mat, 3, 1) * rhs[1] + _mat(mat, 3, 2) * rhs[2] + _mat(mat, 3, 3) * rhs[3]);
47#undef _mat
48}
49
50 inline ogt_vox_transform matMult4x4(const float* m, const float* n)
51{
52#define _mat(m, c, r) m[c * 4 + r]
53
54 return ogt_vox_transform{
55 _mat(m, 0, 0) * _mat(n, 0, 0) + _mat(m, 0, 1) * _mat(n, 1, 0) + _mat(m, 0, 2) * _mat(n, 2, 0) + _mat(m, 0, 3) * _mat(n, 3, 0),
56 _mat(m, 0, 0) * _mat(n, 0, 1) + _mat(m, 0, 1) * _mat(n, 1, 1) + _mat(m, 0, 2) * _mat(n, 2, 1) + _mat(m, 0, 3) * _mat(n, 3, 1),
57 _mat(m, 0, 0) * _mat(n, 0, 2) + _mat(m, 0, 1) * _mat(n, 1, 2) + _mat(m, 0, 2) * _mat(n, 2, 2) + _mat(m, 0, 3) * _mat(n, 3, 2),
58 _mat(m, 0, 0) * _mat(n, 0, 3) + _mat(m, 0, 1) * _mat(n, 1, 3) + _mat(m, 0, 2) * _mat(n, 2, 3) + _mat(m, 0, 3) * _mat(n, 3, 3),
59
60 _mat(m, 1, 0) * _mat(n, 0, 0) + _mat(m, 1, 1) * _mat(n, 1, 0) + _mat(m, 1, 2) * _mat(n, 2, 0) + _mat(m, 1, 3) * _mat(n, 3, 0),
61 _mat(m, 1, 0) * _mat(n, 0, 1) + _mat(m, 1, 1) * _mat(n, 1, 1) + _mat(m, 1, 2) * _mat(n, 2, 1) + _mat(m, 1, 3) * _mat(n, 3, 1),
62 _mat(m, 1, 0) * _mat(n, 0, 2) + _mat(m, 1, 1) * _mat(n, 1, 2) + _mat(m, 1, 2) * _mat(n, 2, 2) + _mat(m, 1, 3) * _mat(n, 3, 2),
63 _mat(m, 1, 0) * _mat(n, 0, 3) + _mat(m, 1, 1) * _mat(n, 1, 3) + _mat(m, 1, 2) * _mat(n, 2, 3) + _mat(m, 1, 3) * _mat(n, 3, 3),
64
65 _mat(m, 2, 0) * _mat(n, 0, 0) + _mat(m, 2, 1) * _mat(n, 1, 0) + _mat(m, 2, 2) * _mat(n, 2, 0) + _mat(m, 2, 3) * _mat(n, 3, 0),
66 _mat(m, 2, 0) * _mat(n, 0, 1) + _mat(m, 2, 1) * _mat(n, 1, 1) + _mat(m, 2, 2) * _mat(n, 2, 1) + _mat(m, 2, 3) * _mat(n, 3, 1),
67 _mat(m, 2, 0) * _mat(n, 0, 2) + _mat(m, 2, 1) * _mat(n, 1, 2) + _mat(m, 2, 2) * _mat(n, 2, 2) + _mat(m, 2, 3) * _mat(n, 3, 2),
68 _mat(m, 2, 0) * _mat(n, 0, 3) + _mat(m, 2, 1) * _mat(n, 1, 3) + _mat(m, 2, 2) * _mat(n, 2, 3) + _mat(m, 2, 3) * _mat(n, 3, 3),
69
70 _mat(m, 3, 0) * _mat(n, 0, 0) + _mat(m, 3, 1) * _mat(n, 1, 0) + _mat(m, 3, 2) * _mat(n, 2, 0) + _mat(m, 3, 3) * _mat(n, 3, 0),
71 _mat(m, 3, 0) * _mat(n, 0, 1) + _mat(m, 3, 1) * _mat(n, 1, 1) + _mat(m, 3, 2) * _mat(n, 2, 1) + _mat(m, 3, 3) * _mat(n, 3, 1),
72 _mat(m, 3, 0) * _mat(n, 0, 2) + _mat(m, 3, 1) * _mat(n, 1, 2) + _mat(m, 3, 2) * _mat(n, 2, 2) + _mat(m, 3, 3) * _mat(n, 3, 2),
73 _mat(m, 3, 0) * _mat(n, 0, 3) + _mat(m, 3, 1) * _mat(n, 1, 3) + _mat(m, 3, 2) * _mat(n, 2, 3) + _mat(m, 3, 3) * _mat(n, 3, 3),
74 };
75#undef _mat
76}
77
78ogt_vox_transform getXform(const ogt_vox_scene& scene, const ogt_vox_instance& instance)
79{
80 ogt_vox_transform transform = instance.transform; //{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
81
82 auto groupIndex = instance.group_index;
83 while (groupIndex != 0 && groupIndex != k_invalid_group_index) {
84 const auto& group = scene.groups[groupIndex];
85 transform = matMult4x4((const float*)&transform, (const float*)&group.transform);
86 groupIndex = group.parent_group_index;
87 }
88
89 return transform;
90}
91
92 bool isVisible(const ogt_vox_scene& scene, const ogt_vox_instance& instance)
93{
94 if (instance.hidden)
95 return false;
96
97 if (scene.layers[instance.layer_index].hidden)
98 return false;
99
100 auto groupIndex = instance.group_index;
101 while (groupIndex != 0 && groupIndex != k_invalid_group_index) {
102 const auto& group = scene.groups[groupIndex];
103 if (group.hidden)
104 return false;
105 if (scene.layers[group.layer_index].hidden)
106 return false;
107 groupIndex = group.parent_group_index;
108 printf("group.parent_group_index = %d\n", groupIndex);
109 }
110 return true;
111}
112
113} // namespace detail
114
115/// @brief load a .vox file.
116 template<typename BufferT = nanovdb::HostBuffer>
117 nanovdb::GridHandle<BufferT> convertVoxToNanoVDB(const std::string& inFilename, const std::string& modelName)
118{
119#if 0
120 // just debugging the xforms!
121 {
122 ogt_vox_transform translate{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 2, 0, 1};
123 ogt_vox_transform scale{10, 0, 0, 0, 0, 10, 0, 0, 0, 0, 10, 0, 0, 0, 0, 1};
124 ogt_vox_transform translate2{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 2, 0, 1};
125 ogt_vox_transform xform = detail::matMult4x4((float*)&scale, (float*)&translate);
126 xform = detail::matMult4x4((float*)&translate2, (float*)&xform);
127 auto v = detail::matMult4x4((float*)&xform, nanovdb::Vec4f(0, 1, 0, 1));
128 std::cout << v[0] << ' ' << v[1] << ' ' << v[2] << '\n';
129 }
130#endif
131
132 try {
133 if (const auto* scene = detail::load_vox_scene(inFilename.c_str())) {
134 // we just merge into one grid...
135 nanovdb::tools::build::Grid<nanovdb::math::Rgba8> grid(nanovdb::math::Rgba8(),modelName,nanovdb::GridClass::VoxelVolume);
136 auto acc = grid.getAccessor();
137
138 auto processModelFn = [&](int modelIndex, const ogt_vox_transform& xform) {
139 const auto* model = scene->models[modelIndex];
140
141 uint32_t voxel_index = 0;
142 for (uint32_t z = 0; z < model->size_z; ++z) {
143 for (uint32_t y = 0; y < model->size_y; ++y) {
144 for (uint32_t x = 0; x < model->size_x; ++x, ++voxel_index) {
145 if (uint8_t color_index = model->voxel_data[voxel_index]) {
146 ogt_vox_rgba rgba = scene->palette.color[color_index];
147 auto ijk = nanovdb::Coord::Floor(detail::matMult4x4((float*)&xform, nanovdb::Vec4f(x, y, z, 1)));
148 acc.setValue(nanovdb::Coord(ijk[0], ijk[2], -ijk[1]), *reinterpret_cast<nanovdb::math::Rgba8*>(&rgba));
149 }
150 }
151 }
152 }
153 };
154
155 if (scene->num_instances > 0) {
156 printf("scene processing begin... %d instances\n", scene->num_instances);
157
158 for (uint32_t instanceIndex = 0; instanceIndex < scene->num_instances; instanceIndex++) {
159 const auto& instance = scene->instances[instanceIndex];
160 uint32_t modelIndex = instance.model_index;
161
162 //printf("instance[%d].model_index = %d\n", instanceIndex, instance.model_index);
163 //printf("instance[%d].layer_index = %d\n", instanceIndex, instance.layer_index);
164 //printf("instance[%d].group_index = %d\n", instanceIndex, instance.group_index);
165#if 1
166 if (!detail::isVisible(*scene, instance))
167 continue;
168
169 auto xform = detail::getXform(*scene, instance);
170#else
171 auto xform = instance.transform;
172#endif
173 processModelFn(modelIndex, xform);
174 }
175 } else {
176 printf("scene processing begin... %d models\n", scene->num_models);
177
178 ogt_vox_transform xform{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
179
180 for (uint32_t modelIndex = 0; modelIndex < scene->num_models; modelIndex++) {
181 processModelFn(modelIndex, xform);
182 xform.m30 += 30;
183 }
184 }
185
186 printf("scene processing end.\n");
187 ogt_vox_destroy_scene(scene);
188 return nanovdb::tools::createNanoGrid(grid);
189 } else {
190 std::ostringstream ss;
191 ss << "Invalid file \"" << inFilename << "\"";
192 throw std::runtime_error(ss.str());
193 }
194 }
195 catch (const std::exception& e) {
196 std::cerr << "An exception occurred: \"" << e.what() << "\"" << std::endl;
197 }
198 return nanovdb::GridHandle<BufferT>();
199}
convertVoxToNanoVDB
nanovdb::GridHandle< BufferT > convertVoxToNanoVDB(const std::string &inFilename, const std::string &modelName)
load a .vox file.
Definition VoxToNanoVDB.h:117
_mat
#define _mat(m, r, c)
nanovdb::GridHandle
This class serves to manage a buffer containing one or more NanoVDB Grids.
Definition GridHandle.h:38
detail
Definition VoxToNanoVDB.h:15
detail::matMult4x4
nanovdb::Vec4f matMult4x4(const float *mat, const nanovdb::Vec4f &rhs)
Definition VoxToNanoVDB.h:39
detail::isVisible
bool isVisible(const ogt_vox_scene &scene, const ogt_vox_instance &instance)
Definition VoxToNanoVDB.h:92
detail::load_vox_scene
const ogt_vox_scene * load_vox_scene(const char *filename, uint32_t scene_read_flags=0)
Definition VoxToNanoVDB.h:17
detail::getXform
ogt_vox_transform getXform(const ogt_vox_scene &scene, const ogt_vox_instance &instance)
Definition VoxToNanoVDB.h:78
nanovdb::GridClass::VoxelVolume
@ VoxelVolume
Definition NanoVDB.h:290
nanovdb::GridType::Vec4f
@ Vec4f
Definition NanoVDB.h:231