OpenVDB  9.0.1
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 
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 
77 ogt_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.
115 template<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...
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);
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  }
199 }
const ogt_vox_scene * load_vox_scene(const char *filename, uint32_t scene_read_flags=0)
Definition: VoxToNanoVDB.h:16
bool isVisible(const ogt_vox_scene &scene, const ogt_vox_instance &instance)
Definition: VoxToNanoVDB.h:91
A simple vector class with three double components, similar to openvdb::math::Vec4.
Definition: NanoVDB.h:1188
Allows for the construction of NanoVDB grids without any dependecy.
Definition: GridBuilder.h:91
nanovdb::GridHandle< BufferT > convertVoxToNanoVDB(const std::string &inFilename, const std::string &modelName)
load a .vox file.
Definition: VoxToNanoVDB.h:116
This class serves to manage a raw memory buffer of a NanoVDB Grid.
Definition: GridHandle.h:70
#define _mat(m, r, c)
Vec4< float > Vec4f
Definition: NanoVDB.h:1304
ValueAccessor getAccessor()
Definition: GridBuilder.h:180
Definition: VoxToNanoVDB.h:14
static Coord Floor(const Vec3T &xyz)
Return the largest integer coordinates that are not greater than xyz (node centered conversion)...
Definition: NanoVDB.h:1019
Generates a NanoVDB grid from any volume or function.
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
Definition: Mat.h:637
void setGridClass(GridClass mode=GridClass::Unknown)
Definition: GridBuilder.h:201
ogt_vox_transform getXform(const ogt_vox_scene &scene, const ogt_vox_instance &instance)
Definition: VoxToNanoVDB.h:77
GridHandle< BufferT > getHandle(double voxelSize=1.0, const Vec3d &gridOrigin=Vec3d(0), const std::string &name="", const OracleT &oracle=OracleT(), const BufferT &buffer=BufferT())
Return an instance of a GridHandle (invoking move semantics)
Definition: GridBuilder.h:535
Vec3< double > Vec3d
Definition: NanoVDB.h:1174
nanovdb::Vec4f matMult4x4(const float *mat, const nanovdb::Vec4f &rhs)
Definition: VoxToNanoVDB.h:38
Signed (i, j, k) 32-bit integer coordinate class, similar to openvdb::math::Coord.
Definition: NanoVDB.h:859