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