OpenVDB  12.1.0
CNanoVDB.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: Apache-2.0
3 
4 //
5 // Simple C-wrapper for the nanovdb structure
6 // Meant for systems where you lack a C++ compiler.
7 //
8 
9 /// @warning This header file will soon be deprecated in favor of PNanoVDB.h
10 
11 #ifndef __CNANOVDB__
12 #define __CNANOVDB__
13 
14 #define CNANOVDB_DATA_ALIGNMENT 32
15 #define CNANOVDB_ALIGNMENT_PADDING(x, n) (-(x) & ((n)-1))
16 
17 #define USE_SINGLE_ROOT_KEY
18 
19 #ifdef __OPENCL_VERSION__
20 
21 #define CNANOVDB_GLOBAL __global
22 #define RESTRICT restrict
23 
24 // OpenCL doesn't define these basic types:
25 typedef unsigned long uint64_t;
26 typedef long int64_t;
27 typedef unsigned int uint32_t;
28 typedef int int32_t;
29 typedef short int16_t;
30 typedef unsigned short uint16_t;
31 typedef unsigned char uint8_t;
32 
33 #else
34 
35 #define CNANOVDB_GLOBAL
36 #define RESTRICT __restrict
37 
38 #endif
39 
40 
42 {
54 };
55 
56 #define ROOT_LEVEL 3
57 
58 #define DEFINEMASK_int(LOG2DIM, SIZE) \
59 typedef struct \
60 { \
61  uint64_t mWords[SIZE >> 6]; \
62 } cnanovdb_mask##LOG2DIM; \
63 \
64 static void cnanovdb_mask##LOG2DIM##_clear(CNANOVDB_GLOBAL cnanovdb_mask##LOG2DIM *RESTRICT mask) \
65 { for (uint32_t i = 0; i < (SIZE >> 6); i++) mask->mWords[i] = 0; } \
66 \
67 static bool cnanovdb_mask##LOG2DIM##_isOn(const CNANOVDB_GLOBAL cnanovdb_mask##LOG2DIM *RESTRICT mask, uint32_t n) \
68 { return 0 != (mask->mWords[n >> 6] & (((uint64_t)(1)) << (n & 63))); } \
69 /**/
70 
71 #define DEFINEMASK(LOG2DIM) \
72  DEFINEMASK_int(LOG2DIM, (1U << (3*LOG2DIM)))
73 
74 #define INSTANTIATE(LOG2DIM) \
75  DEFINEMASK(LOG2DIM)
76 
80 
81 typedef struct
82 {
83  float mMatF[9]; // r,c = 3*r + c
84  float mInvMatF[9]; // r,c = 3*r + c
85  float mVecF[3];
86  float mTaperF;
87  double mMatD[9]; // r,c = 3*r + c
88  double mInvMatD[9]; // r,c = 3*r + c
89  double mVecD[3];
90  double mTaperD;
91 } cnanovdb_map;
92 
93 typedef struct
94 {
95  float mVec[3];
97 
98 typedef struct
99 {
100  int32_t mVec[3];
102 
103 static int
105 {
106  if (a->mVec[0] < b->mVec[0])
107  return -1;
108  if (a->mVec[0] > b->mVec[0])
109  return 1;
110  if (a->mVec[1] < b->mVec[1])
111  return -1;
112  if (a->mVec[1] > b->mVec[1])
113  return 1;
114  if (a->mVec[2] < b->mVec[2])
115  return -1;
116  if (a->mVec[2] > b->mVec[2])
117  return 1;
118  return 0;
119 }
120 
121 #ifdef USE_SINGLE_ROOT_KEY
122 static uint64_t
124 {
125  // Define to workaround a bug with 64-bit shifts in the AMD OpenCL compiler.
126 #if defined(AVOID_64BIT_SHIFT)
127  uint2 key = (uint2)( ((uint32_t)ijk->mVec[2]) >> 12, 0) |
128  (uint2)((((uint32_t)ijk->mVec[1]) >> 12) << 21,
129  ((uint32_t)ijk->mVec[1]) >> 23) |
130  (uint2)(0, (((uint32_t)ijk->mVec[0]) >> 12) << 10);
131  return *(uint64_t *)&key;
132 #else
133  return ((uint64_t) (((uint32_t)ijk->mVec[2]) >> 12)) |
134  (((uint64_t) (((uint32_t)ijk->mVec[1]) >> 12)) << 21) |
135  (((uint64_t) (((uint32_t)ijk->mVec[0]) >> 12)) << 42);
136 #endif
137 }
138 #else
139 static void
141 {
142  key->mVec[0] = ijk->mVec[0] & ~((1u << 12) - 1u);
143  key->mVec[1] = ijk->mVec[1] & ~((1u << 12) - 1u);
144  key->mVec[2] = ijk->mVec[2] & ~((1u << 12) - 1u);
145 }
146 #endif
147 
148 static void
150 {
151  float sx = src->mVec[0];
152  float sy = src->mVec[1];
153  float sz = src->mVec[2];
154  dst->mVec[0] = sx * map->mMatF[0] + sy * map->mMatF[1] + sz * map->mMatF[2] + map->mVecF[0];
155  dst->mVec[1] = sx * map->mMatF[3] + sy * map->mMatF[4] + sz * map->mMatF[5] + map->mVecF[1];
156  dst->mVec[2] = sx * map->mMatF[6] + sy * map->mMatF[7] + sz * map->mMatF[8] + map->mVecF[2];
157 }
158 
159 static void
161 {
162  float sx = src->mVec[0] - map->mVecF[0];
163  float sy = src->mVec[1] - map->mVecF[1];
164  float sz = src->mVec[2] - map->mVecF[2];
165  dst->mVec[0] = sx * map->mInvMatF[0] + sy * map->mInvMatF[1] + sz * map->mInvMatF[2];
166  dst->mVec[1] = sx * map->mInvMatF[3] + sy * map->mInvMatF[4] + sz * map->mInvMatF[5];
167  dst->mVec[2] = sx * map->mInvMatF[6] + sy * map->mInvMatF[7] + sz * map->mInvMatF[8];
168 }
169 
170 static void
172 {
173  float sx = src->mVec[0];
174  float sy = src->mVec[1];
175  float sz = src->mVec[2];
176  dst->mVec[0] = sx * map->mMatF[0] + sy * map->mMatF[1] + sz * map->mMatF[2];
177  dst->mVec[1] = sx * map->mMatF[3] + sy * map->mMatF[4] + sz * map->mMatF[5];
178  dst->mVec[2] = sx * map->mMatF[6] + sy * map->mMatF[7] + sz * map->mMatF[8];
179 }
180 
181 static void
183 {
184  float sx = src->mVec[0];
185  float sy = src->mVec[1];
186  float sz = src->mVec[2];
187  dst->mVec[0] = sx * map->mInvMatF[0] + sy * map->mInvMatF[1] + sz * map->mInvMatF[2];
188  dst->mVec[1] = sx * map->mInvMatF[3] + sy * map->mInvMatF[4] + sz * map->mInvMatF[5];
189  dst->mVec[2] = sx * map->mInvMatF[6] + sy * map->mInvMatF[7] + sz * map->mInvMatF[8];
190 }
191 
192 static void
194 {
195  float sx = src->mVec[0];
196  float sy = src->mVec[1];
197  float sz = src->mVec[2];
198  dst->mVec[0] = sx * map->mInvMatF[0] + sy * map->mInvMatF[3] + sz * map->mInvMatF[6];
199  dst->mVec[1] = sx * map->mInvMatF[1] + sy * map->mInvMatF[4] + sz * map->mInvMatF[7];
200  dst->mVec[2] = sx * map->mInvMatF[2] + sy * map->mInvMatF[5] + sz * map->mInvMatF[8];
201 }
202 
203 typedef struct
204 {
205  int64_t mByteOffset; // byte offset to the blind data, relative to the GridData.
206  uint64_t mElementCount; // number of elements, e.g. point count
207  uint32_t mFlags; // flags
208  uint32_t mSemantic; // semantic meaning of the data.
209  uint32_t mDataClass; // 4 bytes
210  uint32_t mDataType; // 4 bytes
211  char mName[256];
212  uint8_t _reserved[CNANOVDB_ALIGNMENT_PADDING(sizeof(int64_t)+sizeof(uint64_t)+2*sizeof(uint32_t)+2*sizeof(uint32_t)+256*sizeof(char), CNANOVDB_DATA_ALIGNMENT)];
214 
215 typedef struct
216 {
217  uint64_t mMagic; // 8B magic to validate it is valid grid data.
218  uint64_t mChecksum; // 8B. Checksum of grid buffer.
219  uint32_t mVersion;// 4B. compacted major.minor.path version number.
220  uint32_t mFlags; // 4B. flags for grid.
221  uint32_t mGridIndex;// 4B. Index of this grid in the buffer
222  uint32_t mGridCount; // 4B. Total number of grids in the buffer
223  uint64_t mGridSize; // 8B. byte count of this entire grid occupied in the buffer.
224  char mGridName[256]; // 256B
225  cnanovdb_map mMap; // 264B. affine transformation between index and world space in both single and double precision
226  double mBBox[6]; // 48B. floating-point bounds of active values in WORLD SPACE
227  double mVoxelSize[3]; // 24B. size of a voxel in world units
228  uint32_t mGridClass; // 4B.
229  uint32_t mGridType; // 4B.
230  uint64_t mBlindMetadataOffset; // 8B. offset of GridBlindMetaData structures.
231  int32_t mBlindMetadataCount; // 4B. count of GridBlindMetaData structures.
232  uint32_t _reserved[CNANOVDB_ALIGNMENT_PADDING(8 + 8 + 4 + 4 + 4 + 4 + 8 + 256 + 24 + 24 + sizeof(cnanovdb_map) + 24 + 4 + 4 + 8 + 4, CNANOVDB_DATA_ALIGNMENT) / 4];
234 
235 static void
237 {
238  cnanovdb_map_applyInverse(dst, &grid->mMap, src);
239 }
240 
241 static void
243 {
244  cnanovdb_map_apply(dst, &grid->mMap, src);
245 }
246 
247 static void
249 {
250  cnanovdb_map_applyInverseJacobi(dst, &grid->mMap, src);
251 }
252 
253 static void
255 {
256  cnanovdb_map_applyJacobi(dst, &grid->mMap, src);
257 }
258 
259 static void
261 {
262  cnanovdb_map_applyIJT(dst, &grid->mMap, src);
263 }
264 
265 typedef struct
266 {
267  uint64_t mNodeOffset[ROOT_LEVEL + 1];
268  uint32_t mNodeCount[ROOT_LEVEL];
269  uint32_t mTileCount[ROOT_LEVEL];
270  uint64_t mVoxelCount;
271  uint8_t _reserved[CNANOVDB_ALIGNMENT_PADDING(4*sizeof(uint64_t)+(3+3)*sizeof(uint32_t)+sizeof(uint64_t), CNANOVDB_DATA_ALIGNMENT)];
273 
274 static const CNANOVDB_GLOBAL cnanovdb_treedata *
276 {
277  return (const CNANOVDB_GLOBAL cnanovdb_treedata *)(griddata + 1);
278 }
279 
280 #define CREATE_TILEENTRY(VALUETYPE, SUFFIX) \
281 typedef union \
282 { \
283  VALUETYPE value; \
284  uint64_t child; \
285 } cnanovdb_tileentry##SUFFIX; \
286 /**/
287 
288 typedef struct
289 {
291  const CNANOVDB_GLOBAL void *mNode[4];
293 
294 
295 static void
297 {
298  acc->mNode[childlevel] = node;
299  acc->mKey.mVec[0] = ijk->mVec[0];
300  acc->mKey.mVec[1] = ijk->mVec[1];
301  acc->mKey.mVec[2] = ijk->mVec[2];
302 }
303 
304 #define CREATE_LEAF_NODE_int(LEVEL, LOG2DIM, CHILDTOTAL, TOTAL, MASK, VALUETYPE, STATSTYPE, SUFFIX) \
305 typedef struct \
306 { \
307  cnanovdb_coord mBBox_min; \
308  uint8_t mBBoxDif[3]; \
309  uint8_t mFlags; \
310  cnanovdb_mask##LOG2DIM mValueMask; \
311  VALUETYPE mMinimum; \
312  VALUETYPE mMaximum; \
313  STATSTYPE mAverage; \
314  STATSTYPE mStdDevi; \
315  uint32_t _reserved[ CNANOVDB_ALIGNMENT_PADDING(sizeof(cnanovdb_mask##LOG2DIM)+2*sizeof(VALUETYPE)+2*sizeof(STATSTYPE)+sizeof(cnanovdb_coord)+sizeof(uint8_t[3])+sizeof(uint8_t), CNANOVDB_DATA_ALIGNMENT)/4]; \
316  VALUETYPE mVoxels[1u << (3*LOG2DIM)]; \
317 } cnanovdb_node##LEVEL##SUFFIX; \
318 \
319 static uint32_t \
320 cnanovdb_node##LEVEL##SUFFIX##_CoordToOffset(const cnanovdb_coord *RESTRICT ijk) \
321 { \
322  return ( ( ( ijk->mVec[0] & MASK ) >> CHILDTOTAL ) << ( 2 * LOG2DIM ) ) + \
323  ( ( ( ijk->mVec[1] & MASK ) >> CHILDTOTAL ) << ( LOG2DIM ) ) + \
324  ( ( ijk->mVec[2] & MASK ) >> CHILDTOTAL ); \
325 } \
326 \
327 static VALUETYPE \
328 cnanovdb_node##LEVEL##SUFFIX##_getValue(const CNANOVDB_GLOBAL cnanovdb_node##LEVEL##SUFFIX *RESTRICT node, const cnanovdb_coord *RESTRICT ijk) \
329 { \
330  uint32_t n = cnanovdb_node##LEVEL##SUFFIX##_CoordToOffset(ijk); \
331  return node->mVoxels[n]; \
332 } \
333 \
334 static VALUETYPE \
335 cnanovdb_node##LEVEL##SUFFIX##_getValueAndCache(const CNANOVDB_GLOBAL cnanovdb_node##LEVEL##SUFFIX *RESTRICT node, const cnanovdb_coord *RESTRICT ijk, cnanovdb_readaccessor *RESTRICT /* DO NOT REMOVE: Required for C99 compliance */ acc) \
336 { \
337  (void)(acc); \
338  uint32_t n = cnanovdb_node##LEVEL##SUFFIX##_CoordToOffset(ijk); \
339  return node->mVoxels[n]; \
340 } \
341 \
342 static bool \
343 cnanovdb_node##LEVEL##SUFFIX##_isActive(const CNANOVDB_GLOBAL cnanovdb_node##LEVEL##SUFFIX *RESTRICT node, const cnanovdb_coord *RESTRICT ijk) \
344 { \
345  uint32_t n = cnanovdb_node##LEVEL##SUFFIX##_CoordToOffset(ijk); \
346  if (cnanovdb_mask##LOG2DIM##_isOn(&node->mValueMask, n)) \
347  return true; \
348  return false; \
349 } \
350 \
351 static bool \
352 cnanovdb_node##LEVEL##SUFFIX##_isActiveAndCache(const CNANOVDB_GLOBAL cnanovdb_node##LEVEL##SUFFIX *RESTRICT node, const cnanovdb_coord *RESTRICT ijk, cnanovdb_readaccessor *RESTRICT /* DO NOT REMOVE: Required for C99 compliance */ acc) \
353 { \
354  (void)(acc); \
355  uint32_t n = cnanovdb_node##LEVEL##SUFFIX##_CoordToOffset(ijk); \
356  if (cnanovdb_mask##LOG2DIM##_isOn(&node->mValueMask, n)) \
357  return true; \
358  return false; \
359 } \
360 \
361 static const CNANOVDB_GLOBAL cnanovdb_node##LEVEL##SUFFIX * \
362 cnanovdb_tree_getNode##LEVEL##SUFFIX(const CNANOVDB_GLOBAL cnanovdb_treedata *RESTRICT tree, uint64_t i) \
363 { \
364  const CNANOVDB_GLOBAL cnanovdb_node##LEVEL##SUFFIX *basenode = (const CNANOVDB_GLOBAL cnanovdb_node##LEVEL##SUFFIX *)((CNANOVDB_GLOBAL uint8_t *)(tree) + tree->mNodeOffset[LEVEL]); \
365  return basenode + i; \
366 } \
367 \
368 /**/
369 
370 #define CREATE_LEAF_NODE(LEVEL, LOG2DIM, TOTAL, VALUETYPE, STATSTYPE, SUFFIX) \
371 CREATE_LEAF_NODE_int(LEVEL, LOG2DIM, (TOTAL-LOG2DIM), TOTAL, ((1u << TOTAL) - 1u), VALUETYPE, STATSTYPE, SUFFIX)
372 
373 #define CREATE_INTERNAL_NODE_int(CHILDLEVEL, LEVEL, LOG2DIM, CHILDTOTAL, TOTAL, MASK, VALUETYPE, STATSTYPE, SUFFIX) \
374 typedef struct \
375 { \
376  cnanovdb_coord mBBox_min, mBBox_max; \
377  int32_t mOffset; \
378  uint32_t mFlags; \
379  cnanovdb_mask##LOG2DIM mValueMask, mChildMask; \
380  VALUETYPE mMinimum, mMaximum; \
381  STATSTYPE mAverage, mStdDevi; \
382  uint8_t _reserved[CNANOVDB_ALIGNMENT_PADDING(sizeof(cnanovdb_mask##LOG2DIM)+sizeof(VALUETYPE)*2+sizeof(STATSTYPE)*2+sizeof(cnanovdb_coord)*2+sizeof(int32_t)+sizeof(uint32_t), CNANOVDB_DATA_ALIGNMENT)]; \
383  cnanovdb_tileentry##SUFFIX mTable[1u << (3*LOG2DIM)]; \
384 } cnanovdb_node##LEVEL##SUFFIX; \
385 \
386 static uint32_t \
387 cnanovdb_node##LEVEL##SUFFIX##_CoordToOffset(const cnanovdb_coord *RESTRICT ijk) \
388 { \
389  return ( ( ( ijk->mVec[0] & MASK ) >> CHILDTOTAL ) << ( 2 * LOG2DIM ) ) + \
390  ( ( ( ijk->mVec[1] & MASK ) >> CHILDTOTAL ) << ( LOG2DIM ) ) + \
391  ( ( ijk->mVec[2] & MASK ) >> CHILDTOTAL ); \
392 } \
393 \
394 static const CNANOVDB_GLOBAL cnanovdb_node##CHILDLEVEL##SUFFIX * \
395 cnanovdb_node##LEVEL##SUFFIX##_getChild(const CNANOVDB_GLOBAL cnanovdb_node##LEVEL##SUFFIX *RESTRICT node, uint32_t n) \
396 { \
397  const CNANOVDB_GLOBAL cnanovdb_node##CHILDLEVEL##SUFFIX *childnode = (const CNANOVDB_GLOBAL cnanovdb_node##CHILDLEVEL##SUFFIX *)( ((CNANOVDB_GLOBAL uint8_t *)node) + node->mTable[n].child); \
398  return childnode; \
399 } \
400 \
401 static VALUETYPE \
402 cnanovdb_node##LEVEL##SUFFIX##_getValue(const CNANOVDB_GLOBAL cnanovdb_node##LEVEL##SUFFIX *RESTRICT node, const cnanovdb_coord *RESTRICT ijk) \
403 { \
404  uint32_t n = cnanovdb_node##LEVEL##SUFFIX##_CoordToOffset(ijk); \
405  if (cnanovdb_mask##LOG2DIM##_isOn(&node->mChildMask, n)) \
406  { \
407  const CNANOVDB_GLOBAL cnanovdb_node##CHILDLEVEL##SUFFIX *child = cnanovdb_node##LEVEL##SUFFIX##_getChild(node, n); \
408  return cnanovdb_node##CHILDLEVEL##SUFFIX##_getValue(child, ijk); \
409  } \
410  return node->mTable[n].value; \
411 } \
412 \
413 static VALUETYPE \
414 cnanovdb_node##LEVEL##SUFFIX##_getValueAndCache(const CNANOVDB_GLOBAL cnanovdb_node##LEVEL##SUFFIX *RESTRICT node, const cnanovdb_coord *RESTRICT ijk, cnanovdb_readaccessor *RESTRICT acc) \
415 { \
416  uint32_t n = cnanovdb_node##LEVEL##SUFFIX##_CoordToOffset(ijk); \
417  if (cnanovdb_mask##LOG2DIM##_isOn(&node->mChildMask, n)) \
418  { \
419  const CNANOVDB_GLOBAL cnanovdb_node##CHILDLEVEL##SUFFIX *child = cnanovdb_node##LEVEL##SUFFIX##_getChild(node, n); \
420  cnanovdb_readaccessor_insert(acc, CHILDLEVEL, child, ijk); \
421  return cnanovdb_node##CHILDLEVEL##SUFFIX##_getValueAndCache(child, ijk, acc); \
422  } \
423  return node->mTable[n].value; \
424 } \
425 \
426 static bool \
427 cnanovdb_node##LEVEL##SUFFIX##_isActive(const CNANOVDB_GLOBAL cnanovdb_node##LEVEL##SUFFIX *RESTRICT node, const cnanovdb_coord *RESTRICT ijk) \
428 { \
429  uint32_t n = cnanovdb_node##LEVEL##SUFFIX##_CoordToOffset(ijk); \
430  if (cnanovdb_mask##LOG2DIM##_isOn(&node->mChildMask, n)) \
431  { \
432  const CNANOVDB_GLOBAL cnanovdb_node##CHILDLEVEL##SUFFIX *child = cnanovdb_node##LEVEL##SUFFIX##_getChild(node, n); \
433  return cnanovdb_node##CHILDLEVEL##SUFFIX##_isActive(child, ijk); \
434  } \
435  return cnanovdb_mask##LOG2DIM##_isOn(&node->mValueMask, n) ? true : false; \
436 } \
437 \
438 static bool \
439 cnanovdb_node##LEVEL##SUFFIX##_isActiveAndCache(const CNANOVDB_GLOBAL cnanovdb_node##LEVEL##SUFFIX *RESTRICT node, const cnanovdb_coord *RESTRICT ijk, cnanovdb_readaccessor *RESTRICT acc) \
440 { \
441  uint32_t n = cnanovdb_node##LEVEL##SUFFIX##_CoordToOffset(ijk); \
442  if (cnanovdb_mask##LOG2DIM##_isOn(&node->mChildMask, n)) \
443  { \
444  const CNANOVDB_GLOBAL cnanovdb_node##CHILDLEVEL##SUFFIX *child = cnanovdb_node##LEVEL##SUFFIX##_getChild(node, n); \
445  cnanovdb_readaccessor_insert(acc, CHILDLEVEL, child, ijk); \
446  return cnanovdb_node##CHILDLEVEL##SUFFIX##_isActiveAndCache(child, ijk, acc); \
447  } \
448  return cnanovdb_mask##LOG2DIM##_isOn(&node->mValueMask, n) ? true : false; \
449 } \
450 \
451 static const CNANOVDB_GLOBAL cnanovdb_node##LEVEL##SUFFIX * \
452 cnanovdb_tree_getNode##LEVEL##SUFFIX(const CNANOVDB_GLOBAL cnanovdb_treedata *RESTRICT tree, uint64_t i) \
453 { \
454  const CNANOVDB_GLOBAL cnanovdb_node##LEVEL##SUFFIX *basenode = (const CNANOVDB_GLOBAL cnanovdb_node##LEVEL##SUFFIX *)((CNANOVDB_GLOBAL uint8_t *)(tree) + tree->mNodeOffset[LEVEL]); \
455  return basenode + i; \
456 } \
457 \
458 /**/
459 
460 #define CREATE_INTERNAL_NODE(CHILDLEVEL, LEVEL, LOG2DIM, TOTAL, VALUETYPE, STATSTYPE, SUFFIX) \
461 CREATE_INTERNAL_NODE_int(CHILDLEVEL, LEVEL, LOG2DIM, (TOTAL-LOG2DIM), TOTAL, ((1u << TOTAL) - 1u), VALUETYPE, STATSTYPE, SUFFIX)
462 
463 
464 #ifdef USE_SINGLE_ROOT_KEY
465 #define DEFINE_KEY(KEY) \
466  uint64_t KEY;
467 #define KEYSIZE sizeof(uint64_t)
468 
469 #define KEYSEARCH(SUFFIX) \
470  uint64_t key; \
471  key = cnanovdb_coord_to_key(ijk); \
472 \
473  for (int i = low; i < high; i++) \
474  { \
475  const CNANOVDB_GLOBAL cnanovdb_rootdata_tile##SUFFIX *tile = tiles + i; \
476  if (tile->key == key) \
477  return tile; \
478  } \
479 /**/
480 #else
481 #define DEFINE_KEY(KEY) \
482  cnanovdb_coord KEY;
483 #define KEYSIZE sizeof(cnanovdb_coord)
484 #define KEYSEARCH(SUFFIX) \
485  cnanovdb_coord key; \
486  cnanovdb_coord_to_key(&key, ijk); \
487  \
488  while (low != high) \
489  { \
490  int32_t mid = low + (( high - low ) >> 1 ); \
491  const CNANOVDB_GLOBAL cnanovdb_rootdata_tile##SUFFIX *tile = tiles + mid; \
492  \
493  int keycmp = cnanovdb_coord_compare(&tile->key, &key); \
494  if (keycmp == 0) \
495  { \
496  return tile; \
497  } \
498  \
499  if (keycmp < 0) \
500  low = mid + 1; \
501  else \
502  high = mid; \
503  } \
504 /**/
505 #endif
506 
507 
508 #define CREATE_ROOTDATA(VALUETYPE, STATSTYPE, SUFFIX) \
509 typedef struct \
510 { \
511  DEFINE_KEY(key); \
512  int64_t child; \
513  uint32_t state; \
514  VALUETYPE value; \
515  uint8_t _reserved[CNANOVDB_ALIGNMENT_PADDING(sizeof(KEYSIZE)+sizeof(VALUETYPE)+sizeof(int64_t)+sizeof(uint32_t), CNANOVDB_DATA_ALIGNMENT)]; \
516 } cnanovdb_rootdata_tile##SUFFIX; \
517  \
518 typedef struct \
519 { \
520  cnanovdb_coord mBBox_min, mBBox_max; \
521  uint32_t mTableSize; \
522  VALUETYPE mBackground; \
523  VALUETYPE mMinimum, mMaximum; \
524  STATSTYPE mAverage, mStdDevi; \
525  uint32_t _reserved[CNANOVDB_ALIGNMENT_PADDING(sizeof(cnanovdb_coord)*2+sizeof(uint32_t)+sizeof(VALUETYPE)*3+sizeof(STATSTYPE)*2, CNANOVDB_DATA_ALIGNMENT)/4]; \
526 } cnanovdb_rootdata##SUFFIX; \
527  \
528 static const CNANOVDB_GLOBAL cnanovdb_rootdata##SUFFIX * \
529 cnanovdb_treedata_root##SUFFIX(const CNANOVDB_GLOBAL cnanovdb_treedata *RESTRICT treedata) \
530 { \
531  return (const CNANOVDB_GLOBAL cnanovdb_rootdata##SUFFIX *) ((const CNANOVDB_GLOBAL uint8_t *)(treedata) + treedata->mNodeOffset[ROOT_LEVEL]); \
532 } \
533  \
534 static const CNANOVDB_GLOBAL cnanovdb_rootdata_tile##SUFFIX * \
535 cnanovdb_rootdata##SUFFIX##_getTile(const CNANOVDB_GLOBAL cnanovdb_rootdata##SUFFIX *RESTRICT rootdata, uint32_t n) \
536 { \
537  const CNANOVDB_GLOBAL cnanovdb_rootdata_tile##SUFFIX *basetile = (const CNANOVDB_GLOBAL cnanovdb_rootdata_tile##SUFFIX *) (rootdata + 1); \
538  return basetile + n; \
539 } \
540  \
541 static const CNANOVDB_GLOBAL cnanovdb_node2##SUFFIX * \
542 cnanovdb_rootdata##SUFFIX##_getChild(const CNANOVDB_GLOBAL cnanovdb_rootdata##SUFFIX *RESTRICT rootdata, const CNANOVDB_GLOBAL cnanovdb_rootdata_tile##SUFFIX *RESTRICT tile) \
543 { \
544  CNANOVDB_GLOBAL cnanovdb_node2##SUFFIX *basenode = (CNANOVDB_GLOBAL cnanovdb_node2##SUFFIX *) (((CNANOVDB_GLOBAL uint8_t *) rootdata) + tile->child); \
545  return basenode; \
546 } \
547  \
548 static const CNANOVDB_GLOBAL cnanovdb_rootdata_tile##SUFFIX * \
549 cnanovdb_rootdata##SUFFIX##_findTile(const CNANOVDB_GLOBAL cnanovdb_rootdata##SUFFIX *RESTRICT rootdata, const cnanovdb_coord *RESTRICT ijk) \
550 { \
551  int32_t low = 0, high = rootdata->mTableSize; \
552  const CNANOVDB_GLOBAL cnanovdb_rootdata_tile##SUFFIX *tiles = cnanovdb_rootdata##SUFFIX##_getTile(rootdata, 0); \
553  \
554  KEYSEARCH(SUFFIX) \
555  return 0; \
556 } \
557  \
558 static VALUETYPE \
559 cnanovdb_rootdata##SUFFIX##_getValue(const CNANOVDB_GLOBAL cnanovdb_rootdata##SUFFIX *RESTRICT rootdata, const cnanovdb_coord *RESTRICT ijk) \
560 { \
561  const CNANOVDB_GLOBAL cnanovdb_rootdata_tile##SUFFIX *tile = cnanovdb_rootdata##SUFFIX##_findTile(rootdata, ijk); \
562  if (!tile) \
563  return rootdata->mBackground; \
564  if (tile->child == 0) \
565  return tile->value; \
566  return cnanovdb_node2##SUFFIX##_getValue( cnanovdb_rootdata##SUFFIX##_getChild(rootdata, tile), ijk ); \
567 } \
568  \
569 static VALUETYPE \
570 cnanovdb_rootdata##SUFFIX##_getValueAndCache(const CNANOVDB_GLOBAL cnanovdb_rootdata##SUFFIX *RESTRICT rootdata, const cnanovdb_coord *RESTRICT ijk, cnanovdb_readaccessor *RESTRICT acc) \
571 { \
572  const CNANOVDB_GLOBAL cnanovdb_rootdata_tile##SUFFIX *tile = cnanovdb_rootdata##SUFFIX##_findTile(rootdata, ijk); \
573  if (!tile) \
574  return rootdata->mBackground; \
575  if (tile->child == 0) \
576  return tile->value; \
577  const CNANOVDB_GLOBAL cnanovdb_node2##SUFFIX *child = cnanovdb_rootdata##SUFFIX##_getChild(rootdata, tile); \
578  cnanovdb_readaccessor_insert(acc, 2, child, ijk); \
579  return cnanovdb_node2##SUFFIX##_getValueAndCache( child, ijk, acc ); \
580 } \
581 \
582 static bool \
583 cnanovdb_rootdata##SUFFIX##_isActive(const CNANOVDB_GLOBAL cnanovdb_rootdata##SUFFIX *RESTRICT rootdata, const cnanovdb_coord *RESTRICT ijk) \
584 { \
585  const CNANOVDB_GLOBAL cnanovdb_rootdata_tile##SUFFIX *tile = cnanovdb_rootdata##SUFFIX##_findTile(rootdata, ijk); \
586  if (!tile) \
587  return false; \
588  if (tile->child == 0) \
589  return tile->state; \
590  return cnanovdb_node2##SUFFIX##_isActive( cnanovdb_rootdata##SUFFIX##_getChild(rootdata, tile), ijk ); \
591 } \
592  \
593 static bool \
594 cnanovdb_rootdata##SUFFIX##_isActiveAndCache(const CNANOVDB_GLOBAL cnanovdb_rootdata##SUFFIX *RESTRICT rootdata, const cnanovdb_coord *RESTRICT ijk, cnanovdb_readaccessor *RESTRICT acc) \
595 { \
596  const CNANOVDB_GLOBAL cnanovdb_rootdata_tile##SUFFIX *tile = cnanovdb_rootdata##SUFFIX##_findTile(rootdata, ijk); \
597  if (!tile) \
598  return false; \
599  if (tile->child == 0) \
600  return tile->state; \
601  const CNANOVDB_GLOBAL cnanovdb_node2##SUFFIX *child = cnanovdb_rootdata##SUFFIX##_getChild(rootdata, tile); \
602  cnanovdb_readaccessor_insert(acc, 2, child, ijk); \
603  return cnanovdb_node2##SUFFIX##_isActiveAndCache( child, ijk, acc ); \
604 } \
605 /**/
606 
607 
608 inline void
610  const CNANOVDB_GLOBAL void /*cnanovdb_rootdata* */ *RESTRICT rootdata)
611 {
612  acc->mNode[0] = acc->mNode[1] = acc->mNode[2] = 0;
613  acc->mNode[3] = rootdata;
614 }
615 
616 #define DEFINE_ISCACHED(LEVEL, MASK) \
617 inline bool \
618 cnanovdb_readaccessor_isCached##LEVEL(cnanovdb_readaccessor *RESTRICT acc, int32_t dirty) \
619 { \
620  if (!acc->mNode[LEVEL]) \
621  return false; \
622  if (dirty & ~MASK) \
623  { \
624  acc->mNode[LEVEL] = 0; \
625  return false; \
626  } \
627  return true; \
628 } \
629 /**/
630 
631 DEFINE_ISCACHED(0, ((1u << 3) - 1u) )
632 DEFINE_ISCACHED(1, ((1u << 7) - 1u) )
633 DEFINE_ISCACHED(2, ((1u << 12) - 1u) )
634 
635 inline int32_t
637 {
638  return (ijk->mVec[0] ^ acc->mKey.mVec[0]) |
639  (ijk->mVec[1] ^ acc->mKey.mVec[1]) |
640  (ijk->mVec[2] ^ acc->mKey.mVec[2]);
641 }
642 
643 #define CREATE_ACCESSOR(VALUETYPE, SUFFIX) \
644 inline VALUETYPE \
645 cnanovdb_readaccessor_getValue##SUFFIX(cnanovdb_readaccessor *RESTRICT acc, const cnanovdb_coord *RESTRICT ijk) \
646 { \
647  int32_t dirty = cnanovdb_readaccessor_computeDirty(acc, ijk); \
648  \
649  if (cnanovdb_readaccessor_isCached0(acc, dirty)) \
650  return cnanovdb_node0##SUFFIX##_getValue( ((CNANOVDB_GLOBAL cnanovdb_node0##SUFFIX *) acc->mNode[0]), ijk); \
651  if (cnanovdb_readaccessor_isCached1(acc, dirty)) \
652  return cnanovdb_node1##SUFFIX##_getValueAndCache( ((CNANOVDB_GLOBAL cnanovdb_node1##SUFFIX *) acc->mNode[1]), ijk, acc); \
653  if (cnanovdb_readaccessor_isCached2(acc, dirty)) \
654  return cnanovdb_node2##SUFFIX##_getValueAndCache( ((CNANOVDB_GLOBAL cnanovdb_node2##SUFFIX *) acc->mNode[2]), ijk, acc); \
655  \
656  return cnanovdb_rootdata##SUFFIX##_getValueAndCache( ((CNANOVDB_GLOBAL cnanovdb_rootdata##SUFFIX *)acc->mNode[3]), ijk, acc); \
657 } \
658 \
659 inline bool \
660 cnanovdb_readaccessor_isActive##SUFFIX(cnanovdb_readaccessor *RESTRICT acc, const cnanovdb_coord *RESTRICT ijk) \
661 { \
662  int32_t dirty = cnanovdb_readaccessor_computeDirty(acc, ijk); \
663  \
664  if (cnanovdb_readaccessor_isCached0(acc, dirty)) \
665  return cnanovdb_node0##SUFFIX##_isActive( ((CNANOVDB_GLOBAL cnanovdb_node0##SUFFIX *) acc->mNode[0]), ijk); \
666  if (cnanovdb_readaccessor_isCached1(acc, dirty)) \
667  return cnanovdb_node1##SUFFIX##_isActiveAndCache( ((CNANOVDB_GLOBAL cnanovdb_node1##SUFFIX *) acc->mNode[1]), ijk, acc); \
668  if (cnanovdb_readaccessor_isCached2(acc, dirty)) \
669  return cnanovdb_node2##SUFFIX##_isActiveAndCache( ((CNANOVDB_GLOBAL cnanovdb_node2##SUFFIX *) acc->mNode[2]), ijk, acc); \
670  \
671  return cnanovdb_rootdata##SUFFIX##_isActiveAndCache( ((CNANOVDB_GLOBAL cnanovdb_rootdata##SUFFIX *)acc->mNode[3]), ijk, acc); \
672 } \
673 /**/
674 
675 
676 #define CREATE_GRIDTYPE(VALUETYPE, STATSTYPE, SUFFIX) \
677 CREATE_TILEENTRY(VALUETYPE, SUFFIX) \
678 CREATE_LEAF_NODE(0, 3, 3, VALUETYPE, STATSTYPE, SUFFIX) \
679 CREATE_INTERNAL_NODE(0, 1, 4, 7, VALUETYPE, STATSTYPE, SUFFIX) \
680 CREATE_INTERNAL_NODE(1, 2, 5, 12, VALUETYPE, STATSTYPE, SUFFIX) \
681 CREATE_ROOTDATA(VALUETYPE, STATSTYPE, SUFFIX) \
682 CREATE_ACCESSOR(VALUETYPE, SUFFIX) \
683 /**/
684 
685 CREATE_GRIDTYPE(float, float, F)
687 
688 static int
690 {
691  if (!grid)
692  return 0;
693  if (grid->mMagic != 0x304244566f6e614eUL && grid->mMagic != 0x314244566f6e614eUL)
694  return 0;
695  return 1;
696 }
697 
698 static int
700 {
701  if (!cnanovdb_griddata_valid(grid))
702  return 0;
703  if (grid->mGridType != cnanovdb_GridType_Float)
704  return 0;
705  return 1;
706 }
707 
708 static int
710 {
711  if (!cnanovdb_griddata_valid(grid))
712  return 0;
713  if (grid->mGridType != cnanovdb_GridType_Vec3f)
714  return 0;
715  return 1;
716 }
717 
718 #endif
Definition: CNanoVDB.h:45
Definition: CNanoVDB.h:49
#define INSTANTIATE(LOG2DIM)
Definition: CNanoVDB.h:74
Definition: CNanoVDB.h:46
static void cnanovdb_map_applyInverseJacobi(cnanovdb_Vec3F *dst, const cnanovdb_map *__restrict map, const cnanovdb_Vec3F *src)
Definition: CNanoVDB.h:182
static int cnanovdb_griddata_validF3(const cnanovdb_griddata *__restrict grid)
Definition: CNanoVDB.h:709
uint64_t mGridSize
Definition: CNanoVDB.h:223
static void cnanovdb_griddata_worldToIndexDir(cnanovdb_Vec3F *dst, const cnanovdb_griddata *__restrict grid, const cnanovdb_Vec3F *src)
Definition: CNanoVDB.h:248
static int cnanovdb_coord_compare(const cnanovdb_coord *a, const cnanovdb_coord *b)
Definition: CNanoVDB.h:104
uint32_t mDataType
Definition: CNanoVDB.h:210
int64_t mByteOffset
Definition: CNanoVDB.h:205
void cnanovdb_readaccessor_init(cnanovdb_readaccessor *__restrict acc, const void *__restrict rootdata)
Definition: CNanoVDB.h:609
uint32_t mGridIndex
Definition: CNanoVDB.h:221
Definition: CNanoVDB.h:81
Definition: CNanoVDB.h:203
Definition: CNanoVDB.h:215
uint32_t mSemantic
Definition: CNanoVDB.h:208
static void cnanovdb_map_applyJacobi(cnanovdb_Vec3F *dst, const cnanovdb_map *__restrict map, const cnanovdb_Vec3F *src)
Definition: CNanoVDB.h:171
uint64_t mElementCount
Definition: CNanoVDB.h:206
uint32_t mGridType
Definition: CNanoVDB.h:229
Definition: CNanoVDB.h:43
cnanovdb_GridType
Definition: CNanoVDB.h:41
Definition: CNanoVDB.h:44
static void cnanovdb_griddata_indexToWorld(cnanovdb_Vec3F *dst, const cnanovdb_griddata *__restrict grid, const cnanovdb_Vec3F *src)
Definition: CNanoVDB.h:242
Definition: CNanoVDB.h:98
Definition: CNanoVDB.h:265
int32_t cnanovdb_readaccessor_computeDirty(const cnanovdb_readaccessor *__restrict acc, const cnanovdb_coord *__restrict ijk)
Definition: CNanoVDB.h:636
#define CREATE_GRIDTYPE(VALUETYPE, STATSTYPE, SUFFIX)
Definition: CNanoVDB.h:676
Definition: CNanoVDB.h:51
float mVec[3]
Definition: CNanoVDB.h:95
uint64_t mVoxelCount
Definition: CNanoVDB.h:270
uint32_t mDataClass
Definition: CNanoVDB.h:209
static void cnanovdb_griddata_applyIJT(cnanovdb_Vec3F *dst, const cnanovdb_griddata *__restrict grid, const cnanovdb_Vec3F *src)
Definition: CNanoVDB.h:260
#define CNANOVDB_GLOBAL
Definition: CNanoVDB.h:35
uint32_t mGridCount
Definition: CNanoVDB.h:222
static void cnanovdb_map_applyIJT(cnanovdb_Vec3F *dst, const cnanovdb_map *__restrict map, const cnanovdb_Vec3F *src)
Definition: CNanoVDB.h:193
#define RESTRICT
Definition: CNanoVDB.h:36
#define DEFINE_ISCACHED(LEVEL, MASK)
Definition: CNanoVDB.h:616
Definition: CNanoVDB.h:53
uint32_t mGridClass
Definition: CNanoVDB.h:228
#define ROOT_LEVEL
Definition: CNanoVDB.h:56
uint64_t mBlindMetadataOffset
Definition: CNanoVDB.h:230
Definition: CNanoVDB.h:288
static void cnanovdb_griddata_worldToIndex(cnanovdb_Vec3F *dst, const cnanovdb_griddata *__restrict grid, const cnanovdb_Vec3F *src)
Definition: CNanoVDB.h:236
static int cnanovdb_griddata_valid(const cnanovdb_griddata *__restrict grid)
Definition: CNanoVDB.h:689
#define CNANOVDB_ALIGNMENT_PADDING(x, n)
Definition: CNanoVDB.h:15
cnanovdb_coord mKey
Definition: CNanoVDB.h:290
#define CNANOVDB_DATA_ALIGNMENT
Definition: CNanoVDB.h:14
uint32_t mVersion
Definition: CNanoVDB.h:219
uint64_t mMagic
Definition: CNanoVDB.h:217
Definition: CNanoVDB.h:93
int32_t mVec[3]
Definition: CNanoVDB.h:100
static uint64_t cnanovdb_coord_to_key(const cnanovdb_coord *__restrict ijk)
Definition: CNanoVDB.h:123
uint32_t mFlags
Definition: CNanoVDB.h:207
float mTaperF
Definition: CNanoVDB.h:86
cnanovdb_map mMap
Definition: CNanoVDB.h:225
static void cnanovdb_map_apply(cnanovdb_Vec3F *dst, const cnanovdb_map *__restrict map, const cnanovdb_Vec3F *src)
Definition: CNanoVDB.h:149
Definition: CNanoVDB.h:50
Definition: CNanoVDB.h:47
static const cnanovdb_treedata * cnanovdb_griddata_tree(const cnanovdb_griddata *__restrict griddata)
Definition: CNanoVDB.h:275
int32_t mBlindMetadataCount
Definition: CNanoVDB.h:231
static void cnanovdb_griddata_indexToWorldDir(cnanovdb_Vec3F *dst, const cnanovdb_griddata *__restrict grid, const cnanovdb_Vec3F *src)
Definition: CNanoVDB.h:254
uint32_t mFlags
Definition: CNanoVDB.h:220
Definition: CNanoVDB.h:52
static void cnanovdb_map_applyInverse(cnanovdb_Vec3F *dst, const cnanovdb_map *__restrict map, const cnanovdb_Vec3F *src)
Definition: CNanoVDB.h:160
double mTaperD
Definition: CNanoVDB.h:90
uint64_t mChecksum
Definition: CNanoVDB.h:218
static void cnanovdb_readaccessor_insert(cnanovdb_readaccessor *__restrict acc, int childlevel, const void *__restrict node, const cnanovdb_coord *__restrict ijk)
Definition: CNanoVDB.h:296
Definition: CNanoVDB.h:48
static int cnanovdb_griddata_validF(const cnanovdb_griddata *__restrict grid)
Definition: CNanoVDB.h:699