OpenVDB: nanovdb/examples/ex_vox_to_nanovdb/VoxToNanoVDB.h Source File

OpenVDB 10.0.1

Loading...
Searching...
No Matches
VoxToNanoVDB.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: MPL-2.0
3
4#pragma once
5
6#include <nanovdb/util/GridBuilder.h>
7
8#define OGT_VOX_IMPLEMENTATION
9#include "ogt_vox.h"
10#if defined(_MSC_VER)
11#include <io.h>
12#endif
13
14 namespace detail {
15
16 inline const ogt_vox_scene* load_vox_scene(const char* filename, uint32_t scene_read_flags = 0)
17{
18#if defined(_MSC_VER) && _MSC_VER >= 1400
19 FILE* fp;
20 if (0 != fopen_s(&fp, filename, "rb"))
21 fp = 0;
22#else
23 FILE* fp = fopen(filename, "rb");
24#endif
25 if (!fp)
26 return NULL;
27 fseek(fp, 0, SEEK_END);
28 uint32_t buffer_size = ftell(fp);
29 fseek(fp, 0, SEEK_SET);
30 uint8_t* buffer = new uint8_t[buffer_size];
31 fread(buffer, buffer_size, 1, fp);
32 fclose(fp);
33 const ogt_vox_scene* scene = ogt_vox_read_scene_with_flags(buffer, buffer_size, scene_read_flags);
34 delete[] buffer; // the buffer can be safely deleted once the scene is instantiated.
35 return scene;
36}
37
38 inline nanovdb::Vec4f matMult4x4(const float* mat, const nanovdb::Vec4f& rhs)
39{
40#define _mat(m, r, c) m[c * 4 + r]
41
42 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],
43 _mat(mat, 1, 0) * rhs[0] + _mat(mat, 1, 1) * rhs[1] + _mat(mat, 1, 2) * rhs[2] + _mat(mat, 1, 3) * rhs[3],
44 _mat(mat, 2, 0) * rhs[0] + _mat(mat, 2, 1) * rhs[1] + _mat(mat, 2, 2) * rhs[2] + _mat(mat, 2, 3) * rhs[3],
45 _mat(mat, 3, 0) * rhs[0] + _mat(mat, 3, 1) * rhs[1] + _mat(mat, 3, 2) * rhs[2] + _mat(mat, 3, 3) * rhs[3]);
46#undef _mat
47}
48
49 inline ogt_vox_transform matMult4x4(const float* m, const float* n)
50{
51#define _mat(m, c, r) m[c * 4 + r]
52
53 return ogt_vox_transform{
54 _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),
55 _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),
56 _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),
57 _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),
58
59 _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),
60 _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),
61 _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),
62 _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),
63
64 _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),
65 _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),
66 _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),
67 _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),
68
69 _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),
70 _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),
71 _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),
72 _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),
73 };
74#undef _mat
75}
76
77ogt_vox_transform getXform(const ogt_vox_scene& scene, const ogt_vox_instance& instance)
78{
79 ogt_vox_transform transform = instance.transform; //{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
80
81 auto groupIndex = instance.group_index;
82 while (groupIndex != 0 && groupIndex != k_invalid_group_index) {
83 const auto& group = scene.groups[groupIndex];
84 transform = matMult4x4((const float*)&transform, (const float*)&group.transform);
85 groupIndex = group.parent_group_index;
86 }
87
88 return transform;
89}
90
91 bool isVisible(const ogt_vox_scene& scene, const ogt_vox_instance& instance)
92{
93 if (instance.hidden)
94 return false;
95
96 if (scene.layers[instance.layer_index].hidden)
97 return false;
98
99 auto groupIndex = instance.group_index;
100 while (groupIndex != 0 && groupIndex != k_invalid_group_index) {
101 const auto& group = scene.groups[groupIndex];
102 if (group.hidden)
103 return false;
104 if (scene.layers[group.layer_index].hidden)
105 return false;
106 groupIndex = group.parent_group_index;
107 printf("group.parent_group_index = %d\n", groupIndex);
108 }
109 return true;
110}
111
112} // namespace detail
113
114/// @brief load a .vox file.
115template<typename BufferT = nanovdb::HostBuffer>
116 nanovdb::GridHandle<BufferT> convertVoxToNanoVDB(const std::string& inFilename, const std::string& modelName)
117{
118#if 0
119 // just debugging the xforms!
120 {
121 ogt_vox_transform translate{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 2, 0, 1};
122 ogt_vox_transform scale{10, 0, 0, 0, 0, 10, 0, 0, 0, 0, 10, 0, 0, 0, 0, 1};
123 ogt_vox_transform translate2{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 2, 0, 1};
124 ogt_vox_transform xform = detail::matMult4x4((float*)&scale, (float*)&translate);
125 xform = detail::matMult4x4((float*)&translate2, (float*)&xform);
126 auto v = detail::matMult4x4((float*)&xform, nanovdb::Vec4f(0, 1, 0, 1));
127 std::cout << v[0] << ' ' << v[1] << ' ' << v[2] << '\n';
128 }
129#endif
130
131 try {
132 if (const auto* scene = detail::load_vox_scene(inFilename.c_str())) {
133 // we just merge into one grid...
134 nanovdb::GridBuilder<nanovdb::PackedRGBA8> builder;
135 auto acc = builder.getAccessor();
136
137 auto processModelFn = [&](int modelIndex, const ogt_vox_transform& xform) {
138 const auto* model = scene->models[modelIndex];
139
140 uint32_t voxel_index = 0;
141 for (uint32_t z = 0; z < model->size_z; ++z) {
142 for (uint32_t y = 0; y < model->size_y; ++y) {
143 for (uint32_t x = 0; x < model->size_x; ++x, ++voxel_index) {
144 if (uint8_t color_index = model->voxel_data[voxel_index]) {
145 ogt_vox_rgba rgba = scene->palette.color[color_index];
146 auto ijk = nanovdb::Coord::Floor(detail::matMult4x4((float*)&xform, nanovdb::Vec4f(x, y, z, 1)));
147 acc.setValue(nanovdb::Coord(ijk[0], ijk[2], -ijk[1]), *reinterpret_cast<nanovdb::PackedRGBA8*>(&rgba));
148 }
149 }
150 }
151 }
152 };
153
154 if (scene->num_instances > 0) {
155 printf("scene processing begin... %d instances\n", scene->num_instances);
156
157 for (uint32_t instanceIndex = 0; instanceIndex < scene->num_instances; instanceIndex++) {
158 const auto& instance = scene->instances[instanceIndex];
159 uint32_t modelIndex = instance.model_index;
160
161 //printf("instance[%d].model_index = %d\n", instanceIndex, instance.model_index);
162 //printf("instance[%d].layer_index = %d\n", instanceIndex, instance.layer_index);
163 //printf("instance[%d].group_index = %d\n", instanceIndex, instance.group_index);
164#if 1
165 if (!detail::isVisible(*scene, instance))
166 continue;
167
168 auto xform = detail::getXform(*scene, instance);
169#else
170 auto xform = instance.transform;
171#endif
172 processModelFn(modelIndex, xform);
173 }
174 } else {
175 printf("scene processing begin... %d models\n", scene->num_models);
176
177 ogt_vox_transform xform{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
178
179 for (uint32_t modelIndex = 0; modelIndex < scene->num_models; modelIndex++) {
180 processModelFn(modelIndex, xform);
181 xform.m30 += 30;
182 }
183 }
184
185 printf("scene processing end.\n");
186 ogt_vox_destroy_scene(scene);
187 builder.setGridClass(nanovdb::GridClass::VoxelVolume);
188 return builder.getHandle<>(1.0f, nanovdb::Vec3d(0), modelName);
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}
GridBuilder.h
Generates a NanoVDB grid from any volume or function.
convertVoxToNanoVDB
nanovdb::GridHandle< BufferT > convertVoxToNanoVDB(const std::string &inFilename, const std::string &modelName)
load a .vox file.
Definition VoxToNanoVDB.h:116
_mat
#define _mat(m, r, c)
nanovdb::Coord
Signed (i, j, k) 32-bit integer coordinate class, similar to openvdb::math::Coord.
Definition NanoVDB.h:967
nanovdb::Coord::Floor
static Coord Floor(const Vec3T &xyz)
Return the largest integer coordinates that are not greater than xyz (node centered conversion).
Definition NanoVDB.h:1133
nanovdb::DenseGridHandle
Definition DenseGrid.h:402
nanovdb::Rgba8
8-bit red, green, blue, alpha packed into 32 bit unsigned int
Definition NanoVDB.h:559
io.h
detail
Definition VoxToNanoVDB.h:14
detail::matMult4x4
nanovdb::Vec4f matMult4x4(const float *mat, const nanovdb::Vec4f &rhs)
Definition VoxToNanoVDB.h:38
detail::isVisible
bool isVisible(const ogt_vox_scene &scene, const ogt_vox_instance &instance)
Definition VoxToNanoVDB.h:91
detail::load_vox_scene
const ogt_vox_scene * load_vox_scene(const char *filename, uint32_t scene_read_flags=0)
Definition VoxToNanoVDB.h:16
detail::getXform
ogt_vox_transform getXform(const ogt_vox_scene &scene, const ogt_vox_instance &instance)
Definition VoxToNanoVDB.h:77
nanovdb::Vec4f
Vec4< float > Vec4f
Definition NanoVDB.h:1418
nanovdb::GridClass::VoxelVolume
@ VoxelVolume
nanovdb::Vec3d
Vec3< double > Vec3d
Definition NanoVDB.h:1288